|
|
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.