2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
4 * Copyright (c) 2001 Jake Burkholder.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 #include <sys/cdefs.h>
30 __FBSDID("$FreeBSD$");
32 #include <sys/param.h>
33 #include <sys/systm.h>
36 #include <sys/stack.h>
37 #include <sys/sysent.h>
40 #include <vm/vm_page.h>
41 #include <vm/vm_map.h>
43 #include <machine/cpu.h>
44 #include <machine/pcb.h>
45 #include <machine/stack.h>
46 #include <machine/trap.h>
47 #include <machine/vmparam.h>
50 #include <ddb/db_access.h>
51 #include <ddb/db_sym.h>
52 #include <ddb/db_variables.h>
53 #include <ddb/db_watch.h>
55 static db_varfcn_t db_frame;
57 #define DB_OFFSET(x) (db_expr_t *)offsetof(struct trapframe, x)
58 struct db_variable db_regs[] = {
59 { "g0", DB_OFFSET(tf_global[0]), db_frame },
60 { "g1", DB_OFFSET(tf_global[1]), db_frame },
61 { "g2", DB_OFFSET(tf_global[2]), db_frame },
62 { "g3", DB_OFFSET(tf_global[3]), db_frame },
63 { "g4", DB_OFFSET(tf_global[4]), db_frame },
64 { "g5", DB_OFFSET(tf_global[5]), db_frame },
65 { "g6", DB_OFFSET(tf_global[6]), db_frame },
66 { "g7", DB_OFFSET(tf_global[7]), db_frame },
67 { "i0", DB_OFFSET(tf_out[0]), db_frame },
68 { "i1", DB_OFFSET(tf_out[1]), db_frame },
69 { "i2", DB_OFFSET(tf_out[2]), db_frame },
70 { "i3", DB_OFFSET(tf_out[3]), db_frame },
71 { "i4", DB_OFFSET(tf_out[4]), db_frame },
72 { "i5", DB_OFFSET(tf_out[5]), db_frame },
73 { "i6", DB_OFFSET(tf_out[6]), db_frame },
74 { "i7", DB_OFFSET(tf_out[7]), db_frame },
75 { "tnpc", DB_OFFSET(tf_tnpc), db_frame },
76 { "tpc", DB_OFFSET(tf_tpc), db_frame },
77 { "tstate", DB_OFFSET(tf_tstate), db_frame },
79 struct db_variable *db_eregs = db_regs + nitems(db_regs);
82 db_frame(struct db_variable *vp, db_expr_t *valuep, int op)
86 if (kdb_frame == NULL)
88 reg = (uint64_t*)((uintptr_t)kdb_frame + (uintptr_t)vp->valuep);
97 * User stack trace (debugging aid).
100 db_utrace(struct thread *td, struct trapframe *tf, int count)
103 db_addr_t sp, rsp, o7, pc;
107 sp = db_get_value((db_addr_t)&tf->tf_sp, sizeof(tf->tf_sp), FALSE);
108 o7 = db_get_value((db_addr_t)&tf->tf_out[7], sizeof(tf->tf_out[7]),
110 pc = db_get_value((db_addr_t)&tf->tf_tpc, sizeof(tf->tf_tpc), FALSE);
111 db_printf("user trace: trap %%o7=%#lx\n", o7);
112 while (count-- && sp != 0 && !db_pager_quit) {
113 db_printf("pc %#lx, sp %#lx\n", pc, sp);
114 /* First, check whether the frame is in the pcb. */
116 for (i = 0; i < pcb->pcb_nsaved; i++) {
117 if (pcb->pcb_rwsp[i] == sp) {
119 sp = pcb->pcb_rw[i].rw_in[6];
120 pc = pcb->pcb_rw[i].rw_in[7];
127 if (copyin((void *)(rsp + offsetof(struct frame, fr_fp)),
128 &sp, sizeof(sp)) != 0 ||
129 copyin((void *)(rsp + offsetof(struct frame, fr_pc)),
130 &pc, sizeof(pc)) != 0)
138 db_print_trap(struct thread *td, struct trapframe *tf, int count)
157 type = db_get_value((db_addr_t)&tf->tf_type,
158 sizeof(tf->tf_type), FALSE);
159 db_printf("-- %s", trap_msg[type & ~T_KERNEL]);
160 switch (type & ~T_KERNEL) {
161 case T_DATA_PROTECTION:
162 tar = (u_long)db_get_value((db_addr_t)&tf->tf_tar,
163 sizeof(tf->tf_tar), FALSE);
164 db_printf(" tar=%#lx", tar);
166 case T_DATA_EXCEPTION:
167 case T_INSTRUCTION_EXCEPTION:
168 case T_MEM_ADDRESS_NOT_ALIGNED:
169 sfar = (u_long)db_get_value((db_addr_t)&tf->tf_sfar,
170 sizeof(tf->tf_sfar), FALSE);
171 sfsr = (u_long)db_get_value((db_addr_t)&tf->tf_sfsr,
172 sizeof(tf->tf_sfsr), FALSE);
173 db_printf(" sfar=%#lx sfsr=%#lx", sfar, sfsr);
176 case T_INSTRUCTION_MISS:
177 tar = (u_long)db_get_value((db_addr_t)&tf->tf_tar,
178 sizeof(tf->tf_tar), FALSE);
179 db_printf(" tar=%#lx", tar);
182 code = db_get_value((db_addr_t)&tf->tf_global[1],
183 sizeof(tf->tf_global[1]), FALSE);
184 db_printf(" (%ld", code);
185 if (code >= 0 && code < p->p_sysent->sv_size) {
186 func = (db_addr_t)p->p_sysent->sv_table[code].sy_call;
187 sym = db_search_symbol(func, DB_STGY_ANY, &diff);
188 if (sym != DB_SYM_NULL && diff == 0) {
189 db_symbol_values(sym, &symname, NULL);
190 db_printf(", %s, %s", p->p_sysent->sv_name,
197 level = (u_long)db_get_value((db_addr_t)&tf->tf_level,
198 sizeof(tf->tf_level), FALSE);
199 pil = (u_long)db_get_value((db_addr_t)&tf->tf_pil,
200 sizeof(tf->tf_pil), FALSE);
201 db_printf(" level=%#lx pil=%#lx", level, pil);
206 o7 = (u_long)db_get_value((db_addr_t)&tf->tf_out[7],
207 sizeof(tf->tf_out[7]), FALSE);
208 db_printf(" %%o7=%#lx --\n", o7);
209 user = (type & T_KERNEL) == 0;
211 tpc = db_get_value((db_addr_t)&tf->tf_tpc,
212 sizeof(tf->tf_tpc), FALSE);
213 db_printf("userland() at ");
214 db_printsym(tpc, DB_STGY_PROC);
216 db_utrace(td, tf, count);
222 db_backtrace(struct thread *td, struct frame *fp, int count)
224 struct trapframe *tf;
240 while (count-- && !user && !db_pager_quit) {
241 pc = (db_addr_t)db_get_value((db_addr_t)&fp->fr_pc,
242 sizeof(fp->fr_pc), FALSE);
247 if (!INKERNEL((vm_offset_t)pc))
249 sym = db_search_symbol(pc, DB_STGY_ANY, &offset);
250 if (sym == C_DB_SYM_NULL) {
254 db_symbol_values(sym, &name, &value);
257 fp = (struct frame *)(db_get_value((db_addr_t)&fp->fr_fp,
258 sizeof(fp->fr_fp), FALSE) + SPOFF);
259 if ((value > (u_long)tl_trap_begin &&
260 value < (u_long)tl_trap_end) ||
261 (value > (u_long)tl_text_begin &&
262 value < (u_long)tl_text_end)) {
263 tf = (struct trapframe *)(fp + 1);
264 npc = db_get_value((db_addr_t)&tf->tf_tpc,
265 sizeof(tf->tf_tpc), FALSE);
266 user = db_print_trap(td, tf, count);
269 db_printf("%s() at ", name);
270 db_printsym(pc, DB_STGY_PROC);
281 db_backtrace(curthread,
282 (struct frame *)__builtin_frame_address(1), -1);
286 db_trace_thread(struct thread *td, int count)
290 ctx = kdb_thr_ctx(td);
291 return (db_backtrace(td,
292 (struct frame *)(ctx->pcb_sp + SPOFF), count));