1 /* $NetBSD: db_trace.c,v 1.57 2023/01/24 23:23:31 riastradh Exp $ */ 2 3 /* 4 * Copyright (c) 1996-2002 Eduardo Horvath. All rights reserved. 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 (at) 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/cdefs.h> 31 __KERNEL_RCSID(0, "$NetBSD: db_trace.c,v 1.57 2023/01/24 23:23:31 riastradh Exp $"); 32 33 #include <sys/param.h> 34 #include <sys/proc.h> 35 #include <sys/cpu.h> 36 #include <sys/systm.h> 37 #include <machine/db_machdep.h> 38 #include <machine/ctlreg.h> 39 #include <machine/vmparam.h> 40 41 #include <ddb/db_access.h> 42 #include <ddb/db_proc.h> 43 #include <ddb/db_sym.h> 44 #include <ddb/db_interface.h> 45 #include <ddb/db_output.h> 46 47 #ifndef _KERNEL 48 #include <stdbool.h> 49 #endif 50 51 void db_print_window(uint64_t); 52 53 #if 0 54 #define INKERNEL(va) (((vaddr_t)(va)) >= USRSTACK) /* Not really true, y'know */ 55 #else 56 #define INKERNEL(va) 1 /* Everything's in the kernel now. 8^) */ 57 #endif 58 59 #ifdef _KERNEL 60 #define KLOAD(x) probeget((paddr_t)(u_long)&(x), ASI_PRIMARY, sizeof(x)) 61 #else 62 static long 63 kload(db_addr_t addr) 64 { 65 long val; 66 67 db_read_bytes(addr, sizeof val, (char *)&val); 68 69 return val; 70 } 71 #define KLOAD(x) kload((db_addr_t)(u_long)&(x)) 72 #endif 73 74 void 75 db_stack_trace_print(db_expr_t addr, bool have_addr, db_expr_t count, 76 const char *modif, void (*pr) (const char *, ...)) 77 { 78 vaddr_t frame; 79 bool kernel_only = true; 80 bool trace_thread = false; 81 bool lwpaddr = false; 82 char c; 83 const char *cp = modif; 84 85 while ((c = *cp++) != 0) { 86 if (c == 'a') { 87 lwpaddr = true; 88 trace_thread = true; 89 } 90 if (c == 't') 91 trace_thread = true; 92 if (c == 'u') 93 kernel_only = false; 94 } 95 96 if (!have_addr) { 97 #ifndef _KERNEL 98 extern struct pcb pcb; 99 frame = (vaddr_t)pcb.pcb_sp; 100 #else 101 frame = (vaddr_t)DDB_TF->tf_out[6]; 102 #endif 103 } else { 104 if (trace_thread) { 105 static proc_t p; 106 static lwp_t l; 107 struct pcb *pcb; 108 109 if (lwpaddr) { 110 db_read_bytes(addr, sizeof(l), (char *)&l); 111 db_read_bytes((db_addr_t)l.l_proc, 112 sizeof(p), (char *)&p); 113 114 (*pr)("trace: pid %d ", p.p_pid); 115 } else { 116 proc_t *pp; 117 (*pr)("trace: pid %d ", (int)addr); 118 pp = db_proc_find((pid_t)addr); 119 if (pp == NULL) { 120 (*pr)("not found\n"); 121 return; 122 } 123 db_read_bytes((db_addr_t)pp, sizeof(p), 124 (char *)&p); 125 addr = (db_addr_t)p.p_lwps.lh_first; 126 db_read_bytes(addr, sizeof(l), (char *)&l); 127 } 128 (*pr)("lid %d ", l.l_lid); 129 pcb = lwp_getpcb(&l); 130 db_read_bytes((db_addr_t)&pcb->pcb_sp, 131 sizeof(frame), (char *)&frame); 132 (*pr)("at %p\n", frame); 133 } else { 134 frame = (vaddr_t)addr; 135 } 136 } 137 138 while (count--) { 139 int i; 140 db_expr_t offset; 141 const char *name; 142 db_addr_t pc; 143 struct frame64 *f64; 144 struct frame32 *f32; 145 146 /* 147 * Switch to frame that contains arguments 148 */ 149 if (frame & 1) { 150 f64 = (struct frame64 *)(frame + BIAS); 151 pc = (db_addr_t)KLOAD(f64->fr_pc); 152 153 frame = KLOAD(f64->fr_fp); 154 } else { 155 f32 = (struct frame32 *)(frame); 156 pc = (db_addr_t)KLOAD(f32->fr_pc); 157 158 frame = (long)KLOAD(f32->fr_fp); 159 } 160 161 if (kernel_only) { 162 if (pc < KERNBASE || pc >= KERNEND) 163 break; 164 if (frame < KERNBASE || frame >= VM_MAX_KERNEL_ADDRESS) 165 break; 166 } else { 167 if (frame == 0 || frame == (vaddr_t)-1) 168 break; 169 } 170 #if 0 171 if (!INKERNEL(frame)) 172 break; 173 #endif 174 175 db_find_sym_and_offset(pc, &name, &offset); 176 if (name == NULL) 177 name = "?"; 178 179 (*pr)("%s(", name); 180 181 /* 182 * Print %i0..%i5; hope these still reflect the 183 * actual arguments somewhat... 184 */ 185 if (frame & 1) { 186 f64 = (struct frame64 *)(frame + BIAS); 187 for (i = 0; i < 5; i++) 188 (*pr)("%lx, ", (long)KLOAD(f64->fr_arg[i])); 189 (*pr)("%lx) at ", (long)KLOAD(f64->fr_arg[i])); 190 } else { 191 f32 = (struct frame32 *)(frame); 192 for (i = 0; i < 5; i++) 193 (*pr)("%x, ", (u_int)KLOAD(f32->fr_arg[i])); 194 (*pr)("%x) at ", (u_int)KLOAD(f32->fr_arg[i])); 195 } 196 db_printsym(pc, DB_STGY_PROC, pr); 197 (*pr)("\n"); 198 } 199 } 200 201 202 #ifdef _KERNEL 203 void 204 db_dump_window(db_expr_t addr, bool have_addr, db_expr_t count, const char *modif) 205 { 206 int i; 207 uint64_t frame = DDB_TF->tf_out[6]; 208 209 /* Addr is really window number */ 210 if (!have_addr) 211 addr = 0; 212 213 /* Traverse window stack */ 214 for (i=0; i<addr && frame; i++) { 215 if (frame & 1) 216 frame = (uint64_t)((struct frame64 *)(u_long)(frame + BIAS))->fr_fp; 217 else frame = (uint64_t)((struct frame32 *)(u_long)frame)->fr_fp; 218 } 219 220 db_printf("Window %lx ", (long)addr); 221 db_print_window(frame); 222 } 223 #endif 224 225 void 226 db_print_window(uint64_t frame) 227 { 228 if (frame & 1) { 229 struct frame64* f = (struct frame64*)(u_long)(frame + BIAS); 230 231 db_printf("frame64 %p locals, ins:\n", f); 232 if (INKERNEL(f)) { 233 db_printf("%llx %llx %llx %llx ", 234 (unsigned long long)f->fr_local[0], 235 (unsigned long long)f->fr_local[1], 236 (unsigned long long)f->fr_local[2], 237 (unsigned long long)f->fr_local[3]); 238 db_printf("%llx %llx %llx %llx\n", 239 (unsigned long long)f->fr_local[4], 240 (unsigned long long)f->fr_local[5], 241 (unsigned long long)f->fr_local[6], 242 (unsigned long long)f->fr_local[7]); 243 db_printf("%llx %llx %llx %llx ", 244 (unsigned long long)f->fr_arg[0], 245 (unsigned long long)f->fr_arg[1], 246 (unsigned long long)f->fr_arg[2], 247 (unsigned long long)f->fr_arg[3]); 248 db_printf("%llx %llx %llx=sp %llx=pc:", 249 (unsigned long long)f->fr_arg[4], 250 (unsigned long long)f->fr_arg[5], 251 (unsigned long long)f->fr_fp, 252 (unsigned long long)f->fr_pc); 253 /* Sometimes this don't work. Dunno why. */ 254 db_printsym(f->fr_pc, DB_STGY_PROC, db_printf); 255 db_printf("\n"); 256 } else { 257 struct frame64 fr; 258 259 if (copyin(f, &fr, sizeof(fr))) return; 260 f = &fr; 261 db_printf("%llx %llx %llx %llx ", 262 (unsigned long long)f->fr_local[0], (unsigned long long)f->fr_local[1], (unsigned long long)f->fr_local[2], (unsigned long long)f->fr_local[3]); 263 db_printf("%llx %llx %llx %llx\n", 264 (unsigned long long)f->fr_local[4], (unsigned long long)f->fr_local[5], (unsigned long long)f->fr_local[6], (unsigned long long)f->fr_local[7]); 265 db_printf("%llx %llx %llx %llx ", 266 (unsigned long long)f->fr_arg[0], 267 (unsigned long long)f->fr_arg[1], 268 (unsigned long long)f->fr_arg[2], 269 (unsigned long long)f->fr_arg[3]); 270 db_printf("%llx %llx %llx=sp %llx=pc", 271 (unsigned long long)f->fr_arg[4], 272 (unsigned long long)f->fr_arg[5], 273 (unsigned long long)f->fr_fp, 274 (unsigned long long)f->fr_pc); 275 db_printf("\n"); 276 } 277 } else { 278 struct frame32* f = (struct frame32*)(u_long)frame; 279 280 db_printf("frame %p locals, ins:\n", f); 281 if (INKERNEL(f)) { 282 db_printf("%8x %8x %8x %8x %8x %8x %8x %8x\n", 283 f->fr_local[0], f->fr_local[1], f->fr_local[2], f->fr_local[3], 284 f->fr_local[4], f->fr_local[5], f->fr_local[6], f->fr_local[7]); 285 db_printf("%8x %8x %8x %8x %8x %8x %8x=sp %8x=pc:", 286 f->fr_arg[0], f->fr_arg[1], f->fr_arg[2], f->fr_arg[3], 287 f->fr_arg[4], f->fr_arg[5], f->fr_fp, f->fr_pc); 288 db_printsym(f->fr_pc, DB_STGY_PROC, db_printf); 289 db_printf("\n"); 290 } else { 291 struct frame32 fr; 292 293 if (copyin(f, &fr, sizeof(fr))) return; 294 f = &fr; 295 db_printf("%8x %8x %8x %8x %8x %8x %8x %8x\n", 296 f->fr_local[0], f->fr_local[1], 297 f->fr_local[2], f->fr_local[3], 298 f->fr_local[4], f->fr_local[5], 299 f->fr_local[6], f->fr_local[7]); 300 db_printf("%8x %8x %8x %8x %8x %8x %8x=sp %8x=pc\n", 301 f->fr_arg[0], f->fr_arg[1], 302 f->fr_arg[2], f->fr_arg[3], 303 f->fr_arg[4], f->fr_arg[5], 304 f->fr_fp, f->fr_pc); 305 } 306 } 307 } 308 309 #ifdef _KERNEL 310 void 311 db_dump_stack(db_expr_t addr, bool have_addr, db_expr_t count, const char *modif) 312 { 313 int i; 314 uint64_t frame, oldframe; 315 bool kernel_only = true; 316 char c; 317 const char *cp = modif; 318 319 while ((c = *cp++) != 0) 320 if (c == 'u') 321 kernel_only = false; 322 323 if (count == -1) 324 count = 65535; 325 326 if (!have_addr) 327 frame = DDB_TF->tf_out[6]; 328 else 329 frame = addr; 330 331 /* Traverse window stack */ 332 oldframe = 0; 333 for (i=0; i<count && frame; i++) { 334 if (oldframe == frame) { 335 db_printf("WARNING: stack loop at %llx\n", 336 (unsigned long long) frame); 337 break; 338 } 339 oldframe = frame; 340 if (frame & 1) { 341 frame += BIAS; 342 if (!INKERNEL(((struct frame64 *)(u_long)(frame))) 343 && kernel_only) break; 344 db_printf("Window %x ", i); 345 db_print_window(frame - BIAS); 346 if (!INKERNEL(((struct frame64 *)(u_long)(frame)))) 347 copyin(((void *)&((struct frame64 *)(u_long)frame)->fr_fp), &frame, sizeof(frame)); 348 else 349 frame = ((struct frame64 *)(u_long)frame)->fr_fp; 350 } else { 351 uint32_t tmp; 352 if (!INKERNEL(((struct frame32 *)(u_long)frame)) 353 && kernel_only) break; 354 db_printf("Window %x ", i); 355 db_print_window(frame); 356 if (!INKERNEL(((struct frame32 *)(u_long)frame))) { 357 copyin(&((struct frame32 *)(u_long)frame)->fr_fp, &tmp, sizeof(tmp)); 358 frame = (uint64_t)tmp; 359 } else 360 frame = (uint64_t)((struct frame32 *)(u_long)frame)->fr_fp; 361 } 362 } 363 364 } 365 366 367 void 368 db_dump_trap(db_expr_t addr, bool have_addr, db_expr_t count, const char *modif) 369 { 370 struct trapframe64 *tf; 371 372 /* Use our last trapframe? */ 373 tf = DDB_TF; 374 { 375 /* Or the user trapframe? */ 376 register char c; 377 register const char *cp = modif; 378 while ((c = *cp++) != 0) 379 if (c == 'u') 380 tf = curlwp->l_md.md_tf; 381 } 382 /* Or an arbitrary trapframe */ 383 if (have_addr) 384 tf = (struct trapframe64 *)(uintptr_t)addr; 385 386 db_printf("Trapframe %p:\ttstate: %llx\tpc: %llx\tnpc: %llx\n", 387 tf, (unsigned long long)tf->tf_tstate, 388 (unsigned long long)tf->tf_pc, 389 (unsigned long long)tf->tf_npc); 390 db_printf("y: %x\tpil: %d\toldpil: %d\tfault: %llx\ttt: %x\tGlobals:\n", 391 (int)tf->tf_y, (int)tf->tf_pil, (int)tf->tf_oldpil, 392 (unsigned long long)tf->tf_fault, (int)tf->tf_tt); 393 db_printf("%016llx %016llx %016llx %016llx\n", 394 (unsigned long long)tf->tf_global[0], 395 (unsigned long long)tf->tf_global[1], 396 (unsigned long long)tf->tf_global[2], 397 (unsigned long long)tf->tf_global[3]); 398 db_printf("%016llx %016llx %016llx %016llx\nouts:\n", 399 (unsigned long long)tf->tf_global[4], 400 (unsigned long long)tf->tf_global[5], 401 (unsigned long long)tf->tf_global[6], 402 (unsigned long long)tf->tf_global[7]); 403 db_printf("%016llx %016llx %016llx %016llx\n", 404 (unsigned long long)tf->tf_out[0], 405 (unsigned long long)tf->tf_out[1], 406 (unsigned long long)tf->tf_out[2], 407 (unsigned long long)tf->tf_out[3]); 408 db_printf("%016llx %016llx %016llx %016llx\n", 409 (unsigned long long)tf->tf_out[4], 410 (unsigned long long)tf->tf_out[5], 411 (unsigned long long)tf->tf_out[6], 412 (unsigned long long)tf->tf_out[7]); 413 #ifdef DEBUG 414 db_printf("locals:\n%016llx %016llx %016llx %016llx\n", 415 (unsigned long long)tf->tf_local[0], 416 (unsigned long long)tf->tf_local[1], 417 (unsigned long long)tf->tf_local[2], 418 (unsigned long long)tf->tf_local[3]); 419 db_printf("%016llx %016llx %016llx %016llx\nins:\n", 420 (unsigned long long)tf->tf_local[4], 421 (unsigned long long)tf->tf_local[5], 422 (unsigned long long)tf->tf_local[6], 423 (unsigned long long)tf->tf_local[7]); 424 db_printf("%016llx %016llx %016llx %016llx\n", 425 (unsigned long long)tf->tf_in[0], 426 (unsigned long long)tf->tf_in[1], 427 (unsigned long long)tf->tf_in[2], 428 (unsigned long long)tf->tf_in[3]); 429 db_printf("%016llx %016llx %016llx %016llx\n", 430 (unsigned long long)tf->tf_in[4], 431 (unsigned long long)tf->tf_in[5], 432 (unsigned long long)tf->tf_in[6], 433 (unsigned long long)tf->tf_in[7]); 434 #endif 435 #if 0 436 if (tf == curlwp->p_md.md_tf) { 437 struct rwindow32 *kstack = (struct rwindow32 *)(((void *)tf)+CCFSZ); 438 db_printf("ins (from stack):\n%016llx %016llx %016llx %016llx\n", 439 (int64_t)kstack->rw_local[0], (int64_t)kstack->rw_local[1], 440 (int64_t)kstack->rw_local[2], (int64_t)kstack->rw_local[3]); 441 db_printf("%016llx %016llx %016llx %016llx\n", 442 (int64_t)kstack->rw_local[4], (int64_t)kstack->rw_local[5], 443 (int64_t)kstack->rw_local[6], (int64_t)kstack->rw_local[7]); 444 } 445 #endif 446 } 447 448 void 449 db_dump_fpstate(db_expr_t addr, bool have_addr, db_expr_t count, const char *modif) 450 { 451 struct fpstate64 *fpstate; 452 453 /* Use our last trapframe? */ 454 fpstate = DDB_FP; 455 /* Or an arbitrary trapframe */ 456 if (have_addr) 457 fpstate = (struct fpstate64 *)(uintptr_t)addr; 458 459 db_printf("fpstate %p: fsr = %llx gsr = %lx\nfpregs:\n", 460 fpstate, (unsigned long long)fpstate->fs_fsr, 461 (unsigned long)fpstate->fs_gsr); 462 db_printf(" 0: %08x %08x %08x %08x %08x %08x %08x %08x\n", 463 (unsigned int)fpstate->fs_regs[0], 464 (unsigned int)fpstate->fs_regs[1], 465 (unsigned int)fpstate->fs_regs[2], 466 (unsigned int)fpstate->fs_regs[3], 467 (unsigned int)fpstate->fs_regs[4], 468 (unsigned int)fpstate->fs_regs[5], 469 (unsigned int)fpstate->fs_regs[6], 470 (unsigned int)fpstate->fs_regs[7]); 471 db_printf(" 8: %08x %08x %08x %08x %08x %08x %08x %08x\n", 472 (unsigned int)fpstate->fs_regs[8], 473 (unsigned int)fpstate->fs_regs[9], 474 (unsigned int)fpstate->fs_regs[10], 475 (unsigned int)fpstate->fs_regs[11], 476 (unsigned int)fpstate->fs_regs[12], 477 (unsigned int)fpstate->fs_regs[13], 478 (unsigned int)fpstate->fs_regs[14], 479 (unsigned int)fpstate->fs_regs[15]); 480 db_printf("16: %08x %08x %08x %08x %08x %08x %08x %08x\n", 481 (unsigned int)fpstate->fs_regs[16], 482 (unsigned int)fpstate->fs_regs[17], 483 (unsigned int)fpstate->fs_regs[18], 484 (unsigned int)fpstate->fs_regs[19], 485 (unsigned int)fpstate->fs_regs[20], 486 (unsigned int)fpstate->fs_regs[21], 487 (unsigned int)fpstate->fs_regs[22], 488 (unsigned int)fpstate->fs_regs[23]); 489 db_printf("24: %08x %08x %08x %08x %08x %08x %08x %08x\n", 490 (unsigned int)fpstate->fs_regs[24], 491 (unsigned int)fpstate->fs_regs[25], 492 (unsigned int)fpstate->fs_regs[26], 493 (unsigned int)fpstate->fs_regs[27], 494 (unsigned int)fpstate->fs_regs[28], 495 (unsigned int)fpstate->fs_regs[29], 496 (unsigned int)fpstate->fs_regs[30], 497 (unsigned int)fpstate->fs_regs[31]); 498 db_printf("32: %08x%08x %08x%08x %08x%08x %08x%08x\n", 499 (unsigned int)fpstate->fs_regs[32], 500 (unsigned int)fpstate->fs_regs[33], 501 (unsigned int)fpstate->fs_regs[34], 502 (unsigned int)fpstate->fs_regs[35], 503 (unsigned int)fpstate->fs_regs[36], 504 (unsigned int)fpstate->fs_regs[37], 505 (unsigned int)fpstate->fs_regs[38], 506 (unsigned int)fpstate->fs_regs[39]); 507 db_printf("40: %08x%08x %08x%08x %08x%08x %08x%08x\n", 508 (unsigned int)fpstate->fs_regs[40], 509 (unsigned int)fpstate->fs_regs[41], 510 (unsigned int)fpstate->fs_regs[42], 511 (unsigned int)fpstate->fs_regs[43], 512 (unsigned int)fpstate->fs_regs[44], 513 (unsigned int)fpstate->fs_regs[45], 514 (unsigned int)fpstate->fs_regs[46], 515 (unsigned int)fpstate->fs_regs[47]); 516 db_printf("48: %08x%08x %08x%08x %08x%08x %08x%08x\n", 517 (unsigned int)fpstate->fs_regs[48], 518 (unsigned int)fpstate->fs_regs[49], 519 (unsigned int)fpstate->fs_regs[50], 520 (unsigned int)fpstate->fs_regs[51], 521 (unsigned int)fpstate->fs_regs[52], 522 (unsigned int)fpstate->fs_regs[53], 523 (unsigned int)fpstate->fs_regs[54], 524 (unsigned int)fpstate->fs_regs[55]); 525 db_printf("56: %08x%08x %08x%08x %08x%08x %08x%08x\n", 526 (unsigned int)fpstate->fs_regs[56], 527 (unsigned int)fpstate->fs_regs[57], 528 (unsigned int)fpstate->fs_regs[58], 529 (unsigned int)fpstate->fs_regs[59], 530 (unsigned int)fpstate->fs_regs[60], 531 (unsigned int)fpstate->fs_regs[61], 532 (unsigned int)fpstate->fs_regs[62], 533 (unsigned int)fpstate->fs_regs[63]); 534 } 535 536 void 537 db_dump_ts(db_expr_t addr, bool have_addr, db_expr_t count, const char *modif) 538 { 539 struct trapstate *ts; 540 int i, tl; 541 542 /* Use our last trapframe? */ 543 ts = &DDB_REGS->db_ts[0]; 544 tl = DDB_REGS->db_tl; 545 for (i=0; i<tl; i++) { 546 db_printf("%d tt=%lx tstate=%lx tpc=%p tnpc=%p\n", 547 i+1, (long)ts[i].tt, (u_long)ts[i].tstate, 548 (void*)(u_long)ts[i].tpc, (void*)(u_long)ts[i].tnpc); 549 } 550 551 } 552 #endif 553