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