1 /* $OpenBSD: db_trace.c,v 1.28 2024/11/07 16:02:29 miod Exp $ */ 2 /* $NetBSD: db_trace.c,v 1.23 2001/07/10 06:06:16 eeh Exp $ */ 3 4 /* 5 * Mach Operating System 6 * Copyright (c) 1991,1990 Carnegie Mellon University 7 * All Rights Reserved. 8 * 9 * Permission to use, copy, modify and distribute this software and its 10 * documentation is hereby granted, provided that both the copyright 11 * notice and this permission notice appear in all copies of the 12 * software, derivative works or modified versions, and any portions 13 * thereof, and that both notices appear in supporting documentation. 14 * 15 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" 16 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR 17 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. 18 * 19 * Carnegie Mellon requests users of this software to return to 20 * 21 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU 22 * School of Computer Science 23 * Carnegie Mellon University 24 * Pittsburgh PA 15213-3890 25 * 26 * any improvements or extensions that they make and grant Carnegie the 27 * rights to redistribute these changes. 28 */ 29 30 #include <sys/param.h> 31 #include <sys/proc.h> 32 #include <sys/systm.h> 33 #include <sys/stacktrace.h> 34 #include <sys/user.h> 35 #include <machine/db_machdep.h> 36 #include <machine/ctlreg.h> 37 38 #include <ddb/db_access.h> 39 #include <ddb/db_sym.h> 40 #include <ddb/db_interface.h> 41 #include <ddb/db_output.h> 42 43 void db_dump_fpstate(db_expr_t, int, db_expr_t, char *); 44 void db_dump_window(db_expr_t, int, db_expr_t, char *); 45 void db_dump_stack(db_expr_t, int, db_expr_t, char *); 46 void db_dump_trap(db_expr_t, int, db_expr_t, char *); 47 void db_dump_ts(db_expr_t, int, db_expr_t, char *); 48 void db_print_window(u_int64_t); 49 50 #define KLOAD(x) probeget((paddr_t)(u_long)&(x), ASI_PRIMARY, sizeof(x)) 51 #define ULOAD(x) probeget((paddr_t)(u_long)&(x), ASI_AIUS, sizeof(x)) 52 53 void 54 db_stack_trace_print(db_expr_t addr, int have_addr, db_expr_t count, 55 char *modif, int (*pr)(const char *, ...)) 56 { 57 vaddr_t frame; 58 int kernel_only = 1; 59 int trace_thread = 0; 60 char c, *cp = modif; 61 62 while ((c = *cp++) != 0) { 63 if (c == 't') 64 trace_thread = 1; 65 if (c == 'u') 66 kernel_only = 0; 67 } 68 69 if (!have_addr) 70 frame = (vaddr_t)DDB_TF->tf_out[6]; 71 else { 72 if (trace_thread) { 73 struct proc *p; 74 struct user *u; 75 (*pr)("trace: pid %d ", (int)addr); 76 p = tfind(addr); 77 if (p == NULL) { 78 (*pr)("not found\n"); 79 return; 80 } 81 u = p->p_addr; 82 frame = (vaddr_t)u->u_pcb.pcb_sp; 83 (*pr)("at %p\n", frame); 84 } else { 85 write_all_windows(); 86 87 frame = (vaddr_t)addr - BIAS; 88 } 89 } 90 91 if ((frame & 1) == 0) { 92 db_printf("WARNING: corrupt frame at %lx\n", frame); 93 return; 94 } 95 96 while (count--) { 97 int i; 98 db_expr_t offset; 99 const char *name; 100 vaddr_t pc; 101 struct frame *f64; 102 103 /* 104 * Switch to frame that contains arguments 105 */ 106 107 f64 = (struct frame *)(frame + BIAS); 108 pc = (vaddr_t)KLOAD(f64->fr_pc); 109 110 frame = KLOAD(f64->fr_fp); 111 112 if (kernel_only) { 113 if (pc < KERNBASE || pc >= KERNEND) 114 break; 115 if (frame < KERNBASE) 116 break; 117 } else { 118 if (frame == 0 || frame == (vaddr_t)-1) 119 break; 120 } 121 122 db_find_sym_and_offset(pc, &name, &offset); 123 124 if (name == NULL) 125 (*pr)("%lx(", pc); 126 else 127 (*pr)("%s(", name); 128 129 if ((frame & 1) == 0) { 130 db_printf(")\nWARNING: corrupt frame at %lx\n", frame); 131 break; 132 } 133 134 /* 135 * Print %i0..%i5; hope these still reflect the 136 * actual arguments somewhat... 137 */ 138 f64 = (struct frame *)(frame + BIAS); 139 for (i = 0; i < 5; i++) 140 (*pr)("%lx, ", (long)KLOAD(f64->fr_arg[i])); 141 (*pr)("%lx) at ", (long)KLOAD(f64->fr_arg[i])); 142 db_printsym(pc, DB_STGY_PROC, pr); 143 (*pr)("\n"); 144 } 145 } 146 147 void 148 stacktrace_save_at(struct stacktrace *st, unsigned int skip) 149 { 150 struct frame *f64; 151 vaddr_t pc; 152 vaddr_t frame; 153 154 write_all_windows(); 155 156 frame = (vaddr_t)__builtin_frame_address(0) - BIAS; 157 if ((frame & 1) == 0) 158 return; 159 160 st->st_count = 0; 161 while (st->st_count < STACKTRACE_MAX) { 162 f64 = (struct frame *)(frame + BIAS); 163 pc = (vaddr_t)KLOAD(f64->fr_pc); 164 165 frame = KLOAD(f64->fr_fp); 166 167 if (pc < KERNBASE || pc >= KERNEND) 168 break; 169 if (frame < KERNBASE) 170 break; 171 if ((frame & 1) == 0) 172 break; 173 174 if (skip == 0) 175 st->st_pc[st->st_count++] = pc; 176 else 177 skip--; 178 } 179 } 180 181 void 182 stacktrace_save_utrace(struct stacktrace *st) 183 { 184 st->st_count = 0; 185 } 186 187 void 188 db_dump_window(db_expr_t addr, int have_addr, db_expr_t count, char *modif) 189 { 190 int i; 191 u_int64_t frame = DDB_TF->tf_out[6]; 192 193 /* Addr is really window number */ 194 if (!have_addr) 195 addr = 0; 196 197 /* Traverse window stack */ 198 for (i = 0; i < addr && frame; i++) { 199 if ((frame & 1) == 0) 200 break; 201 frame = ((struct frame *)(frame + BIAS))->fr_fp; 202 } 203 204 if ((frame & 1) == 0) { 205 db_printf("WARNING: corrupt frame at %llx\n", frame); 206 return; 207 } 208 209 db_printf("Window %lx ", addr); 210 db_print_window(frame); 211 } 212 213 void 214 db_print_window(u_int64_t frame) 215 { 216 struct frame *f = (struct frame *)(frame + BIAS); 217 218 db_printf("frame %p locals, ins:\n", f); 219 db_printf("%llx %llx %llx %llx ", 220 (unsigned long long)f->fr_local[0], 221 (unsigned long long)f->fr_local[1], 222 (unsigned long long)f->fr_local[2], 223 (unsigned long long)f->fr_local[3]); 224 db_printf("%llx %llx %llx %llx\n", 225 (unsigned long long)f->fr_local[4], 226 (unsigned long long)f->fr_local[5], 227 (unsigned long long)f->fr_local[6], 228 (unsigned long long)f->fr_local[7]); 229 db_printf("%llx %llx %llx %llx ", 230 (unsigned long long)f->fr_arg[0], 231 (unsigned long long)f->fr_arg[1], 232 (unsigned long long)f->fr_arg[2], 233 (unsigned long long)f->fr_arg[3]); 234 db_printf("%llx %llx %llx=sp %llx=pc:", 235 (unsigned long long)f->fr_arg[4], 236 (unsigned long long)f->fr_arg[5], 237 (unsigned long long)f->fr_fp, 238 (unsigned long long)f->fr_pc); 239 /* Sometimes this don't work. Dunno why. */ 240 db_printsym(f->fr_pc, DB_STGY_PROC, db_printf); 241 db_printf("\n"); 242 } 243 244 void 245 db_dump_stack(db_expr_t addr, int have_addr, db_expr_t count, char *modif) 246 { 247 int i; 248 u_int64_t frame, oldframe; 249 250 if (count == -1) 251 count = 65535; 252 253 if (!have_addr) 254 frame = DDB_TF->tf_out[6]; 255 else 256 frame = addr; 257 258 /* Traverse window stack */ 259 oldframe = 0; 260 for (i = 0; i < count && frame; i++) { 261 if (oldframe == frame) { 262 db_printf("WARNING: stack loop at %llx\n", frame); 263 break; 264 } 265 oldframe = frame; 266 267 if ((frame & 1) == 0) { 268 db_printf("WARNING: corrupt stack at %llx\n", frame); 269 break; 270 } 271 272 frame += BIAS; 273 db_printf("Window %x ", i); 274 db_print_window(frame - BIAS); 275 frame = ((struct frame *)frame)->fr_fp; 276 } 277 } 278 279 280 void 281 db_dump_trap(db_expr_t addr, int have_addr, db_expr_t count, char *modif) 282 { 283 struct trapframe *tf; 284 285 /* Use our last trapframe? */ 286 tf = &ddb_regs.ddb_tf; 287 { 288 /* Or the user trapframe? */ 289 register char c, *cp = modif; 290 while ((c = *cp++) != 0) 291 if (c == 'u') 292 tf = curproc->p_md.md_tf; 293 } 294 /* Or an arbitrary trapframe */ 295 if (have_addr) 296 tf = (struct trapframe *)addr; 297 298 db_printf("Trapframe %p:\ttstate: %llx\tpc: %llx\tnpc: %llx\n", 299 tf, (unsigned long long)tf->tf_tstate, 300 (unsigned long long)tf->tf_pc, 301 (unsigned long long)tf->tf_npc); 302 db_printf("y: %x\tpil: %d\toldpil: %d\ttt: %x\nGlobals:\n", 303 (int)tf->tf_y, (int)tf->tf_pil, (int)tf->tf_oldpil, 304 (int)tf->tf_tt); 305 db_printf("%016llx %016llx %016llx %016llx\n", 306 (unsigned long long)tf->tf_global[0], 307 (unsigned long long)tf->tf_global[1], 308 (unsigned long long)tf->tf_global[2], 309 (unsigned long long)tf->tf_global[3]); 310 db_printf("%016llx %016llx %016llx %016llx\nouts:\n", 311 (unsigned long long)tf->tf_global[4], 312 (unsigned long long)tf->tf_global[5], 313 (unsigned long long)tf->tf_global[6], 314 (unsigned long long)tf->tf_global[7]); 315 db_printf("%016llx %016llx %016llx %016llx\n", 316 (unsigned long long)tf->tf_out[0], 317 (unsigned long long)tf->tf_out[1], 318 (unsigned long long)tf->tf_out[2], 319 (unsigned long long)tf->tf_out[3]); 320 db_printf("%016llx %016llx %016llx %016llx\nlocals:\n", 321 (unsigned long long)tf->tf_out[4], 322 (unsigned long long)tf->tf_out[5], 323 (unsigned long long)tf->tf_out[6], 324 (unsigned long long)tf->tf_out[7]); 325 db_printf("%016llx %016llx %016llx %016llx\n", 326 (unsigned long long)tf->tf_local[0], 327 (unsigned long long)tf->tf_local[1], 328 (unsigned long long)tf->tf_local[2], 329 (unsigned long long)tf->tf_local[3]); 330 db_printf("%016llx %016llx %016llx %016llx\nins:\n", 331 (unsigned long long)tf->tf_local[4], 332 (unsigned long long)tf->tf_local[5], 333 (unsigned long long)tf->tf_local[6], 334 (unsigned long long)tf->tf_local[7]); 335 db_printf("%016llx %016llx %016llx %016llx\n", 336 (unsigned long long)tf->tf_in[0], 337 (unsigned long long)tf->tf_in[1], 338 (unsigned long long)tf->tf_in[2], 339 (unsigned long long)tf->tf_in[3]); 340 db_printf("%016llx %016llx %016llx %016llx\n", 341 (unsigned long long)tf->tf_in[4], 342 (unsigned long long)tf->tf_in[5], 343 (unsigned long long)tf->tf_in[6], 344 (unsigned long long)tf->tf_in[7]); 345 } 346 347 void 348 db_dump_fpstate(db_expr_t addr, int have_addr, db_expr_t count, char *modif) 349 { 350 struct fpstate *fpstate; 351 352 /* Use our last trapframe? */ 353 fpstate = &ddb_regs.ddb_fpstate; 354 /* Or an arbitrary trapframe */ 355 if (have_addr) 356 fpstate = (struct fpstate *)addr; 357 358 db_printf("fpstate %p: fsr = %llx gsr = %lx\nfpregs:\n", 359 fpstate, (unsigned long long)fpstate->fs_fsr, 360 (unsigned long)fpstate->fs_gsr); 361 db_printf(" 0: %08x %08x %08x %08x %08x %08x %08x %08x\n", 362 (unsigned int)fpstate->fs_regs[0], 363 (unsigned int)fpstate->fs_regs[1], 364 (unsigned int)fpstate->fs_regs[2], 365 (unsigned int)fpstate->fs_regs[3], 366 (unsigned int)fpstate->fs_regs[4], 367 (unsigned int)fpstate->fs_regs[5], 368 (unsigned int)fpstate->fs_regs[6], 369 (unsigned int)fpstate->fs_regs[7]); 370 db_printf(" 8: %08x %08x %08x %08x %08x %08x %08x %08x\n", 371 (unsigned int)fpstate->fs_regs[8], 372 (unsigned int)fpstate->fs_regs[9], 373 (unsigned int)fpstate->fs_regs[10], 374 (unsigned int)fpstate->fs_regs[11], 375 (unsigned int)fpstate->fs_regs[12], 376 (unsigned int)fpstate->fs_regs[13], 377 (unsigned int)fpstate->fs_regs[14], 378 (unsigned int)fpstate->fs_regs[15]); 379 db_printf("16: %08x %08x %08x %08x %08x %08x %08x %08x\n", 380 (unsigned int)fpstate->fs_regs[16], 381 (unsigned int)fpstate->fs_regs[17], 382 (unsigned int)fpstate->fs_regs[18], 383 (unsigned int)fpstate->fs_regs[19], 384 (unsigned int)fpstate->fs_regs[20], 385 (unsigned int)fpstate->fs_regs[21], 386 (unsigned int)fpstate->fs_regs[22], 387 (unsigned int)fpstate->fs_regs[23]); 388 db_printf("24: %08x %08x %08x %08x %08x %08x %08x %08x\n", 389 (unsigned int)fpstate->fs_regs[24], 390 (unsigned int)fpstate->fs_regs[25], 391 (unsigned int)fpstate->fs_regs[26], 392 (unsigned int)fpstate->fs_regs[27], 393 (unsigned int)fpstate->fs_regs[28], 394 (unsigned int)fpstate->fs_regs[29], 395 (unsigned int)fpstate->fs_regs[30], 396 (unsigned int)fpstate->fs_regs[31]); 397 db_printf("32: %08x%08x %08x%08x %08x%08x %08x%08x\n", 398 (unsigned int)fpstate->fs_regs[32], 399 (unsigned int)fpstate->fs_regs[33], 400 (unsigned int)fpstate->fs_regs[34], 401 (unsigned int)fpstate->fs_regs[35], 402 (unsigned int)fpstate->fs_regs[36], 403 (unsigned int)fpstate->fs_regs[37], 404 (unsigned int)fpstate->fs_regs[38], 405 (unsigned int)fpstate->fs_regs[39]); 406 db_printf("40: %08x%08x %08x%08x %08x%08x %08x%08x\n", 407 (unsigned int)fpstate->fs_regs[40], 408 (unsigned int)fpstate->fs_regs[41], 409 (unsigned int)fpstate->fs_regs[42], 410 (unsigned int)fpstate->fs_regs[43], 411 (unsigned int)fpstate->fs_regs[44], 412 (unsigned int)fpstate->fs_regs[45], 413 (unsigned int)fpstate->fs_regs[46], 414 (unsigned int)fpstate->fs_regs[47]); 415 db_printf("48: %08x%08x %08x%08x %08x%08x %08x%08x\n", 416 (unsigned int)fpstate->fs_regs[48], 417 (unsigned int)fpstate->fs_regs[49], 418 (unsigned int)fpstate->fs_regs[50], 419 (unsigned int)fpstate->fs_regs[51], 420 (unsigned int)fpstate->fs_regs[52], 421 (unsigned int)fpstate->fs_regs[53], 422 (unsigned int)fpstate->fs_regs[54], 423 (unsigned int)fpstate->fs_regs[55]); 424 db_printf("56: %08x%08x %08x%08x %08x%08x %08x%08x\n", 425 (unsigned int)fpstate->fs_regs[56], 426 (unsigned int)fpstate->fs_regs[57], 427 (unsigned int)fpstate->fs_regs[58], 428 (unsigned int)fpstate->fs_regs[59], 429 (unsigned int)fpstate->fs_regs[60], 430 (unsigned int)fpstate->fs_regs[61], 431 (unsigned int)fpstate->fs_regs[62], 432 (unsigned int)fpstate->fs_regs[63]); 433 } 434 435 void 436 db_dump_ts(db_expr_t addr, int have_addr, db_expr_t count, char *modif) 437 { 438 struct trapstate *ts; 439 int i, tl; 440 441 /* Use our last trapframe? */ 442 ts = &ddb_regs.ddb_ts[0]; 443 tl = ddb_regs.ddb_tl; 444 for (i = 0; i < tl; i++) { 445 printf("%d tt=%lx tstate=%lx tpc=%p tnpc=%p\n", 446 i+1, (long)ts[i].tt, (u_long)ts[i].tstate, 447 (void *)(u_long)ts[i].tpc, (void *)(u_long)ts[i].tnpc); 448 } 449 450 } 451