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