This is debug.c in view mode; [Download] [Up]
/* This is file DEBUG.C */ /* ** Copyright (C) 1993 DJ Delorie, 24 Kirsten Ave, Rochester NH 03867-2954 ** ** This file is distributed under the terms listed in the document ** "copying.dj", available from DJ Delorie at the address above. ** A copy of "copying.dj" should accompany this file; if not, a copy ** should be available from where this file was obtained. This file ** may not be distributed without a verbatim copy of "copying.dj". ** ** This file is distributed WITHOUT ANY WARRANTY; without even the implied ** warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. */ #include <stdio.h> #include <setjmp.h> #include <math.h> #include "ed.h" #include "unassmbl.h" #include "syms.h" typedef struct { word16 sig0; word16 sig1; word16 sig2; word16 sig3; word16 exponent:15; word16 sign:1; } NPXREG; typedef struct { word32 control; word32 status; word32 tag; word32 eip; word32 cs; word32 dataptr; word32 datasel; NPXREG reg[8]; } NPX; static char char32spc[] = "xxxúxxxúxxxúxxxùxxxúxxxúxxxúxxx "; static char flset[] = "VMRF NT OFDNIETFMIZR AC PE CY"; static char floff[] = " UPID PLNZ PO NC"; static char fluse[] = {1,1,0,1,0,0,1,1,1,1,1,1,0,1,0,1,0,1}; static NPX npx; void save_npx(void) { asm( "\n\ inb $0xa0,%al \n\ testb $0x20,%al \n\ jz Lfclex_done \n\ xorl %eax,%eax \n\ outb %al,$0xf0 \n\ movb $0x20,%al \n\ outb %al,$0xa0 \n\ outb %al,$0x20 \n\ Lfclex_done: \n\ movl $_npx, %eax \n\ fnsave (%eax) \n\ fwait " ); } void load_npx(void) { asm( "\n\ movl $_npx, %eax \n\ movb $0,4(%eax) /* clear pending exceptions */ \n\ frstor (%eax) " ); } void tssprint(TSS *t) { int i; printf("eax=%08lx ebx=%08lx ecx=%08lx edx=%08lx\n", t->tss_eax, t->tss_ebx, t->tss_ecx, t->tss_edx); printf("esi=%08lx edi=%08lx ebp=%08lx ", t->tss_esi, t->tss_edi, t->tss_ebp); for (i=0; i<18; i++) if (fluse[i]) if (t->tss_eflags & (1<<(17-i))) printf(" %2.2s", flset+i*2); else printf(" %2.2s", floff+i*2); printf("\nds=%04x es=%04x fs=%04x gs=%04x ss:esp=%04x:%08lx cs=%04x\n", t->tss_ds, t->tss_es, t->tss_fs, t->tss_gs, t->tss_ss, t->tss_esp, t->tss_cs); } my_getline(char *buf, char *lasttoken) { int idx, i, ch, erase_it=1; unsigned char old_enable; ansi(A_green); printf(">>"); ansi(A_green | A_bold); printf(" %s", lasttoken); for (i=0; lasttoken[i]; i++) putchar(8); ansi(A_white); fflush(stdout); idx = 0; while (1) { ch = getkey(); if (erase_it) { for (i=0; lasttoken[i]; i++) putchar(' '); for (i=0; lasttoken[i]; i++) putchar(8); } switch (ch) { case 10: case 13: buf[idx] = 0; if (!idx && lasttoken[0]) printf("\r \r"); else putchar('\n'); ansi(A_grey); fflush(stdout); return; case 27: case 21: while (idx) { printf("\b \b"); idx--; } fflush(stdout); break; case 8: if (idx) { printf("\b \b"); fflush(stdout); idx--; } break; default: putchar(ch); fflush(stdout); buf[idx++] = ch; break; } } } typedef enum { Zero, Unknown, CONT, STEP, NEXT, REGS, SET, HELP, LIST, DUMP, PRINT, QUIT, BREAK, STATUS, WHERE, DUMP_A, DUMP_B, DUMP_W, WHEREIS, XNPX, CLS } COMMAND_TYPES; extern struct { char *name; int size; int ofs; } regs[]; typedef struct { char *cp; int t; } item; item cmds[] = { "g", CONT, "go", CONT, "cont", CONT, "c", CONT, "step", STEP, "s", STEP, "next", NEXT, "n", NEXT, "regs", REGS, "r", REGS, "set", SET, "help", HELP, "h", HELP, "?", HELP, "list", LIST, "l", LIST, "u", LIST, "dump", DUMP, "d", DUMP, "da", DUMP_A, "db", DUMP_B, "dw", DUMP_W, "dd", DUMP, "p", PRINT, "print", PRINT, "quit", QUIT, "q", QUIT, "break", BREAK, "b", BREAK, "bl", STATUS, "status", STATUS, "where", WHERE, "whereis", WHEREIS, "npx", XNPX, "cls", CLS, 0, 0 }; #define dr0 edi.dr[0] #define dr1 edi.dr[1] #define dr2 edi.dr[2] #define dr3 edi.dr[3] #define dr4 edi.dr[4] #define dr5 edi.dr[5] #define dr6 edi.dr[6] #define dr7 edi.dr[7] int can_longjmp = 0; jmp_buf debugger_jmpbuf; int do_where(word32 vaddr) { int i; int32 delta; char *name; printf("0x%08lx %s", vaddr, syms_val2name(vaddr, &delta)); name = syms_val2line(vaddr, &i, 0); if (name) printf(", line %d in file %s", i, name); else if (delta) printf("%+ld", delta); putchar('\n'); return delta; } debugger(void) { char buf[140], token[10]; char buf2[140], *name, lasttoken[140]; int i, n, s, len, rem_cmd, cmd, vstep, found; word32 vaddr, v, rem_v, olddr7; int32 delta; dr0 = dr1 = dr2 = edi.app_base; dr3 = syms_name2val("_main") + edi.app_base; if (undefined_symbol) dr3 = a_tss.tss_eip + edi.app_base; can_longjmp = 1; setjmp(debugger_jmpbuf); rem_cmd = Zero; lasttoken[0] = 0; while (1) { int found; undefined_symbol = 0; my_getline(buf, lasttoken); token[0] = 0; if (sscanf(buf, "%s %[^\n]", token, buf) < 2) buf[0] = 0; if (token[0]) strcpy(lasttoken, token); cmd = rem_cmd; found = 0; for (i=0; cmds[i].cp; i++) if (strcmp(cmds[i].cp, token) == 0) { cmd = cmds[i].t; found = 1; } if (!found && token[0]) cmd = Unknown; if (rem_cmd != cmd) vaddr = a_tss.tss_eip; switch (cmd) { case HELP: printf("Commands:\n"); printf("go <v>\tg\tgo, stop at <v>\n"); printf("cont\tc\tcontinue execution\n"); printf("step\ts\tstep through current instruction\n"); printf("next\tn\tstep to next instruction\n"); printf("list\tl u\tlist instructions (takes addr, count)\n"); printf("dump\td\tdump memory (takes addr, count)\n"); printf("print\tp\tprint value of expression (takes expr)\n"); printf("break\tb\tset breakpoint (takes which, addr)\n"); printf("status\t\tbreakpoint status\n"); printf("regs\tr\tprint registers\n"); printf("set\t\tset register/memory\n"); printf("npx\t\tdisplay 80387 contents\n"); printf("where\t\tdisplay list of active functions\n"); printf("whereis\t\tfind a symbol/location (takes wildcard or value)\n"); printf("cls\t\tclear screen\n"); printf("help\th,?\tprint help\n"); printf("quit\tq\tquit\n"); break; case CONT: sscanf(buf, "%s", buf); if (buf[0]) { v = syms_name2val(buf); if (undefined_symbol) break; dr3 = v + edi.app_base; dr7 |= 0xc0; } else dr7 &= ~0xc0; olddr7 = dr7; dr7 = 0; a_tss.tss_eflags |= 0x0100; run_child(); dr7 = olddr7; if (a_tss.tss_irqn == 1) { a_tss.tss_eflags &= ~0x0100; a_tss.tss_eflags |= 0x10000; run_child(); if (a_tss.tss_irqn == 1) tssprint(&a_tss); } print_reason(); dr3 = unassemble(a_tss.tss_eip, 1) + edi.app_base; break; case STEP: if (rem_cmd != cmd) n = 1; sscanf(buf, "%d", &n); a_tss.tss_eflags |= 0x0100; for (i=0; i<n; i++) { int q; olddr7 = dr7; dr7 = 0; run_child(); dr7 = olddr7; q = print_reason(); dr3 = unassemble(a_tss.tss_eip, 1) + edi.app_base; if ((a_tss.tss_irqn != 1) || q) break; } a_tss.tss_eflags &= ~0x0100; break; case NEXT: if (rem_cmd != cmd) n = 1; sscanf(buf, "%d", &n); for (i=0; i<n; i++) { olddr7 = dr7; dr7 &= ~0xc0; dr7 |= 0xc0; if (last_unassemble_unconditional || last_unassemble_jump) a_tss.tss_eflags |= 0x0100; /* step */ else a_tss.tss_eflags &= ~0x0100; run_child(); dr7 = olddr7; print_reason(); dr3 = unassemble(a_tss.tss_eip, 1) + edi.app_base; if (a_tss.tss_irqn != 1) break; } a_tss.tss_eflags &= ~0x0100; break; case WHERE: lasttoken[0] = 0; v = a_tss.tss_ebp; vaddr = a_tss.tss_eip; delta = do_where(vaddr); if (delta == 0) /* try to find out where we just came from */ { read_child(a_tss.tss_esp, &rem_v, 4); if (rem_v) do_where(rem_v); } do { if (v == 0) break; if (read_child(v, &rem_v, 4)) break; if (rem_v == 0) break; if (read_child(v+4, &vaddr, 4)) break; do_where(vaddr); v = rem_v; } while ((v>=a_tss.tss_esp) && (v<0x80000000L)); break; case WHEREIS: lasttoken[0] = 0; sscanf(buf, "%s", buf2); if (strpbrk(buf2, "*?")) { syms_listwild(buf2); break; } if (buf2[0]) vaddr = syms_name2val(buf2); if (undefined_symbol) break; name = syms_val2name(vaddr, &delta); printf("0x%08lx %s", vaddr, name); if (delta) printf("+%lx", delta); name = syms_val2line(vaddr, &i, 0); if (name) printf(", line %d in file %s", i, name); putchar('\n'); break; case LIST: if (rem_cmd != cmd) n = 10; buf2[0] = 0; sscanf(buf, "%s %d", buf2, &n); if (buf2[0] && strcmp(buf2, ".")) vaddr = syms_name2val(buf2); if (undefined_symbol) break; for (i=0; i<n; i++) { vaddr = unassemble(vaddr, 0); i += last_unassemble_extra_lines; } break; case DUMP_A: buf2[0] = 0; sscanf(buf, "%s %d", buf2, &n); if (buf2[0]) vaddr = syms_name2val(buf2); if (undefined_symbol) break; while (1) { word8 ch; if (vaddr == 0) { printf("<bad address>\n"); break; } if (read_child(vaddr, &ch, 1)) break; if (ch == 0) { putchar('\n'); break; } if (ch < ' ') printf("^%c", ch+'@'); else if ((ch >= ' ') && (ch < 0x7f)) putchar(ch); else if (ch == 0x7f) printf("^?"); else if ((ch >= 0x80) && (ch < 0xa0)) printf("M-^%c", ch-0x80+'@'); else if (ch >= 0xa0) printf("M-%c", ch-0x80); vaddr++; } break; case DUMP: case DUMP_B: case DUMP_W: if (rem_cmd != cmd) n = 4; buf2[0] = 0; sscanf(buf, "%s %d", buf2, &n); if (buf2[0]) vaddr = syms_name2val(buf2); if (undefined_symbol) { printf("undefined symbol\n"); break; } s = 0; len = n + (~((vaddr&15)/4-1) & 3); for (i=-((vaddr&15)/4); i<len; i++) { if ((s&3) == 0) printf("0x%08lx:", vaddr+i*4); if ((i>=0) && (i<n)) { word32 v; if (read_child(vaddr+i*4, &v, 4)) break; printf(" 0x%08lx", v); } else printf(" "); if ((s & 3) == 3) { int j, c; printf(" "); for (j=0; j<16; j++) if ((j+i*4-12>=0) && (j+i*4-12 < n*4)) { if (read_child(vaddr+j+i*4-12, &c, 1)) break; if (c<' ') putchar('.'); else putchar(c); } else putchar(' '); printf("\n"); } s++; } if (s & 3) printf("\n"); vaddr += n*4; break; case PRINT: lasttoken[0] = 0; sscanf(buf, "%s", buf2); if (buf2[0]) vaddr = syms_name2val(buf2); if (undefined_symbol) break; name = syms_val2name(vaddr, &delta); printf("0x%08lx %ld", vaddr, (long)vaddr); for (i=31; i>=0; i--) { if (char32spc[i] != 'x') putchar(char32spc[i]); printf("%d", (int)((vaddr>>i)&1)); } printf("\n"); break; case BREAK: vaddr = n = 0; buf2[0] = 0; sscanf(buf, "%d %s", &n, buf2); if (buf2[0]) vaddr = syms_name2val(buf2); if (undefined_symbol) break; edi.dr[n] = vaddr + edi.app_base; if (vaddr == 0) dr7 &= ~(2 << (n*2)); else dr7 |= 2 << (n*2); case STATUS: s = 0; for (n=0; n<4; n++) { s = 1; name = syms_val2name(edi.dr[n] - edi.app_base, &delta); printf(" dr%d %s", n, name); if (delta) printf("+%#lx", delta); if (name[0] != '0') printf(" (0x%lx)", edi.dr[n] - edi.app_base); if (!(dr7 & (3 << (n*2)))) printf(" (disabled)"); putchar('\n'); } if (s == 0) printf(" No breakpoints set\n"); break; case REGS: tssprint(&a_tss); unassemble(a_tss.tss_eip, 0); break; case SET: cmd = Zero; lasttoken[0] = 0; buf2[0] = 0; len = sscanf(buf, "%s %s", buf2, buf); if (buf2[0] == 0) { break; } if (len > 1) { v = syms_name2val(buf); if (undefined_symbol) break; } found = 0; for (i=0; regs[i].name; i++) if (strcmp(regs[i].name, buf2) == 0) { TSS *tss_ptr = &a_tss; found = 1; if (len > 1) { switch (regs[i].size) { case 1: *(word8 *)((word8 *)tss_ptr + regs[i].ofs) = v; break; case 2: *(word16 *)((word8 *)tss_ptr + regs[i].ofs) = v; break; case 4: *(word32 *)((word8 *)tss_ptr + regs[i].ofs) = v; break; } } else { switch (regs[i].size) { case 1: printf("%02x ", *(word8 *)((word8 *)tss_ptr + regs[i].ofs)); my_getline(buf, ""); if (buf[0]) { v = syms_name2val(buf); if (undefined_symbol) break; *(word8 *)((word8 *)tss_ptr + regs[i].ofs) = v; } break; case 2: printf("%04x ", *(word16 *)((word16 *)tss_ptr + regs[i].ofs)); my_getline(buf, ""); if (buf[0]) { v = syms_name2val(buf); if (undefined_symbol) break; *(word16 *)((word16 *)tss_ptr + regs[i].ofs) = v; } break; case 4: printf("%08lx ", *(word32 *)((word32 *)tss_ptr + regs[i].ofs)); my_getline(buf, ""); if (buf[0]) { v = syms_name2val(buf); if (undefined_symbol) break; *(word32 *)((word32 *)tss_ptr + regs[i].ofs) = v; } break; } } break; } if (found) break; vaddr = syms_name2val(buf2); if (undefined_symbol) break; if (len < 2) { v = syms_name2val(buf); if (undefined_symbol) break; write_child(vaddr, &v, 4); } while (1) { word32 vv; if (read_child(vaddr, &vv,4)) break; printf("0x%08lx 0x%08lx", vaddr, vv); my_getline(buf, ""); if (buf[0]) { word32 vv; if (strcmp(buf, ".") == 0) break; vv = syms_name2val(buf); if (write_child(vaddr, &vv, 4)) break; } vaddr += 4; } break; case XNPX: save_npx(); printf("Control: 0x%04lx Status: 0x%04lx Tag: 0x%04lx\n", npx.control & 0xffff, npx.status & 0xffff, npx.tag & 0xffff); for (i=0; i<8; i++) { double d; int tag; int tos = (npx.status >> 11) & 7; printf("st(%d) ", i); if (npx.reg[i].sign) putchar('-'); else putchar('+'); printf(" %04x %04x %04x %04x e %04x ", npx.reg[i].sig3, npx.reg[i].sig2, npx.reg[i].sig1, npx.reg[i].sig0, npx.reg[i].exponent); tag = (npx.tag >> (((i+tos)%8)*2)) & 3; switch (tag) { case 0: printf("Valid"); if (((int)npx.reg[i].exponent-16382 < 1000) && ((int)npx.reg[i].exponent-16382 > -1000)) { d = npx.reg[i].sig3/65536.0 + npx.reg[i].sig2/65536.0/65536.0 + npx.reg[i].sig1/65536.0/65536.0/65536.0; d = ldexp(d,(int)npx.reg[i].exponent-16382); if (npx.reg[i].sign) d = -d; printf(" %.16g", d); } else printf(" (too big to display)"); putchar('\n'); break; case 1: printf("Zero\n"); break; case 2: printf("Special\n"); break; case 3: printf("Empty\n"); break; } } load_npx(); break; case QUIT: return; case Zero: break; case CLS: asm volatile("pusha; movb $15,%ah; int $0x10; movb $0,%ah; int $0x10; popa"); break; default: printf("Unknown command\n"); lasttoken[0] = 0; cmd = Zero; break; } if (undefined_symbol) { lasttoken[0] = 0; cmd = Zero; undefined_symbol = 0; } rem_cmd = cmd; } } int print_reason(void) { int n, i, rv=0; i = a_tss.tss_irqn; if ((i == 0x21) && ((a_tss.tss_eax & 0xff00) == 0x4c00)) { ansi(A_green|A_bold); printf("Program terminated normally, exit code is %d\n", (word8)a_tss.tss_eax); a_tss.tss_eip -= 2; /* point to int 21h */ return 1; } ansi(A_red | A_bold); if (i != 1) { tssprint(&a_tss); if (i == 0x79) printf("Keyboard interrupt\n"); else if (i == 0x75) { save_npx(); printf("Numeric Exception ("); if ((npx.status & 0x0241) == 0x0241) printf("stack overflow"); else if ((npx.status & 0x0241) == 0x0041) printf("stack underflow"); else if (npx.status & 1) printf("invalid operation"); else if (npx.status & 2) printf("denormal operand"); else if (npx.status & 4) printf("divide by zero"); else if (npx.status & 8) printf("overflow"); else if (npx.status & 16) printf("underflow"); else if (npx.status & 32) printf("loss of precision"); printf(") at eip=0x%08lx\n", npx.eip); unassemble(npx.eip, 0); load_npx(); } else { printf("exception %d (%#02x) occurred", i, i); if ((i == 8) || ((i>=10) && (i<=14))) printf(", error code=%#lx", a_tss.tss_error); putchar('\n'); rv = 1; } } ansi(A_cyan | A_bold); for (n=0; n<3; n++) if ((dr6 & (1<<n)) && (dr7 & (3<<(n*2)))) { printf("breakpoint %d hit\n", n); rv = 1; } return rv; }
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.