This source file includes following definitions.
- db_find_trace_symbols
- db_numargs
- db_nextframe
- db_stack_trace_print
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30 #include <sys/param.h>
31 #include <sys/systm.h>
32 #include <sys/proc.h>
33 #include <sys/user.h>
34
35 #include <machine/db_machdep.h>
36
37 #include <ddb/db_sym.h>
38 #include <ddb/db_access.h>
39 #include <ddb/db_variables.h>
40 #include <ddb/db_output.h>
41 #include <ddb/db_interface.h>
42
43
44
45
46 struct db_variable db_regs[] = {
47 { "ds", (long *)&ddb_regs.tf_ds, FCN_NULL },
48 { "es", (long *)&ddb_regs.tf_es, FCN_NULL },
49 { "fs", (long *)&ddb_regs.tf_fs, FCN_NULL },
50 { "gs", (long *)&ddb_regs.tf_gs, FCN_NULL },
51 { "edi", (long *)&ddb_regs.tf_edi, FCN_NULL },
52 { "esi", (long *)&ddb_regs.tf_esi, FCN_NULL },
53 { "ebp", (long *)&ddb_regs.tf_ebp, FCN_NULL },
54 { "ebx", (long *)&ddb_regs.tf_ebx, FCN_NULL },
55 { "edx", (long *)&ddb_regs.tf_edx, FCN_NULL },
56 { "ecx", (long *)&ddb_regs.tf_ecx, FCN_NULL },
57 { "eax", (long *)&ddb_regs.tf_eax, FCN_NULL },
58 { "eip", (long *)&ddb_regs.tf_eip, FCN_NULL },
59 { "cs", (long *)&ddb_regs.tf_cs, FCN_NULL },
60 { "eflags", (long *)&ddb_regs.tf_eflags, FCN_NULL },
61 { "esp", (long *)&ddb_regs.tf_esp, FCN_NULL },
62 { "ss", (long *)&ddb_regs.tf_ss, FCN_NULL },
63 };
64 struct db_variable *db_eregs = db_regs + sizeof(db_regs)/sizeof(db_regs[0]);
65
66
67
68
69 #define INKERNEL(va) (((vaddr_t)(va)) >= VM_MIN_KERNEL_ADDRESS)
70
71 struct i386_frame {
72 struct i386_frame *f_frame;
73 int f_retaddr;
74 int f_arg0;
75 };
76
77 #define NONE 0
78 #define TRAP 1
79 #define SYSCALL 2
80 #define INTERRUPT 3
81
82 db_addr_t db_trap_symbol_value = 0;
83 db_addr_t db_syscall_symbol_value = 0;
84 db_addr_t db_kdintr_symbol_value = 0;
85 boolean_t db_trace_symbols_found = FALSE;
86
87 void db_find_trace_symbols(void);
88 int db_numargs(struct i386_frame *);
89 void db_nextframe(struct i386_frame **, db_addr_t *, int *, int,
90 int (*pr)(const char *, ...));
91
92 void
93 db_find_trace_symbols(void)
94 {
95 db_expr_t value;
96
97 if (db_value_of_name("trap", &value))
98 db_trap_symbol_value = (db_addr_t) value;
99 if (db_value_of_name("kdintr", &value))
100 db_kdintr_symbol_value = (db_addr_t) value;
101 if (db_value_of_name("syscall", &value))
102 db_syscall_symbol_value = (db_addr_t) value;
103 db_trace_symbols_found = TRUE;
104 }
105
106
107
108
109 int
110 db_numargs(struct i386_frame *fp)
111 {
112 int *argp;
113 int inst;
114 int args;
115 extern char etext[];
116
117 argp = (int *)db_get_value((int)&fp->f_retaddr, 4, FALSE);
118 if (argp < (int *)VM_MIN_KERNEL_ADDRESS || argp > (int *)etext) {
119 args = 5;
120 } else {
121 inst = db_get_value((int)argp, 4, FALSE);
122 if ((inst & 0xff) == 0x59)
123 args = 1;
124 else if ((inst & 0xffff) == 0xc483)
125 args = ((inst >> 16) & 0xff) / 4;
126 else
127 args = 5;
128 }
129 return (args);
130 }
131
132
133
134
135
136
137
138
139
140
141
142 void
143 db_nextframe(struct i386_frame **fp, db_addr_t *ip, int *argp, int is_trap,
144 int (*pr)(const char *, ...))
145 {
146
147 switch (is_trap) {
148 case NONE:
149 *ip = (db_addr_t)
150 db_get_value((int) &(*fp)->f_retaddr, 4, FALSE);
151 *fp = (struct i386_frame *)
152 db_get_value((int) &(*fp)->f_frame, 4, FALSE);
153 break;
154
155 default: {
156 struct trapframe *tf;
157
158
159 tf = (struct trapframe *)argp;
160 switch (is_trap) {
161 case TRAP:
162 (*pr)("--- trap (number %d) ---\n", tf->tf_trapno);
163 break;
164 case SYSCALL:
165 (*pr)("--- syscall (number %d) ---\n", tf->tf_eax);
166 break;
167 case INTERRUPT:
168 (*pr)("--- interrupt ---\n");
169 break;
170 }
171 *fp = (struct i386_frame *)tf->tf_ebp;
172 *ip = (db_addr_t)tf->tf_eip;
173 break;
174 }
175 }
176 }
177
178 void
179 db_stack_trace_print(db_expr_t addr, boolean_t have_addr, db_expr_t count,
180 char *modif, int (*pr)(const char *, ...))
181 {
182 struct i386_frame *frame, *lastframe;
183 int *argp;
184 db_addr_t callpc;
185 int is_trap = 0;
186 boolean_t kernel_only = TRUE;
187 boolean_t trace_thread = FALSE;
188 boolean_t trace_proc = FALSE;
189
190 #if 0
191 if (!db_trace_symbols_found)
192 db_find_trace_symbols();
193 #endif
194
195 {
196 char *cp = modif;
197 char c;
198
199 while ((c = *cp++) != 0) {
200 if (c == 't')
201 trace_thread = TRUE;
202 if (c == 'p')
203 trace_proc = TRUE;
204 if (c == 'u')
205 kernel_only = FALSE;
206 }
207 }
208
209 if (count == -1)
210 count = 65535;
211
212 if (!have_addr) {
213 frame = (struct i386_frame *)ddb_regs.tf_ebp;
214 callpc = (db_addr_t)ddb_regs.tf_eip;
215 } else if (trace_thread) {
216 (*pr) ("db_trace.c: can't trace thread\n");
217 } else if (trace_proc) {
218 struct proc *p = pfind((pid_t)addr);
219 if (p == NULL) {
220 (*pr) ("db_trace.c: process not found\n");
221 return;
222 }
223 frame = (struct i386_frame *)p->p_addr->u_pcb.pcb_ebp;
224 callpc = (db_addr_t)
225 db_get_value((int)&frame->f_retaddr, 4, FALSE);
226 } else {
227 frame = (struct i386_frame *)addr;
228 callpc = (db_addr_t)
229 db_get_value((int)&frame->f_retaddr, 4, FALSE);
230 }
231
232 lastframe = 0;
233 while (count && frame != 0) {
234 int narg;
235 char * name;
236 db_expr_t offset;
237 db_sym_t sym;
238 #define MAXNARG 16
239 char *argnames[MAXNARG], **argnp = NULL;
240
241 sym = db_search_symbol(callpc, DB_STGY_ANY, &offset);
242 db_symbol_values(sym, &name, NULL);
243
244 if (lastframe == 0 && sym == NULL) {
245
246 int instr = db_get_value(callpc, 4, FALSE);
247
248 offset = 1;
249 if ((instr & 0x00ffffff) == 0x00e58955 ||
250
251 (instr & 0x0000ffff) == 0x0000e589
252 ) {
253 offset = 0;
254 }
255 }
256 if (INKERNEL((int)frame) && name) {
257 if (!strcmp(name, "trap")) {
258 is_trap = TRAP;
259 } else if (!strcmp(name, "syscall")) {
260 is_trap = SYSCALL;
261 } else if (!strncmp(name, "Xintr", 5) ||
262 !strncmp(name, "Xresume", 7) ||
263 !strncmp(name, "Xstray", 6) ||
264 !strncmp(name, "Xhold", 5) ||
265 !strncmp(name, "Xrecurse", 8) ||
266 !strcmp(name, "Xdoreti") ||
267 !strncmp(name, "Xsoft", 5)) {
268 is_trap = INTERRUPT;
269 } else
270 goto normal;
271 narg = 0;
272 } else {
273 normal:
274 is_trap = NONE;
275 narg = MAXNARG;
276 if (db_sym_numargs(sym, &narg, argnames))
277 argnp = argnames;
278 else
279 narg = db_numargs(frame);
280 }
281
282 (*pr)("%s(", name);
283
284 if (lastframe == 0 && offset == 0 && !have_addr) {
285
286
287
288
289 argp = &((struct i386_frame *)(ddb_regs.tf_esp-4))->f_arg0;
290 } else {
291 argp = &frame->f_arg0;
292 }
293
294 while (narg) {
295 if (argnp)
296 (*pr)("%s=", *argnp++);
297 (*pr)("%x", db_get_value((int)argp, 4, FALSE));
298 argp++;
299 if (--narg != 0)
300 (*pr)(",");
301 }
302 (*pr)(") at ");
303 db_printsym(callpc, DB_STGY_PROC, pr);
304 (*pr)("\n");
305
306 if (lastframe == 0 && offset == 0 && !have_addr) {
307
308 lastframe = (struct i386_frame *)(ddb_regs.tf_esp-4);
309 callpc = (db_addr_t)
310 db_get_value((int)&lastframe->f_retaddr, 4, FALSE);
311 continue;
312 }
313
314 lastframe = frame;
315 db_nextframe(&frame, &callpc, &frame->f_arg0, is_trap, pr);
316
317 if (frame == 0) {
318
319 break;
320 }
321 if (INKERNEL((int)frame)) {
322
323 if (frame <= lastframe) {
324 (*pr)("Bad frame pointer: %p\n", frame);
325 break;
326 }
327 } else if (INKERNEL((int)lastframe)) {
328
329 if (kernel_only)
330 break;
331 } else {
332
333 if (frame <= lastframe) {
334 (*pr)("Bad user frame pointer: %p\n",
335 frame);
336 break;
337 }
338 }
339 --count;
340 }
341
342 if (count && is_trap != NONE) {
343 db_printsym(callpc, DB_STGY_XTRN, pr);
344 (*pr)(":\n");
345 }
346 }