1 1.50 simonb /* $NetBSD: db_trace.c,v 1.50 2021/02/10 07:19:54 simonb Exp $ */ 2 1.2 perry 3 1.8 simonb /* 4 1.1 jonathan * Mach Operating System 5 1.1 jonathan * Copyright (c) 1993-1987 Carnegie Mellon University 6 1.1 jonathan * All Rights Reserved. 7 1.8 simonb * 8 1.1 jonathan * Permission to use, copy, modify and distribute this software and its 9 1.1 jonathan * documentation is hereby granted, provided that both the copyright 10 1.1 jonathan * notice and this permission notice appear in all copies of the 11 1.1 jonathan * software, derivative works or modified versions, and any portions 12 1.1 jonathan * thereof, and that both notices appear in supporting documentation. 13 1.8 simonb * 14 1.1 jonathan * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" 15 1.1 jonathan * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR 16 1.1 jonathan * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. 17 1.8 simonb * 18 1.1 jonathan * Carnegie Mellon requests users of this software to return to 19 1.8 simonb * 20 1.1 jonathan * Software Distribution Coordinator or Software.Distribution (at) CS.CMU.EDU 21 1.1 jonathan * School of Computer Science 22 1.1 jonathan * Carnegie Mellon University 23 1.1 jonathan * Pittsburgh PA 15213-3890 24 1.8 simonb * 25 1.1 jonathan * any improvements or extensions that they make and grant Carnegie Mellon 26 1.1 jonathan * the rights to redistribute these changes. 27 1.1 jonathan */ 28 1.24 lukem 29 1.24 lukem #include <sys/cdefs.h> 30 1.50 simonb __KERNEL_RCSID(0, "$NetBSD: db_trace.c,v 1.50 2021/02/10 07:19:54 simonb Exp $"); 31 1.38 matt 32 1.45 mrg #ifdef _KERNEL_OPT 33 1.38 matt #include "opt_ddb.h" 34 1.45 mrg #endif 35 1.1 jonathan 36 1.16 jeffs #include <sys/types.h> 37 1.13 soren #include <sys/param.h> 38 1.16 jeffs #include <sys/systm.h> 39 1.16 jeffs #include <sys/proc.h> 40 1.34 yamt #include <sys/cpu.h> 41 1.1 jonathan 42 1.5 castor #include <mips/mips_opcode.h> 43 1.44 mrg #include <mips/stacktrace.h> 44 1.5 castor 45 1.7 simonb #include <machine/db_machdep.h> 46 1.44 mrg #include <machine/locore.h> 47 1.34 yamt 48 1.45 mrg #include <ddb/db_access.h> 49 1.1 jonathan #include <ddb/db_interface.h> 50 1.1 jonathan #include <ddb/db_output.h> 51 1.1 jonathan #include <ddb/db_variables.h> 52 1.1 jonathan #include <ddb/db_sym.h> 53 1.1 jonathan 54 1.21 simonb int __start(void); /* lowest kernel code address */ 55 1.21 simonb vaddr_t getreg_val(db_expr_t regno); 56 1.1 jonathan 57 1.1 jonathan #define REG_ARG(i) (4+i) 58 1.1 jonathan #define SAVES_RA(x) isa_spill((x),31) 59 1.1 jonathan 60 1.1 jonathan #define KERN_SAVE_REG_IDX(vp) ( \ 61 1.1 jonathan ((vp)->valuep >= (int *)(&((struct mips_saved_state *)0)->s0) && \ 62 1.1 jonathan (vp)->valuep <= (int *)(&((struct mips_saved_state *)0)->s7))? \ 63 1.1 jonathan vp->valuep - (int *)(&((struct mips_saved_state *)0)->s0): \ 64 1.1 jonathan ((vp)->valuep >= (int *)(&((struct mips_saved_state *)0)->sp) && \ 65 1.1 jonathan (vp)->valuep <= (int *)(&((struct mips_saved_state *)0)->ra))? \ 66 1.1 jonathan ((vp)->valuep-(int *)(&((struct mips_saved_state *)0)->sp)) + \ 67 1.1 jonathan ((int *)(&((struct mips_kernel_state *)0)->sp) - (int *)0): \ 68 1.1 jonathan -1) 69 1.1 jonathan 70 1.32 thorpej db_sym_t localsym(db_sym_t sym, bool isreg, int *lex_level); 71 1.1 jonathan 72 1.1 jonathan /* 73 1.1 jonathan * Machine register set. 74 1.1 jonathan */ 75 1.1 jonathan struct mips_saved_state *db_cur_exc_frame = 0; 76 1.1 jonathan 77 1.21 simonb int db_mips_variable_func(const struct db_variable *, db_expr_t *, int); 78 1.1 jonathan 79 1.5 castor #define DB_SETF_REGS db_mips_variable_func 80 1.1 jonathan 81 1.17 jdolecek const struct db_variable db_regs[] = { 82 1.45 mrg { "at", (long *)&ddb_regs.r_regs[_R_AST], DB_SETF_REGS, NULL }, 83 1.45 mrg { "v0", (long *)&ddb_regs.r_regs[_R_V0], DB_SETF_REGS, NULL }, 84 1.45 mrg { "v1", (long *)&ddb_regs.r_regs[_R_V1], DB_SETF_REGS, NULL }, 85 1.45 mrg { "a0", (long *)&ddb_regs.r_regs[_R_A0], DB_SETF_REGS, NULL }, 86 1.45 mrg { "a1", (long *)&ddb_regs.r_regs[_R_A1], DB_SETF_REGS, NULL }, 87 1.45 mrg { "a2", (long *)&ddb_regs.r_regs[_R_A2], DB_SETF_REGS, NULL }, 88 1.45 mrg { "a3", (long *)&ddb_regs.r_regs[_R_A3], DB_SETF_REGS, NULL }, 89 1.22 thorpej #if defined(__mips_n32) || defined(__mips_n64) 90 1.45 mrg { "a4", (long *)&ddb_regs.r_regs[_R_A4], DB_SETF_REGS, NULL }, 91 1.45 mrg { "a5", (long *)&ddb_regs.r_regs[_R_A5], DB_SETF_REGS, NULL }, 92 1.45 mrg { "a6", (long *)&ddb_regs.r_regs[_R_A6], DB_SETF_REGS, NULL }, 93 1.45 mrg { "a7", (long *)&ddb_regs.r_regs[_R_A7], DB_SETF_REGS, NULL }, 94 1.45 mrg { "t0", (long *)&ddb_regs.r_regs[_R_T0], DB_SETF_REGS, NULL }, 95 1.45 mrg { "t1", (long *)&ddb_regs.r_regs[_R_T1], DB_SETF_REGS, NULL }, 96 1.45 mrg { "t2", (long *)&ddb_regs.r_regs[_R_T2], DB_SETF_REGS, NULL }, 97 1.45 mrg { "t3", (long *)&ddb_regs.r_regs[_R_T3], DB_SETF_REGS, NULL }, 98 1.22 thorpej #else 99 1.45 mrg { "t0", (long *)&ddb_regs.r_regs[_R_T0], DB_SETF_REGS, NULL }, 100 1.45 mrg { "t1", (long *)&ddb_regs.r_regs[_R_T1], DB_SETF_REGS, NULL }, 101 1.45 mrg { "t2", (long *)&ddb_regs.r_regs[_R_T2], DB_SETF_REGS, NULL }, 102 1.45 mrg { "t3", (long *)&ddb_regs.r_regs[_R_T3], DB_SETF_REGS, NULL }, 103 1.45 mrg { "t4", (long *)&ddb_regs.r_regs[_R_T4], DB_SETF_REGS, NULL }, 104 1.45 mrg { "t5", (long *)&ddb_regs.r_regs[_R_T5], DB_SETF_REGS, NULL }, 105 1.45 mrg { "t6", (long *)&ddb_regs.r_regs[_R_T6], DB_SETF_REGS, NULL }, 106 1.45 mrg { "t7", (long *)&ddb_regs.r_regs[_R_T7], DB_SETF_REGS, NULL }, 107 1.22 thorpej #endif /* __mips_n32 || __mips_n64 */ 108 1.45 mrg { "s0", (long *)&ddb_regs.r_regs[_R_S0], DB_SETF_REGS, NULL }, 109 1.45 mrg { "s1", (long *)&ddb_regs.r_regs[_R_S1], DB_SETF_REGS, NULL }, 110 1.45 mrg { "s2", (long *)&ddb_regs.r_regs[_R_S2], DB_SETF_REGS, NULL }, 111 1.45 mrg { "s3", (long *)&ddb_regs.r_regs[_R_S3], DB_SETF_REGS, NULL }, 112 1.45 mrg { "s4", (long *)&ddb_regs.r_regs[_R_S4], DB_SETF_REGS, NULL }, 113 1.45 mrg { "s5", (long *)&ddb_regs.r_regs[_R_S5], DB_SETF_REGS, NULL }, 114 1.45 mrg { "s6", (long *)&ddb_regs.r_regs[_R_S6], DB_SETF_REGS, NULL }, 115 1.45 mrg { "s7", (long *)&ddb_regs.r_regs[_R_S7], DB_SETF_REGS, NULL }, 116 1.45 mrg { "t8", (long *)&ddb_regs.r_regs[_R_T8], DB_SETF_REGS, NULL }, 117 1.45 mrg { "t9", (long *)&ddb_regs.r_regs[_R_T9], DB_SETF_REGS, NULL }, 118 1.45 mrg { "k0", (long *)&ddb_regs.r_regs[_R_K0], DB_SETF_REGS, NULL }, 119 1.45 mrg { "k1", (long *)&ddb_regs.r_regs[_R_K1], DB_SETF_REGS, NULL }, 120 1.45 mrg { "gp", (long *)&ddb_regs.r_regs[_R_GP], DB_SETF_REGS, NULL }, 121 1.45 mrg { "sp", (long *)&ddb_regs.r_regs[_R_SP], DB_SETF_REGS, NULL }, 122 1.45 mrg { "fp", (long *)&ddb_regs.r_regs[_R_S8], DB_SETF_REGS, NULL },/* frame ptr */ 123 1.45 mrg { "ra", (long *)&ddb_regs.r_regs[_R_RA], DB_SETF_REGS, NULL }, 124 1.45 mrg { "sr", (long *)&ddb_regs.r_regs[_R_SR], DB_SETF_REGS, NULL }, 125 1.45 mrg { "mdlo",(long *)&ddb_regs.r_regs[_R_MULLO], DB_SETF_REGS, NULL }, 126 1.45 mrg { "mdhi",(long *)&ddb_regs.r_regs[_R_MULHI], DB_SETF_REGS, NULL }, 127 1.45 mrg { "bad", (long *)&ddb_regs.r_regs[_R_BADVADDR], DB_SETF_REGS, NULL }, 128 1.45 mrg { "cs", (long *)&ddb_regs.r_regs[_R_CAUSE], DB_SETF_REGS, NULL }, 129 1.45 mrg { "pc", (long *)&ddb_regs.r_regs[_R_PC], DB_SETF_REGS, NULL }, 130 1.1 jonathan }; 131 1.41 matt const struct db_variable * const db_eregs = db_regs + __arraycount(db_regs); 132 1.1 jonathan 133 1.1 jonathan void 134 1.33 matt db_stack_trace_print(db_expr_t addr, bool have_addr, db_expr_t count, 135 1.26 simonb const char *modif, void (*pr)(const char *, ...)) 136 1.1 jonathan { 137 1.5 castor #ifndef DDB_TRACE 138 1.16 jeffs struct pcb *pcb; 139 1.40 chs const char *cp = modif; 140 1.40 chs char c; 141 1.40 chs bool lwpaddr = false; 142 1.45 mrg vaddr_t pc, sp, s8, ra; 143 1.45 mrg #ifndef _KERNEL 144 1.45 mrg mips_label_t label; 145 1.45 mrg #endif 146 1.16 jeffs 147 1.16 jeffs if (!have_addr) { 148 1.41 matt struct reg * regs = &ddb_regs; 149 1.41 matt stacktrace_subr(regs->r_regs[_R_A0], 150 1.41 matt regs->r_regs[_R_A1], 151 1.41 matt regs->r_regs[_R_A2], 152 1.41 matt regs->r_regs[_R_A3], 153 1.41 matt regs->r_regs[_R_PC], 154 1.41 matt regs->r_regs[_R_SP], 155 1.16 jeffs /* non-virtual frame pointer */ 156 1.41 matt regs->r_regs[_R_S8], 157 1.41 matt regs->r_regs[_R_RA], 158 1.16 jeffs pr); 159 1.16 jeffs return; 160 1.16 jeffs } 161 1.16 jeffs 162 1.40 chs while ((c = *cp++) != 0) { 163 1.40 chs if (c == 'a') { 164 1.40 chs lwpaddr = true; 165 1.40 chs } 166 1.40 chs } 167 1.40 chs 168 1.40 chs if (lwpaddr) { 169 1.47 mrg #ifdef _KERNEL 170 1.47 mrg struct lwp *l; 171 1.47 mrg 172 1.47 mrg l = (struct lwp *)(intptr_t)addr; 173 1.47 mrg (*pr)("pid %d.%d ", l->l_proc->p_pid, l->l_lid); 174 1.47 mrg pcb = lwp_getpcb(l); 175 1.47 mrg #else 176 1.47 mrg struct proc pstore; 177 1.47 mrg struct lwp lstore; 178 1.47 mrg 179 1.47 mrg db_read_bytes(addr, sizeof(lstore), (char *)&lstore); 180 1.48 simonb db_read_bytes((db_addr_t)lstore.l_proc, sizeof(pstore), 181 1.47 mrg (char *)&pstore); 182 1.47 mrg (*pr)("pid %d.%d ", pstore.p_pid, lstore.l_lid); 183 1.47 mrg pcb = lwp_getpcb(&lstore); 184 1.47 mrg #endif 185 1.40 chs } else { 186 1.40 chs /* "trace/t" */ 187 1.40 chs 188 1.40 chs (*pr)("pid %d ", (int)addr); 189 1.45 mrg #ifdef _KERNEL 190 1.47 mrg struct lwp *l; 191 1.47 mrg struct proc *p = proc_find_raw(addr); 192 1.47 mrg 193 1.47 mrg if (p == NULL) { 194 1.40 chs (*pr)("not found\n"); 195 1.40 chs return; 196 1.48 simonb } 197 1.47 mrg l = LIST_FIRST(&p->p_lwps); /* XXX NJWLWP */ 198 1.47 mrg pcb = lwp_getpcb(l); 199 1.45 mrg #else 200 1.45 mrg (*pr)("no proc_find_raw() in crash\n"); 201 1.45 mrg return; 202 1.45 mrg #endif 203 1.40 chs } 204 1.42 matt 205 1.16 jeffs (*pr)("at %p\n", pcb); 206 1.16 jeffs 207 1.45 mrg #ifdef _KERNEL 208 1.45 mrg pc = (vaddr_t)cpu_switchto; 209 1.45 mrg sp = pcb->pcb_context.val[_L_SP]; 210 1.45 mrg s8 = pcb->pcb_context.val[_L_S8]; 211 1.45 mrg ra = pcb->pcb_context.val[_L_RA]; 212 1.45 mrg #else 213 1.45 mrg pc = db_mach_addr_cpuswitch(); 214 1.45 mrg db_read_bytes((db_addr_t)&pcb->pcb_context, sizeof(label), (char *)&label); 215 1.45 mrg sp = label.val[_L_SP]; 216 1.45 mrg s8 = label.val[_L_S8]; 217 1.45 mrg ra = label.val[_L_RA]; 218 1.45 mrg #endif 219 1.16 jeffs stacktrace_subr(0,0,0,0, /* no args known */ 220 1.45 mrg pc, sp, s8, ra, 221 1.11 jhawk pr); 222 1.5 castor #else 223 1.5 castor /* 224 1.13 soren * Incomplete but practically useful stack backtrace. 225 1.5 castor */ 226 1.5 castor #define MIPS_JR_RA 0x03e00008 /* instruction code for jr ra */ 227 1.5 castor #define MIPS_JR_K0 0x03400008 /* instruction code for jr k0 */ 228 1.6 nisimura #define MIPS_ERET 0x42000018 /* instruction code for eret */ 229 1.38 matt register_t va, pc, ra, sp, func; 230 1.5 castor int insn; 231 1.5 castor InstFmt i; 232 1.5 castor int stacksize; 233 1.5 castor db_addr_t offset; 234 1.30 martin const char *name; 235 1.5 castor extern char verylocore[]; 236 1.5 castor 237 1.41 matt pc = ddb_regs.r_regs[_R_PC]; 238 1.41 matt sp = ddb_regs.r_regs[_R_SP]; 239 1.41 matt ra = ddb_regs.r_regs[_R_RA]; 240 1.5 castor do { 241 1.5 castor va = pc; 242 1.5 castor do { 243 1.5 castor va -= sizeof(int); 244 1.38 matt insn = *(int *)(intptr_t)va; 245 1.5 castor if (insn == MIPS_ERET) 246 1.5 castor goto mips3_eret; 247 1.5 castor } while (insn != MIPS_JR_RA && insn != MIPS_JR_K0); 248 1.5 castor va += sizeof(int); 249 1.5 castor mips3_eret: 250 1.5 castor va += sizeof(int); 251 1.38 matt while (*(int *)(intptr_t)va == 0x00000000) 252 1.5 castor va += sizeof(int); 253 1.5 castor func = va; 254 1.5 castor stacksize = 0; 255 1.5 castor do { 256 1.38 matt i.word = *(int *)(intptr_t)va; 257 1.38 matt if (((i.IType.op == OP_SW) || (i.IType.op == OP_SD)) 258 1.25 he && i.IType.rs == _R_SP 259 1.25 he && i.IType.rt == _R_RA) 260 1.38 matt ra = *(int *)(intptr_t)(sp + (short)i.IType.imm); 261 1.38 matt if (((i.IType.op == OP_ADDIU) || (i.IType.op == OP_DADDIU)) 262 1.25 he && i.IType.rs == _R_SP 263 1.25 he && i.IType.rt == _R_SP) 264 1.5 castor stacksize = -(short)i.IType.imm; 265 1.5 castor va += sizeof(int); 266 1.5 castor } while (va < pc); 267 1.5 castor 268 1.5 castor db_find_sym_and_offset(func, &name, &offset); 269 1.5 castor if (name == 0) 270 1.5 castor name = "?"; 271 1.11 jhawk (*pr)("%s()+0x%x, called by %p, stack size %d\n", 272 1.38 matt name, pc - func, (void *)(intptr_t)ra, stacksize); 273 1.5 castor 274 1.5 castor if (ra == pc) { 275 1.12 mhitch (*pr)("-- loop? --\n"); 276 1.5 castor return; 277 1.5 castor } 278 1.5 castor sp += stacksize; 279 1.5 castor pc = ra; 280 1.38 matt } while (pc > (intptr_t)verylocore); 281 1.5 castor if (pc < 0x80000000) 282 1.11 jhawk (*pr)("-- user process --\n"); 283 1.5 castor else 284 1.11 jhawk (*pr)("-- kernel entry --\n"); 285 1.5 castor #endif 286 1.1 jonathan } 287 1.1 jonathan 288 1.50 simonb /* 289 1.50 simonb * Helper function for db_stacktrace() and friends, used to get the 290 1.50 simonb * pc via the return address. 291 1.50 simonb */ 292 1.1 jonathan void 293 1.50 simonb db_mips_stack_trace(void *ra, void *fp, void (*pr)(const char *, ...)) 294 1.1 jonathan { 295 1.50 simonb vaddr_t pc; 296 1.20 simonb 297 1.50 simonb /* 298 1.50 simonb * The jal instruction for our caller is two insns before the 299 1.50 simonb * return address. 300 1.50 simonb */ 301 1.50 simonb pc = (vaddr_t)__builtin_return_address(0) - sizeof(uint32_t) * 2; 302 1.50 simonb 303 1.50 simonb stacktrace_subr(0, 0, 0, 0, /* no args known */ 304 1.50 simonb pc, (intptr_t)fp, (intptr_t)fp, (intptr_t)ra, 305 1.50 simonb pr); 306 1.1 jonathan } 307 1.1 jonathan 308 1.8 simonb int 309 1.48 simonb db_mips_variable_func(const struct db_variable *vp, db_expr_t *valuep, 310 1.20 simonb int db_var_fcn) 311 1.5 castor { 312 1.20 simonb 313 1.5 castor switch (db_var_fcn) { 314 1.5 castor case DB_VAR_GET: 315 1.5 castor *valuep = *(mips_reg_t *) vp->valuep; 316 1.5 castor break; 317 1.5 castor case DB_VAR_SET: 318 1.5 castor *(mips_reg_t *) vp->valuep = *valuep; 319 1.5 castor break; 320 1.5 castor } 321 1.5 castor return 0; 322 1.5 castor } 323