2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * The contents of this file constitute Original Code as defined in and
7 * are subject to the Apple Public Source License Version 1.1 (the
8 * "License"). You may not use this file except in compliance with the
9 * License. Please obtain a copy of the License at
10 * http://www.apple.com/publicsource and read it before using this file.
12 * This Original Code and all software distributed under the License are
13 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
14 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
17 * License for the specific language governing rights and limitations
20 * @APPLE_LICENSE_HEADER_END@
28 #include <mach/boolean.h>
29 #include <vm/vm_map.h>
30 #include <kern/thread.h>
31 #include <kern/task.h>
33 #include <machine/asm.h>
34 #include <machine/db_machdep.h>
35 #include <machine/setjmp.h>
36 #include <mach/machine.h>
38 #include <ddb/db_access.h>
39 #include <ddb/db_sym.h>
40 #include <ddb/db_variables.h>
41 #include <ddb/db_command.h>
42 #include <ddb/db_task_thread.h>
43 #include <ddb/db_output.h>
45 extern jmp_buf_t
*db_recover
;
46 extern struct ppc_saved_state
*saved_state
[];
48 struct ppc_saved_state ddb_null_kregs
;
50 extern vm_offset_t vm_min_inks_addr
; /* set by db_clone_symtabXXX */
52 #define DB_NUMARGS_MAX 5
55 extern char FixedStackStart
[], FixedStackEnd
[];
56 #define INFIXEDSTACK(va) \
57 ((((vm_offset_t)(va)) >= (vm_offset_t)&FixedStackStart) && \
58 (((vm_offset_t)(va)) < ((vm_offset_t)&FixedStackEnd)))
62 #define INKERNELSTACK(va, th) \
63 (th == THR_ACT_NULL || \
64 (((vm_offset_t)(va)) >= th->thread->kernel_stack && \
65 (((vm_offset_t)(va)) < th->thread->kernel_stack + \
66 KERNEL_STACK_SIZE)) || \
69 #define INKERNELSTACK(va, th) 1
75 struct db_ppc_frame
*f_frame
;
81 db_addr_t f_arg
[DB_NUMARGS_MAX
];
89 db_addr_t db_user_trap_symbol_value
= 0;
90 db_addr_t db_kernel_trap_symbol_value
= 0;
91 db_addr_t db_interrupt_symbol_value
= 0;
92 db_addr_t db_return_to_iret_symbol_value
= 0;
93 db_addr_t db_syscall_symbol_value
= 0;
94 boolean_t db_trace_symbols_found
= FALSE
;
96 extern int db_ppc_reg_value(
97 struct db_variable
* vp
,
100 db_var_aux_param_t ap
);
101 extern void db_find_trace_symbols(void);
102 extern int db_numargs(
103 struct db_ppc_frame
*fp
,
105 extern boolean_t
db_find_arg(
106 struct db_ppc_frame
*frame
,
111 extern void db_nextframe(
112 struct db_ppc_frame
**lfp
,
113 struct db_ppc_frame
**fp
,
116 thread_act_t thr_act
,
122 * Machine register set.
124 struct db_variable db_regs
[] = {
125 /* XXX "pc" is an alias to "srr0"... */
126 { "pc", (int *)&ddb_regs
.srr0
, db_ppc_reg_value
, 0, 0, 0, 0, TRUE
},
127 { "srr0", (int *)&ddb_regs
.srr0
, db_ppc_reg_value
, 0, 0, 0, 0, TRUE
},
128 { "srr1", (int *)&ddb_regs
.srr1
, db_ppc_reg_value
, 0, 0, 0, 0, TRUE
},
129 { "r0", (int *)&ddb_regs
.r0
, db_ppc_reg_value
, 0, 0, 0, 0, TRUE
},
130 { "r1", (int *)&ddb_regs
.r1
, db_ppc_reg_value
, 0, 0, 0, 0, TRUE
},
131 { "r2", (int *)&ddb_regs
.r2
, db_ppc_reg_value
, 0, 0, 0, 0, TRUE
},
132 { "r3", (int *)&ddb_regs
.r3
, db_ppc_reg_value
, 0, 0, 0, 0, TRUE
},
133 { "r4", (int *)&ddb_regs
.r4
, db_ppc_reg_value
, 0, 0, 0, 0, TRUE
},
134 { "r5", (int *)&ddb_regs
.r5
, db_ppc_reg_value
, 0, 0, 0, 0, TRUE
},
135 { "r6", (int *)&ddb_regs
.r6
, db_ppc_reg_value
, 0, 0, 0, 0, TRUE
},
136 { "r7", (int *)&ddb_regs
.r7
, db_ppc_reg_value
, 0, 0, 0, 0, TRUE
},
137 { "r8", (int *)&ddb_regs
.r8
, db_ppc_reg_value
, 0, 0, 0, 0, TRUE
},
138 { "r9", (int *)&ddb_regs
.r9
, db_ppc_reg_value
, 0, 0, 0, 0, TRUE
},
139 { "r10", (int *)&ddb_regs
.r10
, db_ppc_reg_value
, 0, 0, 0, 0, TRUE
},
140 { "r11", (int *)&ddb_regs
.r11
, db_ppc_reg_value
, 0, 0, 0, 0, TRUE
},
141 { "r12", (int *)&ddb_regs
.r12
, db_ppc_reg_value
, 0, 0, 0, 0, TRUE
},
142 { "r13", (int *)&ddb_regs
.r13
, db_ppc_reg_value
, 0, 0, 0, 0, TRUE
},
143 { "r14", (int *)&ddb_regs
.r14
, db_ppc_reg_value
, 0, 0, 0, 0, TRUE
},
144 { "r15", (int *)&ddb_regs
.r15
, db_ppc_reg_value
, 0, 0, 0, 0, TRUE
},
145 { "r16", (int *)&ddb_regs
.r16
, db_ppc_reg_value
, 0, 0, 0, 0, TRUE
},
146 { "r17", (int *)&ddb_regs
.r17
, db_ppc_reg_value
, 0, 0, 0, 0, TRUE
},
147 { "r18", (int *)&ddb_regs
.r18
, db_ppc_reg_value
, 0, 0, 0, 0, TRUE
},
148 { "r19", (int *)&ddb_regs
.r19
, db_ppc_reg_value
, 0, 0, 0, 0, TRUE
},
149 { "r20", (int *)&ddb_regs
.r20
, db_ppc_reg_value
, 0, 0, 0, 0, TRUE
},
150 { "r21", (int *)&ddb_regs
.r21
, db_ppc_reg_value
, 0, 0, 0, 0, TRUE
},
151 { "r22", (int *)&ddb_regs
.r22
, db_ppc_reg_value
, 0, 0, 0, 0, TRUE
},
152 { "r23", (int *)&ddb_regs
.r23
, db_ppc_reg_value
, 0, 0, 0, 0, TRUE
},
153 { "r24", (int *)&ddb_regs
.r24
, db_ppc_reg_value
, 0, 0, 0, 0, TRUE
},
154 { "r25", (int *)&ddb_regs
.r25
, db_ppc_reg_value
, 0, 0, 0, 0, TRUE
},
155 { "r26", (int *)&ddb_regs
.r26
, db_ppc_reg_value
, 0, 0, 0, 0, TRUE
},
156 { "r27", (int *)&ddb_regs
.r27
, db_ppc_reg_value
, 0, 0, 0, 0, TRUE
},
157 { "r28", (int *)&ddb_regs
.r28
, db_ppc_reg_value
, 0, 0, 0, 0, TRUE
},
158 { "r29", (int *)&ddb_regs
.r29
, db_ppc_reg_value
, 0, 0, 0, 0, TRUE
},
159 { "r30", (int *)&ddb_regs
.r30
, db_ppc_reg_value
, 0, 0, 0, 0, TRUE
},
160 { "r31", (int *)&ddb_regs
.r31
, db_ppc_reg_value
, 0, 0, 0, 0, TRUE
},
161 { "cr", (int *)&ddb_regs
.cr
, db_ppc_reg_value
, 0, 0, 0, 0, TRUE
},
162 { "xer", (int *)&ddb_regs
.xer
, db_ppc_reg_value
, 0, 0, 0, 0, TRUE
},
163 { "lr", (int *)&ddb_regs
.lr
, db_ppc_reg_value
, 0, 0, 0, 0, TRUE
},
164 { "ctr", (int *)&ddb_regs
.ctr
, db_ppc_reg_value
, 0, 0, 0, 0, TRUE
},
165 { "mq", (int *)&ddb_regs
.mq
, db_ppc_reg_value
, 0, 0, 0, 0, TRUE
},
166 { "sr_copyin",(int *)&ddb_regs
.sr_copyin
,db_ppc_reg_value
, 0, 0, 0, 0, TRUE
},
168 struct db_variable
*db_eregs
= db_regs
+ sizeof(db_regs
)/sizeof(db_regs
[0]);
172 struct db_variable
*vp
,
175 db_var_aux_param_t ap
)
178 db_expr_t null_reg
= 0;
179 register thread_act_t thr_act
= ap
->thr_act
;
182 if (db_option(ap
->modif
, 'u')) {
183 if (thr_act
== THR_ACT_NULL
) {
184 if ((thr_act
= current_act()) == THR_ACT_NULL
)
185 db_error("no user registers\n");
187 if (thr_act
== current_act()) {
188 if (IS_USER_TRAP((&ddb_regs
)))
190 else if (INFIXEDSTACK(ddb_regs
.r1
))
191 db_error("cannot get/set user registers in nested interrupt\n");
194 if (thr_act
== THR_ACT_NULL
|| thr_act
== current_act()) {
197 if (thr_act
->thread
&&
198 !(thr_act
->thread
->state
& TH_STACK_HANDOFF
) &&
199 thr_act
->thread
->kernel_stack
) {
202 for (cpu
= 0; cpu
< NCPUS
; cpu
++) {
203 if (machine_slot
[cpu
].running
== TRUE
&&
204 cpu_data
[cpu
].active_thread
== thr_act
->thread
&& saved_state
[cpu
]) {
205 dp
= (int *) (((int)saved_state
[cpu
]) +
206 (((int) vp
->valuep
) -
212 if (dp
== 0 && thr_act
&& thr_act
->thread
)
213 dp
= db_lookup_i386_kreg(vp
->name
,
214 (int *)(STACK_IKS(thr_act
->thread
->kernel_stack
)));
218 } else if (thr_act
->thread
&&
219 (thr_act
->thread
->state
&TH_STACK_HANDOFF
)){
220 /* only PC is valid */
221 if (vp
->valuep
== (int *) &ddb_regs
.srr0
) {
222 dp
= (int *)(&thr_act
->thread
->continuation
);
232 if (!db_option(ap
->modif
, 'u')) {
233 for (cpu
= 0; cpu
< NCPUS
; cpu
++) {
234 if (machine_slot
[cpu
].running
== TRUE
&&
235 cpu_data
[cpu
].active_thread
== thr_act
->thread
&& saved_state
[cpu
]) {
236 dp
= (int *) (((int)saved_state
[cpu
]) +
237 (((int) vp
->valuep
) -
244 if (!thr_act
|| thr_act
->mact
.pcb
== 0)
245 db_error("no pcb\n");
246 dp
= (int *)((int)(&thr_act
->mact
.pcb
->ss
) +
247 ((int)vp
->valuep
- (int)&ddb_regs
));
250 if (flag
== DB_VAR_SET
)
258 db_find_trace_symbols(void)
261 boolean_t found_some
;
264 if (db_value_of_name(CC_SYM_PREFIX
"thandler", &value
)) {
265 db_user_trap_symbol_value
= (db_addr_t
) value
;
268 if (db_value_of_name(CC_SYM_PREFIX
"thandler", &value
)) {
269 db_kernel_trap_symbol_value
= (db_addr_t
) value
;
272 if (db_value_of_name(CC_SYM_PREFIX
"ihandler", &value
)) {
273 db_interrupt_symbol_value
= (db_addr_t
) value
;
277 if (db_value_of_name(CC_SYM_PREFIX
"return_to_iret", &value
)) {
278 db_return_to_iret_symbol_value
= (db_addr_t
) value
;
282 if (db_value_of_name(CC_SYM_PREFIX
"thandler", &value
)) {
283 db_syscall_symbol_value
= (db_addr_t
) value
;
287 db_trace_symbols_found
= TRUE
;
292 struct db_ppc_frame
*fp
,
295 return (DB_NUMARGS_MAX
);
300 struct db_ppc_frame
*fp
,
314 db_find_task_sym_and_offset(calleepc
, &name
, &offset
, task
);
315 calleep
= calleepc
-offset
;
317 for (i
= 0; calleep
< calleepc
; i
++, calleep
++) {
318 if (!DB_CHECK_ACCESS((int) calleep
, 4, task
)) {
321 inst
= db_get_task_value(calleep
, 4, FALSE
, task
);
322 if ((inst
& 0xffff0000) == (0x907f0000 + (narg
<< 21)) ||
323 (inst
& 0xffff0000) == (0x90610000 + (narg
<< 21))) {
324 argp
= (db_addr_t
) &(fp
->f_arg
[narg
]);
334 * Figure out the next frame up in the call stack.
335 * For trap(), we print the address of the faulting instruction and
336 * proceed with the calling frame. We return the ip that faulted.
337 * If the trap was caused by jumping through a bogus pointer, then
338 * the next line in the backtrace will list some random function as
339 * being called. It should get the argument list correct, though.
340 * It might be possible to dig out from the next frame up the name
341 * of the function that faulted, but that could get hairy.
345 struct db_ppc_frame
**lfp
, /* in/out */
346 struct db_ppc_frame
**fp
, /* in/out */
347 db_addr_t
*ip
, /* out */
348 int frame_type
, /* in */
349 thread_act_t thr_act
,
350 db_addr_t linkpc
) /* in */
352 extern char * trap_type
[];
353 extern int TRAP_TYPES
;
355 struct ppc_saved_state
*saved_regs
;
357 task_t task
= (thr_act
!= THR_ACT_NULL
)? thr_act
->task
: TASK_NULL
;
363 * We know that trap() has 1 argument and we know that
364 * it is an (strcut i386_saved_state *).
366 saved_regs
= (struct i386_saved_state
*)
367 db_get_task_value((int)&((*fp
)->f_arg0
),4,FALSE
,task
);
368 if (saved_regs
->trapno
>= 0 && saved_regs
->trapno
< TRAP_TYPES
) {
369 db_printf(">>>>> %s trap at ",
370 trap_type
[saved_regs
->trapno
]);
372 db_printf(">>>>> trap (number %d) at ",
373 saved_regs
->trapno
& 0xffff);
375 db_task_printsym(saved_regs
->eip
, DB_STGY_PROC
, task
);
376 db_printf(" <<<<<\n");
377 *fp
= (struct i386_frame
*)saved_regs
->ebp
;
378 *ip
= (db_addr_t
)saved_regs
->eip
;
380 db_printf(">>>>> trap <<<<<\n");
386 db_printf(">>>>> interrupt <<<<<\n");
390 db_printf(">>>>> interrupt at ");
391 ifp
= (struct interrupt_frame
*)(*lfp
);
393 if (ifp
->if_iretaddr
== db_return_to_iret_symbol_value
)
394 *ip
= ((struct i386_interrupt_state
*) ifp
->if_edx
)->eip
;
396 *ip
= (db_addr_t
) ifp
->if_eip
;
397 db_task_printsym(*ip
, DB_STGY_PROC
, task
);
398 db_printf(" <<<<<\n");
400 db_printf(">>>>> interrupt <<<<<\n");
405 if (thr_act
!= THR_ACT_NULL
&& thr_act
->mact
.pcb
) {
406 *ip
= (db_addr_t
) thr_act
->mact
.pcb
->ss
.srr0
;
407 *fp
= (struct db_ppc_frame
*) (thr_act
->mact
.pcb
->ss
.r1
);
410 /* falling down for unknown case */
415 db_get_task_value((int)&(*fp
)->f_frame
->f_retaddr
,
419 db_get_task_value((int)&(*fp
)->f_retaddr
,
423 *fp
= (struct db_ppc_frame
*)
424 db_get_task_value((int)&(*fp
)->f_frame
, 4, FALSE
, task
);
436 struct db_ppc_frame
*frame
, *lastframe
;
437 db_addr_t callpc
, linkpc
, lastcallpc
;
439 boolean_t kernel_only
= TRUE
;
440 boolean_t trace_thread
= FALSE
;
441 boolean_t trace_all_threads
= FALSE
;
446 thread_act_t th
, top_act
;
450 jmp_buf_t db_jmp_buf
;
451 queue_entry_t act_list
;
453 if (!db_trace_symbols_found
)
454 db_find_trace_symbols();
456 register char *cp
= modif
;
459 while ((c
= *cp
++) != 0) {
463 trace_all_threads
= TRUE
;
471 if (trace_all_threads
) {
472 if (!have_addr
&& !trace_thread
) {
475 act_list
= &(current_task()->thr_acts
);
476 addr
= (db_expr_t
) queue_first(act_list
);
478 else if (trace_thread
) {
480 if (!db_check_act_address_valid((thread_act_t
)addr
)) {
481 if (db_lookup_task((task_t
)addr
) == -1)
483 act_list
= &(((task_t
)addr
)->thr_acts
);
484 addr
= (db_expr_t
) queue_first(act_list
);
487 act_list
= &(((thread_act_t
)addr
)->task
->thr_acts
);
488 thcount
= db_lookup_task_act(((thread_act_t
)addr
)->task
,
494 if (th
== THR_ACT_NULL
)
496 if (th
== THR_ACT_NULL
) {
497 db_printf("no active thr_act\n");
501 act_list
= &th
->task
->thr_acts
;
502 addr
= (db_expr_t
) queue_first(act_list
);
511 top_act
= THR_ACT_NULL
;
516 if (!have_addr
&& !trace_thread
) {
517 frame
= (struct db_ppc_frame
*)(ddb_regs
.r1
);
518 callpc
= (db_addr_t
)ddb_regs
.srr0
;
519 linkpc
= (db_addr_t
)ddb_regs
.lr
;
521 task
= (th
!= THR_ACT_NULL
)? th
->task
: TASK_NULL
;
523 else if (trace_thread
) {
525 th
= (thread_act_t
) addr
;
526 if (!db_check_act_address_valid(th
))
531 if (th
== THR_ACT_NULL
)
533 if (th
== THR_ACT_NULL
) {
534 db_printf("no active thread\n");
538 if (trace_all_threads
)
539 db_printf("---------- Thread 0x%x (#%d of %d) ----------\n",
540 addr
, thcount
, th
->task
->thr_act_count
);
547 if (th
== current_act()) {
548 frame
= (struct db_ppc_frame
*)(ddb_regs
.r1
);
549 callpc
= (db_addr_t
)ddb_regs
.srr0
;
550 linkpc
= (db_addr_t
)ddb_regs
.lr
;
553 if (th
->mact
.pcb
== 0) {
554 db_printf("thread has no pcb\n");
558 register struct ppc_saved_state
*pss
=
561 db_printf("thread has no shuttle\n");
563 frame
= (struct db_ppc_frame
*) (pss
->r1
);
564 callpc
= (db_addr_t
) (pss
->srr0
);
565 linkpc
= (db_addr_t
) (pss
->lr
);
570 else if ((th
->thread
->state
& TH_STACK_HANDOFF
) ||
571 th
->thread
->kernel_stack
== 0) {
572 register struct ppc_saved_state
*pss
=
575 db_printf("Continuation ");
576 db_task_printsym((db_expr_t
)th
->thread
->continuation
,
579 frame
= (struct db_ppc_frame
*) (pss
->r1
);
580 callpc
= (db_addr_t
) (pss
->srr0
);
581 linkpc
= (db_addr_t
) (pss
->lr
);
586 for (cpu
= 0; cpu
< NCPUS
; cpu
++) {
587 if (machine_slot
[cpu
].running
== TRUE
&&
588 cpu_data
[cpu
].active_thread
== th
->thread
&&
593 if (top_act
!= THR_ACT_NULL
) {
595 * Trying to get the backtrace of an activation
596 * which is not the top_most one in the RPC chain:
597 * use the activation's pcb.
599 struct ppc_saved_state
*pss
;
601 pss
= (struct ppc_saved_state
*)th
->mact
.pcb
;
602 frame
= (struct db_ppc_frame
*) (pss
->r1
);
603 callpc
= (db_addr_t
) (pss
->srr0
);
604 linkpc
= (db_addr_t
) (pss
->lr
);
607 register struct ppc_saved_state
*iks
;
610 iks
= (struct ppc_saved_state
*)th
->mact
.pcb
;
612 if ((r
= _setjmp(db_recover
= &db_jmp_buf
)) == 0) {
613 frame
= (struct db_ppc_frame
*) (iks
->r1
);
614 callpc
= (db_addr_t
) (iks
->lr
);
618 * The kernel stack has probably been
619 * paged out (swapped out activation).
622 if (r
== 2) /* 'q' from db_more() */
624 db_printf("<kernel stack (0x%x) error "
625 "(probably swapped out)>\n",
631 db_printf(">>>>> active on cpu %d <<<<<\n",
633 frame
= (struct db_ppc_frame
*)
634 (saved_state
[cpu
]->r1
);
635 callpc
= (db_addr_t
) saved_state
[cpu
]->srr0
;
636 linkpc
= (db_addr_t
) saved_state
[cpu
]->lr
;
642 frame
= (struct db_ppc_frame
*)addr
;
643 th
= (db_default_act
)? db_default_act
: current_act();
644 task
= (th
!= THR_ACT_NULL
)? th
->task
: TASK_NULL
;
645 if (frame
->f_frame
) {
646 callpc
= (db_addr_t
)db_get_task_value
647 ((int)&frame
->f_frame
->f_retaddr
,
648 4, FALSE
, (user_frame
) ? task
: 0);
649 callpc
= callpc
-sizeof(callpc
);
655 if (!INKERNELSTACK((unsigned)frame
, th
)) {
656 db_printf(">>>>> user space <<<<<\n");
663 lastcallpc
= (db_addr_t
) 0;
664 while (frame_count
-- && frame
!= 0) {
665 int narg
= DB_NUMARGS_MAX
;
669 db_addr_t call_func
= 0;
673 db_symbol_values(NULL
,
674 db_search_task_symbol_and_line(
675 callpc
, DB_STGY_XTRN
, &offset
, &filename
,
676 &linenum
, (user_frame
) ? task
: 0, &narg
),
677 &name
, (db_expr_t
*)&call_func
);
679 db_find_task_sym_and_offset(callpc
,
680 &name
, &off
, (user_frame
) ? task
: 0);
681 offset
= (db_expr_t
) off
;
684 if (user_frame
== 0) {
686 (call_func
== db_user_trap_symbol_value
||
687 call_func
== db_kernel_trap_symbol_value
)) {
690 } else if (call_func
&&
691 call_func
== db_interrupt_symbol_value
) {
692 frame_type
= INTERRUPT
;
694 } else if (call_func
&&
695 call_func
== db_syscall_symbol_value
) {
696 frame_type
= SYSCALL
;
701 if ((r
= _setjmp(db_recover
= &db_jmp_buf
))
704 narg
= db_numargs(frame
,
705 (user_frame
) ? task
: 0);
715 if ((r
= _setjmp(db_recover
= &db_jmp_buf
)) == 0) {
717 narg
= db_numargs(frame
,
718 (user_frame
) ? task
: 0);
726 if (name
== 0 || offset
> db_maxoff
) {
727 db_printf("[%08X]0x%08X(", frame
, callpc
);
729 db_printf("[%08X]%s", frame
, name
);
731 db_printf("+%x", offset
);
735 narg
= db_numargs(frame
, (user_frame
) ? task
: 0);
737 for (arg
=0; arg
< narg
; arg
++) {
743 if ((r
= _setjmp(db_recover
= &db_jmp_buf
)) == 0) {
746 found
= db_find_arg(frame
, lastframe
->f_retaddr
,
747 (user_frame
) ? task
: 0, arg
, &argp
);
749 value
= db_get_task_value(argp
, 4, FALSE
,
750 (user_frame
) ? task
: 0);
753 if (r
== 2) /* 'q' from db_more() */
755 db_printf("... <stack error>)");
761 db_printf("%08X", value
);
764 argp
= argp
+ sizeof(argp
);
776 if ((r
= _setjmp(db_recover
= &db_jmp_buf
)) == 0) {
777 db_nextframe(&lastframe
, &frame
, &callpc
, frame_type
,
778 (user_frame
) ? th
: THR_ACT_NULL
, linkpc
);
779 callpc
= callpc
-sizeof(callpc
);
789 if (th
->lower
!= THR_ACT_NULL
) {
790 if (top_act
== THR_ACT_NULL
)
793 db_printf(">>>>> next activation 0x%x ($task%d.%d) <<<<<\n",
795 db_lookup_task(th
->task
),
796 db_lookup_task_act(th
->task
, th
));
797 goto next_activation
;
802 if (!INKERNELSTACK(lastframe
, th
) ||
803 !INKERNELSTACK((unsigned)frame
, th
))
805 if (user_frame
== 1) {
806 db_printf(">>>>> user space <<<<<\n");
811 if (frame
<= lastframe
) {
812 if ((INKERNELSTACK(lastframe
, th
) && !INKERNELSTACK(frame
, th
))) continue;
813 db_printf("Bad frame pointer: 0x%x\n", frame
);
819 if (trace_all_threads
) {
820 if (top_act
!= THR_ACT_NULL
)
822 th
= (thread_act_t
) queue_next(&th
->thr_acts
);
823 if (! queue_end(act_list
, (queue_entry_t
) th
)) {
825 addr
= (db_expr_t
) th
;