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