1 /*- 2 * Copyright (c) 1991 The Regents of the University of California. 3 * All rights reserved. 4 * 5 * %sccs.include.proprietary.c% 6 */ 7 8 #ifndef lint 9 static char sccsid[] = "@(#)machdep.c 5.5 (Berkeley) 04/04/91"; 10 #endif /* not lint */ 11 12 /* 13 * adb - miscellaneous machine dependent routines. 14 */ 15 16 #define RLOCALS /* enable alternate $C stack trace */ 17 18 #include "defs.h" 19 #include "bkpt.h" 20 #include <machine/pte.h> 21 #include <machine/frame.h> 22 #include <machine/reg.h> 23 #include <machine/vmparam.h> 24 #include <sys/ptrace.h> 25 #include <sys/vmmac.h> 26 #include <stab.h> 27 28 struct pte *sbr; 29 int slr; 30 struct pcb pcb; 31 int masterpcbb; 32 33 /* 34 * Activation records. 35 */ 36 37 /* 38 * Set up a stack frame based on the registers in the core image 39 * (or in the kernel core file ... not yet!). 40 */ 41 a_init(ap) 42 register struct activation *ap; 43 { 44 45 ap->a_valid = 1; 46 if (kcore) { 47 ap->a_fp = pcb.pcb_fp; 48 ap->a_pc = pcb.pcb_pc; 49 } else { 50 ap->a_fp = u.u_ar0[FP]; 51 ap->a_pc = u.u_ar0[PC]; 52 } 53 } 54 55 /* 56 * Back up one stack frame in the call stack. 57 * ap points to the activation record from the previous frame. 58 * Clear a_valid field if we ran out of frames. 59 */ 60 a_back(ap) 61 register struct activation *ap; 62 { 63 struct frame fr; 64 65 if (adbread(SP_DATA, ap->a_fp - FRAMEOFF, &fr, sizeof fr) != sizeof fr) 66 ap->a_valid = 0; 67 else { 68 ap->a_fp = fr.fr_savfp; 69 ap->a_pc = fr.fr_savpc; 70 if (ap->a_fp == 0) 71 ap->a_valid = 0; 72 } 73 } 74 75 /* 76 * Evaluate a local symbol (N_LSYM or N_PSYM) using the activation 77 * record pointed to by ap. 78 */ 79 addr_t 80 eval_localsym(sp, ap) 81 register struct nlist *sp; 82 struct activation *ap; 83 { 84 85 switch (sp->n_type) { 86 87 case N_LSYM: 88 return (ap->a_fp - sp->n_value); 89 90 case N_PSYM: 91 return (ap->a_fp + sp->n_value); 92 } 93 panic("eval_localsym"); 94 /* NOTREACHED */ 95 } 96 97 98 /* true iff address a is in instruction space */ 99 #define ispace(a) ((a) < txtmap.m1.e) 100 101 /* 102 * Delete a (single) breakpoint. Return 0 on success. 103 */ 104 int 105 clr_bpt(b) 106 struct bkpt *b; 107 { 108 addr_t a = b->loc; 109 110 return (adbwrite(ispace(a) ? SP_INSTR : SP_DATA, a, &b->ins, 1) != 1); 111 } 112 113 /* 114 * Set a (single) breakpoint. Return 0 on success. 115 */ 116 set_bpt(b) 117 struct bkpt *b; 118 { 119 addr_t a = b->loc; 120 int space; 121 char bpt = 0x30; /* breakpoint instruction */ 122 123 space = ispace(a) ? SP_INSTR : SP_DATA; 124 return (adbread(space, a, &b->ins, 1) != 1 || 125 adbwrite(space, a, &bpt, 1) != 1); 126 } 127 128 /* 129 * Check a float for `correctness' (reserved patterns, etc). Return 130 * a pointer to a character string to be printed instead of the float, 131 * or NULL to print the float as-is. 132 * 133 * The string returned, if any, should be no longer than 16 characters. 134 * 135 * On the Tahoe, we can simply check the second two bytes. Byte two 136 * contains one bit of the exponent, and byte 3 has the remaining 7 137 * exponent bits and the sign bit. If the sign bit is set and the 138 * exponent is zero, the value is reserved. 139 * 140 * PLEASE CHECK THE ABOVE, IT IS PROBABLY WRONG 141 */ 142 /* ARGSUSED */ 143 char * 144 checkfloat(fp, isdouble) 145 caddr_t fp; 146 int isdouble; 147 { 148 149 return ((((short *)fp)[1] & 0xff80) == 0x8000 ? 150 "(reserved oprnd)" : NULL); 151 } 152 153 /* 154 * Convert a value in `expr_t' format to float or double. 155 */ 156 etofloat(e, fp, isdouble) 157 expr_t e; 158 caddr_t fp; 159 int isdouble; 160 { 161 162 if (isdouble) 163 ((int *)fp)[1] = 0; 164 *(int *)fp = e; 165 } 166 167 mch_init() 168 { 169 170 mkioptab(); 171 } 172 173 /* quietly read object obj from address addr */ 174 #define GET(obj, addr) (void) adbread(SP_DATA, addr, &(obj), sizeof(obj)) 175 176 /* set `current process' pcb */ 177 setpcb(addr) 178 addr_t addr; 179 { 180 int pte; 181 182 GET(pte, addr); 183 masterpcbb = (pte & PG_PFNUM) * NBPG; 184 } 185 186 getpcb() 187 { 188 189 /* maybe use adbread() here ... */ 190 (void) readcore((off_t)masterpcbb & ~KERNBASE, 191 (char *)&pcb, sizeof(struct pcb)); 192 adbprintf("p0br %R p0lr %R p2br %R p2lr %R\n", 193 pcb.pcb_p0br, pcb.pcb_p0lr, pcb.pcb_p2br, pcb.pcb_p2lr); 194 } 195 196 /* 197 * Convert a kernel virtual address to a physical address, 198 * a la the Tahoe hardware. Set *err if the resulting address 199 * is invalid. 200 */ 201 addr_t 202 vtophys(addr, err) 203 addr_t addr; 204 char **err; 205 { 206 register unsigned v = btop(addr & ~KERNBASE); 207 register addr_t pteaddr; 208 struct pte pte; 209 210 switch ((int)(addr >> 30)) { /* select space */ 211 212 case 3: 213 /* system space: get system pte */ 214 if (v >= slr) 215 goto oor; 216 pteaddr = (addr_t)(sbr + v) & ~KERNBASE; 217 goto direct; 218 219 case 2: 220 /* P2 space: must not be in shadow region */ 221 if (v < pcb.pcb_p2lr) 222 goto oor; 223 pteaddr = (addr_t)(pcb.pcb_p2br + v); 224 break; 225 226 case 1: 227 /* P1 space: verboten (for now) */ 228 goto oor; 229 230 case 0: 231 /* P0 space: must not be off end of region */ 232 if (v >= pcb.pcb_p0lr) 233 goto oor; 234 pteaddr = (addr_t)(pcb.pcb_p0br + v); 235 break; 236 237 oor: 238 *err = "address out of segment"; 239 return (0); 240 } 241 242 /* in P0/P1/P2 space, pte should be in kernel virtual space */ 243 if ((pteaddr & KERNBASE) != KERNBASE) { 244 *err = "bad p0br, p1br, or p2br in pcb"; 245 return (0); 246 } 247 pteaddr = vtophys(pteaddr, err); 248 if (*err) 249 return (0); 250 251 direct: 252 /* 253 * Read system pte. If valid or reclaimable, 254 * physical address is combination of its page number and 255 * the page offset of the original address. 256 */ 257 if (readcore((off_t)pteaddr, (caddr_t)&pte, 4) != 4) { 258 *err = "page table botch"; 259 return (0); 260 } 261 /* SHOULD CHECK NOT I/O ADDRESS; NEED CPU TYPE! */ 262 if (pte.pg_v == 0 && (pte.pg_fod || pte.pg_pfnum == 0)) { 263 *err = "page not valid/reclaimable"; 264 return (0); 265 } 266 return ((addr_t)(ptob(pte.pg_pfnum) + (addr & PGOFSET))); 267 } 268 269 /* 270 * Print a stack trace ($c, $C). Trace backwards through nback 271 * frames; if locals is set, print local variables. 272 */ 273 printstack(locals, nback) 274 int locals, nback; 275 { 276 register int i; 277 register addr_t a; 278 struct nlist *sym; 279 char *s; 280 addr_t callpc; /* pc that called this frame */ 281 int narg; /* number of arguments to this frame */ 282 struct activation cur; /* this frame itself */ 283 struct frame fr; /* the frame above this frame */ 284 addr_t dummy; /* a variable to scribble on */ 285 #define UNKNOWN -1 286 287 #ifdef RLOCALS 288 /* if locals variables are broken, use an alternate strategy */ 289 register int r; 290 addr_t sp, prev_sp; 291 int regs[13]; 292 static char unknown[] = "<unknown>"; 293 #endif 294 295 #ifdef RLOCALS 296 /* grab registers */ 297 bcopy((caddr_t)(kcore ? &pcb.pcb_r0 : &u.u_ar0[R0]), (caddr_t)regs, 298 sizeof(regs)); 299 #endif 300 301 /* set up the current stack frame */ 302 if (gavedot) { 303 cur.a_fp = dot; 304 cur.a_pc = UNKNOWN; 305 #ifdef RLOCALS 306 sp = UNKNOWN; 307 #endif 308 } else if (kcore) { 309 cur.a_fp = pcb.pcb_fp; 310 cur.a_pc = pcb.pcb_pc; 311 #ifdef RLOCALS 312 sp = pcb.pcb_ksp; 313 #endif 314 } else { 315 cur.a_fp = u.u_ar0[FP]; 316 cur.a_pc = u.u_ar0[PC]; 317 #ifdef RLOCALS 318 sp = u.u_ar0[SP]; 319 #endif 320 } 321 322 /* now back up through the stack */ 323 while (nback-- && cur.a_fp != 0) { 324 /* read this frame, but defer error check */ 325 GET(fr, cur.a_fp - FRAMEOFF); 326 327 /* where are we? ... if u. area, signal trampoline code */ 328 if (cur.a_pc >= USRSTACK && cur.a_pc < KERNBASE) { 329 narg = 0; 330 GET(callpc, cur.a_fp + 44); /* XXX magic 44 */ 331 s = "sigtramp"; 332 } else { 333 narg = (fr.fr_removed >> 2) - 1; 334 callpc = fr.fr_savpc; 335 if (cur.a_pc != UNKNOWN && 336 (sym = findsym(cur.a_pc, SP_INSTR, &dummy)) != 0) { 337 s = sym->n_un.n_name; 338 if (eqstr(s, "start")) { 339 errflag = NULL; 340 break; 341 } 342 } else 343 s = "?"; 344 } 345 /* safe at last to check for error reading frame */ 346 checkerr(); 347 348 /* arguments */ 349 adbprintf("%s(", s); 350 a = cur.a_fp; 351 for (i = narg > 20 ? 20 : narg; i;) { 352 prfrom(a += 4, --i ? ',' : 0); 353 checkerr(); 354 } 355 printc(')'); 356 if (cur.a_pc != UNKNOWN) { 357 prints(" at "); 358 psymoff("%R", cur.a_pc, SP_INSTR, -(addr_t)1, ""); 359 } 360 printc('\n'); 361 362 /* local variables */ 363 if (locals) { 364 #ifdef busted 365 if (cur.a_pc != UNKNOWN) { 366 sym = findsym(cur.a_pc, SP_INSTR, &dummy); 367 while ((sym = nextlocal(sym)) != NULL) { 368 adbprintf("%8t"); 369 printlsym(sym->n_un.n_name); 370 adbprintf(":%12t"); 371 prfrom(eval_localsym(sym, &cur), '\n'); 372 } 373 } 374 #endif 375 #ifdef RLOCALS 376 adbprintf("\ 377 fp: %R\%16tsp: %?s%?R%32tpc: %?s%?R%48tr0: %R\n\ 378 r1: %R\%16tr2: %R\%32tr3: %R\%48tr4: %R\n\ 379 r5: %R\%16tr6: %R\%32tr7: %R\%48tr8: %R\n\ 380 r9: %R\%16tr10: %R\%32tr11: %R\%48tr12: %R\n", 381 #define q(s) s == UNKNOWN, unknown, s != UNKNOWN, s 382 cur.a_fp, q(sp), q(cur.a_pc), regs[0], 383 #undef q 384 regs[1], regs[2], regs[3], regs[4], 385 regs[5], regs[6], regs[7], regs[8], 386 regs[9], regs[10], regs[11], regs[12]); 387 388 /* update registers, and find previous frame's sp */ 389 a = cur.a_fp + 4; 390 for (r = 0, i = fr.fr_mask; i != 0; r++, i >>= 1) 391 if (i & 1) 392 GET(regs[r], a += 4); 393 a += narg * 4; 394 prev_sp = a; 395 396 /* now print automatics */ 397 if (sp != UNKNOWN) { 398 #define MAXPRINT 30 /* max # words to print */ 399 /* XXX should be settable */ 400 i = (cur.a_fp - sp) >> 2; 401 if (i > MAXPRINT) 402 i = MAXPRINT; 403 for (a = cur.a_fp; --i >= 0;) { 404 a -= 4; 405 adbprintf("%R: %V(fp):%24t", 406 a, a - cur.a_fp); 407 prfrom(a, '\n'); 408 } 409 if (a > sp) 410 adbprintf("\ 411 %R: %V(fp) .. %R: %V(fp) not displayed\n", 412 a, a - cur.a_fp, 413 sp, sp - cur.a_fp); 414 } 415 #endif /* RLOCALS */ 416 } 417 418 errflag = NULL; /* clobber any read errors */ 419 420 /* back up one frame */ 421 if (fr.fr_savfp == 0) 422 break; 423 cur.a_fp = fr.fr_savfp; 424 #ifdef RLOCALS 425 sp = prev_sp; 426 #endif 427 cur.a_pc = callpc; 428 429 if (!gavedot && !INSTACK(cur.a_fp) && !kcore) 430 break; 431 432 /* make sure we returned somewhere... */ 433 (void) adbread(kcore ? SP_DATA : SP_INSTR, cur.a_pc, &dummy, 1); 434 checkerr(); 435 } 436 } 437 438 /* 439 * Register offset to u. pointer, and register offset to ptrace value 440 */ 441 #define otoua(o) \ 442 ((int *)(((o) < 0 ? (int)u.u_ar0 : (int)&u.u_pcb) + (o))) 443 #define otopt(o) \ 444 ((int *)((o) < 0 ? (o) + ctob(UPAGES) : (o))) 445 446 /* 447 * Return the value of some register. 448 */ 449 expr_t 450 getreg(reg) 451 register struct reglist *reg; 452 { 453 454 return (kcore ? *reg->r_pcbaddr : *otoua(reg->r_offset)); 455 } 456 457 458 /* 459 * Set the value of some register. Return 0 if all goes well. 460 */ 461 setreg(reg, val) 462 register struct reglist *reg; 463 expr_t val; 464 { 465 466 if (kcore) 467 *reg->r_pcbaddr = val; 468 else { 469 *otoua(reg->r_offset) = val; 470 if (pid) { 471 errno = 0; 472 if (ptrace(PT_WRITE_U, pid, otopt(reg->r_offset), 473 (int)val) == -1 && errno) 474 return (-1); 475 } 476 } 477 return (0); 478 } 479 480 /* 481 * Read registers from current process. 482 */ 483 readregs() 484 { 485 register struct reglist *reg; 486 extern struct reglist reglist[]; 487 488 for (reg = reglist; reg->r_name != NULL; reg++) 489 *otoua(reg->r_offset) = 490 ptrace(PT_READ_U, pid, otopt(reg->r_offset), 0); 491 } 492 493 addr_t 494 getpc() 495 { 496 497 return (kcore ? pcb.pcb_pc : u.u_ar0[PC]); 498 } 499 500 setpc(where) 501 addr_t where; 502 { 503 504 if (kcore) 505 pcb.pcb_pc = where; 506 else 507 u.u_ar0[PC] = where; 508 } 509 510 /* 511 * udot returns true if u.u_pcb appears correct. More extensive 512 * checking is possible.... 513 */ 514 udot() 515 { 516 517 /* user stack should be in stack segment */ 518 if (!INSTACK(u.u_pcb.pcb_usp)) 519 return (0); 520 /* kernel stack should be in u. area */ 521 if (u.u_pcb.pcb_ksp < USRSTACK || u.u_pcb.pcb_ksp >= KERNBASE) 522 return (0); 523 /* looks good to us... */ 524 return (1); 525 } 526 527 sigprint() 528 { 529 extern char *sys_siglist[]; 530 extern char *illinames[], *fpenames[]; 531 extern int nillinames, nfpenames; 532 533 if ((u_int)signo - 1 < NSIG - 1) 534 prints(sys_siglist[signo]); 535 switch (signo) { 536 537 case SIGFPE: 538 if ((u_int)sigcode < nfpenames) 539 prints(fpenames[sigcode]); 540 break; 541 542 case SIGILL: 543 if ((u_int)sigcode < nillinames) 544 prints(illinames[sigcode]); 545 break; 546 } 547 } 548