|
|
1.1 ! root 1: /* ! 2: * A debugger. ! 3: * Intel 8086. ! 4: */ ! 5: #include <stdio.h> ! 6: #include <sys/const.h> ! 7: #include <l.out.h> ! 8: #include <signal.h> ! 9: #include <sys/uproc.h> ! 10: #include "trace.h" ! 11: #include "i8086.h" ! 12: ! 13: /* ! 14: * Given an l.out header, set up segmentation for an l.out. ! 15: */ ! 16: setaseg(ldhp) ! 17: register struct ldheader *ldhp; ! 18: { ! 19: register long fbase; ! 20: register long si; ! 21: register long pi; ! 22: register long bi; ! 23: register long sd; ! 24: register long pd; ! 25: register long rs; ! 26: ! 27: fbase = sizeof(*ldhp); ! 28: si = ldhp->l_ssize[L_SHRI]; ! 29: pi = ldhp->l_ssize[L_PRVI]; ! 30: bi = ldhp->l_ssize[L_BSSI]; ! 31: sd = ldhp->l_ssize[L_SHRD]; ! 32: pd = ldhp->l_ssize[L_PRVD]; ! 33: switch (ldhp->l_flag & (LF_SEP|LF_SHR)) { ! 34: case 0: ! 35: endpure = NULL; ! 36: DSPACE = setsmap(NULL, (long)0, si+pi, fbase, ! 37: getf, putf, 0); ! 38: DSPACE = setsmap(DSPACE, si+pi+bi, sd+pd, fbase+si+pi, ! 39: getf, putf, 0); ! 40: ISPACE = DSPACE; ! 41: break; ! 42: ! 43: case LF_SHR: ! 44: endpure = NULL; ! 45: rs = (si+sd+0xF) & ~0xF; ! 46: DSPACE = setsmap(NULL, (long)0, si, fbase, getf, putf, 0); ! 47: DSPACE = setsmap(DSPACE, si, sd, fbase+si+pi, getf, putf, 0); ! 48: DSPACE = setsmap(DSPACE, rs, pi, fbase+si, getf, putf, 0); ! 49: DSPACE = setsmap(DSPACE, rs+pi, pd, fbase+si+pi+sd, ! 50: getf, putf, 0); ! 51: ISPACE = DSPACE; ! 52: break; ! 53: ! 54: case LF_SEP: ! 55: endpure = NULL; ! 56: ISPACE = setsmap(NULL, (long)0, si+pi, fbase, getf, putf, 0); ! 57: DSPACE = setsmap(NULL, (long)0, sd+pd, fbase+si+pi, ! 58: getf, putf, 0); ! 59: break; ! 60: ! 61: case LF_SEP|LF_SHR: ! 62: endpure = NULL; /* No pure data */ ! 63: rs = (sd+0xF) & ~0xF; ! 64: ISPACE = setsmap(NULL, (long)0, si+pi, fbase, getf, putf, 0); ! 65: DSPACE = setsmap(NULL, (long)0, sd, fbase+si+pi, getf, putf, 0); ! 66: DSPACE = setsmap(DSPACE, rs, pd, fbase+si+pi+sd, getf, putf, 0); ! 67: break; ! 68: } ! 69: } ! 70: ! 71: /* ! 72: * Set up segmentation for kernel memory. ! 73: */ ! 74: setkmem(np) ! 75: char *np; ! 76: { ! 77: register fsize_t l; ! 78: unsigned n; ! 79: struct ldsym lds; ! 80: ! 81: cfp = openfil(np, rflag); ! 82: USPACE = setsmap(NULL, (fsize_t)0, (fsize_t)LI, (fsize_t)0, ! 83: getf, putf, 1); ! 84: add = 2; ! 85: if (getb(2, &n, sizeof(n)) == 0) ! 86: panic("Bad memory file"); ! 87: l = (fsize_t)n << 4; ! 88: ISPACE = setsmap(NULL, (fsize_t)0, (fsize_t)LI, (fsize_t)l, ! 89: getf, putf, 1); ! 90: strncpy(lds.ls_id, "etext_", NCPLN); ! 91: if (nameval(&lds) == 0) ! 92: DSPACE = ISPACE; ! 93: else { ! 94: n = (lds.ls_addr+0xF) & ~0xF; ! 95: DSPACE = setsmap(NULL, (fsize_t)0, (fsize_t)LI, (fsize_t)l+n, ! 96: getf, putf, 1); ! 97: } ! 98: } ! 99: ! 100: /* ! 101: * Set up segmentation for a system dump. ! 102: */ ! 103: setdump(np) ! 104: char *np; ! 105: { ! 106: setkmem(np); ! 107: } ! 108: ! 109: /* ! 110: * Update register structure in memory. ! 111: */ ! 112: setregs() ! 113: { ! 114: struct ureg ureg; ! 115: ! 116: regflag = 0; ! 117: add = UREGOFF; ! 118: if (getb(2, (char *)&ureg, sizeof(ureg)) == 0) { ! 119: printr("Cannot read registers"); ! 120: return (0); ! 121: } ! 122: copyreg(&ureg); ! 123: regflag = 1; ! 124: return (1); ! 125: } ! 126: ! 127: /* ! 128: * Copy registers from the User area structure to the register ! 129: * structure. ! 130: */ ! 131: copyreg(up) ! 132: register struct ureg *up; ! 133: { ! 134: reg.r_ax = up->ur_ax; ! 135: reg.r_bx = up->ur_bx; ! 136: reg.r_cx = up->ur_cx; ! 137: reg.r_dx = up->ur_dx; ! 138: reg.r_sp = up->ur_sp; ! 139: reg.r_bp = up->ur_bp; ! 140: reg.r_si = up->ur_si; ! 141: reg.r_di = up->ur_di; ! 142: reg.r_cs = up->ur_cs; ! 143: reg.r_ds = up->ur_ds; ! 144: reg.r_ss = up->ur_ss; ! 145: reg.r_es = up->ur_es; ! 146: reg.r_ip = up->ur_ip; ! 147: reg.r_fw = up->ur_fw; ! 148: } ! 149: ! 150: /* ! 151: * If the given name matches a register, set up `ldp' with the address ! 152: * of a registers in the user area. ! 153: */ ! 154: regaddr(ldp) ! 155: struct ldsym *ldp; ! 156: { ! 157: register char *cp; ! 158: register int c0; ! 159: register int c1; ! 160: register int a; ! 161: ! 162: a = UPASIZE - sizeof(struct ureg); ! 163: cp = ldp->ls_id; ! 164: if ((c0=*cp++) == '\0') ! 165: return (0); ! 166: if ((c1=*cp++) == '\0') ! 167: return (0); ! 168: if (*cp != '\0') ! 169: return (0); ! 170: switch (c1) { ! 171: case 'h': ! 172: a++; ! 173: case 'l': ! 174: c1 = 'x'; ! 175: } ! 176: cp = regitab; ! 177: do { ! 178: if (cp[0]==c0 && cp[1]==c1) { ! 179: ldp->ls_addr = a; ! 180: ldp->ls_type = L_REG; ! 181: return (1); ! 182: } ! 183: a += 2; ! 184: cp += 2; ! 185: } while (*cp != '\0'); ! 186: return (0); ! 187: } ! 188: ! 189: /* ! 190: * Return the programme counter. ! 191: */ ! 192: vaddr_t ! 193: getpc() ! 194: { ! 195: return (reg.r_ip); ! 196: } ! 197: ! 198: /* ! 199: * Set the programme counter. ! 200: */ ! 201: setpc(ip) ! 202: vaddr_t ip; ! 203: { ! 204: reg.r_ip = ip; ! 205: add = UREGOFF + offset(ureg, ur_ip); ! 206: putb(2, (char *)®.r_ip, sizeof(reg.r_ip)); ! 207: } ! 208: ! 209: /* ! 210: * Return the frame pointer. ! 211: */ ! 212: vaddr_t ! 213: getfp() ! 214: { ! 215: return (reg.r_bp); ! 216: } ! 217: ! 218: /* ! 219: * Display registers. ! 220: */ ! 221: dispreg() ! 222: { ! 223: if (testint()) ! 224: return; ! 225: printf("ip=%04x fw=%04x\n", reg.r_ip, reg.r_fw); ! 226: ! 227: if (testint()) ! 228: return; ! 229: printf("ax=%04x bx=%04x cx=%04x dx=%04x\n", ! 230: reg.r_ax, reg.r_bx, reg.r_cx, reg.r_dx); ! 231: ! 232: if (testint()) ! 233: return; ! 234: printf("sp=%04x bp=%04x si=%04x di=%04x\n", ! 235: reg.r_sp, reg.r_bp, reg.r_si, reg.r_di); ! 236: ! 237: if (testint()) ! 238: return; ! 239: printf("cs=%04x ds=%04x ss=%04x es=%04x\n", ! 240: reg.r_cs, reg.r_ds, reg.r_ss, reg.r_es); ! 241: } ! 242: ! 243: /* ! 244: * Stack traceback. ! 245: */ ! 246: dispsbt(l) ! 247: { ! 248: int sdbase = dbase; ! 249: register int argc; ! 250: register int iflag; ! 251: register int sflag; ! 252: register int qflag; ! 253: unsigned amain; ! 254: unsigned rpc; ! 255: unsigned pc; ! 256: unsigned fp; ! 257: unsigned n; ! 258: unsigned char e[1]; ! 259: unsigned char b[3]; ! 260: struct ldsym ldsym; ! 261: ! 262: dbase = 16; ! 263: amain = 1; ! 264: strcpy(ldsym.ls_id, "main_"); ! 265: if (nameval(&ldsym) != 0) ! 266: amain = ldsym.ls_addr; ! 267: add = reg.r_ip; ! 268: if (getb(1, b, 1) == 0) { ! 269: printe("Illegal ip"); ! 270: goto done; ! 271: } ! 272: sflag = 0; ! 273: fp = reg.r_bp; ! 274: e[0] = 0x56; /* push si */ ! 275: if (valname(1, (vaddr_t)reg.r_ip, &ldsym) != 0) { ! 276: add = (long)ldsym.ls_addr; ! 277: getb(1, (char *)e, 1); ! 278: } ! 279: if (b[0]==0x56 || e[0]!=0x56) { /* push si */ ! 280: sflag = 1; ! 281: fp = reg.r_sp - 6; ! 282: } ! 283: pc = reg.r_ip; ! 284: qflag = 0; ! 285: for (;;) { ! 286: add = fp + 6; ! 287: if (getb(0, &rpc, 2) == 0) ! 288: break; ! 289: argc = 0; ! 290: add = rpc; ! 291: if (getb(1, b, 3) != 0) { ! 292: if (b[0]==0x83 && b[1]==0xC4) /* add sp,$? */ ! 293: argc = b[2]/2; ! 294: } ! 295: add = rpc - 3; ! 296: if (getb(1, b, 1) == 0) ! 297: break; ! 298: if (getb(1, &n, sizeof(n)) == 0) ! 299: break; ! 300: printx(DAFMT, (long)fp); ! 301: printx(" "); ! 302: printx(DAFMT, (long)pc); ! 303: printx(" "); ! 304: if (b[0] == 0xE8) { /* call ? */ ! 305: n += rpc; ! 306: putaddr(1, (long)n, I); ! 307: if (n == amain) { ! 308: qflag = 1; ! 309: argc = 3; ! 310: } ! 311: } else { ! 312: if (valname(1, (vaddr_t)pc, &ldsym) == 0) ! 313: printx("*"); ! 314: else { ! 315: printx("%.*s", NCPLN, ldsym.ls_id); ! 316: if (strcmp(ldsym.ls_id, "main_") == 0) { ! 317: qflag = 1; ! 318: argc = 3; ! 319: } ! 320: } ! 321: } ! 322: putx('('); ! 323: iflag = 0; ! 324: add = fp + 8; ! 325: while (argc--) { ! 326: if (getb(0, &n, 2) == 0) ! 327: break; ! 328: if (iflag++ != 0) ! 329: printx(", "); ! 330: putaddr(1, (long)n, -1); ! 331: } ! 332: printx(")\n"); ! 333: if (testint()) ! 334: goto done; ! 335: if (qflag) ! 336: break; ! 337: if (sflag) { ! 338: sflag = 0; ! 339: fp = reg.r_bp; ! 340: } else { ! 341: add = fp; ! 342: if (getb(0, &fp, sizeof(fp)) == 0) ! 343: break; ! 344: } ! 345: if (--l == 0) ! 346: goto done; ! 347: pc = rpc; ! 348: } ! 349: done: dbase = sdbase; ! 350: } ! 351: ! 352: /* ! 353: * Get the return pc and frame pointer to set a return breakpoint. ! 354: */ ! 355: setretf(pcp, fpp) ! 356: register vaddr_t *pcp; ! 357: register vaddr_t *fpp; ! 358: { ! 359: char b[1]; ! 360: ! 361: add = reg.r_ip; ! 362: if (getb(0, b, sizeof(b)) == 0) ! 363: return (0); ! 364: if (b[0] == 0x56) { /* push si */ ! 365: *fpp = reg.r_bp; ! 366: add = reg.r_sp; ! 367: } else { ! 368: add = reg.r_bp; ! 369: if (getb(0, (char *)fpp, sizeof(*fpp)) == 0) ! 370: return (0); ! 371: add = reg.r_bp + 6; ! 372: } ! 373: if (getb(0, (char *)pcp, sizeof(*pcp)) == 0) ! 374: return (0); ! 375: } ! 376: ! 377: /* ! 378: * Initialise after getting a trap. ! 379: */ ! 380: trapint() ! 381: { ! 382: vaddr_t pc; ! 383: vaddr_t fw; ! 384: ! 385: cacsegn = -1; ! 386: add = UREGOFF + offset(ureg, ur_fw); ! 387: if (getb(2, (char *)&fw, sizeof(fw)) == 0) { ! 388: printr("Cannot get fw"); ! 389: return (0); ! 390: } ! 391: fw &= ~TBIT; ! 392: add = UREGOFF + offset(ureg, ur_fw); ! 393: if (putb(2, (char *)&fw, sizeof(fw)) == 0) { ! 394: printr("Cannot set fw"); ! 395: return (0); ! 396: } ! 397: if (sysflag) { ! 398: add = UREGOFF + offset(ureg, ur_ip); ! 399: if (getb(2, (char *)&pc, sizeof(pc)) == 0) { ! 400: printr("Cannot get pc"); ! 401: return (0); ! 402: } ! 403: pc -= 2; ! 404: add = UREGOFF + offset(ureg, ur_ip); ! 405: if (putb(2, (char *)&pc, sizeof(pc)) == 0) { ! 406: printr("Cannot set pc"); ! 407: return (0); ! 408: } ! 409: add = (long)pc; ! 410: if (putb(1, (char *)sin, sizeof(sin)) == 0) { ! 411: printr("Cannot set sin"); ! 412: return (0); ! 413: } ! 414: bitflag = 1; ! 415: } ! 416: return (1); ! 417: } ! 418: ! 419: /* ! 420: * Set up before returning from a trap. Single stepping over a system ! 421: * call is handled here. ! 422: */ ! 423: restret() ! 424: { ! 425: char w[1]; ! 426: ! 427: sysflag = 0; ! 428: if (bitflag == 0) ! 429: return (1); ! 430: add = reg.r_ip; ! 431: if (getb(1, (char *)w, sizeof(w)) == 0) ! 432: return (1); ! 433: if (w[0] != 0xCD) /* Interrupt (system call) */ ! 434: return (1); ! 435: add = reg.r_ip + 2; ! 436: if (getb(1, (char *)sin, sizeof(sin)) == 0) { ! 437: printr("Cannot get breakpoint"); ! 438: return (0); ! 439: } ! 440: add -= sizeof(sin); ! 441: if (putb(1, (char *)bin, sizeof(bin)) == 0) { ! 442: printr("Cannot set breakpoint"); ! 443: return (0); ! 444: } ! 445: bitflag = 0; ! 446: sysflag = 1; ! 447: return (1); ! 448: } ! 449: ! 450: /* ! 451: * Set up breakpoint for single step continue. ! 452: */ ! 453: setcont() ! 454: { ! 455: char w[2]; ! 456: ! 457: add = reg.r_ip; ! 458: if (getb(1, (char *)w, sizeof(w)) == 0) ! 459: return; ! 460: if (w[0] == 0xE8) /* Direct call */ ! 461: sinmode = SCSET; ! 462: if (w[0]==0xFF && (w[1]&0x38)==0x10) /* Indirect call */ ! 463: sinmode = SCSET; ! 464: } ! 465: ! 466: /* ! 467: * Continue after initial break in single step continue. ! 468: */ ! 469: intcont() ! 470: { ! 471: unsigned a; ! 472: ! 473: add = reg.r_sp; ! 474: if (getb(0, (char *)&a, sizeof(a))) ! 475: setibpt(BSIN, a, reg.r_bp, NULL); ! 476: } ! 477: ! 478: /* ! 479: * See if the given instruction is a breakpoint. ! 480: */ ! 481: testbpt(pc) ! 482: { ! 483: char w[1]; ! 484: ! 485: add = pc; ! 486: return (getb(1, (char *)w, sizeof(w))!=0 && w==0xCC); ! 487: } ! 488: ! 489: /* ! 490: * Read `n' characters into the buffer `bp' starting at address `a' ! 491: * from the traced process. ! 492: */ ! 493: getp(f, la, bp, n) ! 494: long la; ! 495: register char *bp; ! 496: register int n; ! 497: { ! 498: register unsigned a; ! 499: ! 500: a = la; ! 501: if (a != la) ! 502: return (0); ! 503: while (n--) { ! 504: if (getq(f, a++, bp++) == 0) ! 505: return (0); ! 506: } ! 507: return (1); ! 508: } ! 509: ! 510: /* ! 511: * Write `n' characters from the buffer `bp' starting at address `a' in ! 512: * the traced process. ! 513: */ ! 514: putp(f, la, bp, n) ! 515: long la; ! 516: register char *bp; ! 517: register int n; ! 518: { ! 519: extern int errno; ! 520: int d; ! 521: register unsigned a; ! 522: ! 523: a = la; ! 524: if (a != la) ! 525: return (0); ! 526: cacsegn = -1; ! 527: if (n!=0 && (a&1)!=0) { ! 528: if (getq(f, --a, (char *)&d) == 0) ! 529: return (0); ! 530: ((char *)&d)[1] = *bp++; ! 531: ptrace(4+f, pid, (int *) a, d); ! 532: if (errno) ! 533: return (0); ! 534: a += 2; ! 535: --n; ! 536: } ! 537: while (n > 1) { ! 538: ((char *)&d)[0] = *bp++; ! 539: ((char *)&d)[1] = *bp++; ! 540: ptrace(4+f, pid, (int *) a, d); ! 541: if (errno) ! 542: return (0); ! 543: a += 2; ! 544: n -= 2; ! 545: } ! 546: if (n) { ! 547: ((char *)&d)[0] = *bp++; ! 548: if (getq(f, a+1, &((char *)&d)[1]) == 0) ! 549: return (0); ! 550: ptrace(4+f, pid, (int *)a, d); ! 551: if (errno) ! 552: return (0); ! 553: } ! 554: return (1); ! 555: } ! 556: ! 557: /* ! 558: * Return the byte at address `a' in segment `f' indirectly through ! 559: * the byte pointer `bp'. ! 560: */ ! 561: getq(f, a, bp) ! 562: register int a; ! 563: register char *bp; ! 564: { ! 565: extern int errno; ! 566: register int w; ! 567: ! 568: if ((w=(a&~1))!=cacaddr || f!=cacsegn) { ! 569: errno = 0; ! 570: cacdata = ptrace(1+f, pid, (int *) w, 0); ! 571: if (errno) { ! 572: cacsegn = -1; ! 573: return (0); ! 574: } ! 575: cacsegn = f; ! 576: cacaddr = w; ! 577: } ! 578: *bp = ((char *)&cacdata)[a&1]; ! 579: return (1); ! 580: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.