UNIX PC COFF Disassembler (Part 2 of 2)
Lenny Tropiano
lenny at icus.islp.ny.us
Tue Sep 27 10:35:46 AEST 1988
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 <file", e.g.. If this archive is complete, you
# will see the following message at the end:
# "End of archive 2 (of 2)."
# Contents: heur.c libmtch.c main.c prin.c robj.c unc.h
# Wrapped by lenny at icus on Mon Sep 26 20:30:25 1988
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'heur.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'heur.c'\"
else
echo shar: Extracting \"'heur.c'\" \(9925 characters\)
sed "s/^X//" >'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 <stdio.h>
X#include <a.out.h>
X#include <ldfcn.h>
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 <stdio.h>
X#include <fcntl.h>
X#include <string.h>
X#include <a.out.h>
X#include <ar.h>
X#include <setjmp.h>
X#include <ldfcn.h>
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 <stdio.h>
X#include <fcntl.h>
X#include <a.out.h>
X#include <ldfcn.h>
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 <stdio.h>
X#include <a.out.h>
X#include <ldfcn.h>
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 <stdio.h>
X#include <a.out.h>
X#include <ldfcn.h>
X#include <string.h>
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<nsyms; symindex++) {
X ldtbread(ldptr,symindex,&isym);
X if (isym.n_zeroes == 0) { /* get from string table */
X FSEEK(ldptr,stroff + isym.n_offset,0);
X cp = inbuf;
X do {
X if (FREAD(cp,1,1,ldptr) != 1)/* Read symbol chars 1-by-1 */
X return 0;
X if ( cp - inbuf >= 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 at 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
More information about the Unix-pc.sources
mailing list