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