Path: utzoo!utgpu!water!watmath!uunet!cos!hqda-ai!icus!lenny From: lenny@icus.islp.ny.us (Lenny Tropiano) Newsgroups: unix-pc.sources Subject: UNIX PC COFF Disassembler (Part 2 of 2) Keywords: unc, m68k disassembler Message-ID: <512@icus.islp.ny.us> Date: 27 Sep 88 00:35:46 GMT Distribution: unix-pc Organization: ICUS Software Systems, Islip, New York Lines: 2567 Here's part 2... #! /bin/sh # This is a shell archive. Remove anything before this line, then unpack # it by saving it into a file and typing "sh file". To overwrite existing # files, type "sh file -c". You can also feed this as standard input via # unshar, or by typing "sh 'heur.c' <<'END_OF_FILE' X/* X * SCCS: @(#)heur.c 1.2 11/2/84 14:17:46 X * Attempt to guess things about the file. X * X *********************************************************************** X * This software is copyright of X * X * John M Collins X * 47 Cedarwood Drive X * St Albans X * Herts, AL4 0DN X * England +44 727 57267 X * X * and is released into the public domain on the following conditions: X * X * 1. No free maintenance will be guaranteed. X * 2. Nothing may be based on this software without X * acknowledgement, including incorporation of this X * notice. X * X * Notwithstanding the above, the author welcomes correspondence and bug X * fixes. X *********************************************************************** X */ X X#include X#include X#include X#include "unc.h" X X#define INITDAT 256 X#define INCDAT 128 X X#define STRSCNT 3 X#define STRECNT 3 X Xchar *malloc(), *realloc(); X Xvoid gette(), getde(), setde(), putte(), putde(); Xvoid nomem(); Xlong getdw(); Xsymbol inventsymb(); X Xlong endt; Xef_fids mainfile; X X/* X * Talk about implemented things..... X */ X Xvoid unimpl(msg) Xchar *msg; X{ X (void) fprintf(stderr, "Warning: handling of \"%s\" not implemented\n", msg); X} X X/* X * Return 1 if string char, otherwise 0. X */ X Xint possstr(x) Xunsigned x; X{ X if (x >= ' ' && x <= '~') X return 1; X if (x == '\n' || x == '\t') X return 1; X return 0; X} X X/* X * Guess things about data files. X */ X Xvoid intudat(fid) Xef_fid fid; X{ X register int i, j; X int lt, input, invcnt; X long offs, soffs, endd; X d_entry fdat; X unsigned char *inbuf; X int ibsize; X X inbuf = (unsigned char *)malloc(INITDAT); X if (inbuf == NULL) X nomem(); X ibsize = INITDAT; X X offs = fid->ef_dbase; X endd = fid->ef_bbase; X X while (offs < endd) { X getde(fid, offs, &fdat); X if (fdat.d_type != D_BYTE) { X offs += fdat.d_lng; X continue; X } X X /* X * Looks like general data. Read in as much as possible. X */ X X input = 0; X soffs = offs; X do { X if (input >= ibsize) { X ibsize += INCDAT; X inbuf = (unsigned char *) X realloc((char *)inbuf, (unsigned)ibsize); X if (inbuf == NULL) X nomem(); X } X inbuf[input++] = fdat.d_contents; X offs++; X if (offs >= endd) X break; X getde(fid, offs, &fdat); X } while (fdat.d_type == D_BYTE && fdat.d_lab == NULL); X X /* X * Now split up the data. X */ X X for (i = 0; i < input; ) { X X /* X * Might be a string. X */ X X if (possstr(inbuf[i])) { X lt = input; X if (i + STRSCNT < lt) X lt = i + STRSCNT; X for (j = i + 1; j < lt; j++) { X if (inbuf[j] == '\0') X break; X if (!possstr(inbuf[j])) X goto notstr; X } X X /* X * Looks like a string then. X */ X X invcnt = 0; X for (j = i + 1; j < input; j++) { X if (inbuf[j] == '\0') { X j++; X break; X } X if (possstr(inbuf[j])) X invcnt = 0; X else { X invcnt++; X if (invcnt >= STRECNT) { X j -= invcnt - 1; X break; X } X } X } X X setde(fid, X soffs+i, X (unsigned)(inbuf[j-1]=='\0'?D_ASCZ:D_ASC), X j - i); X for (i++; i < j; i++) X setde(fid, soffs+i, D_CONT, 1); X continue; X } X Xnotstr: X /* X * If on odd boundary, treat as a byte. X */ X X if ((soffs + i) & 1 || i + 1 >= input) { X setde(fid, soffs + i, D_BYTE, 1); X i++; X continue; X } X X /* X * Treat as longs unless not enough. X */ X X if (i + 3 >= input) { X setde(fid, soffs + i, D_WORD, 2); X setde(fid, soffs + i + 1, D_CONT, -1); X i += 2; X continue; X } X X /* X * Treat as a long but mark changable. X */ X X setde(fid, soffs + i, D_LONG, 4); X for (j = 1; j < 4; j++) X setde(fid, soffs + i + j, D_CONT, -j); X i += 4; X } X } X free((char *)inbuf); X X /* X * Now zap bss segment. X */ X X offs = fid->ef_bbase; X endd = fid->ef_end; X X while (offs < endd) { X getde(fid, offs, &fdat); X if (fdat.d_type != D_BYTE) { X offs += fdat.d_lng; X continue; X } X X soffs = offs; X do { X offs++; X if (offs >= endd) X break; X getde(fid, offs, &fdat); X } while (fdat.d_type == D_BYTE && fdat.d_lab == NULL); X X setde(fid, soffs, D_BYTE, (int)(offs-soffs)); X for (i = -1, soffs++; soffs < offs; i--, soffs++) X setde(fid, soffs, D_CONT, i); X } X} X X/* X * For non relocatable files, try to identify address pointers in X * the data. X */ X Xvoid inturdat(fid) Xef_fid fid; X{ X register long offs = fid->ef_dbase; X register int i; X register symbol ds; X long endd = fid->ef_bbase; X long cont; X d_entry dent, refdent; X X while (offs < endd) { X getde(fid, offs, &dent); X if (dent.d_type != D_LONG) X goto endit; X cont = getdw(fid, offs, R_LONG); X if (cont < fid->ef_dbase || cont > fid->ef_end) X goto endit; X getde(fid, cont, &refdent); X if (refdent.d_type == D_CONT) { X d_entry pdent; X int siz; X X if (refdent.d_lng >= 0) X goto endit; X getde(fid, cont+refdent.d_lng, &pdent); X i = -refdent.d_lng; X refdent.d_lng += pdent.d_lng; X pdent.d_lng = i; X if (pdent.d_type == D_LONG && i == 2) X siz = D_WORD; X else X siz = D_BYTE; X refdent.d_type = siz; X pdent.d_type = siz; X putde(fid, cont - i, &pdent); X for (i = 1; i < refdent.d_lng; i++) X setde(fid, cont+i, D_CONT, -i); X } X if ((ds = refdent.d_lab) == NULL) { X if (cont >= fid->ef_bbase) { X ds = inventsymb("BS"); X ds->s_type = S_BSS; X } X else { X ds = inventsymb("DS"); X ds->s_type = S_DATA; X } X ds->s_value = cont; X refdent.d_lab = ds; X putde(fid, cont, &refdent); X } X else X ds->s_used++; X dent.d_type = D_ADDR; X dent.d_relsymb = ds; X dent.d_rptr = ds->s_type; X putde(fid, offs, &dent); X for (i = 1; i < 4; i++) X setde(fid, offs+i, D_CONT, 1); Xendit: X offs += dent.d_lng; X } X} X X/* X * Recursively follow through the code, stopping at unconditional X * branches and invalid instructions. X */ X Xvoid follseq(pos) Xlong pos; X{ X t_entry tent; X int lng; X long npos; X X while (pos < endt) { X gette(&mainfile, pos, &tent); X if (tent.t_amap) /* Been here */ X return; X tent.t_amap = 1; X lng = findinst(&tent, pos); X npos = pos + lng*2; X if (npos > endt) { X tent.t_vins = 0; X tent.t_lng = 1; X tent.t_type = T_UNKNOWN; X lng = 0; X npos = endt; X } X putte(&mainfile, pos, &tent); X pos = npos; X X if (lng <= 0) X return; X X switch (tent.t_bchtyp) { X case T_UNBR: X if (tent.t_relsymb == NULL) X return; X pos = tent.t_relsymb->s_value; X continue; X case T_JSR: X if (tent.t_relsymb != NULL) X follseq(tent.t_relsymb->s_value); X continue; X case T_CONDBR: X follseq(tent.t_relsymb->s_value); X default: X continue; X } X } X} X X X/* X * Try to work out things about text files. X */ X Xvoid intutext() X{ X long pos; X t_entry tent; X int lng; X X endt = mainfile.ef_tbase + mainfile.ef_tsize; X pos = mainfile.ef_entry; Xnextv: X for (; pos < endt;) { X gette(&mainfile, pos, &tent); X if (!tent.t_amap && tent.t_vins) { X follseq(pos); X pos += 2; X goto nextiv; X } X pos += tent.t_lng * 2; X if (tent.t_bchtyp == T_UNBR) X goto nextiv; X } X goto dorest; Xnextiv: X for (; pos < endt; pos += 2) { X gette(&mainfile, pos, &tent); X if (tent.t_bdest) X goto nextv; X } Xdorest: X /* X * Deal with unmapped instructions. X */ X X for (pos = mainfile.ef_tbase; pos < endt;) { X gette(&mainfile, pos, &tent); X switch (tent.t_type) { X case T_BEGIN: X pos += tent.t_lng * 2; X continue; X case T_UNKNOWN: X if (tent.t_vins) { X lng = findinst(&tent, pos); X putte(&mainfile, pos, &tent); X if (lng > 0) { X pos += lng * 2; X continue; X } X } X default: X pos += 2; X continue; X } X } X} X X/* X * Invent local symbols. X */ X Xvoid intlsym() X{ X long bpos, epos, hiref, hipos; X unsigned llnum; X t_entry tent; X register symbol tl; X X endt = mainfile.ef_tbase + mainfile.ef_tsize; X epos = mainfile.ef_entry; X for (;;) { X bpos = epos; X hiref = bpos; X if (epos >= endt) X return; X gette(&mainfile, epos, &tent); X epos += tent.t_lng * 2; X for (; epos < endt;) { X gette(&mainfile, epos, &tent); X if (tent.t_gbdest || tent.t_dref) X break; X if (tent.t_reflo < bpos) X break; X if (tent.t_refhi > hiref) { X hiref = tent.t_refhi; X hipos = epos; X } X epos += tent.t_lng * 2; X } X if (hiref > epos) X epos = hipos; X llnum = 0; X for (hipos = bpos; hipos < epos;) { X gette(&mainfile, hipos, &tent); X if (!tent.t_gbdest && !tent.t_dref && X tent.t_reflo >= bpos && tent.t_refhi < epos && X (tl = tent.t_lab) != NULL) X tl->s_lsymb = ++llnum; X hipos += tent.t_lng * 2; X } X } X} X X/* X * Given the main file, a possible candidate for matching in the X * file and an offset, see if text matches. Return 1 if matches, X * or 0 if no match. X */ X Xint matchup(mf, lf, startpos) Xregister ef_fid mf, lf; Xlong startpos; X{ X register int i, matches = 0; X t_entry ltent, mtent; X X if (lf->ef_tsize > mf->ef_tsize - startpos + mf->ef_tbase) X return 0; /* At end - can't fit */ X X for (i = 0; i < lf->ef_tsize; i += 2) { X gette(lf, lf->ef_tbase + i, <ent); X if (ltent.t_isrel) X continue; X gette(mf, startpos + i, &mtent); X if (mtent.t_contents != ltent.t_contents) X return 0; X matches++; X } X X /* X * Give up on zero length or all relocatable files. X */ X X return matches > 0; X} X X/* X * Scan through main file looking for a match. X */ X Xlong findstart(mf, lf) Xregister ef_fid mf, lf; X{ X register long res = mf->ef_tbase; X long lim = mf->ef_tbase + mf->ef_tsize - lf->ef_tsize; X t_entry tent; X Xrestart: X for (; res <= lim; res += 2) { X gette(mf, res, &tent); X if (tent.t_match != 0) { X res += tent.t_match; X goto restart; X } X if (matchup(mf, lf, res)) X return res; X } X return -1; X} X X/* X * Mark the head of a matched module to save searching. X */ X Xvoid markmatch(mf, lf, pos) Xef_fid mf, lf; Xlong pos; X{ X t_entry tent; X X gette(mf, pos, &tent); X tent.t_match = (unsigned) lf->ef_tsize; X putte(mf, pos, &tent); X} END_OF_FILE if test 9925 -ne `wc -c <'heur.c'`; then echo shar: \"'heur.c'\" unpacked with wrong size! fi # end of 'heur.c' fi if test -f 'libmtch.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'libmtch.c'\" else echo shar: Extracting \"'libmtch.c'\" \(6912 characters\) sed "s/^X//" >'libmtch.c' <<'END_OF_FILE' X/* X * SCCS: @(#)libmtch.c 1.2 11/2/84 14:18:55 X * Read library files. X * X *********************************************************************** X * This software is copyright of X * X * John M Collins X * 47 Cedarwood Drive X * St Albans X * Herts, AL4 0DN X * England +44 727 57267 X * X * and is released into the public domain on the following conditions: X * X * 1. No free maintenance will be guaranteed. X * 2. Nothing may be based on this software without X * acknowledgement, including incorporation of this X * notice. X * X * Notwithstanding the above, the author welcomes correspondence and bug X * fixes. X *********************************************************************** X */ X X#include X#include X#include X#include X#include X#include X#include X#include "unc.h" X Xlong atol(); Xlong lseek(); Xvoid bfopen(), bfclose(), nomem(); Xvoid rrell2(), markmatch(); Xchar *malloc(); Xint matchup(); Xlong findstart(); X Xchar verbose; /* Tell the world what we are doing */ Xchar *tfnam; Xchar *cfile; Xef_fids mainfile; Xstruct commit dreltab; Xint donedrel, donebrel; Xlong trelpos, drelpos, brelpos; Xstatic struct libit currlib = {NULL, NULL, ""}; X Xvoid lclash(str) Xchar *str; X{ X (void) fprintf(stderr, "Library scan failure - %s\n", str); X (void) fprintf(stderr, "Searching %s\n", cfile); X if (currlib.lf_name[0]) X (void) fprintf(stderr, "Member is %s\n", currlib.lf_name); X exit(255); X} X X/* X * Find next member. X */ X Xlong nextmemb(filename,lfd) Xchar *filename; Xregister struct libit *lfd; X{ X struct ar_hdr arbuf; X X ldaclose(lfd->ldptr2); X if (ldclose(lfd->ldptr != FAILURE)) /* end of archive */ X return -1; X lfd->ldptr = ldopen(filename,lfd->ldptr); X ldahread(lfd->ldptr, (char *)&arbuf); X (void) strncpy(lfd->lf_name, arbuf.ar_name, sizeof(lfd->lf_name)); X return 1; X} X X/* X * Decode a file name thus - X * X * -lxxx decode as /lib/libxxx.a /usr/lib/libxxx.a etc X * -Lxxx forget "lib" ".a" bit thus -Lcrt0.o X * or read LDPATH environment var to give list of directories as sh X * (default /lib:/usr/lib). X * X * Alternatively treat as normal pathname. X * X * File names may be followed by (membername) if the file is an archive, X * thus X * X * -lc(printf.o) X * X * in which case the specified module is fetched. X */ X Xstruct libit *getfnam(str) Xchar *str; /* will be expanded to full path name if necessary */ X{ X char *bp, *ep = NULL, *pathb, *pathe, *fullpath = NULL; X static char *pathn; X extern char *getenv(); X char magic[8]; X struct ar_hdr arhdr; X LDFILE *ldptr; X X if ((bp = strrchr(str, '(')) != NULL && X (ep = strrchr(str, ')')) != NULL) X *ep = *bp = '\0'; X X if (str[0] == '-' && (str[1] == 'l' || str[1] == 'L')) { X if (pathn == NULL) { X if ((pathn = getenv("LDPATH")) == NULL) X pathn = "/lib:/usr/lib"; X } X fullpath = malloc((unsigned)(strlen(pathn) + strlen(str) + 1)); X if (fullpath == NULL) X nomem(); X pathb = pathn; X do { X pathe = strchr(pathb, ':'); X if (*pathb == ':') X fullpath[0] = '\0'; X else { X if (pathe != NULL) X *pathe = '\0'; X (void) strcpy(fullpath, pathb); X (void) strcat(fullpath, "/"); X if (pathe != NULL) X *pathe = ':'; X } X if (str[1] == 'l') X (void) strcat(fullpath, "lib"); X (void) strcat(fullpath, &str[2]); X if (str[1] == 'l') X (void) strcat(fullpath, ".a"); X if ((ldptr = ldopen(fullpath, NULL)) != NULL) X goto found; X pathb = pathe + 1; X } while (pathe != NULL); X X (void) fprintf(stderr, "Unable to locate lib%s.a in %s\n", X &str[2], pathn); X exit(101); X } X else if ((ldptr = ldopen(str, NULL)) == NULL) { X (void) fprintf(stderr, "Cannot open %s\n", str); X exit(102); X } X Xfound: X X str = fullpath? fullpath: str; X if (FREAD(magic, sizeof(magic),1,ldptr) != 1 || X strcmp(magic, ARMAG) != 0) { X if (ep != NULL) { X (void) fprintf(stderr, "%s is not library file\n", str); X exit(103); X } X currlib.ldptr = ldptr; X currlib.ldptr2 = ldaopen(str,ldptr); X currlib.lf_name[0] = '\0'; X return &currlib; X } X X /* X * It appears to be a library file - see if we want a specific X * one. X */ X X if (ep != NULL) { X char *cp; X X for (;;) { X if (ldahread(ldptr,&arhdr) == FAILURE) { X (void) fprintf(stderr, "Cannot find member %s in %s\n", X bp+1, str); X exit(103); X } X for ( cp = arhdr.ar_name + sizeof(arhdr.ar_name) - 1; X *cp == ' '; X cp -- ) ; X if (strncmp(bp+1, arhdr.ar_name, cp - arhdr.ar_name + 1) == 0) X break; X X if (ldclose(ldptr) != FAILURE) { X (void) fprintf(stderr, "Cannot find member %s in %s\n", X bp+1, str); X exit(103); X } X ldptr = ldopen(str,ldptr); X } X currlib.ldptr = ldptr; X currlib.ldptr2 = ldaopen(str,ldptr); X currlib.lf_name[0] = '\0'; X *bp = '('; X *ep = ')'; X return &currlib; X } X X /* X * Otherwise point to 1st member in library. X */ X X if (ldahread(ldptr, &arhdr) == FAILURE) { X (void) fprintf(stderr, "Library %s empty\n", str); X exit(104); X } X currlib.ldptr = ldptr; X currlib.ldptr2 = ldaopen(str,ldptr); X (void) strncpy(currlib.lf_name, arhdr.ar_name, sizeof(currlib.lf_name)); X return &currlib; X} X X/* X * Process library files. X */ X X#define MINTEXT 6 X Xvoid lscan(nfiles, fnames) Xint nfiles; Xchar **fnames; X{ X ef_fids libfile; X register ef_fid ll = &libfile; X register struct libit *clf; X extern symbol dolsymb(); X int firstfile; X X for (; nfiles > 0; fnames++, nfiles--) { X clf = getfnam(*fnames); X cfile = *fnames; X firstfile = 1; X do { X bfopen(tfnam, ll); X X /* X * If file is garbled, silently forget it and go X * on to the next one. X */ X X if (!rtext(clf->ldptr, ll)) X goto closeit; X X if (ll->ef_tsize < MINTEXT) X goto closeit; X X if (!rdata(clf->ldptr, ll)) X goto closeit; X X if (rrell1(clf->ldptr, ll) < 0) X goto closeit; X X /* X * If first file in library, find it from X * beginning of main file. X */ X X if (firstfile) { X if ((trelpos = findstart(&mainfile, ll)) < 0) X goto closeit; X firstfile = 0; X } X else if (!matchup(&mainfile, ll, trelpos)) X goto closeit; X X /* X * Found a match. X */ X X if (!rsymb(clf->ldptr, dolsymb, ll)) { X (void) fprintf(stderr, "Corrupt file %s\n", X *fnames); X exit(150); X } X X donedrel = 0; X donebrel = 0; X rrell2(clf->ldptr, clf->ldptr2, ll); X if (verbose) { X (void) fprintf(stderr, "Found: "); X if (clf->lf_name[0]) X (void) fprintf(stderr, "%.14s in ", X clf->lf_name); X (void) fprintf(stderr, "%s\n", *fnames); X } X if (libfile.ef_stvec != NULL) { X free(libfile.ef_stvec); X libfile.ef_stvec = NULL; X libfile.ef_stcnt = 0; X } X dreltab.c_int = 0; X X /* X * Start looking next time round X * where last one left off. X */ X X markmatch(&mainfile, ll, trelpos); X trelpos += libfile.ef_tsize; Xcloseit: X bfclose(ll); X } while (nextmemb(cfile,clf) >= 0); X } X} END_OF_FILE if test 6912 -ne `wc -c <'libmtch.c'`; then echo shar: \"'libmtch.c'\" unpacked with wrong size! fi # end of 'libmtch.c' fi if test -f 'main.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'main.c'\" else echo shar: Extracting \"'main.c'\" \(5877 characters\) sed "s/^X//" >'main.c' <<'END_OF_FILE' X/* X * SCCS: @(#)main.c 1.2 11/2/84 14:19:31 X * Main routine etc. X * X *********************************************************************** X * This software is copyright of X * X * John M Collins X * 47 Cedarwood Drive X * St Albans X * Herts, AL4 0DN X * England +44 727 57267 X * X * and is released into the public domain on the following conditions: X * X * 1. No free maintenance will be guaranteed. X * 2. Nothing may be based on this software without X * acknowledgement, including incorporation of this X * notice. X * X * Notwithstanding the above, the author welcomes correspondence and bug X * fixes. X *********************************************************************** X */ X X#include X#include X#include X#include X#include "unc.h" X X#define LINELNG 70 X Xvoid inturdat(), intutext(), intudat(), intlsym(); Xvoid ptext(), pdata(), pabs(), pbss(), lscan(); X Xef_fids mainfile; X Xint nmods; /* Number of modules it looks like */ X Xchar *tfnam = "split"; X Xchar lsyms; /* Generate local symbols */ Xchar verbose; /* Tell the world what we are doing */ Xchar noabs; /* No non-global absolutes */ Xint rel; /* File being analysed is relocatable */ Xint lpos; X Xsymbol dosymb(); Xstruct libit *getfnam(); X X/* X * Get hex characters, also allowing for 'k' and 'm'. X */ X Xint ghex(str) Xregister char *str; X{ X register int result = 0; X register int lt; X X for (;;) { X lt = *str++; X switch (lt) { X default: Xerr: (void) fprintf(stderr, "Invalid hex digit \'%c\'\n", lt); X exit(1); X X case '\0': X return result; X X case '0':case '1':case '2':case '3':case '4': X case '5':case '6':case '7':case '8':case '9': X result = (result << 4) + lt - '0'; X continue; X X case 'a':case 'b':case 'c':case 'd':case 'e':case 'f': X result = (result << 4) + lt - 'a' + 10; X continue; X X case 'A':case 'B':case 'C':case 'D':case 'E':case 'F': X result = (result << 4) + lt - 'A' + 10; X continue; X X case 'k':case 'K': X if (*str != '\0') X goto err; X return result << 10; X X case 'm':case 'M': X if (*str != '\0') X goto err; X return result << 20; X } X } X} X X/* X * Process entry line options. Return number dealt with. X */ X Xint doopts(av) Xchar *av[]; X{ X register int cnt = 0, lt; X register char *arg; X X for (;;) { X arg = *++av; X if (*arg++ != '-') X return cnt; X cnt++; X Xnx: switch (lt = *arg++) { X default: X (void) fprintf(stderr, "Bad option -%c\n", lt); X exit(1); X X case '\0': X continue; X X case 'l': /* A file name */ X case 'L': X return cnt - 1; X X case 's': X lsyms++; X goto nx; X X case 'v': X verbose++; X goto nx; X X case 'a': X noabs++; X goto nx; X X case 't': X if (*arg == '\0') { X cnt++; X arg = *++av; X if (arg == NULL) { Xbo: (void) fprintf(stderr,"Bad -%c option\n",lt); X exit(1); X } X } X tfnam = arg; X continue; X X case 'o': X if (*arg == '\0') { X cnt++; X arg = *++av; X if (arg == NULL) X goto bo; X } X if (freopen(arg, "w", stdout) == NULL) { X (void) fprintf(stderr, "Help! cant open %s\n", arg); X exit(20); X } X continue; X } X } X} X X/* X * Open binary files. Arrange to erase them when finished. X */ X Xvoid bfopen(nam, fid) Xchar *nam; Xef_fid fid; X{ X char fnam[80]; X X (void) sprintf(fnam, "%s.tx", nam); X if ((fid->ef_t = open(fnam, O_RDWR|O_CREAT, 0666)) < 0) { Xefil: (void) fprintf(stderr, "Help could not open %s\n", fnam); X exit(4); X } X (void) unlink(fnam); X (void) sprintf(fnam, "%s.dt", nam); X if ((fid->ef_d = open(fnam, O_RDWR|O_CREAT, 0666)) < 0) X goto efil; X (void) unlink(fnam); X} X X/* X * Close binary files. They should get zapped anyway. X */ X Xvoid bfclose(fid) Xef_fid fid; X{ X (void) close(fid->ef_t); X (void) close(fid->ef_d); X} X X/* X * Main routine. X */ X Xmain(argc, argv) Xint argc; Xchar *argv[]; X{ X int i; X char *progname = argv[0]; X char *msg; X register struct libit *lfd; X X i = doopts(argv); X argc -= i; X argv += i; X X if (argc < 2) { X (void) fprintf(stderr, "Usage: %s [ options ] file\n", progname); X exit(1); X } X X lfd = getfnam(argv[1]); X if (TYPE(lfd->ldptr) == ARTYPE) { X (void) fprintf(stderr, "Main file (%s) cannot be library\n", argv[1]); X exit(2); X } X X bfopen(tfnam, &mainfile); X if (verbose) X (void) fprintf(stderr, "Scanning text\n"); X if (!rtext(lfd->ldptr, &mainfile)) { X msg = "text"; Xbf: (void) fprintf(stderr, "Bad format input file - reading %s\n", msg); X exit(5); X } X if (verbose) X (void) fprintf(stderr, "Scanning data\n"); X if (!rdata(lfd->ldptr, &mainfile)) { X msg = "data"; X goto bf; X } X if (verbose) X (void) fprintf(stderr, "Scanning symbols\n"); X if (!rsymb(lfd->ldptr, dosymb, &mainfile)) { X msg = "symbols"; X goto bf; X } X if (verbose) X (void) fprintf(stderr, "Scanning for relocation\n"); X if ((rel = rrel(lfd->ldptr, lfd->ldptr2, &mainfile)) < 0) { X msg = "reloc"; X goto bf; X } X X if (rel) { X if (verbose) X (void) fprintf(stderr, "File is relocatable\n"); X if (argc > 2) X (void) fprintf(stderr, "Sorry - no scan on reloc files\n"); X } X else X lscan(argc - 2, &argv[2]); X X if (verbose) X (void) fprintf(stderr, "End of input\n"); X X ldaclose(lfd->ldptr2); X ldclose(lfd->ldptr); X if (nmods > 0) X (void) fprintf(stderr, "Warning: at least %d merged modules\n", X nmods + 1); X X if (mainfile.ef_stvec != NULL) { X free(mainfile.ef_stvec); X mainfile.ef_stvec = NULL; X mainfile.ef_stcnt = 0; X } X X if (verbose) X (void) fprintf(stderr, "Text anal 1\n"); X intutext(); X if (verbose) X (void) fprintf(stderr, "Data anal 1\n"); X intudat(&mainfile); X if (!rel) { X if (verbose) X (void) fprintf(stderr, "Data anal 2\n"); X inturdat(&mainfile); X } X if (lsyms) { X if (verbose) X (void) fprintf(stderr, "Local symbol scan\n"); X intlsym(); X } X pabs(); X ptext(&mainfile); X pdata(&mainfile); X pbss(&mainfile); X bfclose(&mainfile); X exit(0); X} END_OF_FILE if test 5877 -ne `wc -c <'main.c'`; then echo shar: \"'main.c'\" unpacked with wrong size! fi # end of 'main.c' fi if test -f 'prin.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'prin.c'\" else echo shar: Extracting \"'prin.c'\" \(5515 characters\) sed "s/^X//" >'prin.c' <<'END_OF_FILE' X/* X * SCCS: @(#)prin.c 1.2 11/2/84 14:19:47 X * Print stuff. X * X *********************************************************************** X * This software is copyright of X * X * John M Collins X * 47 Cedarwood Drive X * St Albans X * Herts, AL4 0DN X * England +44 727 57267 X * X * and is released into the public domain on the following conditions: X * X * 1. No free maintenance will be guaranteed. X * 2. Nothing may be based on this software without X * acknowledgement, including incorporation of this X * notice. X * X * Notwithstanding the above, the author welcomes correspondence and bug X * fixes. X *********************************************************************** X */ X X#include X#include X#include X#include "unc.h" X X#define LINELNG 70 X Xvoid gette(), getde(); Xlong gettw(), getdw(); Xvoid prinst(); X Xchar noabs; /* No non-global absolutes */ Xint rel; /* File being analysed is relocatable */ Xint lpos; X Xstruct commit abstab, comtab; X X/* X * Print absolute and common values. X */ X Xvoid pabs() X{ X register int i; X register symbol cs; X X for (i = 0; i < abstab.c_int; i++) X X for (i = 0; i < abstab.c_int; i++) { X cs = abstab.c_symb[i]; X if (cs->s_glob) X (void) printf("\t.globl\t%s\n", cs->s_name); X else if (noabs) X continue; X (void) printf("%s\t=\t0x%lx\n", cs->s_name, cs->s_value); X } X for (i = 0; i < comtab.c_int; i++) { X cs = comtab.c_symb[i]; X (void) printf("\t.comm\t%s,%d\n", cs->s_name, cs->s_value); X } X} X X/* X * Print out labels. X */ X Xvoid plabs(ls, seg) Xregister symbol ls; Xint seg; X{ X for (; ls != NULL; ls = ls->s_link) { X if (ls->s_type != seg) X continue; X if (ls->s_lsymb) { X (void) printf("%u$:\n", ls->s_lsymb); X return; /* Set last */ X } X if (ls->s_glob) X (void) printf("\n\t.globl\t%s", ls->s_name); X (void) printf("\n%s:\n", ls->s_name); X } X} X X/* X * Print out text. X */ X Xvoid ptext(fid) Xregister ef_fid fid; X{ X register long tpos, endt; X t_entry tstr; X X (void) printf(".text\n"); X X tpos = fid->ef_tbase; X endt = tpos + fid->ef_tsize; Xcontin: X for (; tpos < endt; tpos += tstr.t_lng * 2) { X gette(fid, tpos, &tstr); X plabs(tstr.t_lab, S_TEXT); X if (tstr.t_type == T_BEGIN) X prinst(&tstr, tpos); X else if (tstr.t_relsymb != NULL) { X (void) printf("\t.long\t%s", tstr.t_relsymb->s_name); X if (tstr.t_relsymb->s_type!=S_TEXT && X tstr.t_relsymb->s_type!=S_DATA) X (void) printf("+0x%x", gettw(fid, tpos, R_LONG)); X putchar('\n'); X tpos += 4; X goto contin; X } X else X (void) printf("\t.word\t0x%x\n", tstr.t_contents); X } X X /* X * Print out any trailing label. X */ X X gette(fid, tpos, &tstr); X plabs(tstr.t_lab, S_TEXT); X} X X/* X * Print out data. X */ X Xvoid pdata(fid) Xregister ef_fid fid; X{ X register long dpos, endd; X register int lng; X unsigned ctyp; X int had, par, inc; X char *msg; X d_entry dstr; X X (void) printf("\n.data\n"); X X dpos = fid->ef_dbase; X endd = dpos + fid->ef_dsize; X X while (dpos < endd) { X X getde(fid, dpos, &dstr); X plabs(dstr.d_lab, S_DATA); X X switch (dstr.d_type) { X case D_CONT: X (void) fprintf(stderr, "Data sync error\n"); X exit(200); X X case D_ASC: X case D_ASCZ: X ctyp = dstr.d_type; X lng = dstr.d_lng; X (void) printf("\t.asci"); X if (ctyp == D_ASC) X (void) printf("i\t\""); X else { X (void) printf("z\t\""); X lng--; X } X X while (lng > 0) { X getde(fid, dpos, &dstr); X switch (dstr.d_contents) { X default: X if (dstr.d_contents < ' ' || X dstr.d_contents > '~') X (void) printf("\\%.3o", dstr.d_contents); X else X putchar(dstr.d_contents); X break; X case '\"': X case '\'': X case '\\': X case '|': X (void) printf("\\%c", dstr.d_contents); X break; X case '\b': X (void) printf("\\b"); X break; X case '\n': X (void) printf("\\n"); X break; X case '\r': X (void) printf("\\r"); X break; X } X X lng--; X dpos++; X } X (void) printf("\"\n"); X if (ctyp == D_ASCZ) X dpos++; X break; X X case D_BYTE: X msg = "byte"; X par = R_BYTE; X inc = 1; X goto wrest; X X case D_WORD: X msg = "word"; X par = R_WORD; X inc = 2; X goto wrest; X X case D_LONG: X msg = "long"; X par = R_LONG; X inc = 4; X wrest: X (void) printf("\t.%s\t", msg); X lng = dstr.d_lng; X lpos = 16; X had = 0; X while (lng > 0) { X if (lpos > LINELNG) { X (void) printf("\n\t.%s\t", msg); X lpos = 16; X } X else if (had) X lpos += printf(", "); X X lpos += printf("0x%x", getdw(fid, dpos, par)); X lng -= inc; X dpos += inc; X had++; X } X putchar('\n'); X break; X X case D_ADDR: X (void) printf("\t.long\t"); X lng = dstr.d_lng; X lpos = 16; X had = 0; X while (lng > 0) { X if (lpos > LINELNG) { X (void) printf("\n\t.long\t"); X lpos = 16; X } X else if (had) X lpos += printf(", "); X X getde(fid, dpos, &dstr); X lpos += printf("%s", dstr.d_relsymb->s_name); X lng -= sizeof(long); X dpos += sizeof(long); X had++; X } X putchar('\n'); X break; X } X } X X /* X * Print trailing label. X */ X X getde(fid, dpos, &dstr); X plabs(dstr.d_lab, S_DATA); X} X Xvoid pbss(fid) Xregister ef_fid fid; X{ X register long bpos = fid->ef_bbase; X long endb = fid->ef_end; X d_entry bstr; X X (void) printf("\n.bss\n"); X X while (bpos < endb) { X getde(fid, bpos, &bstr); X plabs(bstr.d_lab, S_BSS); X (void) printf("\t.space\t%d\n", bstr.d_lng); X bpos += bstr.d_lng; X } X X getde(fid, endb, &bstr); X plabs(bstr.d_lab, S_BSS); X} END_OF_FILE if test 5515 -ne `wc -c <'prin.c'`; then echo shar: \"'prin.c'\" unpacked with wrong size! fi # end of 'prin.c' fi if test -f 'robj.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'robj.c'\" else echo shar: Extracting \"'robj.c'\" \(18405 characters\) sed "s/^X//" >'robj.c' <<'END_OF_FILE' X/* X * SCCS: @(#)robj.c 1.2 11/2/84 14:19:59 X * Read object files. X * X *********************************************************************** X * This software is copyright of X * X * John M Collins X * 47 Cedarwood Drive X * St Albans X * Herts, AL4 0DN X * England +44 727 57267 X * X * and is released into the public domain on the following conditions: X * X * 1. No free maintenance will be guaranteed. X * 2. Nothing may be based on this software without X * acknowledgement, including incorporation of this X * notice. X * X * Notwithstanding the above, the author welcomes correspondence and bug X * fixes. X *********************************************************************** X * X * This particular module will obviously have to be munged beyond X * recognition for another object format. X */ X X#include X#include X#include X#include X#include "unc.h" X Xvoid gette(), getde(), setde(), putte(), putde(); Xlong gettw(), getdw(); Xvoid reallst(), lclash(), nomem(), unimpl(); Xvoid addit(); Xchar *malloc(); Xlong lseek(); X Xint par_entry, par_round, nmods, donedrel, donebrel; Xstruct commit abstab, comtab, dreltab; Xlong trelpos, drelpos, brelpos; X Xint *symord; /* convert symbol index to symbol ordinal */ X Xef_fids mainfile; X Xsymbol lookup(), inventsymb(), getnsymb(); X X#define RWORD 1 X#define RLONG 2 X#define DBSIZE 100 X#define STINIT 20 X X/* X * Read text segment. Return 0 if not ok. X */ X Xint rtext(ldptr, outf) XLDFILE *ldptr; /* a.out file (possibly in library) */ Xef_fid outf; /* Output file descriptor */ X{ X t_entry tstr; X struct aouthdr unixhdr; X struct scnhdr sect; X register long size; X register int i, l; X unsigned short inbuf[DBSIZE/2]; X X /* X * Initialise fields in structure. X */ X X tstr.t_type = T_UNKNOWN; X tstr.t_vins = 1; /* For the moment */ X tstr.t_bdest = 0; X tstr.t_gbdest = 0; X tstr.t_lng = 1; X tstr.t_reloc = R_NONE; X tstr.t_rdisp = 0; X tstr.t_isrel = 0; X tstr.t_amap = 0; X tstr.t_dref = 0; X tstr.t_relsymb = NULL; X tstr.t_reldisp = 0; X tstr.t_lab = NULL; X tstr.t_lsymb = 0; X tstr.t_refhi = 0; X tstr.t_reflo = 0x7fffffff; X tstr.t_match = 0; X X /* X * Read a.out header. X */ X X if (ldohseek(ldptr) == FAILURE) { /* no optional header */ X X outf->ef_entry = 0; X ldshread(ldptr,1,§); /* text header */ X outf->ef_tbase = sect.s_vaddr; X outf->ef_tsize = sect.s_size; X X ldshread(ldptr,2,§); /* data header */ X outf->ef_dbase = sect.s_vaddr; X outf->ef_dsize = sect.s_size; X X ldshread(ldptr,3,§); /* bss header */ X outf->ef_bbase = sect.s_vaddr; X outf->ef_bsize = sect.s_size; X outf->ef_end = sect.s_vaddr + sect.s_size; X } else { X FREAD((char *)&unixhdr,sizeof(struct aouthdr),1,ldptr); X X if ( N_BADMAG(unixhdr) ) X return 0; X X outf->ef_entry = unixhdr.entry; X outf->ef_tbase = unixhdr.text_start; X outf->ef_dbase = unixhdr.data_start; X outf->ef_bbase = outf->ef_dbase + unixhdr.dsize; X outf->ef_end = outf->ef_bbase + unixhdr.bsize; X X outf->ef_tsize = unixhdr.tsize; X outf->ef_dsize = unixhdr.dsize; X outf->ef_bsize = unixhdr.bsize; X } X X ldsseek(ldptr,1); /* seek to text section */ X X size = outf->ef_tsize; X X while (size > 1) { X l = size > DBSIZE? DBSIZE: size; X if (FREAD((char *)inbuf,1,l,ldptr) != l) X return 0; X l /= 2; X for (i = 0; i < l; i++) { X tstr.t_contents = inbuf[i]; X (void) write(outf->ef_t, (char *)&tstr, sizeof(tstr)); X } X size -= l + l; X } X X /* X * Extra one to cope with "etext". X */ X X (void) write(outf->ef_t, (char *)&tstr, sizeof(tstr)); X return 1; X} X/* X * Same sort of thing for the data segment. X */ X Xint rdata(ldptr, outf) XLDFILE *ldptr; /* a.out file (possibly in library) */ Xef_fid outf; /* Output file descriptor */ X{ X d_entry dstr; X register long size; X register int i, l; X unsigned char inbuf[DBSIZE]; X X /* X * Initialise fields in structure. X */ X X dstr.d_type = D_BYTE; X dstr.d_reloc = R_NONE; X dstr.d_lng = 1; X dstr.d_relsymb = NULL; X dstr.d_reldisp = 0; X dstr.d_lab = NULL; X X ldsseek(ldptr,2); /* seek to data section */ X X size = outf->ef_dsize; X X while (size > 0) { X l = size > DBSIZE? DBSIZE: size; X if (FREAD((char *)inbuf,1,l,ldptr) != l) X return 0; X for (i = 0; i < l; i++) { X dstr.d_contents = inbuf[i]; X (void) write(outf->ef_d, (char *)&dstr, sizeof(dstr)); X } X size -= l; X } X X /* X * Repeat for BSS segment. X */ X X dstr.d_contents = 0; X for (size = outf->ef_bsize; size > 0; size--) X (void) write(outf->ef_d, (char *)&dstr, sizeof(dstr)); X X /* X * Extra one to cope with "end". X */ X X (void) write(outf->ef_d, (char *)&dstr, sizeof(dstr)); X return 1; X} X X/* X * Process symbol table segment. X */ X Xint rsymb(ldptr, dproc, outf) XLDFILE *ldptr; /* a.out file (possibly in library) */ Xsymbol (*dproc)(); Xregister ef_fid outf; /* Output file descriptor */ X{ X#define SYMLENGTH 256 X register symbol csym; X struct syment isym; X register int nsyms,symindex; X unsigned long stroff; X char inbuf[SYMLENGTH+1], *cp; X int ord; X X nsyms = HEADER(ldptr).f_nsyms; X stroff = HEADER(ldptr).f_symptr + nsyms*sizeof(struct syment); X X if (nsyms <= 0) X nsyms = STINIT; X X outf->ef_stvec = (symbol *) malloc(nsyms * sizeof(symbol)); X symord = (int *) malloc(nsyms * sizeof(int)); X if (outf->ef_stvec == NULL) X nomem(); X X outf->ef_stcnt = 0; X outf->ef_stmax = nsyms; X ord = 0; X X for (symindex=0; symindex= SYMLENGTH )/* Check against buffer overflow */ X return 0; X } while (*cp++ != '\0');/* Terminate on null byte */ X } else { /* get from symbol field */ X strncpy(inbuf,isym.n_name,8); X inbuf[8] = '\0'; X } X csym = (*dproc)(lookup(inbuf), convtosun(&isym), X isym.n_value, outf); X if (outf->ef_stcnt >= outf->ef_stmax) X reallst(outf); X outf->ef_stvec[outf->ef_stcnt++] = csym; X symord[symindex] = ord++; /* record ordinal */ X symindex += isym.n_numaux; /* skip aux entries */ X } X return 1; X} X X/* X * Process relocation stuff. -1 error, 0 no relocation, 1 relocation. X */ X Xint rrel(ldptr, ldptr2, outf) XLDFILE *ldptr,*ldptr2; /* a.out file (possibly in library) */ Xef_fid outf; /* Output file descriptor */ X{ X struct reloc crel; X struct scnhdr tsect,dsect; X struct syment isym; X t_entry tstr; X d_entry dstr; X register int nreloc; X long cont, pos; X X ldshread(ldptr,1,&tsect); X ldshread(ldptr,2,&dsect); X if (tsect.s_nreloc <= 0 && dsect.s_nreloc <= 0) X return 0; X X nreloc = tsect.s_nreloc; X X ldrseek(ldptr,1); X while (nreloc-- > 0) { X if (FREAD((char *)&crel, sizeof(crel),1,ldptr) != 1) X return -1; X X pos = crel.r_vaddr; X gette(outf, pos, &tstr); X if (crel.r_type == R_ABS) X tstr.t_reloc = R_NONE; X else X tstr.t_reloc = R_LONG; /* what about PC-relative? */ X ldtbread(ldptr2,crel.r_symndx,&isym); X if (isym.n_sclass == C_EXT) { X tstr.t_relsymb = outf->ef_stvec[symord[crel.r_symndx]]; X tstr.t_reldisp = gettw(outf, pos, (int)tstr.t_reloc); X } X else { X cont = gettw(outf, pos, (int)tstr.t_reloc); X tstr.t_relsymb = getnsymb(outf, convtosun(&isym), cont); X } X tstr.t_relsymb->s_used++; X putte(outf, pos, &tstr); X } X X /* X * And now repeat all that for data relocations. X */ X X nreloc = dsect.s_nreloc; X X ldrseek(ldptr,2); X while (nreloc-- > 0) { X if (FREAD((char *)&crel, sizeof(crel),1,ldptr) != 1) X return -1; X X pos = crel.r_vaddr; X getde(outf, pos, &dstr); X if (crel.r_type == R_ABS) X dstr.d_reloc = R_NONE; X else X dstr.d_reloc = R_LONG; /* what about PC-relative? */ X X ldtbread(ldptr2,crel.r_symndx,&isym); X if (isym.n_sclass == C_EXT) { X dstr.d_relsymb = outf->ef_stvec[symord[crel.r_symndx]]; X dstr.d_reldisp = getdw(outf, pos, (int)dstr.d_reloc); X } X else { X cont = getdw(outf, pos, (int)dstr.d_reloc); X dstr.d_relsymb = getnsymb(outf, convtosun(&isym), cont); X if (dstr.d_relsymb->s_type == S_TEXT) { X gette(outf, cont, &tstr); X tstr.t_dref = 1; X putte(outf, cont, &tstr); X } X } X switch (dstr.d_reloc) { X default: X unimpl("Data byte relocation"); X break; X case R_WORD: X unimpl("data word reloc"); X dstr.d_type = D_WORD; X dstr.d_lng = 2; X setde(outf, pos+1, D_CONT, 1); X break; X case R_LONG: X dstr.d_type = D_ADDR; X dstr.d_lng = 4; X setde(outf, pos+1, D_CONT, 1); X setde(outf, pos+2, D_CONT, 1); X setde(outf, pos+3, D_CONT, 1); X break; X } X dstr.d_relsymb->s_used++; X putde(outf, pos, &dstr); X } X return 1; X} X X/* X * Process a symbol. X */ X Xsymbol dosymb(sy, type, val, fid) Xregister symbol sy; Xint type; Xlong val; Xef_fid fid; X{ X t_entry tstr; X d_entry dstr; X X if (!sy->s_newsym) { X if (type & S_EXT) { X (void) fprintf(stderr, "Duplicate symbol %s\n", sy->s_name); X /* exit(10); temporary? */ X } X if (++sy->s_defs > nmods) X nmods = sy->s_defs; X sy = inventsymb("DUP"); X } X X sy->s_value = val; X X switch (type) { X default: X return NULL; X X case S_EXT|S_UNDF: X if (val != 0) { X sy->s_type = S_COMM; X addit(&comtab, sy); X } X else X sy->s_type = S_UNDF; X sy->s_glob = 1; X break; X X case S_EXT|S_ABS: X sy->s_type = S_ABS; X sy->s_glob = 1; X addit(&abstab, sy); X break; X X case S_ABS: X sy->s_type = S_ABS; X addit(&abstab, sy); X break; X X case S_EXT|S_TEXT: X case S_TEXT: X sy->s_type = S_TEXT; X gette(fid, val, &tstr); X tstr.t_bdest = 1; X if (type & S_EXT) { X tstr.t_gbdest = 1; X sy->s_glob = 1; X } X sy->s_link = tstr.t_lab; X tstr.t_lab = sy; X putte(fid, val, &tstr); X break; X X case S_BSS: X case S_EXT|S_BSS: X sy->s_type = S_BSS; X goto datrest; X case S_DATA: X case S_EXT|S_DATA: X sy->s_type = S_DATA; X datrest: X getde(fid, val, &dstr); X if (type & S_EXT) X sy->s_glob = 1; X sy->s_link = dstr.d_lab; X dstr.d_lab = sy; X putde(fid, val, &dstr); X break; X } X X sy->s_newsym = 0; X return sy; X} X X X/* X * Process relocation stuff in putative library modules. X * The main function of all this is to mark which bits of the text X * not to look at as I compare the stuff. X * X * As with "rrel", return -1 error, 0 no relocation, 1 relocation. X */ X Xint rrell1(ldptr, outf) XLDFILE *ldptr; /* a.out file (possibly in library) */ Xef_fid outf; /* Output file descriptor */ X{ X struct reloc crel; X struct scnhdr tsect,dsect; X t_entry tstr; X register int nreloc; X long pos; X X ldshread(ldptr,1,&tsect); X ldshread(ldptr,2,&dsect); X if (tsect.s_nreloc <= 0 && dsect.s_nreloc <= 0) X return 0; X X nreloc = tsect.s_nreloc; X X ldrseek(ldptr,1); X while (nreloc-- > 0) { X if (FREAD((char *)&crel, sizeof(crel),1,ldptr) != 1) X return -1; X X pos = crel.r_vaddr; X gette(outf, pos, &tstr); X if (crel.r_type == R_ABS) X tstr.t_reloc = R_NONE; X else X tstr.t_reloc = R_LONG; /* what about PC-relative? */ X tstr.t_isrel = 1; X putte(outf, pos, &tstr); X if (tstr.t_reloc == R_LONG) { X gette(outf, pos+2, &tstr); X tstr.t_isrel = 1; X putte(outf, pos+2, &tstr); X } X } X X /* X * Dont bother with data relocation at this stage. We'll X * tie that up later. X */ X X return 1; X} X X/* X * Process a symbol in library file. The extern variable trelpos gives X * the place in the main file where the library module is relocated. X * We don't know the data position until we do the final merge, perhaps X * not even then. X */ X/* trelpos ??? */ X Xsymbol dolsymb(sy, type, val, fid) Xregister symbol sy; Xint type; Xlong val; Xef_fid fid; X{ X t_entry tstr; X X switch (type) { X default: X return NULL; X X case S_EXT|S_UNDF: X if (!sy->s_newsym) X return sy; X sy->s_value = val; X if (val != 0) { X sy->s_type = S_COMM; X addit(&dreltab, sy); X } X else X sy->s_type = S_UNDF; X sy->s_glob = 1; X break; X X case S_EXT|S_ABS: X if (!sy->s_newsym) { X if (sy->s_type != S_ABS || sy->s_value != val) X lclash("abs"); X } X sy->s_type = S_ABS; X sy->s_value = val; X sy->s_glob = 1; X addit(&abstab, sy); X break; X X case S_EXT|S_TEXT: X sy->s_type = S_TEXT; X val += trelpos - fid->ef_tbase; X if (!sy->s_newsym) { X if (val != sy->s_value) X lclash("tsym"); X return sy; X } X sy->s_value = val; X gette(&mainfile, val, &tstr); X tstr.t_bdest = 1; X tstr.t_gbdest = 1; X sy->s_glob = 1; X sy->s_link = tstr.t_lab; X tstr.t_lab = sy; X putte(&mainfile, val, &tstr); X break; X X case S_EXT|S_BSS: X if (!sy->s_newsym) X return sy; X sy->s_type = S_BSS; X sy->s_value = val - fid->ef_bbase; X goto datrest; X X case S_EXT|S_DATA: X if (!sy->s_newsym) X return sy; X sy->s_type = S_DATA; X sy->s_value = val - fid->ef_dbase; X datrest: X sy->s_glob = 1; X addit(&dreltab, sy); X break; X } X X sy->s_newsym = 0; X return sy; X} X X/* X * Change definition of undefined symbol as we define it. X */ X Xvoid reassign(sy, val) Xregister symbol sy; Xlong val; X{ X sy->s_value = val; X X if (val < mainfile.ef_tbase) { X sy->s_type = S_ABS; X addit(&abstab, sy); X } X else if (val < mainfile.ef_dbase) { X t_entry tstr; X X sy->s_type = S_TEXT; X gette(&mainfile, val, &tstr); X tstr.t_bdest = 1; X tstr.t_gbdest = 1; X sy->s_glob = 1; X sy->s_link = tstr.t_lab; X tstr.t_lab = sy; X putte(&mainfile, val, &tstr); X } X else { X d_entry dstr; X X sy->s_type = val < mainfile.ef_bbase? S_DATA: S_BSS; X getde(&mainfile, val, &dstr); X sy->s_link = dstr.d_lab; X dstr.d_lab = sy; X putde(&mainfile, val, &dstr); X } X} X X/* X * When we discover where bss or data come, reallocate the table. X */ X Xvoid zapdat(seg, inc) Xint seg; Xlong inc; X{ X register int i; X register symbol csymb; X d_entry dent; X X for (i = 0; i < dreltab.c_int; i++) { X csymb = dreltab.c_symb[i]; X if (csymb->s_type != seg) X continue; X csymb->s_value += inc; X getde(&mainfile, csymb->s_value, &dent); X csymb->s_link = dent.d_lab; X dent.d_lab = csymb; X putde(&mainfile, csymb->s_value, &dent); X } X} X X/* X * Process relocation stuff in library module which we are inserting. X * Horrors if something goes wrong. X */ X/* trelpos, drelpos ??? */ X Xrrell2(ldptr, ldptr2, outf) XLDFILE *ldptr,*ldptr2; /* a.out file (possibly in library) */ Xef_fid outf; /* Output file descriptor */ X{ X struct reloc crel; X t_entry mtstr; X d_entry mdstr; X struct scnhdr tsect,dsect; X struct syment isym; X int nreloc; X unsigned rtype; X register long size; X register symbol csymb; X long pos, mpos, mval, lval; X int dhere = 0; /* Mark whether bss done */ X X ldshread(ldptr,1,&tsect); X ldshread(ldptr,2,&dsect); X if (tsect.s_nreloc <= 0 && dsect.s_nreloc <= 0) X return 0; X X nreloc = tsect.s_nreloc; X X ldrseek(ldptr,1); X while (nreloc-- > 0) { X if (FREAD((char *)&crel, sizeof(crel),1,ldptr) != 1) X lclash("rd trel"); X X pos = crel.r_vaddr; X mpos = crel.r_vaddr + trelpos; X gette(&mainfile, mpos, &mtstr); X if (crel.r_type == R_ABS) X rtype = R_NONE; X else X rtype = R_LONG; /* what about PC-relative? */ X ldtbread(ldptr2,crel.r_symndx,&isym); X lval = gettw(outf, pos, (int)rtype); X mval = gettw(&mainfile, mpos, (int)rtype); X X if ( isym.n_sclass != C_EXT ) { X switch (convtosun(&isym)) { X case S_TEXT: X if (lval + trelpos - outf->ef_tbase != mval) X lclash("Trel"); X continue; X case S_DATA: X if (donedrel) { X if (lval + drelpos - outf->ef_dbase != mval) X lclash("Drel"); X } X else { X donedrel++; X drelpos = mval - lval + outf->ef_dbase; X } X continue; X case S_BSS: X if (donebrel) { X if (lval + brelpos - outf->ef_bbase != mval) X lclash("brel"); X } X else { X donebrel++; X brelpos = mval - lval + outf->ef_bbase; X } X continue; X } X } else { X if (crel.r_symndx >= outf->ef_stcnt) X lclash("Bad sy no"); X csymb = outf->ef_stvec[symord[crel.r_symndx]]; X if (csymb == NULL) X continue; X switch (csymb->s_type) { X case S_UNDF: X reassign(csymb, mval - lval); X break; X case S_ABS: X if (lval + csymb->s_value != mval) X lclash("abs rel"); X break; X case S_TEXT: X if (lval + csymb->s_value != mval) X lclash("text rel"); X break; X case S_DATA: X if (lval + csymb->s_value != mval) X lclash("data rel"); X break; X case S_BSS: X if (lval + csymb->s_value != mval) X lclash("bss rel"); X break; X case S_COMM: X reassign(csymb, mval - lval); X break; X } X mtstr.t_relsymb = csymb; X mtstr.t_reldisp = lval; X } X } X X /* X * Relocate data and bss if possible. X */ X X if (donebrel) { X zapdat(S_BSS, brelpos); X dhere++; X } X X if (!donedrel) X return; X X X zapdat(S_DATA, drelpos); X X /* X * And now repeat all that for data relocations if possible X */ X X nreloc = tsect.s_nreloc; X X ldrseek(ldptr,2); X X while (nreloc-- > 0) { X if (FREAD((char *)&crel, sizeof(crel),1,ldptr) != 1) X lclash("Rd drel"); X X if (crel.r_type == R_ABS) X continue; X X pos = crel.r_vaddr; X mpos = crel.r_vaddr + drelpos; X getde(&mainfile, mpos, &mdstr); X rtype = R_LONG; /* what about PC-relative? */ X ldtbread(ldptr2,crel.r_symndx,&isym); X X lval = getdw(outf, pos, (int)rtype); X mval = getdw(&mainfile, mpos, (int)rtype); X if ( isym.n_sclass != C_EXT ) { X switch (convtosun(&isym)) { X case S_TEXT: X if (lval + trelpos - outf->ef_tbase != mval) X lclash("Trel-d"); X continue; X case S_DATA: X if (lval + drelpos - outf->ef_dbase != mval) X lclash("Drel-d"); X continue; X case S_BSS: X if (donebrel) { X if (lval + brelpos - outf->ef_bbase != mval) X lclash("brel"); X } X else { X donebrel++; X brelpos = mval - lval + outf->ef_bbase; X } X continue; X } X } else { X if (crel.r_symndx >= outf->ef_stcnt) X lclash("Bad sy no"); X csymb = outf->ef_stvec[symord[crel.r_symndx]]; X if (csymb == NULL) X continue; X switch (csymb->s_type) { X case S_UNDF: X reassign(csymb, mval - lval); X break; X case S_ABS: X if (lval + csymb->s_value != mval) X lclash("abs rel"); X break; X case S_TEXT: X if (lval + csymb->s_value != mval) X lclash("text rel"); X break; X case S_DATA: X if (lval + csymb->s_value != mval) X lclash("data rel"); X break; X case S_BSS: X if (lval + csymb->s_value != mval) X lclash("bss rel"); X break; X case S_COMM: X reassign(csymb, mval - lval); X break; X } X mtstr.t_relsymb = csymb; X mtstr.t_reldisp = lval; X } X } X X if (dhere || !donebrel) X return; X X zapdat(S_BSS, brelpos); X} END_OF_FILE if test 18405 -ne `wc -c <'robj.c'`; then echo shar: \"'robj.c'\" unpacked with wrong size! fi # end of 'robj.c' fi if test -f 'unc.h' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'unc.h'\" else echo shar: Extracting \"'unc.h'\" \(5112 characters\) sed "s/^X//" >'unc.h' <<'END_OF_FILE' X/* X * SCCS: @(#)unc.h 1.2 11/2/84 14:21:02 X * Header file for uncompile program. X * X *********************************************************************** X * This software is copyright of X * X * John M Collins X * 47 Cedarwood Drive X * St Albans X * Herts, AL4 0DN X * England +44 727 57267 X * X * and is released into the public domain on the following conditions: X * X * 1. No free maintenance will be guaranteed. X * 2. Nothing may be based on this software without X * acknowledgement, including incorporation of this X * notice. X * X * Notwithstanding the above, the author welcomes correspondence and bug X * fixes. X *********************************************************************** X */ X X#define MAXCHARS 50 X#define HASHMOD 97 X X/* X * The following structure is used to keep track of symbols. X */ X Xstruct symstr { X struct symstr *s_next; /* Next in hash chain */ X struct symstr *s_link; /* Next in duplicate labels */ X unsigned s_type : 5; /* Symbol type */ X unsigned s_newsym: 1; /* A new symbol */ X unsigned s_invent: 1; /* Invented symbol */ X unsigned s_glob : 1; /* Global symbol */ X long s_value; /* Value if defined */ X short s_defs; /* Defined count */ X short s_used; /* Used count */ X unsigned short s_lsymb; /* Local symbol */ X char s_name[1]; /* Chars of name null term */ X}; X Xtypedef struct symstr *symbol; X Xsymbol symbhash[HASHMOD]; X Xtypedef struct { X int ef_t; /* Text file fd */ X int ef_d; /* Data file fd */ X long ef_entry; /* Entry point */ X long ef_tsize; /* Text size */ X long ef_dsize; /* Data size */ X long ef_bsize; /* Bss size */ X long ef_end; /* End of it all */ X long ef_tbase; /* Text base */ X long ef_dbase; /* Data base */ X long ef_bbase; /* Bss base */ X int ef_stcnt; /* Number of symbols */ X int ef_stmax; /* Max number of symbols */ X symbol *ef_stvec; /* Symbol vector */ X} ef_fids; X Xtypedef ef_fids *ef_fid; X X/* X * Description of word in text file. This entry is held in the place X * corresponding to the address in the text file. X */ X Xtypedef struct { X unsigned short t_contents; /* Actual contents */ X unsigned short t_iindex; /* Index in table */ X unsigned t_type : 2; /* Type */ X unsigned t_vins : 1; /* Valid instruction */ X unsigned t_bdest : 1; /* Is branch dest */ X unsigned t_gbdest: 1; /* Is global dest */ X unsigned t_dref : 1; /* Refered to in data */ X unsigned t_bchtyp: 2; /* Branch type */ X unsigned t_lng : 3; /* Length in words */ X unsigned t_reloc : 2; /* Relocatable */ X unsigned t_rptr : 2; /* Where relocated */ X unsigned t_rdisp : 1; /* Relocatable displacement */ X unsigned t_isrel : 1; /* Relocated */ X unsigned t_amap : 1; /* Worked out */ X symbol t_relsymb; /* Relocation symbol */ X long t_reldisp; /* Offset + or - from symb */ X symbol t_lab; /* Label */ X unsigned short t_lsymb; /* Local symbol */ X long t_reflo; /* Lowest place referred */ X long t_refhi; /* Highest place referred */ X unsigned short t_match; /* Lib match lng */ X} t_entry; X X/* X * Types ...... X */ X X#define T_UNKNOWN 0 X#define T_BEGIN 1 X#define T_CONT 2 X X#define R_NONE 0 /* No relocation */ X#define R_BYTE 1 /* Byte relocation */ X#define R_WORD 2 /* Word relocation */ X#define R_LONG 3 /* Long relocation */ X X/* X * Branch types. X */ X X#define T_NOBR 0 X#define T_CONDBR 1 X#define T_UNBR 2 X#define T_JSR 3 X Xtypedef struct { X unsigned char d_contents; /* Actual contents */ X unsigned d_type : 4; /* Data type */ X unsigned d_reloc : 2; /* Relocatable */ X unsigned d_rptr : 2; /* Where relocated */ X short d_lng; /* Length -ve for D_CONT */ X symbol d_relsymb; /* Relocation symbol */ X long d_reldisp; /* Offset + or - from symb */ X symbol d_lab; /* Label */ X} d_entry; X X/* X * Data types. X */ X X#define D_ASC 0 /* Ascii chars */ X#define D_ASCZ 1 /* Null-term ascii */ X#define D_BYTE 2 /* Decimal bytes */ X#define D_WORD 3 /* Words */ X#define D_LONG 4 /* Longs */ X#define D_ADDR 5 /* Address pointer */ X#define D_CONT 6 /* Continuation of last */ X X/* X * 'Common' items. X */ X Xstruct commit { X symbol *c_symb; /* List of symbols */ X int c_int; /* Current number */ X int c_max; /* Maximum */ X}; X X/* X * Library file description. X */ X Xstruct libit { X LDFILE *ldptr,*ldptr2; /* independent file pointer packages X for the same file */ X char lf_name[14]; /* Name of item */ X}; X X/* magic number stuff like Sun */ X#define OMAGIC 0407 X#define NMAGIC 0410 X#define ZMAGIC 0413 X#define N_BADMAG(x) \ X (((x).magic)!=OMAGIC && ((x).magic)!=NMAGIC && ((x).magic)!=ZMAGIC) X X/* definitions of type for Sun -- used for symstr.type, d_entry.d_rptr */ X#define S_UNDF 0x0 /* undefined */ X#define S_ABS 0x2 /* absolute */ X#define S_TEXT 0x4 /* text */ X#define S_DATA 0x6 /* data */ X#define S_BSS 0x8 /* bss */ X#define S_COMM 0x12 /* common (internal to ld) */ X#define S_FN 0x1f /* file name symbol */ X#define S_EXT 01 /* external bit, or'ed in */ X#define S_TYPE 0x1e /* mask for all the type bits */ END_OF_FILE if test 5112 -ne `wc -c <'unc.h'`; then echo shar: \"'unc.h'\" unpacked with wrong size! fi # end of 'unc.h' fi echo shar: End of archive 2 \(of 2\). cp /dev/null ark2isdone MISSING="" for I in 1 2 ; do if test ! -f ark${I}isdone ; then MISSING="${MISSING} ${I}" fi done if test "${MISSING}" = "" ; then echo You have unpacked both archives. echo "Read the README* files for more info" rm -f ark[1-9]isdone else echo You still need to unpack the following archives: echo " " ${MISSING} fi ## End of shell archive. exit 0 -- Lenny Tropiano ICUS Software Systems [work] +1 (516) 582-5525 lenny@icus.islp.ny.us Telex: 154232428 ICUS [home] +1 (516) 968-8576 {talcott,boulder,hombre,pacbell,sbcs}!icus!lenny attmail!icus!lenny ICUS Software Systems -- PO Box 1; Islip Terrace, NY 11752