📄 dis.c
字号:
for (size = 1; size < longestinstsize && size <= offset; size++) if (insts[offset - size].size > size && insts[offset - size].flags & ISFPU) return 1; return 0;}/* * Disassemble! */voiddisassemble(void){ m68kaddr offset; long fsize; int changes; int total_changes; short nlabels; int i; unsigned char consts[BUFSIZ]; size_t stored = 0; size_t curnbreak; static int breakssaved = 0; /* * Determine the longest possible length of an instruction in words. */ switch (CPU(chip)) { case MC68000: case MC68010: longestinstsize = 10; break; case MC68020: case MC68030: default: if (FPU(chip)) longestinstsize = 20; else longestinstsize = 20; break; } /* * Determine the size of the input file. */ if (fseek(infp, 0, SEEK_END) == -1) { perror("fseek"); jumpfree(); } if ((gfsize = fsize = ftell(infp)) == -1) { perror("ftell"); jumpfree(); } else if (fsize < WORDSIZE) jumpfree(); if (fseek(infp, 0, SEEK_SET) == -1) { perror("fseek"); jumpfree(); } maxoffset = (fsize - (WORDSIZE - 1)) & ~(WORDSIZE - 1); /* * Malloc and initialize instruction structures. */ if ((insts = malloc((fsize + maxoffset) * sizeof(*insts))) == NULL) { perror("malloc"); jumpfree(); }#ifndef NOBAD if ((bad = malloc(fsize * sizeof(*bad))) == NULL || (good = malloc(fsize * sizeof(*good))) == NULL) { perror("malloc"); jumpfree(); } memset(bad, '\0', fsize * sizeof(*bad)); memset(good, '\0', fsize * sizeof(*good)); if (!odd) { size_t i; for (i = 1; i < fsize; i += 2) bad[i] = i + initialpc; }#endif memset(insts, '\0', (fsize + maxoffset) * sizeof(*insts)); while (fsize--) insts[fsize].required = NULL; /* * Pass 1: * * Determine where the code is and where the data is. */ pass1(); if (onepass == INCONSISTENT) { printall(); jumpfree(); } /* * Process offsets specified by the user * as places in data to start a new line of output. */ if (bfile && !breakssaved) { FILE *bfp; if (bfp = fopen(bfile, "r")) { char bbuf[80]; unsigned long ul; char *cp; m68kaddr *tmp; while (fgets(bbuf, sizeof bbuf, bfp)) { ul = strtoul(bbuf, &cp, 0); if (cp != bbuf && (odd || (ul & 1) == 0)) { if (ul >= initialpc && ul <= initialpc + maxoffset) { offset = ul - initialpc; if (tmp = realloc(breaks, (nbreaks + 1) * sizeof(*breaks))) { breaks = tmp; breaks[nbreaks++] = offset; } } else fprintf(outfp, "File %s: bad pc: %s\n", bfile, bbuf); } else fprintf(outfp, "File %s: bad pc: %s\n", bfile, bbuf); } (void)fclose(bfp); qsort(breaks, nbreaks, sizeof(*breaks), addrcmp); } else perror(bfile); breakssaved = 1; } /* * Process offsets specified by the user as being data. */ if (nfile) { FILE *nfp; static int notinstssaved = 0; if (nfp = fopen(nfile, "r")) { char nbuf[80]; unsigned long ul; char *cp; m68kaddr *nottmp; size_t size; while (fgets(nbuf, sizeof nbuf, nfp)) { ul = strtoul(nbuf, &cp, 0); if (cp != nbuf && (odd || (ul & 1) == 0)) { if (ul >= initialpc && ul <= initialpc + maxoffset) { offset = ul - initialpc; if (nottmp = realloc(notinsts, (nnotinsts + 1) * sizeof(*notinsts))) { notinsts = nottmp; notinsts[nnotinsts++] = offset; } for (size = 1; size < longestinstsize && size <= offset; size++) if (insts[offset - size].size > size) {#ifndef NOBAD bad[offset - size] = (insts[offset].size) ? offset + initialpc : bad[offset];#endif#ifdef DEBUG if (debug & DELETIONS)fprintf(outfp, "5. Deleting offset %lx, size %d, flags = %d because %lx specified\n", (long)(offset - size), insts[offset - size].size, insts[offset - size].flags, (long)offset);#endif DELETE(offset - size); } if (insts[offset].size) {#ifndef NOBAD bad[offset] = offset + initialpc;#endif#ifdef DEBUG if (debug & DELETIONS)fprintf(outfp, "6. Deleting offset %lx, size %d, flags = %d because specified\n", (long)offset, insts[offset].size, insts[offset].flags);#endif DELETE(offset); } } else fprintf(outfp, "File %s: bad pc: %s\n", nfile, nbuf); } else fprintf(outfp, "File %s: bad pc: %s\n", nfile, nbuf); } (void)fclose(nfp); if (!notinstssaved) { qsort(notinsts, nnotinsts, sizeof(*notinsts), addrcmp); notinstssaved = 1; } } else perror(nfile); } /* * Process offsets specified by the user * as not being the start of valid instructions. */ if (nsfile) { FILE *nfp; static int notinstssaved = 0; if (nfp = fopen(nsfile, "r")) { char nbuf[80]; unsigned long ul; char *cp; m68kaddr *nottmp; while (fgets(nbuf, sizeof nbuf, nfp)) { ul = strtoul(nbuf, &cp, 0); if (cp != nbuf && (odd || (ul & 1) == 0)) { if (ul >= initialpc && ul <= initialpc + maxoffset) { offset = ul - initialpc; if (nottmp = realloc(notinsts, (nnotinsts + 1) * sizeof(*notinsts))) { notinsts = nottmp; notinsts[nnotinsts++] = offset; } if (insts[offset].size) {#ifndef NOBAD bad[offset] = offset + initialpc;#endif#ifdef DEBUG if (debug & DELETIONS)fprintf(outfp, "6. Deleting offset %lx, size %d, flags = %d because specified\n", (long)offset, insts[offset].size, insts[offset].flags);#endif DELETE(offset); } } else fprintf(outfp, "File %s: bad pc: %s\n", nsfile, nbuf); } else fprintf(outfp, "File %s: bad pc: %s\n", nsfile, nbuf); } (void)fclose(nfp); if (!notinstssaved) { qsort(notinsts, nnotinsts, sizeof(*notinsts), addrcmp); notinstssaved = 1; } } else perror(nsfile); } /* * Process offsets specified by the user as being instructions. * Note that does *not* make an invalid instruction suddenly valid. */ if (ifile) { FILE *ifp; if (ifp = fopen(ifile, "r")) { char ibuf[80]; unsigned long ul; char *cp; while (fgets(ibuf, sizeof ibuf, ifp)) { ul = strtoul(ibuf, &cp, 0); if (cp != ibuf && (odd || (ul & 1) == 0)) { if (ul >= initialpc && ul <= initialpc + maxoffset) makegood(ul - initialpc); else fprintf(outfp, "File %s: bad pc: %s\n", ifile, ibuf); } else fprintf(outfp, "File %s: bad pc: %s\n", ifile, ibuf); } (void)fclose(ifp); } else perror(ifile); } /* * Instructions that don't set PC * must be followed by a valid instruction. * * Instructions must reference valid instructions. */ findbadrefs(); if (onepass == CONSISTENT) { printall(); jumpfree(); } /* * Assume that all LINK instructions that are referenced * by BSR or JSR instructions are valid. */ for (offset = 0; offset <= maxoffset; offset += (odd ? 1 : WORDSIZE)) if (insts[offset].size && (insts[offset].flags & (ISBSR | ISJSR)) && (insts[offset].flags & 3) && insts[offset].required[0] >= initialpc && insts[offset].required[0] <= initialpc + maxoffset && (insts[insts[offset].required[0] - initialpc].flags & ISLINK)) {#ifdef DEBUG if (debug & OVERLAPS) fprintf(outfp, "Number of overlaps = %ld\n", overlaps(0));#endif makegood(insts[offset].required[0] - initialpc); } findbadrefs();#ifdef DEBUG if (debug & OVERLAPS) fprintf(outfp, "Number of overlaps after LINKs with labels = %ld\n", overlaps(0));#endif /* * Assume that all remaining LINK instructions are valid. */ total_changes = 0; for (offset = 0; offset <= maxoffset; offset += (odd ? 1 : WORDSIZE)) if (insts[offset].size && (insts[offset].flags & ISGOOD) == 0 && (insts[offset].flags & ISLINK)) {#ifdef DEBUG if (debug & OVERLAPS) fprintf(stderr, "Number of overlaps = %ld\n", overlaps(0));#endif total_changes += makegood(offset); } if (total_changes) findbadrefs();#ifdef DEBUG if (debug & OVERLAPS) fprintf(stderr, "Number of overlaps after all LINKs = %ld\n", overlaps(0));#endif /* * Assume that branch instructions that jump to valid instructions * and that cannot be extension words of math FPU instructions * are valid. */ total_changes = 0; do { changes = 0; for (offset = 0; offset <= maxoffset; offset += (odd ? 1 : WORDSIZE)) if (insts[offset].size && (insts[offset].flags & ISGOOD) == 0 && (insts[offset].flags & (ISBSR | ISJSR | ISBRA | ISBRcc | ISDBcc | ISJMP)) && (insts[offset].flags & 3) && insts[offset].required[0] >= initialpc && insts[offset].required[0] <= initialpc + maxoffset && (insts[insts[offset].required[0] - initialpc].flags & ISGOOD) && !fpuoverlap(offset)) {#ifdef DEBUG if (debug & OVERLAPS) fprintf(stderr, "Number of overlaps = %ld\n", overlaps(0));#endif makegood(offset); changes++; } total_changes += changes; } while (changes); if (total_changes) findbadrefs();#ifdef DEBUG if (debug & OVERLAPS) fprintf(stderr,"Number of overlaps after all LINKs and jumps to good addresses = %ld\n", overlaps(0));#endif /* * Assume that branch instructions that jump outside the current object * file and that cannot be extension words of math FPU instructions * are valid. */ total_changes = 0; do { changes = 0; for (offset = 0; offset <= maxoffset; offset += (odd ? 1 : WORDSIZE)) if (insts[offset].size && (insts[offset].flags & ISGOOD) == 0 && (insts[offset].flags & (ISBSR | ISJSR | ISBRA | ISBRcc | ISDBcc | ISJMP | ISRTS)) && !fpuoverlap(offset)) {#ifdef DEBUG if (debug & OVERLAPS) fprintf(stderr, "Number of overlaps = %ld\n", overlaps(0));#endif makegood(offset); changes++; } total_changes += changes; } while (changes); if (total_changes) findbadrefs();#ifdef DEBUG if (debug & OVERLAPS) fprintf(stderr, "Number of overlaps after all LINKs and branches = %ld\n", overlaps(0));#endif if (fixoverlaps()) findbadrefs();#if 1 { long noverlaps = overlaps(1); if (noverlaps#ifdef DEBUG || debug & OVERLAPS#endif ) fprintf(stderr, "%s: Number of overlaps = %ld\n", sfile, noverlaps); }#endif /* * Get the labels. */ dcpass(); for (offset = 0; offset <= maxoffset; ) { if (insts[offset].size) { for (i = 0; i < NREQD(offset); i++) SETLABEL(insts[offset].required[i]); offset += insts[offset].size; } else if (odd) offset++; else offset += WORDSIZE; } for (nlabels = 0, offset = 0; offset <= maxoffset; offset++) if (insts[offset].flags & ISLABEL) {#ifdef DEBUG if (debug & LABELS) fprintf(outfp, "Label %d at %lx\n", nlabels + 1, (long)offset);#endif insts[offset].labelnum = ++nlabels; } /* * Last pass: Print! */ if (fseek(infp, 0, SEEK_SET) == -1) { perror("fseek"); jumpfree(); } pc = ppc = initialpc; leninstbuf = 0; curnbreak = 0; pass = LASTPASS; for (stored = 0, curoffset = offset = 0; offset < gfsize; ) { if (curoffset != offset && fseek(infp, curoffset = offset, SEEK_SET) == -1) { perror("fseek"); jumpfree(); } flags = 0; if (insts[offset].size) { if (stored) { flush(stored, consts, insts[offset - stored].flags, 1); stored = 0; } pc = ppc = initialpc + offset; leninstbuf = 0; validinst(); offset = curoffset; } else { int incrbreak; if (stored == 0) pc = ppc = initialpc + offset; /* * Break the constant data up so that * all labels are printed on a new line. */ while (curnbreak < nbreaks && breaks[curnbreak] < offset) curnbreak++; incrbreak = curnbreak < nbreaks && offset == breaks[curnbreak]; if (insts[offset].flags & ISLABEL || incrbreak) { flush(stored, consts, insts[offset - stored].flags, 1); stored = 0; if (incrbreak) curnbreak++; } if (fread(consts + stored, 1, 1, infp) == 1) if (++stored >= sizeof consts) { stored = flush(stored, consts, insts[offset - stored].flags, 0); memmove(consts, consts + sizeof consts - stored, stored); } offset++; } } if (stored) flush(stored, consts, insts[offset - stored].flags, 1); jumpfree(); /* NOTREACHED */}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -