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