#include #include #include #include #include #include "intercep.h" #define MAXFILESIZE 20000 /* maximum template file size */ #define MAXLINELEN 200 /* maximum output line length */ #define AVGLINELEN 40 /* average line length */ char template_text[ MAXFILESIZE ]; /* file text */ char *templates[ MAXFILESIZE/AVGLINELEN ]; /* pointers to each line */ int ntemplates; /* number of templates */ /* copy template to dest, changing regname to regval throughout. * assumes dest is big enough to hold result. */ void subst(char *regname, unsigned rval, char *template, char *dest) { char regval[5]; if (regname[1] == 'H' || regname[1] == 'L') sprintf(regval, "%02X", rval); else sprintf(regval, "%04X", rval); while (*dest = *template) { /* copy through '\0' at end of string. */ if (template[0] == regname[0] && template[1] == regname[1]) { dest = stpcpy(dest, regval); template += 2; /* all regnames are 2 chars long */ } else { template++; dest++; } } } /* Read template file into buffer, setting pointers to * beginning of lines. * Sets template_text, templates and ntemplates. * Pads out interrupt IDs to 6 characters. * Returns number of lines. */ int read_template_file(char *filename) { FILE *ifile; char inline[ MAXLINELEN ]; char **nextline = templates; char *dest = template_text; char *q = template_text; if (! (ifile = fopen(filename, "rt"))) return 0; while (fgets(inline, MAXLINELEN, ifile)) { char *p = inline; if (! isxdigit(inline[0])) continue; /* handle comment lines */ *nextline++ = dest = q; while (isxdigit(*p)) *q++ = *p++; /* copy initial hex string */ while (q < dest+6) *q++ = ' '; /* pad out to 6 characters */ *p = ' '; /* convert tab (or whatever) to space */ while (*q++ = *p++) ; /* copy rest of line through null */ while (q[-3] == '\\' && q[-2] == '\n') { /* continuation lines */ if (p = fgets(inline, MAXLINELEN, ifile)) { q -= 3; *q++ = '\n'; while (*q++ = *p++) ; } else goto on_eof; } } on_eof: *nextline = NULL; return (ntemplates = nextline - templates); } int compare_templates(char **t1, char **t2) { return(strnicmp(*t1, *t2, 6)); } /* find a matching template given interrupt number and ax value * works from the most specific (all 6 characters) * back to the most general (just the 2 characters of the interrupt number). */ char *find_template(int intnum, unsigned axval) { char proposed[ 7 ]; char *key = proposed; char **found; char *ignoring = proposed + 6; sprintf(proposed, "%02X%04X", intnum, axval); while (ignoring > proposed) { if (found = bsearch(&key, templates, ntemplates, sizeof(char *), compare_templates)) return(*found); /* else ignore 2 more characters */ ignoring -= 2; ignoring[0] = ignoring[1] = ' '; } return NULL; } #define HI(u) (((u)&0xff00)>>8) #define LO(u) ((u)&0x00ff) /* read Swi_info records from input file * interpret them, and output to output file. */ void interpret_file(FILE *ifp, FILE *ofp, char *progname, int longmode) { Swi_info rec; char s1[ MAXLINELEN ]; char s2[ MAXLINELEN ]; char *templ; if (progname != NULL) fprintf (ofp, "INTERCEPT/INTERPRET by Ned Konz 08/02/87\n" "dump of DOS/BIOS calls from program \"%s\"\n", progname); if (longmode) fprintf(ofp, " CS:IP INT AX BX CX DX DS ES SI DI BP\n"); while (fread(&rec, sizeof(Swi_info), 1, ifp)) { if (templ = find_template(rec.intnum, rec.regs.ovl.old[2])) { subst("AX", rec.regs.ovl.old[2], templ, s1); subst("AH", HI(rec.regs.ovl.old[2]), s1, s2); subst("AL", LO(rec.regs.ovl.old[2]), s2, s1); subst("BX", rec.regs.ovl.old[1], s1, s2); subst("BH", HI(rec.regs.ovl.old[1]), s2, s1); subst("BL", LO(rec.regs.ovl.old[1]), s1, s2); subst("CX", rec.regs.ovl.old[0], s2, s1); subst("CH", HI(rec.regs.ovl.old[0]), s1, s2); subst("CL", LO(rec.regs.ovl.old[0]), s2, s1); subst("DX", rec.regs.dx, s1, s2); subst("DH", HI(rec.regs.dx), s2, s1); subst("DL", LO(rec.regs.dx), s1, s2); subst("BP", rec.regs.bp, s2, s1); subst("DI", rec.regs.di, s1, s2); subst("SI", rec.regs.si, s2, s1); subst("DS", rec.regs.ds, s1, s2); subst("ES", rec.regs.es, s2, s1); subst("CS", FP_SEG(rec.caller.ipcs), s1, s2); subst("IP", FP_OFF(rec.caller.ipcs), s2, s1); fprintf(ofp, "%Fp %s", (char far *)rec.caller.ipcs - 2, s1); } if ((templ==NULL) || longmode) { fprintf(ofp, "%Fp %2x %04x " "%04x %04x %04x " "%04x %04x %04x %04x %04x\n", (char far *)rec.caller.ipcs - 2, rec.intnum, rec.regs.ovl.old[2], /*AX*/ rec.regs.ovl.old[1] /*BX*/, rec.regs.ovl.old[0],/*CX*/ rec.regs.dx, rec.regs.ds, rec.regs.es, rec.regs.si, rec.regs.di, rec.regs.bp); } } /*while*/ return; } int main(int argc, char *argv[]) { int longmode = 0; char *templfile = TFILENAME; char *progname = argv[0]; FILE *ifp, *ofp; if (argc < 3) { fprintf(stderr, "INTERCEPT/INTERPRET by Ned Konz 08/02/87\n" "usage: %s [-l] [-t templ_file] " "infile outfile [progname]\n", argv[0]); exit(1); } argv++; while (argv[0][0] == '-') { if (! stricmp(argv[0], "-l")) { longmode++; } else if (! stricmp(argv[0], "-t")) { templfile = argv[1]; argv++; } else { fprintf(stderr, "%s: unknown switch \"%s\"\n", progname, argv[0]); exit(4); } argv++; } if (! read_template_file( searchpath(templfile) )) { fprintf(stderr, "%s: error during read of \"%s\"\n", progname, templfile); exit(5); } qsort(templates, ntemplates, sizeof(char *), compare_templates); if (! (ifp = fopen(argv[0], "rb"))) { fprintf(stderr, "%s: can't open input file \"%s\"\n", progname, argv[0]); exit(2); } if (! (ofp = fopen(argv[1], "wt"))) { fprintf(stderr, "%s: can't open output file \"%s\"\n", progname, argv[1]); exit(3); } interpret_file(ifp, ofp, argv[2], longmode); fclose(ifp); fclose(ofp); exit(0); }