unix-pc dissassembler (2 of 2)
Alex S. Crain
alex at umbc3.UMD.EDU
Thu Oct 6 13:11:22 AEST 1988
#!/bin/sh
# shar: Shell Archiver (v1.22)
#
# Run the following text with /bin/sh to create:
# Makefile
# README.FIRST
# README.orig
# README.unixpc
# alloc.c
# conv.c
# doc.nr
# file.c
# heur.c
# main.c
# prin.c
# unc.h
#
sed 's/^X//' << 'SHAR_EOF' > Makefile &&
XCFLAGS=-O
XLDFLAGS=-s
XOBJS=alloc.o file.o libmtch.o robj.o iset.o prin.o heur.o main.o conv.o
XSHAREDLIB=/lib/shlib.ifile /lib/crt0s.o
X
Xdis: $(OBJS)
X $(LD) $(LDFLAGS) -o dis $(OBJS) $(SHAREDLIB) -lld
X
X$(OBJS): unc.h
SHAR_EOF
chmod 0644 Makefile || echo "restore of Makefile fails"
sed 's/^X//' << 'SHAR_EOF' > README.FIRST &&
X WARNING * WARNING * WARNING * WARNING * WARNING * WARNING * WARNING * WARNING
X
X The AT&T licence agreement specifically prohibits the dissassembly
X of propritory AT&T software. Be aware that use of this program on system
X software is in clear violation of that agreement. The author(s) of this
X software in no way incourage its use in any way shape or form for any reason
X whatsoever, and will not be held liable for anything ever if we can help it.
X
X WARNING * WARNING * WARNING * WARNING * WARNING * WARNING * WARNING * WARNING
SHAR_EOF
chmod 0644 README.FIRST || echo "restore of README.FIRST fails"
sed 's/^X//' << 'SHAR_EOF' > README.orig &&
XI have gotten many many requests to email this or post it, because of
Xits size email'ing it screws up most mailers, so i am submitting it to
Xmod.sources to be posted. Please note a major cavaet with this, it was
Xwritten under Unisoft's port of Unix so the a.out file that it uses
Xmore closely resembles the b.out.h file that most cross assemblers
X(e.g. greenhills) use. For the obvious reasons i have not included that
Xfile with the posting. I did not write this nor do i make any claim to
Xthat effect.
X
X turner at imagen.UUCP <talcott!topaz!Shasta!imagen!Jim.Turner>
X
X----------------------------
XThis is the 68000 disassembler mentioned on the net.
XIt is not my final version by any means, but I have found it extremely
Xuseful and it represents several weeks' work.
X
X John Collins. <jmc at inset.UUCP>
SHAR_EOF
chmod 0644 README.orig || echo "restore of README.orig fails"
sed 's/^X//' << 'SHAR_EOF' > README.unixpc &&
X***** README *****
X
XThis README superceeds all other README's.
X
XProgram History:
X This started out as the unc program, by John Collins. At that
Xtime it was a 68000 assembler for the UNISOFT unix environment. It was
Xposted to the net as a dissasembler for Suns, I don't know who
Xmodified it for the sun environment or if that was ever done, but
XJanet Walz taught it about COFF, using the existing assembly syntax, I
Xreworked the syntax to match the SGS syntax used by the unixpc (and
Xthe HP9000, I believe). Surprisingly, the code has remained resonably
Xcoherent during this time, and has remained well structured.
X
X
XCurrent Status:
X At best, dissassemblers are of dubious value to anyone but system
Xhackers and compiler writers. As I am both, I expect that this tool will
Xget used a great deal on *my* machine.
X
X The following features are supported
X 1) symbol resolution is done whenever possible. addresses abouve
X0x300000 are considered constants (on a unix-pc, ths shared libraries are
Xmapped in the address space above 0x300000)
X 2) the dissassembler will attempt to convert pc relative addresses
Xto label jumps, in that it will calculate the destination address and insert
Xa label at that point, if one is not already present.
X 3) the dissassembler decodes jump tables by recognising the swbeg
Xpsuedo instuction and treating the table as a list of offsets relative
Xto the start of the table. Again, label insertion is done where neccessary.
X
XTHe idea is that you should be able to do
X
X % dis foo > foo.s
X % as foo.s
X % ld foo.o
X
XThis is never completely possible, but it will work on some things. Remember
Xthat code originally linked to the shared libraries must be loaded with
X/lib/shlib.ifile. dis output will need a _start symbol inserted at the top
Xof the output file, as in:
X
X text
X global _start # insert this
X_start: # and this
X ...
X ...
X
XAlso note that the assembly output will already contain any necessary
Xlibrary routines, so linking to libraries will not be neccessary.
X
XBUGS:
X THere are certainly bugs present, and I while I offer no support,
XI will gladly accept bug reports and publish fixes as I have time. Send
Xbug reports to:
X
X alex at umbc3.ume.edu
X uunet!umbc3!nerwin!alex
X
X Alex Crain
X
X
SHAR_EOF
chmod 0644 README.unixpc || echo "restore of README.unixpc fails"
sed 's/^X//' << 'SHAR_EOF' > alloc.c &&
X/*
X * SCCS: @(#)alloc.c 1.2 11/2/84 14:17:20
X * Allocate space 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 <a.out.h>
X#include <setjmp.h>
X#include <ldfcn.h>
X#include "unc.h"
X
X#define STINC 10
X
Xchar *malloc(), *realloc();
Xchar *strncpy();
Xvoid gette(), getde(), setde(), putte(), putde();
Xvoid unimpl();
Xlong gettw();
X
Xef_fids mainfile;
X
X/*
X * Oops! out of memory.....
X */
X
Xvoid nomem()
X{
X (void) fprintf(stderr, "Sorry - run out of memory\n");
X exit(255);
X}
X
X/*
X * Look up hash value of symbol.
X */
X
Xunsigned shash(str)
Xregister char *str;
X{
X register unsigned result = 0;
X register int cnt = 0;
X
X while (*str && cnt < MAXCHARS) {
X result += *str++;
X cnt++;
X }
X return result % HASHMOD;
X}
X
X/*
X * Look up hash value of symbol, possibly allocating a new symbol.
X */
X
Xsymbol lookup(str)
Xchar *str;
X{
X register symbol res, *pp;
X register int len;
X
X pp = &symbhash[shash(str)];
X res = *pp;
X while (res != NULL) {
X if (strncmp(res->s_name, str, MAXCHARS) == 0)
X return res;
X pp = &res->s_next;
X res = *pp;
X }
X for (len = 0; len < MAXCHARS; len++)
X if (str[len] == '\0')
X break;
X len++;
X res = (symbol) malloc(sizeof(struct symstr) + len);
X if (res == NULL)
X nomem();
X *pp = res;
X res->s_next = NULL;
X (void) strncpy(res->s_name, str, len);
X res->s_name[len] = '\0'; /* Null-terminate */
X res->s_newsym = 1;
X res->s_glob = 0;
X res->s_invent = 0;
X res->s_link = NULL;
X res->s_used = 0;
X res->s_defs = 0;
X res->s_lsymb = 0;
X return res;
X}
X
X/*
X * Invent a symbol, making sure that we don't know it.
X */
X
Xsymbol inventsymb(prefix)
Xchar *prefix;
X{
X static int nsymb = 0;
X char schars[10];
X register symbol res;
X
X do (void) sprintf(schars, "%s%d", prefix, ++nsymb);
X while (!(res = lookup(schars))->s_newsym);
X
X res->s_newsym = 0;
X res->s_invent = 1;
X return res;
X}
X
X/*
X * Reallocate symbol table.
X */
X
Xvoid reallst(outf)
Xregister ef_fid outf;
X{
X outf->ef_stmax += STINC;
X if (outf->ef_stvec == NULL)
X outf->ef_stvec = (symbol *) malloc(outf->ef_stmax * sizeof(symbol));
X else
X outf->ef_stvec = (symbol *) realloc(outf->ef_stvec,
X outf->ef_stmax * sizeof(symbol));
X if (outf->ef_stvec == NULL)
X nomem();
X}
X
X/*
X * Search through existing symbol table for symbol with given
X * value. Invent a new one if needed.
X */
X
Xsymbol getnsymb(fid, seg, pos)
Xregister ef_fid fid;
Xunsigned seg;
Xlong pos;
X{
X register int i;
X register symbol res;
X
X /*********** MACHINE DEPENDENT ******************************
X * Convert relocation segment type (argument) to symbol type
X * (as remembered in symbol table). Don't ask me why they
X * have to be different.....
X */
X
X /*
X * See if the reference is to an external symbol.
X * If so, use that.
X */
X
X for (i = 0; i < fid->ef_stcnt; i++) {
X res = fid->ef_stvec[i];
X if (res->s_type == seg && res->s_value == pos)
X return res;
X }
X
X /*
X * Invent a symbol and use that.
X */
X
X res = inventsymb("RS");
X if (fid->ef_stcnt >= fid->ef_stmax)
X reallst(fid);
X fid->ef_stvec[fid->ef_stcnt++] = res;
X res->s_type = seg;
X res->s_value = pos;
X if (seg == S_TEXT) {
X t_entry tent;
X gette(fid, pos, &tent);
X tent.t_bdest = 1;
X tent.t_lab = res;
X putte(fid, pos, &tent);
X }
X else if (seg == S_DATA || seg == S_BSS) {
X d_entry dent;
X getde(fid, pos, &dent);
X dent.d_lab = res;
X putde(fid, pos, &dent);
X }
X
X return res;
X}
X
X/*
X * Assuming address given is in text segment, find its label, or invent
X * one. Also set where refered from.
X */
X
Xsymbol textlab(loc, refpos)
Xlong loc, refpos;
X{
X t_entry tent;
X
X gette(&mainfile, loc, &tent);
X if (tent.t_type == T_CONT)
X return NULL;
X if (tent.t_lab == NULL) {
X tent.t_lab = inventsymb("TS");
X tent.t_lab->s_type = S_TEXT;
X tent.t_lab->s_value = loc;
X tent.t_bdest = 1;
X putte(&mainfile, loc, &tent);
X }
X else
X tent.t_lab->s_used++;
X if (tent.t_refhi < refpos) {
X tent.t_refhi = refpos;
X putte(&mainfile, loc, &tent);
X }
X if (tent.t_reflo > refpos) {
X tent.t_reflo = refpos;
X putte(&mainfile, loc, &tent);
X }
X return tent.t_lab;
X}
X
X/*
X * Note references to data.
X */
X
Xvoid mkdref(tpos, size)
Xlong tpos;
Xunsigned size;
X{
X t_entry tent;
X d_entry dent;
X register symbol ds;
X int dchng = 0;
X int wsize;
X long dpos;
X
X gette(&mainfile, tpos, &tent);
X if (tent.t_relsymb != NULL)
X return;
X
X dpos = gettw(&mainfile, tpos, R_LONG);
X if (dpos < mainfile.ef_dbase || dpos > mainfile.ef_end)
X return;
X
X switch (size) {
X default:
X wsize = D_BYTE;
X break;
X case 2:
X wsize = D_WORD;
X break;
X case 4:
X wsize = D_LONG;
X break;
X }
X
X getde(&mainfile, dpos, &dent);
X if ((ds = dent.d_lab) == NULL) {
X if (dpos >= mainfile.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 = dpos;
X dent.d_lab = ds;
X dchng++;
X }
X else
X ds->s_used++;
X
X if (dent.d_type != D_BYTE) {
X if (dent.d_type != wsize) {
X if (dent.d_type == D_ADDR) {
X if (wsize != D_LONG)
X unimpl("Addr word usage");
X }
X else if (dent.d_type > wsize) {
X dchng++;
X dent.d_type = wsize;
X dent.d_lng = size;
X }
X }
X }
X else {
X dent.d_type = wsize;
X dent.d_lng = size;
X dchng++;
X }
X if (dchng) {
X putde(&mainfile, dpos, &dent);
X for (dchng = 1; dchng < size; dchng++)
X setde(&mainfile, dpos+dchng, D_CONT, 1);
X }
X
X tent.t_relsymb = ds;
X putte(&mainfile, tpos, &tent);
X}
X
X/*
X * Add item to common or abs list.
X */
X
X#define COMINC 10
X
Xvoid addit(cp, symb)
Xregister struct commit *cp;
Xsymbol symb;
X{
X if (cp->c_int >= cp->c_max) {
X cp->c_max += COMINC;
X if (cp->c_symb == NULL)
X cp->c_symb = (symbol *) malloc(COMINC*sizeof(symbol));
X else
X cp->c_symb = (symbol *)
X realloc(cp->c_symb,
X cp->c_max * sizeof(symbol));
X if (cp->c_symb == NULL)
X nomem();
X }
X cp->c_symb[cp->c_int++] = symb;
X}
SHAR_EOF
chmod 0644 alloc.c || echo "restore of alloc.c fails"
sed 's/^X//' << 'SHAR_EOF' > conv.c &&
X#include <stdio.h>
X#include <a.out.h>
X#include <ldfcn.h>
X#include "unc.h"
X
Xunsigned convtosun(sym)
Xstruct syment *sym;
X{
X unsigned suntype;
X
X /* everything in shlib is an external constant */
X if (sym->n_value >= 0x300000) {
X sym->n_scnum = N_ABS;
X sym->n_sclass = C_EXT;
X }
X switch(sym->n_scnum) {
X case N_UNDEF:
X case N_DEBUG: /* call things that don't map well "undefined" */
X case N_TV:
X case P_TV:
X suntype = S_UNDF;
X break;
X case N_ABS:
X suntype = S_ABS;
X break;
X case 1:
X suntype = S_TEXT;
X break;
X case 2:
X suntype = S_DATA;
X break;
X case 3:
X suntype = S_BSS;
X break;
X }
X
X if (sym->n_sclass == C_EXT)
X suntype = suntype | S_EXT;
X
X return(suntype);
X}
SHAR_EOF
chmod 0644 conv.c || echo "restore of conv.c fails"
sed 's/^X//' << 'SHAR_EOF' > doc.nr &&
X.\"/*% nroff -cm -rL72 %|epson|spr -f plain.a -h uncdoc -w
X.nr Hb 7
X.nr Hs 3
X.ds HF 3 3 3 3 3 3 3
X.nr Hu 5
X.nr Hc 1
X.SA 1
X.PH "''A Disassembler''"
X.PF "'Issue %I%'- Page \\\\nP -'%G%'"
X.H 1 "Introduction"
XThis document describes the first release of a disassembler for UNIX
Xexecutable files.
XThe key features are:
X.AL
X.LI
XFor object files the output can be assembled to generate the same
Xobject module, (apart from minor variations in symbol table ordering) as the
Xinput.
X.LI
XFor stripped executable files object modules and libraries may be scanned,
Xmodules in the main input identified and the appropriate names automatically
Xinserted into the output.
X.LI
XAn option is available to convert most non-global names into local symbols,
Xwhich cuts down the symbols in the generated assembler file.
X.LI
XThe disassembler copes reasonably with modules merged with the
X.B "-r"
Xoption to
X.B "ld" ,
Xgenerating a warning message as to the number of modules involved.
X.LE
X.P
XAt present this is available for certain Motorola 68000 ports of UNIX
XSystem III and System V. Dependencies on
X.AL a
X.LI
XInstruction set.
X.LI
XObject module format.
X.LI
XLibrary module format.
X.LI
XAssembler output format.
X.LE
X.P
Xare hopefully sufficiently localised to make the product useful as a
Xbasis for other disassemblers for other versions of UNIX.
X.P
XThe product is thus distributed in source form at present.
X.H 1 "Use"
XThe disassembler is run by entering:
X.DS I
Xunc mainfile lib1 lib2 ...
X.DE
X.P
XThe first named file is the file to be disassembled, which should be
Xa single file, either an object module, a (possibly stripped) executable
Xfile, or a library member. Library members are designated using a
Xparenthesis notation, thus:
X.DS I
Xunc '/lib/libc.a(printf.o)'
X.DE
X.P
XIt is usually necessary to escape the arguments in this case to prevent
Xmisinterpretation by the shell. Libraries in standard places such as
X.I "/lib"
Xand
X.I "/usr/lib"
Xmay be specified in the same way as to
X.B "ld" ,
Xthus
X.DS I
Xunc '-lc(printf.o)'
Xunc '-lcurses(wmove.o)'
X.DE
X.P
XAs an additional facility, the list of directories searched for
Xlibraries may be varied by setting the environment variable
X.B "LDPATH" ,
Xwhich is interpreted similarly to the shell
X.B "PATH"
Xvariable, and of course defaults to
X.DS I
XLDPATH=/lib:/usr/lib
X.DE
X.P
XAs a further facility, the insertion of
X.B "lib"
Xbefore and
X.B ".a"
Xafter the argument may be suppressed by using a capital
X.B "-L"
Xargument, thus to print out the assembler for
X.I "/lib/crt0.o" ,
Xthen the command
X.DS I
Xunc -Lcrt0.o
X.DE
X.P
Xshould have the desired effect.
X.P
XSecond and subsequent file arguments are only referenced for stripped
Xexecutable files, and may consist of single object files and library
Xmembers, using the same syntax as before, or whole libraries of object
Xfiles, thus:
X.DS I
Xunc strippedfile -Lcrt0.o -lcurses -ltermcap '-lm(sqrt.o)' -lc
X.DE
X.P
XIt is advisable to make some effort to put the libraries to be searched
Xin the order in which they were originally loaded. This is because the
Xsearch for each module starts where the previously matched module ended.
XHowever, no harm is done if this rule is not adhered to apart from
Xincreased execution time except in the rare cases where the disassembler
Xis confused by object modules which are very nearly similar.
X.H 1 "Additional options"
XThe following options are available to modify the behaviour of the
Xdisassembler.
X.VL 15 2
X.LI "-o file"
XCauses output to be sent to the specified file instead of the standard
Xoutput.
X.LI "-t prefix"
XCauses temporary files to be created with the given prefix. The default
Xprefix is
X.B "split" ,
Xthus causing two temporary files to be created with this prefix in the
Xcurrent directory. If it is desired, for example, to create the files as
X.B "/tmp/xx*" ,
Xthen the argument
X.B "-t /tmp/xx"
Xshould be given. Note that the temporary files may be very large as a
Xcomplete map of the text and data segments is generated.
X.LI "-a"
XSuppresses the generation of non-global absolute symbols from the
Xoutput. This saves output from C compilations without any obvious
Xproblems, but the symbols are by default included in the name of
Xproducing as nearly identical output as possible to the original source.
X.LI "-s"
XCauses an additional scan to take place where all possible labels are
Xreplaced by local symbols. The local symbols are inserted in strictly
Xascending order, starting at 1.
X.LI "-v"
XCauses a blow-by-blow account of activities to be output on the standard
Xerror.
X.LI "-V"
XCauses shlib symbol values to be printed at the top of the output, if they
Xexist in the symbol table. normally these are ommited because they are constant
Xvalues derived form the file /lib/shlib.ifile
X.LE
X.H 1 "Diagnostics etc"
XTruncated or garbled object and library files usually cause processing
Xto stop with an explanatory message.
X.P
XThe only other kinds of message are some passing warnings concerning
Xobscure constructs not handled, such as the relocation of byte fields,
Xor the relocation of overlapping fields. Occasionally a message
X.DS I
XLibrary clash: message
X.DE
X.P
Xmay appear and processing cease. This message is found where at a late
Xstage in processing libraries, the program discovers that due to the
Xextreme similarity of two or more library members, it has come to the
Xwrong conclusion about which one to use. The remedy here is to spell out
Xto the program which members to take in which order.
X.H 1 "Future development"
XIn the future it is hoped to devise ways of making the disassembler
Xindependent of all the above-mentioned version dependencies, by first
Xreading a files defining these things. This will probably be applied
Xafter the Common Object Format becomes more standard.
X.P
XIn the long term it would be desirable and useful to enhance the product
Xto produce compilable C in addition to assemblable assembler. Stages in
Xthe process are seen as follows:
X.AL
X.LI
XBetter identification of basic blocks in the code. Switch statements are
Xa major problem here, as are constant data held in the text segment.
X.LI
XMarrying of data to the corresponding text. It is in various places hard
Xto divorce static references "on the fly" (e.g. strings, and switch
Xlists in some implementations) from static at the head of a module. This
Xis part of the problem of identifying basic blocks.
X.LI
XCompilation of header files to work out structure references within the
Xtext. At this stage some interaction may be needed.
X.LE
X.P
XMeanwhile the product is one which is a useful tool to the author in its
Xpresent form. Comments and suggestions as to the most practical method
Xof improving the product in the ways suggested or in other ways would be
Xgratefully considered.
SHAR_EOF
chmod 0644 doc.nr || echo "restore of doc.nr fails"
sed 's/^X//' << 'SHAR_EOF' > file.c &&
X/*
X * SCCS: @(#)file.c 1.2 11/2/84 14:17:35
X * Various operations on 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 <a.out.h>
X#include <ldfcn.h>
X#include "unc.h"
X
Xlong lseek();
Xvoid unimpl();
X
X/*
X * Validate addr and get text entry corresponding to it from the given
X * file.
X */
X
Xvoid gette(fid, addr, te)
Xregister ef_fid fid;
Xregister long addr;
Xt_entry *te;
X{
X addr -= fid->ef_tbase;
X if (addr < 0x300000 &&
X (addr < 0 || addr > fid->ef_tsize || (addr & 1) != 0))
X {
X (void) fprintf(stderr, "Invalid text address %lx\n", addr);
X exit(200);
X }
X (void) lseek(fid->ef_t, (long)(addr * sizeof(t_entry)/2), 0);
X if (read(fid->ef_t, (char *) te, sizeof(t_entry)) != sizeof(t_entry)) {
X (void) fprintf(stderr, "Trouble reading text at %lx\n", addr);
X exit(201);
X }
X}
X
X/*
X * Store a text entry.
X */
X
Xvoid putte(fid, addr, te)
Xregister ef_fid fid;
Xregister long addr;
Xt_entry *te;
X{
X addr -= fid->ef_tbase;
X if (addr < 0x300000 &&
X (addr < 0 || addr > fid->ef_tsize || (addr & 1) != 0))
X {
X (void) fprintf(stderr, "Invalid text address %lx\n", addr);
X exit(200);
X }
X (void) lseek(fid->ef_t, (long)(addr * sizeof(t_entry)/2), 0);
X (void) write(fid->ef_t, (char *) te, sizeof(t_entry));
X}
X
X/*
X * Validate addr and get data entry corresponding to it from the given
X * file.
X */
X
Xvoid getde(fid, addr, de)
Xregister ef_fid fid;
Xregister long addr;
Xd_entry *de;
X{
X if (addr < 0x300000 && (addr < fid->ef_dbase || addr > fid->ef_end))
X {
X (void) fprintf(stderr, "Invalid data address %lx\n", addr);
X exit(200);
X }
X addr -= fid->ef_dbase;
X (void) lseek(fid->ef_d, (long)(addr * sizeof(d_entry)), 0);
X if (read(fid->ef_d, (char *) de, sizeof(d_entry)) != sizeof(d_entry)) {
X (void) fprintf(stderr, "Trouble reading data at %lx\n", addr);
X exit(201);
X }
X}
X
X/*
X * Store a data entry.
X */
X
Xvoid putde(fid, addr, de)
Xregister ef_fid fid;
Xregister long addr;
Xd_entry *de;
X{
X if (addr < 0x300000 &&
X (addr < fid->ef_dbase || addr > fid->ef_end))
X {
X (void) fprintf(stderr, "Invalid data address %lx\n", addr);
X exit(200);
X }
X addr -= fid->ef_dbase;
X (void) lseek(fid->ef_d, (long)(addr * sizeof(d_entry)), 0);
X (void) write(fid->ef_d, (char *) de, sizeof(d_entry));
X}
X
X/*
X * Set type and length of given data entry.
X */
X
Xvoid setde(fid, addr, type, lng)
Xef_fid fid;
Xlong addr;
Xunsigned type;
Xint lng;
X{
X d_entry dat;
X
X if (addr > fid->ef_end)
X return;
X getde(fid, addr, &dat);
X if (type == D_CONT && dat.d_reloc != R_NONE) {
X char obuf[30];
X (void) sprintf(obuf, "overlapped reloc 0x%x", addr);
X unimpl(obuf);
X }
X dat.d_type = type;
X dat.d_lng = lng;
X putde(fid, addr, &dat);
X}
X
X/*
X * Get a word of data file, size as requested.
X */
X
Xlong getdw(fid, pos, size)
Xregister ef_fid fid;
Xlong pos;
Xint size;
X{
X d_entry dat;
X register long res;
X register int i, lt;
X
X getde(fid, pos, &dat);
X
X switch (size) {
X case R_BYTE:
X return dat.d_contents;
X
X case R_LONG:
X lt = 4;
X goto rest;
X
X case R_WORD:
X lt = 2;
X rest:
X res = dat.d_contents;
X for (i = 1; i < lt; i++) {
X getde(fid, pos+i, &dat);
X res = (res << 8) + dat.d_contents;
X }
X return res;
X
X default:
X (void) fprintf(stderr, "Data word size error\n");
X exit(20);
X }
X /*NOTREACHED*/
X}
X
X/*
X * Get a word of text file.
X */
X
Xlong gettw(fid, pos, size)
Xregister ef_fid fid;
Xlong pos;
Xint size;
X{
X t_entry tex;
X long res;
X
X gette(fid, pos, &tex);
X
X switch (size) {
X case R_BYTE:
X return tex.t_contents >> 8;
X
X case R_WORD:
X return tex.t_contents;
X
X case R_LONG:
X res = tex.t_contents;
X gette(fid, pos+2, &tex);
X return (res << 16) + tex.t_contents;
X default:
X (void) fprintf(stderr, "Text< word size error\n");
X exit(20);
X }
X /*NOTREACHED*/
X}
SHAR_EOF
chmod 0644 file.c || echo "restore of file.c fails"
sed 's/^X//' << 'SHAR_EOF' > heur.c &&
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}
SHAR_EOF
chmod 0644 heur.c || echo "restore of heur.c fails"
sed 's/^X//' << 'SHAR_EOF' > main.c &&
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;
Xchar shlibout; /* output values for shlib constants */
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 'V':
X shlibout++;
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 setbuf(stdout,NULL);
X setbuf(stderr,NULL);
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}
SHAR_EOF
chmod 0644 main.c || echo "restore of main.c fails"
sed 's/^X//' << 'SHAR_EOF' > prin.c &&
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;
Xextern char shlibout;
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_value >= 0x300000 && ! shlibout)
X continue;
X if (cs->s_glob)
X (void) printf("#\tglobal\t%s\n", cs->s_name);
X else if (noabs)
X continue;
X (void) printf("# %s\t= 0x%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("\tcomm\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("L%%%u:\n", ls->s_lsymb);
X return; /* Set last */
X }
X if (ls->s_glob)
X (void) printf("\n\tglobal\t%s", ls->s_name);
X if (ls->s_name[0] == '.')
X (void) printf("\n# %s:\n", ls->s_name);
X else
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) fputs("\ttext\n", stdout);
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("\tlong\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 (void) putchar('\n');
X tpos += 4;
X goto contin;
X }
X else
X (void) printf("\tshort\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, ccnt;
X unsigned ctyp;
X int had, par, inc;
X char *msg;
X d_entry dstr;
X
X (void) fputs("\n\tdata\n", stdout);
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 dpos++;
X break;
X
X case D_ASC:
X case D_ASCZ:
X ctyp = dstr.d_type;
X lng = dstr.d_lng;
X nextline:
X (void) fputs("\tbyte\t", stdout);
X ccnt=0;
X while (lng > 0) {
X if (ccnt) (void) putchar(',');
X getde(fid, dpos, &dstr);
X switch (dstr.d_contents) {
X default:
X if (dstr.d_contents < ' ' ||
X dstr.d_contents > '~')
X ccnt += printf("0x%x", dstr.d_contents);
X else {
X (void) putchar('\'');
X (void)putchar(dstr.d_contents);
X ccnt += 2;
X }
X break;
X case '\\':
X (void) putchar('\'');
X (void) putchar('\\');
X (void) putchar('\\');
X ccnt+=2;
X break;
X case '\b':
X (void) putchar('\'');
X (void) putchar('\\');
X (void) putchar('b');
X ccnt+=2;
X break;
X case '\n':
X (void) putchar('\'');
X (void) putchar('\\');
X (void) putchar('n');
X ccnt+=2;
X break;
X case '\r':
X (void) putchar('\'');
X (void) putchar('\\');
X (void) putchar('r');
X ccnt+=2;
X break;
X case '\f':
X (void) putchar('\'');
X (void) putchar('\\');
X (void) putchar('f');
X ccnt+=2;
X break;
X case '\t':
X (void) putchar('\'');
X (void) putchar('\\');
X (void) putchar('t');
X ccnt+=2;
X break;
X }
X
X lng--;
X dpos++;
X if (++ccnt > 40 && lng > 0) {
X (void) putchar('\n');
X goto nextline;
X }
X }
X (void) putchar('\n');
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 = "short";
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) putchar('\t');
X (void) fputs(msg, stdout);
X (void) putchar('\t');
X lng = dstr.d_lng;
X lpos = 16;
X had = 0;
X while (lng > 0) {
X if (lpos > LINELNG) {
X (void) putchar('\n');
X (void) putchar('\t');
X (void) fputs(msg, stdout);
X (void) putchar('\t');
X lpos = 16;
X }
X else if (had) {
X (void) putchar(',');
X (void) putchar(' ');
X lpos += 2;
X }
X lpos += printf("0x%x", getdw(fid, dpos, par));
X lng -= inc;
X dpos += inc;
X had++;
X }
X (void) putchar('\n');
X break;
X
X case D_ADDR:
X (void) fputs("\tlong\t", stdout);
X lng = dstr.d_lng;
X lpos = 16;
X had = 0;
X while (lng > 0) {
X if (lpos > LINELNG) {
X (void) fputs("\n\tlong\t", stdout);
X lpos = 16;
X }
X else if (had) {
X (void) putchar(',');
X (void) putchar(' ');
X lpos += 2;
X }
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 (void) 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) fputs("\n# .bss\n", stdout);
X
X while (bpos < endb) {
X getde(fid, bpos, &bstr);
X plabs(bstr.d_lab, S_BSS);
X (void) printf("\tspace\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}
X
X
SHAR_EOF
chmod 0644 prin.c || echo "restore of prin.c fails"
sed 's/^X//' << 'SHAR_EOF' > unc.h &&
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_zilch : 3; /* used to be t_lng */
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 short t_lng; /* Length in words */
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 */
SHAR_EOF
chmod 0644 unc.h || echo "restore of unc.h fails"
exit 0
--
:alex.
Systems Programmer
nerwin!alex at umbc3.umd.edu UMBC
alex at umbc3.umd.edu
More information about the Unix-pc.sources
mailing list