]> git.saurik.com Git - apple/xnu.git/blob - osfmk/ppc/db_trace.c
xnu-344.21.74.tar.gz
[apple/xnu.git] / osfmk / ppc / db_trace.c
1 /*
2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved.
7 *
8 * This file contains Original Code and/or Modifications of Original Code
9 * as defined in and that are subject to the Apple Public Source License
10 * Version 2.0 (the 'License'). You may not use this file except in
11 * compliance with the License. Please obtain a copy of the License at
12 * http://www.opensource.apple.com/apsl/ and read it before using this
13 * file.
14 *
15 * The Original Code and all software distributed under the License are
16 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
17 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
18 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
20 * Please see the License for the specific language governing rights and
21 * limitations under the License.
22 *
23 * @APPLE_LICENSE_HEADER_END@
24 */
25 /*
26 * @OSF_COPYRIGHT@
27 */
28
29 #include <string.h>
30
31 #include <mach/boolean.h>
32 #include <vm/vm_map.h>
33 #include <kern/thread.h>
34 #include <kern/processor.h>
35 #include <kern/task.h>
36
37 #include <machine/asm.h>
38 #include <machine/db_machdep.h>
39 #include <machine/setjmp.h>
40 #include <mach/machine.h>
41
42 #include <ddb/db_access.h>
43 #include <ddb/db_sym.h>
44 #include <ddb/db_variables.h>
45 #include <ddb/db_command.h>
46 #include <ddb/db_task_thread.h>
47 #include <ddb/db_output.h>
48
49 extern jmp_buf_t *db_recover;
50 extern struct savearea *saved_state[];
51
52 struct savearea ddb_null_kregs;
53
54 extern vm_offset_t vm_min_inks_addr; /* set by db_clone_symtabXXX */
55
56 #define DB_NUMARGS_MAX 5
57
58
59 extern char FixedStackStart[], FixedStackEnd[];
60 #define INFIXEDSTACK(va) \
61 ((((vm_offset_t)(va)) >= (vm_offset_t)&FixedStackStart) && \
62 (((vm_offset_t)(va)) < ((vm_offset_t)&FixedStackEnd)))
63
64 #define INKERNELSTACK(va, th) 1
65
66 struct db_ppc_frame {
67 struct db_ppc_frame *f_frame;
68 int pad1;
69 uint32_t f_retaddr;
70 int pad3;
71 int pad4;
72 int pad5;
73 uint32_t f_arg[DB_NUMARGS_MAX];
74 };
75
76 #define TRAP 1
77 #define INTERRUPT 2
78 #define SYSCALL 3
79
80 db_addr_t db_user_trap_symbol_value = 0;
81 db_addr_t db_kernel_trap_symbol_value = 0;
82 db_addr_t db_interrupt_symbol_value = 0;
83 db_addr_t db_return_to_iret_symbol_value = 0;
84 db_addr_t db_syscall_symbol_value = 0;
85 boolean_t db_trace_symbols_found = FALSE;
86
87 extern int db_ppc_reg_value(
88 struct db_variable * vp,
89 db_expr_t * val,
90 int flag,
91 db_var_aux_param_t ap);
92 extern void db_find_trace_symbols(void);
93 extern int db_numargs(
94 struct db_ppc_frame *fp,
95 task_t task);
96 extern boolean_t db_find_arg(
97 struct db_ppc_frame *frame,
98 db_addr_t calleepc,
99 task_t task,
100 int narg,
101 db_addr_t *arg);
102 extern void db_nextframe(
103 struct db_ppc_frame **lfp,
104 struct db_ppc_frame **fp,
105 db_addr_t *ip,
106 int frame_type,
107 thread_act_t thr_act,
108 db_addr_t linkpc);
109 extern int _setjmp(
110 jmp_buf_t * jb);
111
112 /*
113 * Machine register set.
114 */
115 struct db_variable db_regs[] = {
116 /* XXX "pc" is an alias to "srr0"... */
117 { "pc", &ddb_regs.save_srr0, db_ppc_reg_value, 0, 0, 0, 0, TRUE },
118 { "srr0", &ddb_regs.save_srr0, db_ppc_reg_value, 0, 0, 0, 0, TRUE },
119 { "srr1", &ddb_regs.save_srr1, db_ppc_reg_value, 0, 0, 0, 0, TRUE },
120 { "r0", &ddb_regs.save_r0, db_ppc_reg_value, 0, 0, 0, 0, TRUE },
121 { "r1", &ddb_regs.save_r1, db_ppc_reg_value, 0, 0, 0, 0, TRUE },
122 { "r2", &ddb_regs.save_r2, db_ppc_reg_value, 0, 0, 0, 0, TRUE },
123 { "r3", &ddb_regs.save_r3, db_ppc_reg_value, 0, 0, 0, 0, TRUE },
124 { "r4", &ddb_regs.save_r4, db_ppc_reg_value, 0, 0, 0, 0, TRUE },
125 { "r5", &ddb_regs.save_r5, db_ppc_reg_value, 0, 0, 0, 0, TRUE },
126 { "r6", &ddb_regs.save_r6, db_ppc_reg_value, 0, 0, 0, 0, TRUE },
127 { "r7", &ddb_regs.save_r7, db_ppc_reg_value, 0, 0, 0, 0, TRUE },
128 { "r8", &ddb_regs.save_r8, db_ppc_reg_value, 0, 0, 0, 0, TRUE },
129 { "r9", &ddb_regs.save_r9, db_ppc_reg_value, 0, 0, 0, 0, TRUE },
130 { "r10", &ddb_regs.save_r10, db_ppc_reg_value, 0, 0, 0, 0, TRUE },
131 { "r11", &ddb_regs.save_r11, db_ppc_reg_value, 0, 0, 0, 0, TRUE },
132 { "r12", &ddb_regs.save_r12, db_ppc_reg_value, 0, 0, 0, 0, TRUE },
133 { "r13", &ddb_regs.save_r13, db_ppc_reg_value, 0, 0, 0, 0, TRUE },
134 { "r14", &ddb_regs.save_r14, db_ppc_reg_value, 0, 0, 0, 0, TRUE },
135 { "r15", &ddb_regs.save_r15, db_ppc_reg_value, 0, 0, 0, 0, TRUE },
136 { "r16", &ddb_regs.save_r16, db_ppc_reg_value, 0, 0, 0, 0, TRUE },
137 { "r17", &ddb_regs.save_r17, db_ppc_reg_value, 0, 0, 0, 0, TRUE },
138 { "r18", &ddb_regs.save_r18, db_ppc_reg_value, 0, 0, 0, 0, TRUE },
139 { "r19", &ddb_regs.save_r19, db_ppc_reg_value, 0, 0, 0, 0, TRUE },
140 { "r20", &ddb_regs.save_r20, db_ppc_reg_value, 0, 0, 0, 0, TRUE },
141 { "r21", &ddb_regs.save_r21, db_ppc_reg_value, 0, 0, 0, 0, TRUE },
142 { "r22", &ddb_regs.save_r22, db_ppc_reg_value, 0, 0, 0, 0, TRUE },
143 { "r23", &ddb_regs.save_r23, db_ppc_reg_value, 0, 0, 0, 0, TRUE },
144 { "r24", &ddb_regs.save_r24, db_ppc_reg_value, 0, 0, 0, 0, TRUE },
145 { "r25", &ddb_regs.save_r25, db_ppc_reg_value, 0, 0, 0, 0, TRUE },
146 { "r26", &ddb_regs.save_r26, db_ppc_reg_value, 0, 0, 0, 0, TRUE },
147 { "r27", &ddb_regs.save_r27, db_ppc_reg_value, 0, 0, 0, 0, TRUE },
148 { "r28", &ddb_regs.save_r28, db_ppc_reg_value, 0, 0, 0, 0, TRUE },
149 { "r29", &ddb_regs.save_r29, db_ppc_reg_value, 0, 0, 0, 0, TRUE },
150 { "r30", &ddb_regs.save_r30, db_ppc_reg_value, 0, 0, 0, 0, TRUE },
151 { "r31", &ddb_regs.save_r31, db_ppc_reg_value, 0, 0, 0, 0, TRUE },
152 { "cr", &ddb_regs.save_cr, db_ppc_reg_value, 0, 0, 0, 0, TRUE },
153 { "xer", &ddb_regs.save_xer, db_ppc_reg_value, 0, 0, 0, 0, TRUE },
154 { "lr", &ddb_regs.save_lr, db_ppc_reg_value, 0, 0, 0, 0, TRUE },
155 { "ctr", &ddb_regs.save_ctr, db_ppc_reg_value, 0, 0, 0, 0, TRUE },
156 };
157 struct db_variable *db_eregs = db_regs + sizeof(db_regs)/sizeof(db_regs[0]);
158
159 int
160 db_ppc_reg_value(
161 struct db_variable *vp,
162 db_expr_t *valuep,
163 int flag,
164 db_var_aux_param_t ap)
165 {
166 db_expr_t *dp = 0;
167 db_expr_t null_reg = 0;
168 uint32_t *dp32;
169
170 register thread_act_t thr_act = ap->thr_act;
171 int cpu;
172
173 if (db_option(ap->modif, 'u')) {
174 if (thr_act == THR_ACT_NULL) {
175 if ((thr_act = current_act()) == THR_ACT_NULL)
176 db_error("no user registers\n");
177 }
178 if (thr_act == current_act()) {
179 if (IS_USER_TRAP((&ddb_regs))) dp = vp->valuep;
180 else if (INFIXEDSTACK(ddb_regs.save_r1))
181 db_error("cannot get/set user registers in nested interrupt\n");
182 }
183 }
184 else {
185 if (thr_act == THR_ACT_NULL || thr_act == current_act()) {
186 dp = vp->valuep;
187 }
188 else {
189 if (thr_act->thread &&
190 !(thr_act->thread->state & TH_STACK_HANDOFF) &&
191 thr_act->thread->kernel_stack) {
192
193 int cpu;
194
195 for (cpu = 0; cpu < NCPUS; cpu++) {
196 if (cpu_to_processor(cpu)->state == PROCESSOR_RUNNING &&
197 cpu_to_processor(cpu)->cpu_data->active_thread == thr_act->thread && saved_state[cpu]) {
198
199 dp = (db_expr_t)(((uint32_t)saved_state[cpu]) +
200 (((uint32_t) vp->valuep) -
201 (uint32_t) &ddb_regs));
202 break;
203 }
204 }
205
206 if (dp == 0) dp = &null_reg;
207 }
208 else if (thr_act->thread && (thr_act->thread->state & TH_STACK_HANDOFF)){
209 /* only PC is valid */
210 if (vp->valuep == (int *) &ddb_regs.save_srr0) {
211 dp = (int *)(&thr_act->thread->continuation);
212 }
213 else {
214 dp = &null_reg;
215 }
216 }
217 }
218 }
219 if (dp == 0) {
220
221 if (!db_option(ap->modif, 'u')) {
222 for (cpu = 0; cpu < NCPUS; cpu++) {
223 if (cpu_to_processor(cpu)->state == PROCESSOR_RUNNING &&
224 cpu_to_processor(cpu)->cpu_data->active_thread == thr_act->thread && saved_state[cpu]) {
225 dp = (int *) (((int)saved_state[cpu]) +
226 (((int) vp->valuep) - (int) &ddb_regs));
227 break;
228 }
229 }
230 }
231 if (dp == 0) {
232 if (!thr_act || thr_act->mact.pcb == 0) db_error("no pcb\n");
233 dp = (int *)((int)thr_act->mact.pcb + ((int)vp->valuep - (int)&ddb_regs));
234 }
235 }
236
237 if(vp->valuep == (int *) &ddb_regs.save_cr) { /* Is this the CR we are doing? */
238 dp32 = (uint32_t *)dp; /* Make this easier */
239 if (flag == DB_VAR_SET) *dp32 = *valuep;
240 else *valuep = *dp32;
241 }
242 else { /* Normal 64-bit registers */
243 if (flag == DB_VAR_SET) *dp = *valuep;
244 else *valuep = *(unsigned long long *)dp;
245 }
246
247 return(0);
248 }
249
250
251 void
252 db_find_trace_symbols(void)
253 {
254 db_expr_t value;
255 boolean_t found_some;
256
257 found_some = FALSE;
258 if (db_value_of_name(CC_SYM_PREFIX "thandler", &value)) {
259 db_user_trap_symbol_value = (db_addr_t) value;
260 found_some = TRUE;
261 }
262 if (db_value_of_name(CC_SYM_PREFIX "thandler", &value)) {
263 db_kernel_trap_symbol_value = (db_addr_t) value;
264 found_some = TRUE;
265 }
266 if (db_value_of_name(CC_SYM_PREFIX "ihandler", &value)) {
267 db_interrupt_symbol_value = (db_addr_t) value;
268 found_some = TRUE;
269 }
270 #if 0
271 if (db_value_of_name(CC_SYM_PREFIX "return_to_iret", &value)) {
272 db_return_to_iret_symbol_value = (db_addr_t) value;
273 found_some = TRUE;
274 }
275 #endif
276 if (db_value_of_name(CC_SYM_PREFIX "thandler", &value)) {
277 db_syscall_symbol_value = (db_addr_t) value;
278 found_some = TRUE;
279 }
280 if (found_some)
281 db_trace_symbols_found = TRUE;
282 }
283
284 int
285 db_numargs(
286 struct db_ppc_frame *fp,
287 task_t task)
288 {
289 return (DB_NUMARGS_MAX);
290 }
291
292 boolean_t
293 db_find_arg(
294 struct db_ppc_frame *fp,
295 db_addr_t calleepc,
296 task_t task,
297 int narg,
298 db_addr_t *arg)
299 {
300 db_addr_t argp;
301 db_addr_t calleep;
302 db_addr_t offset;
303 int i;
304 int inst;
305 char *name;
306
307 #if XXX_BS
308 db_find_task_sym_and_offset(calleepc, &name, &offset, task);
309 calleep = calleepc-offset;
310
311 for (i = 0; calleep < calleepc; i++, calleep++) {
312 if (!DB_CHECK_ACCESS((int) calleep, 4, task)) {
313 continue;
314 }
315 inst = db_get_task_value(calleep, 4, FALSE, task);
316 if ((inst & 0xffff0000) == (0x907f0000 + (narg << 21)) ||
317 (inst & 0xffff0000) == (0x90610000 + (narg << 21))) {
318 argp = (db_addr_t) &(fp->f_arg[narg]);
319 *arg = argp;
320 return TRUE;
321 }
322 }
323 #endif
324 return FALSE;
325 }
326
327 /*
328 * Figure out the next frame up in the call stack.
329 * For trap(), we print the address of the faulting instruction and
330 * proceed with the calling frame. We return the ip that faulted.
331 * If the trap was caused by jumping through a bogus pointer, then
332 * the next line in the backtrace will list some random function as
333 * being called. It should get the argument list correct, though.
334 * It might be possible to dig out from the next frame up the name
335 * of the function that faulted, but that could get hairy.
336 */
337 void
338 db_nextframe(
339 struct db_ppc_frame **lfp, /* in/out */
340 struct db_ppc_frame **fp, /* in/out */
341 db_addr_t *ip, /* out */
342 int frame_type, /* in */
343 thread_act_t thr_act,
344 db_addr_t linkpc) /* in */
345 {
346 extern char * trap_type[];
347 extern int TRAP_TYPES;
348
349 struct savearea *saved_regs;
350
351 task_t task = (thr_act != THR_ACT_NULL)? thr_act->task: TASK_NULL;
352
353 switch(frame_type) {
354 case TRAP:
355
356 db_printf(">>>>> trap <<<<<\n");
357 goto miss_frame;
358 break;
359 case INTERRUPT:
360 if (*lfp == 0) {
361 db_printf(">>>>> interrupt <<<<<\n");
362 goto miss_frame;
363 }
364 db_printf(">>>>> interrupt <<<<<\n");
365 goto miss_frame;
366 break;
367 case SYSCALL:
368 if (thr_act != THR_ACT_NULL && thr_act->mact.pcb) {
369 *ip = (db_addr_t) thr_act->mact.pcb->save_srr0;
370 *fp = (struct db_ppc_frame *) (thr_act->mact.pcb->save_r1);
371 break;
372 }
373 /* falling down for unknown case */
374 default:
375 miss_frame:
376
377 if(!pmap_find_phys(kernel_pmap, (addr64_t)*fp)) { /* Check if this is valid */
378 db_printf("Frame not mapped %08X\n",*fp); /* Say not found */
379 *fp = 0; /* Show not found */
380 break; /* Out of here */
381 }
382
383 if ((*fp)->f_frame)
384 *ip = (db_addr_t)
385 db_get_task_value((int)&(*fp)->f_frame->f_retaddr,
386 4, FALSE, task);
387 else
388 *ip = (db_addr_t)
389 db_get_task_value((int)&(*fp)->f_retaddr,
390 4, FALSE, task);
391
392 *lfp = *fp;
393 *fp = (struct db_ppc_frame *)
394 db_get_task_value((int)&(*fp)->f_frame, 4, FALSE, task);
395 break;
396 }
397 }
398
399 void
400 db_stack_trace_cmd(
401 db_expr_t addr,
402 boolean_t have_addr,
403 db_expr_t count,
404 char *modif)
405 {
406 struct db_ppc_frame *frame, *lastframe;
407 db_addr_t callpc, linkpc, lastcallpc;
408 int frame_type;
409 boolean_t kernel_only = TRUE;
410 boolean_t trace_thread = FALSE;
411 boolean_t trace_all_threads = FALSE;
412 int thcount = 0;
413 char *filename;
414 int linenum;
415 task_t task;
416 thread_act_t th, top_act;
417 int user_frame;
418 int frame_count;
419 jmp_buf_t *prev;
420 jmp_buf_t db_jmp_buf;
421 queue_entry_t act_list;
422
423 if (!db_trace_symbols_found)
424 db_find_trace_symbols();
425 {
426 register char *cp = modif;
427 register char c;
428
429 while ((c = *cp++) != 0) {
430 if (c == 't')
431 trace_thread = TRUE;
432 if (c == 'T') {
433 trace_all_threads = TRUE;
434 trace_thread = TRUE;
435 }
436 if (c == 'u')
437 kernel_only = FALSE;
438 }
439 }
440
441 if (trace_all_threads) {
442 if (!have_addr && !trace_thread) {
443 have_addr = TRUE;
444 trace_thread = TRUE;
445 act_list = &(current_task()->thr_acts);
446 addr = (db_expr_t) queue_first(act_list);
447 }
448 else if (trace_thread) {
449 if (have_addr) {
450 if (!db_check_act_address_valid((thread_act_t)addr)) {
451 if (db_lookup_task((task_t)addr) == -1)
452 return;
453 act_list = &(((task_t)addr)->thr_acts);
454 addr = (db_expr_t) queue_first(act_list);
455 }
456 else {
457 act_list = &(((thread_act_t)addr)->task->thr_acts);
458 thcount = db_lookup_task_act(((thread_act_t)addr)->task,
459 (thread_act_t)addr);
460 }
461 }
462 else {
463 th = db_default_act;
464 if (th == THR_ACT_NULL)
465 th = current_act();
466 if (th == THR_ACT_NULL) {
467 db_printf("no active thr_act\n");
468 return;
469 }
470 have_addr = TRUE;
471 act_list = &th->task->thr_acts;
472 addr = (db_expr_t) queue_first(act_list);
473 }
474 }
475 }
476
477 if (count == -1)
478 count = 65535;
479
480 next_thread:
481 top_act = THR_ACT_NULL;
482
483 user_frame = 0;
484 frame_count = count;
485
486 if (!have_addr && !trace_thread) {
487 frame = (struct db_ppc_frame *)(ddb_regs.save_r1);
488 callpc = (db_addr_t)ddb_regs.save_srr0;
489 linkpc = (db_addr_t)ddb_regs.save_lr;
490 th = current_act();
491 task = (th != THR_ACT_NULL)? th->task: TASK_NULL;
492 }
493 else if (trace_thread) {
494 if (have_addr) {
495 th = (thread_act_t) addr;
496 if (!db_check_act_address_valid(th))
497 return;
498 }
499 else {
500 th = db_default_act;
501 if (th == THR_ACT_NULL)
502 th = current_act();
503 if (th == THR_ACT_NULL) {
504 db_printf("no active thread\n");
505 return;
506 }
507 }
508 if (trace_all_threads)
509 db_printf("---------- Thread 0x%x (#%d of %d) ----------\n",
510 addr, thcount, th->task->thr_act_count);
511
512 next_activation:
513
514 user_frame = 0;
515
516 task = th->task;
517 if (th == current_act()) {
518 frame = (struct db_ppc_frame *)(ddb_regs.save_r1);
519 callpc = (db_addr_t)ddb_regs.save_srr0;
520 linkpc = (db_addr_t)ddb_regs.save_lr;
521 }
522 else {
523 if (th->mact.pcb == 0) {
524 db_printf("thread has no pcb\n");
525 goto thread_done;
526 }
527 if (!th->thread) {
528 register struct savearea *pss =
529 th->mact.pcb;
530
531 db_printf("thread has no shuttle\n");
532 goto thread_done;
533 }
534 else if ((th->thread->state & TH_STACK_HANDOFF) ||
535 th->thread->kernel_stack == 0) {
536 register struct savearea *pss =
537 th->mact.pcb;
538
539 db_printf("Continuation ");
540 db_task_printsym((db_expr_t)th->thread->continuation,
541 DB_STGY_PROC, task);
542 db_printf("\n");
543 frame = (struct db_ppc_frame *) (pss->save_r1);
544 callpc = (db_addr_t) (pss->save_srr0);
545 linkpc = (db_addr_t) (pss->save_lr);
546 }
547 else {
548 int cpu;
549
550 for (cpu = 0; cpu < NCPUS; cpu++) {
551 if (cpu_to_processor(cpu)->state == PROCESSOR_RUNNING &&
552 cpu_to_processor(cpu)->cpu_data->active_thread == th->thread &&
553 saved_state[cpu]) {
554 break;
555 }
556 }
557 if (top_act != THR_ACT_NULL) {
558 /*
559 * Trying to get the backtrace of an activation
560 * which is not the top_most one in the RPC chain:
561 * use the activation's pcb.
562 */
563 struct savearea *pss;
564
565 pss = th->mact.pcb;
566 frame = (struct db_ppc_frame *) (pss->save_r1);
567 callpc = (db_addr_t) (pss->save_srr0);
568 linkpc = (db_addr_t) (pss->save_lr);
569 } else {
570 if (cpu == NCPUS) {
571 register struct savearea *iks;
572 int r;
573
574 iks = th->mact.pcb;
575 prev = db_recover;
576 if ((r = _setjmp(db_recover = &db_jmp_buf)) == 0) {
577 frame = (struct db_ppc_frame *) (iks->save_r1);
578 callpc = (db_addr_t) (iks->save_lr);
579 linkpc = 0;
580 } else {
581 /*
582 * The kernel stack has probably been
583 * paged out (swapped out activation).
584 */
585 db_recover = prev;
586 if (r == 2) /* 'q' from db_more() */
587 db_error(0);
588 db_printf("<kernel stack (0x%x) error "
589 "(probably swapped out)>\n",
590 iks);
591 goto next_act;
592 }
593 db_recover = prev;
594 } else {
595 db_printf(">>>>> active on cpu %d <<<<<\n",
596 cpu);
597 frame = (struct db_ppc_frame *)
598 (saved_state[cpu]->save_r1);
599 callpc = (db_addr_t) saved_state[cpu]->save_srr0;
600 linkpc = (db_addr_t) saved_state[cpu]->save_lr;
601 }
602 }
603 }
604 }
605 } else {
606 frame = (struct db_ppc_frame *)addr;
607 th = (db_default_act)? db_default_act: current_act();
608 task = (th != THR_ACT_NULL)? th->task: TASK_NULL;
609 if (frame->f_frame) {
610 callpc = (db_addr_t)db_get_task_value
611 ((int)&frame->f_frame->f_retaddr,
612 4, FALSE, (user_frame) ? task : 0);
613 callpc = callpc-sizeof(callpc);
614 } else
615 callpc =0;
616 linkpc = 0;
617 }
618
619 if (!INKERNELSTACK((unsigned)frame, th)) {
620 db_printf(">>>>> user space <<<<<\n");
621 if (kernel_only)
622 goto thread_done;
623 user_frame++;
624 }
625
626 lastframe = 0;
627 lastcallpc = (db_addr_t) 0;
628 while (frame_count-- && frame != 0) {
629 int narg = DB_NUMARGS_MAX;
630 int arg;
631 char * name;
632 db_expr_t offset;
633 db_addr_t call_func = 0;
634 int r;
635 db_addr_t off;
636
637 db_symbol_values(NULL,
638 db_search_task_symbol_and_line(
639 callpc, DB_STGY_XTRN, &offset, &filename,
640 &linenum, (user_frame) ? task : 0, &narg),
641 &name, (db_expr_t *)&call_func);
642 if ( name == NULL) {
643 db_find_task_sym_and_offset(callpc,
644 &name, &off, (user_frame) ? task : 0);
645 offset = (db_expr_t) off;
646 }
647
648 if (user_frame == 0) {
649 if (call_func &&
650 (call_func == db_user_trap_symbol_value ||
651 call_func == db_kernel_trap_symbol_value)) {
652 frame_type = TRAP;
653 narg = 1;
654 } else if (call_func &&
655 call_func == db_interrupt_symbol_value) {
656 frame_type = INTERRUPT;
657 goto next_frame;
658 } else if (call_func &&
659 call_func == db_syscall_symbol_value) {
660 frame_type = SYSCALL;
661 goto next_frame;
662 } else {
663 frame_type = 0;
664 prev = db_recover;
665 if ((r = _setjmp(db_recover = &db_jmp_buf))
666 == 0) {
667 if (narg < 0)
668 narg = db_numargs(frame,
669 (user_frame) ? task : 0);
670 db_recover = prev;
671 } else {
672 db_recover = prev;
673 goto next_act;
674 }
675 }
676 } else {
677 frame_type = 0;
678 prev = db_recover;
679 if ((r = _setjmp(db_recover = &db_jmp_buf)) == 0) {
680 if (narg < 0)
681 narg = db_numargs(frame,
682 (user_frame) ? task : 0);
683 db_recover = prev;
684 } else {
685 db_recover = prev;
686 goto next_act;
687 }
688 }
689
690 if (name == 0 || offset > db_maxoff) {
691 db_printf("[%08X]0x%08X(", frame, callpc);
692 } else {
693 db_printf("[%08X]%s", frame, name);
694 if (offset)
695 db_printf("+%x", offset);
696 db_printf("(");
697 };
698
699 narg = db_numargs(frame, (user_frame) ? task : 0);
700
701 for (arg =0; arg < narg; arg++) {
702 db_addr_t argp;
703 int value;
704 boolean_t found;
705
706 prev = db_recover;
707 if ((r = _setjmp(db_recover = &db_jmp_buf)) == 0) {
708 found = FALSE;
709 if (lastframe)
710 found = db_find_arg(frame, lastframe->f_retaddr,
711 (user_frame) ? task : 0, arg, &argp);
712 if (found)
713 value = db_get_task_value(argp, 4, FALSE,
714 (user_frame) ? task : 0);
715 } else {
716 db_recover = prev;
717 if (r == 2) /* 'q' from db_more() */
718 db_error(0);
719 db_printf("... <stack error>)");
720 db_printf("\n");
721 goto next_act;
722 }
723 db_recover = prev;
724 if (found)
725 db_printf("%08X", value);
726 else
727 db_printf("??");
728 argp = argp + sizeof(argp);
729 if (arg < narg-1)
730 db_printf(",");
731 }
732 if (arg != narg)
733 db_printf("...");
734 db_printf(")");
735 db_printf("\n");
736
737 next_frame:
738 lastcallpc = callpc;
739 prev = db_recover;
740 if ((r = _setjmp(db_recover = &db_jmp_buf)) == 0) {
741 db_nextframe(&lastframe, &frame, &callpc, frame_type,
742 (user_frame) ? th : THR_ACT_NULL, linkpc);
743 callpc = callpc-sizeof(callpc);
744 db_recover = prev;
745 } else {
746 db_recover = prev;
747 frame = 0;
748 }
749 linkpc = 0;
750
751 if (frame == 0) {
752 next_act:
753 if (th->lower != THR_ACT_NULL) {
754 if (top_act == THR_ACT_NULL)
755 top_act = th;
756 th = th->lower;
757 db_printf(">>>>> next activation 0x%x ($task%d.%d) <<<<<\n",
758 th,
759 db_lookup_task(th->task),
760 db_lookup_task_act(th->task, th));
761 goto next_activation;
762 }
763 /* end of chain */
764 break;
765 }
766 if (!INKERNELSTACK(lastframe, th) ||
767 !INKERNELSTACK((unsigned)frame, th))
768 user_frame++;
769 if (user_frame == 1) {
770 db_printf(">>>>> user space <<<<<\n");
771 if (kernel_only)
772 break;
773 }
774
775 if (frame <= lastframe) {
776 if ((INKERNELSTACK(lastframe, th) && !INKERNELSTACK(frame, th))) continue;
777 db_printf("Bad frame pointer: 0x%x\n", frame);
778 break;
779 }
780 }
781
782 thread_done:
783 if (trace_all_threads) {
784 if (top_act != THR_ACT_NULL)
785 th = top_act;
786 th = (thread_act_t) queue_next(&th->thr_acts);
787 if (! queue_end(act_list, (queue_entry_t) th)) {
788 db_printf("\n");
789 addr = (db_expr_t) th;
790 thcount++;
791 goto next_thread;
792
793 }
794 }
795 }