|
|
1.1 root 1: /*
2: * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
3: *
4: * @APPLE_LICENSE_HEADER_START@
5: *
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.
11: *
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
18: * under the License.
19: *
20: * @APPLE_LICENSE_HEADER_END@
21: */
22: /*
23: * @OSF_COPYRIGHT@
24: */
25:
26: #include <string.h>
27:
28: #include <mach/boolean.h>
29: #include <vm/vm_map.h>
30: #include <kern/thread.h>
31: #include <kern/task.h>
32:
33: #include <machine/asm.h>
34: #include <machine/db_machdep.h>
35: #include <machine/setjmp.h>
36: #include <mach/machine.h>
37:
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>
44:
45: extern jmp_buf_t *db_recover;
46: extern struct ppc_saved_state *saved_state[];
47:
48: struct ppc_saved_state ddb_null_kregs;
49:
50: extern vm_offset_t vm_min_inks_addr; /* set by db_clone_symtabXXX */
51:
52: #define DB_NUMARGS_MAX 5
53:
54:
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)))
59:
60: #define INKERNELSTACK(va, th) \
61: (th == THR_ACT_NULL || \
62: (((vm_offset_t)(va)) >= th->thread->kernel_stack && \
63: (((vm_offset_t)(va)) < th->thread->kernel_stack + \
64: KERNEL_STACK_SIZE)) || \
65: INFIXEDSTACK(va))
66:
67: #ifdef __MACHO__
68: struct db_ppc_frame {
69: struct db_ppc_frame *f_frame;
70: int pad1;
71: db_addr_t f_retaddr;
72: int pad3;
73: int pad4;
74: int pad5;
75: db_addr_t f_arg[DB_NUMARGS_MAX];
76: };
77: #endif
78:
79: #define TRAP 1
80: #define INTERRUPT 2
81: #define SYSCALL 3
82:
83: db_addr_t db_user_trap_symbol_value = 0;
84: db_addr_t db_kernel_trap_symbol_value = 0;
85: db_addr_t db_interrupt_symbol_value = 0;
86: db_addr_t db_return_to_iret_symbol_value = 0;
87: db_addr_t db_syscall_symbol_value = 0;
88: boolean_t db_trace_symbols_found = FALSE;
89:
90: extern int db_ppc_reg_value(
91: struct db_variable * vp,
92: db_expr_t * val,
93: int flag,
94: db_var_aux_param_t ap);
95: extern void db_find_trace_symbols(void);
96: extern int db_numargs(
97: struct db_ppc_frame *fp,
98: task_t task);
99: extern boolean_t db_find_arg(
100: struct db_ppc_frame *frame,
101: db_addr_t calleepc,
102: task_t task,
103: int narg,
104: db_addr_t *arg);
105: extern void db_nextframe(
106: struct db_ppc_frame **lfp,
107: struct db_ppc_frame **fp,
108: db_addr_t *ip,
109: int frame_type,
110: thread_act_t thr_act,
111: db_addr_t linkpc);
112: extern int _setjmp(
113: jmp_buf_t * jb);
114:
115: /*
116: * Machine register set.
117: */
118: struct db_variable db_regs[] = {
119: /* XXX "pc" is an alias to "srr0"... */
120: { "pc", (int *)&ddb_regs.srr0, db_ppc_reg_value, 0, 0, 0, 0, TRUE },
121: { "srr0", (int *)&ddb_regs.srr0, db_ppc_reg_value, 0, 0, 0, 0, TRUE },
122: { "srr1", (int *)&ddb_regs.srr1, db_ppc_reg_value, 0, 0, 0, 0, TRUE },
123: { "r0", (int *)&ddb_regs.r0, db_ppc_reg_value, 0, 0, 0, 0, TRUE },
124: { "r1", (int *)&ddb_regs.r1, db_ppc_reg_value, 0, 0, 0, 0, TRUE },
125: { "r2", (int *)&ddb_regs.r2, db_ppc_reg_value, 0, 0, 0, 0, TRUE },
126: { "r3", (int *)&ddb_regs.r3, db_ppc_reg_value, 0, 0, 0, 0, TRUE },
127: { "r4", (int *)&ddb_regs.r4, db_ppc_reg_value, 0, 0, 0, 0, TRUE },
128: { "r5", (int *)&ddb_regs.r5, db_ppc_reg_value, 0, 0, 0, 0, TRUE },
129: { "r6", (int *)&ddb_regs.r6, db_ppc_reg_value, 0, 0, 0, 0, TRUE },
130: { "r7", (int *)&ddb_regs.r7, db_ppc_reg_value, 0, 0, 0, 0, TRUE },
131: { "r8", (int *)&ddb_regs.r8, db_ppc_reg_value, 0, 0, 0, 0, TRUE },
132: { "r9", (int *)&ddb_regs.r9, db_ppc_reg_value, 0, 0, 0, 0, TRUE },
133: { "r10", (int *)&ddb_regs.r10, db_ppc_reg_value, 0, 0, 0, 0, TRUE },
134: { "r11", (int *)&ddb_regs.r11, db_ppc_reg_value, 0, 0, 0, 0, TRUE },
135: { "r12", (int *)&ddb_regs.r12, db_ppc_reg_value, 0, 0, 0, 0, TRUE },
136: { "r13", (int *)&ddb_regs.r13, db_ppc_reg_value, 0, 0, 0, 0, TRUE },
137: { "r14", (int *)&ddb_regs.r14, db_ppc_reg_value, 0, 0, 0, 0, TRUE },
138: { "r15", (int *)&ddb_regs.r15, db_ppc_reg_value, 0, 0, 0, 0, TRUE },
139: { "r16", (int *)&ddb_regs.r16, db_ppc_reg_value, 0, 0, 0, 0, TRUE },
140: { "r17", (int *)&ddb_regs.r17, db_ppc_reg_value, 0, 0, 0, 0, TRUE },
141: { "r18", (int *)&ddb_regs.r18, db_ppc_reg_value, 0, 0, 0, 0, TRUE },
142: { "r19", (int *)&ddb_regs.r19, db_ppc_reg_value, 0, 0, 0, 0, TRUE },
143: { "r20", (int *)&ddb_regs.r20, db_ppc_reg_value, 0, 0, 0, 0, TRUE },
144: { "r21", (int *)&ddb_regs.r21, db_ppc_reg_value, 0, 0, 0, 0, TRUE },
145: { "r22", (int *)&ddb_regs.r22, db_ppc_reg_value, 0, 0, 0, 0, TRUE },
146: { "r23", (int *)&ddb_regs.r23, db_ppc_reg_value, 0, 0, 0, 0, TRUE },
147: { "r24", (int *)&ddb_regs.r24, db_ppc_reg_value, 0, 0, 0, 0, TRUE },
148: { "r25", (int *)&ddb_regs.r25, db_ppc_reg_value, 0, 0, 0, 0, TRUE },
149: { "r26", (int *)&ddb_regs.r26, db_ppc_reg_value, 0, 0, 0, 0, TRUE },
150: { "r27", (int *)&ddb_regs.r27, db_ppc_reg_value, 0, 0, 0, 0, TRUE },
151: { "r28", (int *)&ddb_regs.r28, db_ppc_reg_value, 0, 0, 0, 0, TRUE },
152: { "r29", (int *)&ddb_regs.r29, db_ppc_reg_value, 0, 0, 0, 0, TRUE },
153: { "r30", (int *)&ddb_regs.r30, db_ppc_reg_value, 0, 0, 0, 0, TRUE },
154: { "r31", (int *)&ddb_regs.r31, db_ppc_reg_value, 0, 0, 0, 0, TRUE },
155: { "cr", (int *)&ddb_regs.cr, db_ppc_reg_value, 0, 0, 0, 0, TRUE },
156: { "xer", (int *)&ddb_regs.xer, db_ppc_reg_value, 0, 0, 0, 0, TRUE },
157: { "lr", (int *)&ddb_regs.lr, db_ppc_reg_value, 0, 0, 0, 0, TRUE },
158: { "ctr", (int *)&ddb_regs.ctr, db_ppc_reg_value, 0, 0, 0, 0, TRUE },
159: { "mq", (int *)&ddb_regs.mq, db_ppc_reg_value, 0, 0, 0, 0, TRUE },
160: { "sr_copyin",(int *)&ddb_regs.sr_copyin,db_ppc_reg_value, 0, 0, 0, 0, TRUE },
161: };
162: struct db_variable *db_eregs = db_regs + sizeof(db_regs)/sizeof(db_regs[0]);
163:
164: int
165: db_ppc_reg_value(
166: struct db_variable *vp,
167: db_expr_t *valuep,
168: int flag,
169: db_var_aux_param_t ap)
170: {
171: int *dp = 0;
172: db_expr_t null_reg = 0;
173: register thread_act_t thr_act = ap->thr_act;
174: int cpu;
175:
176: if (db_option(ap->modif, 'u')) {
177: if (thr_act == THR_ACT_NULL) {
178: if ((thr_act = current_act()) == THR_ACT_NULL)
179: db_error("no user registers\n");
180: }
181: if (thr_act == current_act()) {
182: if (IS_USER_TRAP((&ddb_regs)))
183: dp = vp->valuep;
184: else if (INFIXEDSTACK(ddb_regs.r1))
185: db_error("cannot get/set user registers in nested interrupt\n");
186: }
187: } else {
188: if (thr_act == THR_ACT_NULL || thr_act == current_act()) {
189: dp = vp->valuep;
190: } else {
191: if (thr_act->thread &&
192: !(thr_act->thread->state & TH_STACK_HANDOFF) &&
193: thr_act->thread->kernel_stack) {
194: int cpu;
195:
196: for (cpu = 0; cpu < NCPUS; cpu++) {
197: if (machine_slot[cpu].running == TRUE &&
198: cpu_data[cpu].active_thread == thr_act->thread && saved_state[cpu]) {
199: dp = (int *) (((int)saved_state[cpu]) +
200: (((int) vp->valuep) -
201: (int) &ddb_regs));
202: break;
203: }
204: }
205: #if 0
206: if (dp == 0 && thr_act && thr_act->thread)
207: dp = db_lookup_i386_kreg(vp->name,
208: (int *)(STACK_IKS(thr_act->thread->kernel_stack)));
209: #endif
210: if (dp == 0)
211: dp = &null_reg;
212: } else if (thr_act->thread &&
213: (thr_act->thread->state&TH_STACK_HANDOFF)){
214: /* only PC is valid */
215: if (vp->valuep == (int *) &ddb_regs.srr0) {
216: dp = (int *)(&thr_act->thread->continuation);
217: } else {
218: dp = &null_reg;
219: }
220: }
221: }
222: }
223: if (dp == 0) {
224: int cpu;
225:
226: if (!db_option(ap->modif, 'u')) {
227: for (cpu = 0; cpu < NCPUS; cpu++) {
228: if (machine_slot[cpu].running == TRUE &&
229: cpu_data[cpu].active_thread == thr_act->thread && saved_state[cpu]) {
230: dp = (int *) (((int)saved_state[cpu]) +
231: (((int) vp->valuep) -
232: (int) &ddb_regs));
233: break;
234: }
235: }
236: }
237: if (dp == 0) {
238: if (!thr_act || thr_act->mact.pcb == 0)
239: db_error("no pcb\n");
240: dp = (int *)((int)(&thr_act->mact.pcb->ss) +
241: ((int)vp->valuep - (int)&ddb_regs));
242: }
243: }
244: if (flag == DB_VAR_SET)
245: *dp = *valuep;
246: else
247: *valuep = *dp;
248: return(0);
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 ppc_saved_state *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: #if 0
356: /*
357: * We know that trap() has 1 argument and we know that
358: * it is an (strcut i386_saved_state *).
359: */
360: saved_regs = (struct i386_saved_state *)
361: db_get_task_value((int)&((*fp)->f_arg0),4,FALSE,task);
362: if (saved_regs->trapno >= 0 && saved_regs->trapno < TRAP_TYPES) {
363: db_printf(">>>>> %s trap at ",
364: trap_type[saved_regs->trapno]);
365: } else {
366: db_printf(">>>>> trap (number %d) at ",
367: saved_regs->trapno & 0xffff);
368: }
369: db_task_printsym(saved_regs->eip, DB_STGY_PROC, task);
370: db_printf(" <<<<<\n");
371: *fp = (struct i386_frame *)saved_regs->ebp;
372: *ip = (db_addr_t)saved_regs->eip;
373: #else
374: db_printf(">>>>> trap <<<<<\n");
375: goto miss_frame;
376: #endif
377: break;
378: case INTERRUPT:
379: if (*lfp == 0) {
380: db_printf(">>>>> interrupt <<<<<\n");
381: goto miss_frame;
382: }
383: #if 0
384: db_printf(">>>>> interrupt at ");
385: ifp = (struct interrupt_frame *)(*lfp);
386: *fp = ifp->if_frame;
387: if (ifp->if_iretaddr == db_return_to_iret_symbol_value)
388: *ip = ((struct i386_interrupt_state *) ifp->if_edx)->eip;
389: else
390: *ip = (db_addr_t) ifp->if_eip;
391: db_task_printsym(*ip, DB_STGY_PROC, task);
392: db_printf(" <<<<<\n");
393: #else
394: db_printf(">>>>> interrupt <<<<<\n");
395: goto miss_frame;
396: #endif
397: break;
398: case SYSCALL:
399: if (thr_act != THR_ACT_NULL && thr_act->mact.pcb) {
400: *ip = (db_addr_t) thr_act->mact.pcb->ss.srr0;
401: *fp = (struct db_ppc_frame *) (thr_act->mact.pcb->ss.r1);
402: break;
403: }
404: /* falling down for unknown case */
405: default:
406: miss_frame:
407: if ((*fp)->f_frame)
408: *ip = (db_addr_t)
409: db_get_task_value((int)&(*fp)->f_frame->f_retaddr,
410: 4, FALSE, task);
411: else
412: *ip = (db_addr_t)
413: db_get_task_value((int)&(*fp)->f_retaddr,
414: 4, FALSE, task);
415:
416: *lfp = *fp;
417: *fp = (struct db_ppc_frame *)
418: db_get_task_value((int)&(*fp)->f_frame, 4, FALSE, task);
419: break;
420: }
421: }
422:
423: void
424: db_stack_trace_cmd(
425: db_expr_t addr,
426: boolean_t have_addr,
427: db_expr_t count,
428: char *modif)
429: {
430: struct db_ppc_frame *frame, *lastframe;
431: db_addr_t callpc, linkpc, lastcallpc;
432: int frame_type;
433: boolean_t kernel_only = TRUE;
434: boolean_t trace_thread = FALSE;
435: boolean_t trace_all_threads = FALSE;
436: int thcount = 0;
437: char *filename;
438: int linenum;
439: task_t task;
440: thread_act_t th, top_act;
441: int user_frame;
442: int frame_count;
443: jmp_buf_t *prev;
444: jmp_buf_t db_jmp_buf;
445: queue_entry_t act_list;
446:
447: if (!db_trace_symbols_found)
448: db_find_trace_symbols();
449: {
450: register char *cp = modif;
451: register char c;
452:
453: while ((c = *cp++) != 0) {
454: if (c == 't')
455: trace_thread = TRUE;
456: if (c == 'T') {
457: trace_all_threads = TRUE;
458: trace_thread = TRUE;
459: }
460: if (c == 'u')
461: kernel_only = FALSE;
462: }
463: }
464:
465: if (trace_all_threads) {
466: if (!have_addr && !trace_thread) {
467: have_addr = TRUE;
468: trace_thread = TRUE;
469: act_list = &(current_task()->thr_acts);
470: addr = (db_expr_t) queue_first(act_list);
471: } else if (trace_thread) {
472: if (have_addr) {
473: if (!db_check_act_address_valid((thread_act_t)addr)) {
474: if (db_lookup_task((task_t)addr) == -1)
475: return;
476: act_list = &(((task_t)addr)->thr_acts);
477: addr = (db_expr_t) queue_first(act_list);
478: } else {
479: act_list = &(((thread_act_t)addr)->task->thr_acts);
480: thcount = db_lookup_task_act(((thread_act_t)addr)->task,
481: (thread_act_t)addr);
482: }
483: } else {
484: th = db_default_act;
485: if (th == THR_ACT_NULL)
486: th = current_act();
487: if (th == THR_ACT_NULL) {
488: db_printf("no active thr_act\n");
489: return;
490: }
491: have_addr = TRUE;
492: act_list = &th->task->thr_acts;
493: addr = (db_expr_t) queue_first(act_list);
494: }
495: }
496: }
497:
498: if (count == -1)
499: count = 65535;
500:
501: next_thread:
502: top_act = THR_ACT_NULL;
503:
504: user_frame = 0;
505: frame_count = count;
506:
507: if (!have_addr && !trace_thread) {
508: frame = (struct db_ppc_frame *)(ddb_regs.r1);
509: callpc = (db_addr_t)ddb_regs.srr0;
510: linkpc = (db_addr_t)ddb_regs.lr;
511: th = current_act();
512: task = (th != THR_ACT_NULL)? th->task: TASK_NULL;
513: } else if (trace_thread) {
514: if (have_addr) {
515: th = (thread_act_t) addr;
516: if (!db_check_act_address_valid(th))
517: return;
518: } else {
519: th = db_default_act;
520: if (th == THR_ACT_NULL)
521: th = current_act();
522: if (th == THR_ACT_NULL) {
523: db_printf("no active thread\n");
524: return;
525: }
526: }
527: if (trace_all_threads)
528: db_printf("---------- Thread 0x%x (#%d of %d) ----------\n",
529: addr, thcount, th->task->thr_act_count);
530:
531: next_activation:
532: user_frame = 0;
533:
534: task = th->task;
535: if (th == current_act()) {
536: frame = (struct db_ppc_frame *)(ddb_regs.r1);
537: callpc = (db_addr_t)ddb_regs.srr0;
538: linkpc = (db_addr_t)ddb_regs.lr;
539: } else {
540: if (th->mact.pcb == 0) {
541: db_printf("thread has no pcb\n");
542: return;
543: }
544: if (!th->thread) {
545: register struct ppc_saved_state *pss =
546: &th->mact.pcb->ss;
547:
548: db_printf("thread has no shuttle\n");
549: #if 0
550: frame = (struct db_ppc_frame *) (pss->r1);
551: callpc = (db_addr_t) (pss->srr0);
552: linkpc = (db_addr_t) (pss->lr);
553: #else
554: goto thread_done;
555: #endif
556: }
557: else if ((th->thread->state & TH_STACK_HANDOFF) ||
558: th->thread->kernel_stack == 0) {
559: register struct ppc_saved_state *pss =
560: &th->mact.pcb->ss;
561:
562: db_printf("Continuation ");
563: db_task_printsym((db_expr_t)th->thread->continuation,
564: DB_STGY_PROC, task);
565: db_printf("\n");
566: frame = (struct db_ppc_frame *) (pss->r1);
567: callpc = (db_addr_t) (pss->srr0);
568: linkpc = (db_addr_t) (pss->lr);
569: } else {
570: int cpu;
571:
572: for (cpu = 0; cpu < NCPUS; cpu++) {
573: if (machine_slot[cpu].running == TRUE &&
574: cpu_data[cpu].active_thread == th->thread &&
575: saved_state[cpu]) {
576: break;
577: }
578: }
579: if (top_act != THR_ACT_NULL) {
580: /*
581: * Trying to get the backtrace of an activation
582: * which is not the top_most one in the RPC chain:
583: * use the activation's pcb.
584: */
585: struct ppc_saved_state *pss;
586:
587: pss = (struct ppc_saved_state *)th->mact.pcb;
588: frame = (struct db_ppc_frame *) (pss->r1);
589: callpc = (db_addr_t) (pss->srr0);
590: linkpc = (db_addr_t) (pss->lr);
591: } else {
592: if (cpu == NCPUS) {
593: register struct ppc_saved_state *iks;
594: int r;
595:
596: iks = (struct ppc_saved_state *)th->mact.pcb;
597: prev = db_recover;
598: if ((r = _setjmp(db_recover = &db_jmp_buf)) == 0) {
599: frame = (struct db_ppc_frame *) (iks->r1);
600: callpc = (db_addr_t) (iks->lr);
601: linkpc = 0;
602: } else {
603: /*
604: * The kernel stack has probably been
605: * paged out (swapped out activation).
606: */
607: db_recover = prev;
608: if (r == 2) /* 'q' from db_more() */
609: db_error(0);
610: db_printf("<kernel stack (0x%x) error "
611: "(probably swapped out)>\n",
612: iks);
613: goto next_act;
614: }
615: db_recover = prev;
616: } else {
617: db_printf(">>>>> active on cpu %d <<<<<\n",
618: cpu);
619: frame = (struct db_ppc_frame *)
620: (saved_state[cpu]->r1);
621: callpc = (db_addr_t) saved_state[cpu]->srr0;
622: linkpc = (db_addr_t) saved_state[cpu]->lr;
623: }
624: }
625: }
626: }
627: } else {
628: frame = (struct db_ppc_frame *)addr;
629: th = (db_default_act)? db_default_act: current_act();
630: task = (th != THR_ACT_NULL)? th->task: TASK_NULL;
631: if (frame->f_frame) {
632: callpc = (db_addr_t)db_get_task_value
633: ((int)&frame->f_frame->f_retaddr,
634: 4, FALSE, (user_frame) ? task : 0);
635: callpc = callpc-sizeof(callpc);
636: } else
637: callpc =0;
638: linkpc = 0;
639: }
640:
641: if (!INKERNELSTACK((unsigned)frame, th)) {
642: db_printf(">>>>> user space <<<<<\n");
643: if (kernel_only)
644: goto thread_done;
645: user_frame++;
646: }
647:
648: lastframe = 0;
649: lastcallpc = (db_addr_t) 0;
650: while (frame_count-- && frame != 0) {
651: int narg = DB_NUMARGS_MAX;
652: int arg;
653: char * name;
654: db_expr_t offset;
655: db_addr_t call_func = 0;
656: int r;
657: db_addr_t off;
658:
659: db_symbol_values(NULL,
660: db_search_task_symbol_and_line(
661: callpc, DB_STGY_XTRN, &offset, &filename,
662: &linenum, (user_frame) ? task : 0, &narg),
663: &name, (db_expr_t *)&call_func);
664: if ( name == NULL) {
665: db_find_task_sym_and_offset(callpc,
666: &name, &off, (user_frame) ? task : 0);
667: offset = (db_expr_t) off;
668: }
669:
670: if (user_frame == 0) {
671: if (call_func &&
672: (call_func == db_user_trap_symbol_value ||
673: call_func == db_kernel_trap_symbol_value)) {
674: frame_type = TRAP;
675: narg = 1;
676: } else if (call_func &&
677: call_func == db_interrupt_symbol_value) {
678: frame_type = INTERRUPT;
679: goto next_frame;
680: } else if (call_func &&
681: call_func == db_syscall_symbol_value) {
682: frame_type = SYSCALL;
683: goto next_frame;
684: } else {
685: frame_type = 0;
686: prev = db_recover;
687: if ((r = _setjmp(db_recover = &db_jmp_buf))
688: == 0) {
689: if (narg < 0)
690: narg = db_numargs(frame,
691: (user_frame) ? task : 0);
692: db_recover = prev;
693: } else {
694: db_recover = prev;
695: goto next_act;
696: }
697: }
698: } else {
699: frame_type = 0;
700: prev = db_recover;
701: if ((r = _setjmp(db_recover = &db_jmp_buf)) == 0) {
702: if (narg < 0)
703: narg = db_numargs(frame,
704: (user_frame) ? task : 0);
705: db_recover = prev;
706: } else {
707: db_recover = prev;
708: goto next_act;
709: }
710: }
711:
712: if (name == 0 || offset > db_maxoff) {
713: db_printf("[%08X]0x%08X(", frame, callpc);
714: } else {
715: db_printf("[%08X]%s", frame, name);
716: if (offset)
717: db_printf("+%x", offset);
718: db_printf("(");
719: };
720:
721: narg = db_numargs(frame, (user_frame) ? task : 0);
722:
723: for (arg =0; arg < narg; arg++) {
724: db_addr_t argp;
725: int value;
726: boolean_t found;
727:
728: prev = db_recover;
729: if ((r = _setjmp(db_recover = &db_jmp_buf)) == 0) {
730: found = FALSE;
731: if (lastframe)
732: found = db_find_arg(frame, lastframe->f_retaddr,
733: (user_frame) ? task : 0, arg, &argp);
734: if (found)
735: value = db_get_task_value(argp, 4, FALSE,
736: (user_frame) ? task : 0);
737: } else {
738: db_recover = prev;
739: if (r == 2) /* 'q' from db_more() */
740: db_error(0);
741: db_printf("... <stack error>)");
742: db_printf("\n");
743: goto next_act;
744: }
745: db_recover = prev;
746: if (found)
747: db_printf("%08X", value);
748: else
749: db_printf("??");
750: argp = argp + sizeof(argp);
751: if (arg < narg-1)
752: db_printf(",");
753: }
754: if (arg != narg)
755: db_printf("...");
756: db_printf(")");
757: db_printf("\n");
758:
759: next_frame:
760: lastcallpc = callpc;
761: prev = db_recover;
762: if ((r = _setjmp(db_recover = &db_jmp_buf)) == 0) {
763: db_nextframe(&lastframe, &frame, &callpc, frame_type,
764: (user_frame) ? th : THR_ACT_NULL, linkpc);
765: callpc = callpc-sizeof(callpc);
766: db_recover = prev;
767: } else {
768: db_recover = prev;
769: frame = 0;
770: }
771: linkpc = 0;
772:
773: if (frame == 0) {
774: next_act:
775: if (th->lower != THR_ACT_NULL) {
776: if (top_act == THR_ACT_NULL)
777: top_act = th;
778: th = th->lower;
779: db_printf(">>>>> next activation 0x%x ($task%d.%d) <<<<<\n",
780: th,
781: db_lookup_task(th->task),
782: db_lookup_task_act(th->task, th));
783: goto next_activation;
784: }
785: /* end of chain */
786: break;
787: }
788: if (!INKERNELSTACK(lastframe, th) ||
789: !INKERNELSTACK((unsigned)frame, th))
790: user_frame++;
791: if (user_frame == 1) {
792: db_printf(">>>>> user space <<<<<\n");
793: if (kernel_only)
794: break;
795: }
796:
797: if (frame <= lastframe) {
798: if ((INKERNELSTACK(lastframe, th) && !INKERNELSTACK(frame, th))) continue;
799: db_printf("Bad frame pointer: 0x%x\n", frame);
800: break;
801: }
802: }
803:
804: thread_done:
805: if (trace_all_threads) {
806: if (top_act != THR_ACT_NULL)
807: th = top_act;
808: th = (thread_act_t) queue_next(&th->thr_acts);
809: if (! queue_end(act_list, (queue_entry_t) th)) {
810: db_printf("\n");
811: addr = (db_expr_t) th;
812: thcount++;
813: goto next_thread;
814:
815: }
816: }
817: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.