1 /* $NetBSD: db_trace.c,v 1.13 2013/10/19 14:03:04 skrll Exp $ */ 2 3 /* $OpenBSD: db_interface.c,v 1.16 2001/03/22 23:31:45 mickey Exp $ */ 4 5 /* 6 * Copyright (c) 1999-2003 Michael Shalayeff 7 * All rights reserved. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in the 16 * documentation and/or other materials provided with the distribution. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 21 * IN NO EVENT SHALL THE AUTHOR OR HIS RELATIVES BE LIABLE FOR ANY DIRECT, 22 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 23 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 24 * SERVICES; LOSS OF MIND, USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 26 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 27 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 28 * THE POSSIBILITY OF SUCH DAMAGE. 29 */ 30 31 #include <sys/cdefs.h> 32 __KERNEL_RCSID(0, "$NetBSD: db_trace.c,v 1.13 2013/10/19 14:03:04 skrll Exp $"); 33 34 #include <sys/param.h> 35 #include <sys/systm.h> 36 #include <sys/proc.h> 37 38 #include <machine/db_machdep.h> 39 40 #include <ddb/db_access.h> 41 #include <ddb/db_sym.h> 42 #include <ddb/db_interface.h> 43 #include <ddb/db_proc.h> 44 45 void 46 db_stack_trace_print(db_expr_t addr, bool have_addr, db_expr_t count, 47 const char *modif, void (*pr)(const char *, ...)) 48 { 49 register_t *fp, pc, rp; 50 #if 0 51 bool kernel_only = true; 52 #endif 53 bool trace_thread = false; 54 bool lwpaddr = false; 55 db_sym_t sym; 56 db_expr_t off; 57 const char *name; 58 const char *cp = modif; 59 char c; 60 61 if (count < 0) 62 count = 65536; 63 64 while ((c = *cp++) != 0) { 65 if (c == 'a') { 66 lwpaddr = true; 67 trace_thread = true; 68 } 69 if (c == 't') 70 trace_thread = true; 71 #if 0 72 if (c == 'u') 73 kernel_only = false; 74 #endif 75 } 76 77 if (!have_addr) { 78 fp = (register_t *)ddb_regs.tf_r3; 79 pc = ddb_regs.tf_iioq_head; 80 rp = ddb_regs.tf_rp; 81 } else { 82 if (trace_thread) { 83 proc_t p; 84 lwp_t l; 85 pid_t pid; 86 87 if (lwpaddr) { 88 db_read_bytes(addr, sizeof(l), (char *)&l); 89 db_read_bytes((db_addr_t)l.l_proc, sizeof(p), 90 (char *)&p); 91 (*pr)("trace: pid %d ", p.p_pid); 92 } else { 93 proc_t *pp; 94 95 pid = (pid_t)addr; 96 (*pr)("trace: pid %d ", pid); 97 pp = db_proc_find(pid); 98 if (pp == NULL) { 99 (*pr)("not found\n"); 100 return; 101 } 102 db_read_bytes((db_addr_t)pp, sizeof(p), 103 (char *)&p); 104 addr = (db_addr_t)p.p_lwps.lh_first; 105 db_read_bytes(addr, sizeof(l), (char *)&l); 106 } 107 (*pr)("lid %d ", l.l_lid); 108 #ifdef _KERNEL 109 if (l.l_proc == curproc && (lwp_t *)addr == curlwp) { 110 fp = (int *)ddb_regs.tf_r3; 111 pc = ddb_regs.tf_iioq_head; 112 rp = ddb_regs.tf_rp; 113 } else 114 #endif 115 { 116 struct pcb *pcb = lwp_getpcb(&l); 117 register_t sp; 118 /* cpu_switchto fp, and return point */ 119 db_read_bytes((db_addr_t)&pcb->pcb_ksp, 120 sizeof(sp), (char *)&sp); 121 fp = (register_t *)(sp - 122 (HPPA_FRAME_SIZE + 16*4)); 123 pc = 0; 124 125 db_read_bytes((db_addr_t)&fp[-5], sizeof(rp), 126 (char *)&rp); 127 } 128 (*pr)("at %p\n", fp); 129 } else { 130 pc = 0; 131 fp = (register_t *)addr; 132 db_read_bytes((db_addr_t)&fp[-5], sizeof(rp), 133 (char *)&rp); 134 } 135 } 136 137 while (fp && count--) { 138 register_t *newfp; 139 #ifdef DDB_DEBUG 140 pr(">> %08x %08x %08x\t", fp, pc, rp); 141 #endif 142 143 if (USERMODE(pc)) 144 return; 145 146 if (pc) { 147 sym = db_search_symbol(pc, DB_STGY_ANY, &off); 148 db_symbol_values (sym, &name, NULL); 149 150 pr("%s() at ", name); 151 db_printsym(pc, DB_STGY_PROC, pr); 152 pr("\n"); 153 } 154 155 db_read_bytes((db_addr_t)&fp[0], sizeof(newfp), (char *)&newfp); 156 157 /* 158 * if a terminal frame then report the trapframe and continue 159 * after it (if not the last one). 160 */ 161 if (!newfp) { 162 register_t scargs[5]; 163 struct trapframe tf, *ktf; 164 int scoff; 165 166 /* Stack space for syscall args */ 167 scoff = HPPA_FRAME_ROUND(HPPA_FRAME_SIZE + 168 HPPA_FRAME_MAXARGS); 169 ktf = (struct trapframe *)((char *)fp - scoff - 170 sizeof(tf)); 171 172 db_read_bytes((db_addr_t)((char *)fp - scoff), 173 sizeof(scargs), (char *)&scargs); 174 db_read_bytes((db_addr_t)ktf, sizeof(tf), (char *)&tf); 175 176 if (tf.tf_flags & TFF_SYS) 177 pr("-- syscall #%d(%x, %x, %x, %x, ...) (%p)\n", 178 tf.tf_t1, scargs[1], scargs[2], 179 scargs[3], scargs[4], ktf); 180 else 181 pr("-- trap #%d (%p) %s\n", tf.tf_flags & 0x3f, 182 ktf, (tf.tf_flags & T_USER)? " from user" : 183 ""); 184 185 if (!(tf.tf_flags & TFF_LAST)) { 186 fp = (register_t *)tf.tf_r3; 187 pc = tf.tf_iioq_head; 188 rp = tf.tf_rp; 189 } else { 190 pc = 0; 191 fp = 0; 192 } 193 } else { 194 /* next frame */ 195 fp = newfp; 196 pc = rp; 197 db_read_bytes((db_addr_t)&fp[-5], sizeof(rp), 198 (char *)&rp); 199 } 200 } 201 202 if (count && pc) { 203 db_printsym(pc, DB_STGY_XTRN, pr); 204 pr(":\n"); 205 } 206 } 207