1 /* $NetBSD: db_trace.c,v 1.16 2000/05/26 03:34:29 jhawk Exp $ */ 2 3 /* 4 * Mach Operating System 5 * Copyright (c) 1991,1990 Carnegie Mellon University 6 * All Rights Reserved. 7 * 8 * Permission to use, copy, modify and distribute this software and its 9 * documentation is hereby granted, provided that both the copyright 10 * notice and this permission notice appear in all copies of the 11 * software, derivative works or modified versions, and any portions 12 * thereof, and that both notices appear in supporting documentation. 13 * 14 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" 15 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR 16 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. 17 * 18 * Carnegie Mellon requests users of this software to return to 19 * 20 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU 21 * School of Computer Science 22 * Carnegie Mellon University 23 * Pittsburgh PA 15213-3890 24 * 25 * any improvements or extensions that they make and grant Carnegie the 26 * rights to redistribute these changes. 27 */ 28 29 #include <sys/param.h> 30 #include <sys/proc.h> 31 #include <sys/user.h> 32 #include <machine/db_machdep.h> 33 34 #include <ddb/db_access.h> 35 #include <ddb/db_sym.h> 36 #include <ddb/db_interface.h> 37 #include <ddb/db_output.h> 38 39 #define INKERNEL(va) (((vaddr_t)(va)) >= USRSTACK) 40 41 void 42 db_stack_trace_print(addr, have_addr, count, modif, pr) 43 db_expr_t addr; 44 int have_addr; 45 db_expr_t count; 46 char *modif; 47 void (*pr) __P((const char *, ...)); 48 { 49 struct frame *frame; 50 boolean_t kernel_only = TRUE; 51 boolean_t trace_thread = FALSE; 52 char c, *cp = modif; 53 54 while ((c = *cp++) != 0) { 55 if (c == 't') 56 trace_thread = TRUE; 57 if (c == 'u') 58 kernel_only = FALSE; 59 } 60 61 if (!have_addr) 62 frame = (struct frame *)DDB_TF->tf_out[6]; 63 else { 64 if (trace_thread) { 65 struct proc *p; 66 struct user *u; 67 (*pr)("trace: pid %d ", (int)addr); 68 p = pfind(addr); 69 if (p == NULL) { 70 (*pr)("not found\n"); 71 return; 72 } 73 if ((p->p_flag & P_INMEM) == 0) { 74 (*pr)("swapped out\n"); 75 return; 76 } 77 u = p->p_addr; 78 frame = (struct frame *)u->u_pcb.pcb_sp; 79 (*pr)("at %p\n", frame); 80 } else { 81 frame = (struct frame *)addr; 82 } 83 } 84 85 while (count--) { 86 int i; 87 db_expr_t offset; 88 char *name; 89 db_addr_t pc; 90 91 /* 92 * Switch to frame that contains arguments 93 */ 94 95 pc = frame->fr_pc; 96 frame = frame->fr_fp; 97 98 if (!INKERNEL(pc) || !INKERNEL(frame)) { 99 if (!kernel_only) { 100 count++; 101 while (count--) { 102 (*pr)("0x%lx()\n", pc); 103 pc = fuword(&frame->fr_pc); 104 frame = (void *)fuword(&frame->fr_fp); 105 if (pc == 0 || frame == NULL) { 106 return; 107 } 108 } 109 } 110 return; 111 } 112 113 db_find_sym_and_offset(pc, &name, &offset); 114 if (name == NULL) 115 name = "?"; 116 117 (*pr)("%s(", name); 118 119 /* 120 * Print %i0..%i5, hope these still reflect the 121 * actual arguments somewhat... 122 */ 123 for (i=0; i < 5; i++) 124 (*pr)("0x%x, ", frame->fr_arg[i]); 125 (*pr)("0x%x) at ", frame->fr_arg[i]); 126 db_printsym(pc, DB_STGY_PROC, pr); 127 (*pr)("\n"); 128 } 129 } 130