[unix-pc.sources] UNIX PC COFF Disassembler

lenny@icus.islp.ny.us (Lenny Tropiano) (09/27/88)

Here's an UNIX PC disassembler (68000 assembly) that understands COFF
(Common Object File Format).  It creates output that has the appropriate
symbols in commands like ("jsr printf") and understands the symbols
in the string table and creates .asciz "<string>" (directives).

I didn't write this, but I thought it would be useful to the entire
UNIX PC community.  Especially for reverse engineering UNIX :-)

Enjoy,
Lenny

-- cut here -- -- cut here -- -- cut here -- -- cut here -- -- cut here --
#! /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 1 (of 2)."
# Contents:  Makefile README README.coff alloc.c conv.c doc.nr doc.out
#   file.c iset.c
# Wrapped by lenny@icus on Mon Sep 26 20:30:04 1988
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'Makefile' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'Makefile'\"
else
echo shar: Extracting \"'Makefile'\" \(214 characters\)
sed "s/^X//" >'Makefile' <<'END_OF_FILE'
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
Xunc:	$(OBJS)
X	$(LD) $(LDFLAGS) -o unc $(OBJS) $(SHAREDLIB) -lld
X
X$(OBJS):	unc.h
END_OF_FILE
if test 214 -ne `wc -c <'Makefile'`; then
    echo shar: \"'Makefile'\" unpacked with wrong size!
fi
# end of 'Makefile'
fi
if test -f 'README' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'README'\"
else
echo shar: Extracting \"'README'\" \(806 characters\)
sed "s/^X//" >'README' <<'END_OF_FILE'
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@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@inset.UUCP>
END_OF_FILE
if test 806 -ne `wc -c <'README'`; then
    echo shar: \"'README'\" unpacked with wrong size!
fi
# end of 'README'
fi
if test -f 'README.coff' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'README.coff'\"
else
echo shar: Extracting \"'README.coff'\" \(2737 characters\)
sed "s/^X//" >'README.coff' <<'END_OF_FILE'
X--------------------------------------
XCOFF DISASSEMBLER FOR THE AT&T UNIX pc
X--------------------------------------
XThis file by Lenny Tropiano, ICUS Software Systems -- September 26, 1988
X
XA while back I asked the "net" if anyone had a 68000 disassembler that
Xunderstood the COFF format for executable images.   A few people had replied, 
Xand I did receive a few good leads and two programs.  Most of the people 
Xsaid to get the "unc" disassembler that was posted to comp.sources.unix and
Xtry to work from there.  The unc diassembler worked for 68000 cpu's but
Xdidn't know anything about COFF format.  Some people said to work with the
XSUN patches and then teach it COFF.  This seemed like a big task for someone
Xwho didn't have much time on his hands.  
X
XWell then Janet Walz <walz@mimsy.umd.edu>, replied.  She said she taught
Xthe unc disassembler about COFF format, and it worked fine on the AT&T 
Xmachines.  I then asked if she would send me the patches.   After patiently
Xwaiting she kindly supplied a sharkit that had the new sources (she claimed
Xthat the patches were as *big* as the sources [which it looked like it was]).
X
XI'm not AT&T 68000 assembler expert, but I think the format that the 
X"unc" disassembler prints is sun format, which is fine if you are just
Xtrying to figure out what something is doing.   Tagged along with 
XMichael "Ford" Ditto's "unstrip" program that was posted to unix-pc.sources
Xa while back, one can put the shared library symbols back into source and
Xthen disassemble it.  This program puts generated-labels where appropriate
Xto show looping structures.  It does show .ascii and .asciz string blocks.
XIt has some very nice features, and it much better than the other solution
XI got that was a UNIX PC implementation of the "dis(1)" command that is
Xfound on the 3B2's System V release.
X
XWarning the program is awefully slow, and it does create large output files. 
XHere are some statistics running on my UNIX PC with 3MB of memory (and 
Xfairly loaded) for the follow disassembly of:
X
X$ cat > simple.c
Xmain()
X{
X	printf("hello, world\n");
X}
X
X$ wc simple.c
X      4      5     38 simple.c
X$ make simple
X	cc -O -s simple.c -o simple
X$ time unc -v simple -lc > simple.dis
XScanning text
XScanning data
XScanning symbols
XScanning for relocation
XEnd of input
XText anal 1
XData anal 1
XData anal 2
X
Xreal	4m4.43s
Xuser	0m15.36s
Xsys	2m15.83s
X$ wc simple.dis
X   4787   8428  58070 simple.dis
X
XHmmm, 38 bytes to 58070.... now if I disassembler UNIX I should go from
X168915 bytes to ~6800000 bytes... And probably wait about 5 hours or so.
XIf anyone trys it let me know :-)
X
XAny enhancements (showing code in AT&T m68k assembly, so you can feed
Xback to "as") or anything, I would be interested in seeing it!
X
X-Lenny
X
END_OF_FILE
if test 2737 -ne `wc -c <'README.coff'`; then
    echo shar: \"'README.coff'\" unpacked with wrong size!
fi
# end of 'README.coff'
fi
if test -f 'alloc.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'alloc.c'\"
else
echo shar: Extracting \"'alloc.c'\" \(6403 characters\)
sed "s/^X//" >'alloc.c' <<'END_OF_FILE'
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}
END_OF_FILE
if test 6403 -ne `wc -c <'alloc.c'`; then
    echo shar: \"'alloc.c'\" unpacked with wrong size!
fi
# end of 'alloc.c'
fi
if test -f 'conv.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'conv.c'\"
else
echo shar: Extracting \"'conv.c'\" \(563 characters\)
sed "s/^X//" >'conv.c' <<'END_OF_FILE'
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    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}
END_OF_FILE
if test 563 -ne `wc -c <'conv.c'`; then
    echo shar: \"'conv.c'\" unpacked with wrong size!
fi
# end of 'conv.c'
fi
if test -f 'doc.nr' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'doc.nr'\"
else
echo shar: Extracting \"'doc.nr'\" \(6445 characters\)
sed "s/^X//" >'doc.nr' <<'END_OF_FILE'
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.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.
END_OF_FILE
if test 6445 -ne `wc -c <'doc.nr'`; then
    echo shar: \"'doc.nr'\" unpacked with wrong size!
fi
# end of 'doc.nr'
fi
if test -f 'doc.out' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'doc.out'\"
else
echo shar: Extracting \"'doc.out'\" \(7415 characters\)
sed "s/^X//" >'doc.out' <<'END_OF_FILE'
X
X
X
X                       A Disassembler
X
X
X
X                      1.  Introduction
X
XThis document describes the first release of a  disassembler
Xfor UNIX executable files.  The key features are:
X
X  1.  For object  files  the  output  can  be  assembled  to
X      generate  the  same  object  module, (apart from minor
X      variations in symbol table ordering) as the input.
X
X  2.  For  stripped  executable  files  object  modules  and
X      libraries  may  be  scanned, modules in the main input
X      identified and  the  appropriate  names  automatically
X      inserted into the output.
X
X  3.  An option is  available  to  convert  most  non-global
X      names  into local symbols, which cuts down the symbols
X      in the generated assembler file.
X
X  4.  The disassembler copes reasonably with modules  merged
X      with the -r option to ld, generating a warning message
X      as to the number of modules involved.
X
XAt present this is  available  for  certain  Motorola  68000
Xports of UNIX System III and System V. Dependencies on
X
X  a.  Instruction set.
X
X  b.  Object module format.
X
X  c.  Library module format.
X
X  d.  Assembler output format.
X
Xare hopefully sufficiently localised  to  make  the  product
Xuseful as a basis for other disassemblers for other versions
Xof UNIX.
X
XThe product is thus distributed in source form at present.
X
X
X                          2.  Use
X
XThe disassembler is run by entering:
X
X     unc mainfile lib1 lib2 ...
X
XThe first named file is the file to be  disassembled,  which
Xshould  be  a  single  file,  either  an  object  module,  a
X(possibly stripped) executable file, or  a  library  member.
XLibrary members are designated using a parenthesis notation,
Xthus:
X
X
X
X                                                      Page 1
X
X
X
X
X
X
X
X                       A Disassembler
X
X
X
X     unc '/lib/libc.a(printf.o)'
X
XIt is usually necessary to escape the arguments in this case
Xto  prevent  misinterpretation  by  the  shell. Libraries in
Xstandard places such as /lib and /usr/lib may  be  specified
Xin the same way as to ld, thus
X
X     unc '-lc(printf.o)'
X     unc '-lcurses(wmove.o)'
X
XAs an additional facility, the list of directories  searched
Xfor  libraries  may  be  varied  by  setting the environment
Xvariable LDPATH, which is interpreted similarly to the shell
XPATH variable, and of course defaults to
X
X     LDPATH=/lib:/usr/lib
X
XAs a further facility, the insertion of lib  before  and  .a
Xafter  the  argument may be suppressed by using a capital -L
Xargument, thus to print out the assembler  for  /lib/crt0.o,
Xthen the command
X
X     unc -Lcrt0.o
X
Xshould have the desired effect.
X
XSecond and subsequent file arguments are only referenced for
Xstripped  executable files, and may consist of single object
Xfiles and library members, using the same syntax as  before,
Xor whole libraries of object files, thus:
X
X     unc strippedfile -Lcrt0.o -lcurses -ltermcap '-lm(sqrt.o)' -lc
X
XIt is advisable to make some effort to put the libraries  to
Xbe  searched  in  the  order  in  which they were originally
Xloaded. This is because the search for  each  module  starts
Xwhere the previously matched module ended.  However, no harm
Xis done if this rule is not adhered to apart from  increased
Xexecution   time   except   in  the  rare  cases  where  the
Xdisassembler is confused by object modules  which  are  very
Xnearly similar.
X
X
X                   3.  Additional options
X
XThe following options are available to modify the  behaviour
Xof the disassembler.
X
X  -o file      Causes output to be  sent  to  the  specified
X               file instead of the standard output.
X
X
X
X
X                                                      Page 2
X
X
X
X
X
X
X
X                       A Disassembler
X
X
X
X  -t prefix    Causes temporary files to be created with the
X               given  prefix.  The  default prefix is split,
X               thus  causing  two  temporary  files  to   be
X               created  with  this  prefix  in  the  current
X               directory. If it is desired, for example,  to
X               create   the  files  as  /tmp/xx*,  then  the
X               argument -t /tmp/xx  should  be  given.  Note
X               that the temporary files may be very large as
X               a complete map of the text and data  segments
X               is generated.
X
X  -a           Suppresses  the  generation   of   non-global
X               absolute  symbols from the output. This saves
X               output  from  C  compilations   without   any
X               obvious  problems,  but  the  symbols  are by
X               default included in the name of producing  as
X               nearly  identical  output  as possible to the
X               original source.
X
X  -s           Causes an additional scan to take place where
X               all  possible  labels  are  replaced by local
X               symbols. The local symbols  are  inserted  in
X               strictly ascending order, starting at 1.
X
X  -v           Causes a blow-by-blow account  of  activities
X               to be output on the standard error.
X
X
X                    4.  Diagnostics etc
X
XTruncated or garbled object and library files usually  cause
Xprocessing to stop with an explanatory message.
X
XThe only other kinds of message are  some  passing  warnings
Xconcerning  obscure  constructs  not  handled,  such  as the
Xrelocation of byte fields, or the relocation of  overlapping
Xfields. Occasionally a message
X
X     Library clash: message
X
Xmay appear and processing cease. This message is found where
Xat  a  late  stage  in  processing  libraries,  the  program
Xdiscovers that due to the extreme similarity of two or  more
Xlibrary  members,  it has come to the wrong conclusion about
Xwhich one to use. The remedy here is to  spell  out  to  the
Xprogram which members to take in which order.
X
X
X
X
X
X
X
X
X                                                      Page 3
X
X
X
X
X
X
X
X                       A Disassembler
X
X
X
X                   5.  Future development
X
XIn the future it is hoped  to  devise  ways  of  making  the
Xdisassembler  independent of all the above-mentioned version
Xdependencies,  by  first  reading  a  files  defining  these
Xthings.  This  will  probably  be  applied  after the Common
XObject Format becomes more standard.
X
XIn the long term it would be desirable and useful to enhance
Xthe   product   to  produce  compilable  C  in  addition  to
Xassemblable assembler. Stages in the  process  are  seen  as
Xfollows:
X
X  1.  Better identification of basic  blocks  in  the  code.
X      Switch  statements  are  a  major problem here, as are
X      constant data held in the text segment.
X
X  2.  Marrying of data to the corresponding text. It  is  in
X      various  places  hard to divorce static references "on
X      the fly" (e.g.  strings,  and  switch  lists  in  some
X      implementations)  from static at the head of a module.
X      This is part  of  the  problem  of  identifying  basic
X      blocks.
X
X  3.  Compilation of header  files  to  work  out  structure
X      references   within  the  text.  At  this  stage  some
X      interaction may be needed.
X
XMeanwhile the product is one which is a useful tool  to  the
Xauthor  in  its present form. Comments and suggestions as to
Xthe most practical method of improving the  product  in  the
Xways   suggested  or  in  other  ways  would  be  gratefully
Xconsidered.
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X                                                      Page 4
X
X
X
X
END_OF_FILE
if test 7415 -ne `wc -c <'doc.out'`; then
    echo shar: \"'doc.out'\" unpacked with wrong size!
fi
# end of 'doc.out'
fi
if test -f 'file.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'file.c'\"
else
echo shar: Extracting \"'file.c'\" \(4203 characters\)
sed "s/^X//" >'file.c' <<'END_OF_FILE'
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 < 0  ||  addr > fid->ef_tsize  || (addr & 1) != 0)  {
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 < 0  ||  addr > fid->ef_tsize  ||  (addr & 1) != 0)  {
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 < fid->ef_dbase  ||  addr > fid->ef_end)  {
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 < fid->ef_dbase  ||  addr > fid->ef_end)  {
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}
END_OF_FILE
if test 4203 -ne `wc -c <'file.c'`; then
    echo shar: \"'file.c'\" unpacked with wrong size!
fi
# end of 'file.c'
fi
if test -f 'iset.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'iset.c'\"
else
echo shar: Extracting \"'iset.c'\" \(20063 characters\)
sed "s/^X//" >'iset.c' <<'END_OF_FILE'
X/*
X *	SCCS:	@(#)iset.c	1.2	11/2/84	14:18:23
X *	Decode instructions.
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
Xef_fids	mainfile;
Xlong	endt;
X
Xvoid	gette(), putte();
Xvoid	mkdref();
Xlong	gettw();
Xsymbol	textlab();
X
Xint	l1(), l2(), el1(), lea(), lmove(), lcbch(), jj();
Xint	limed(), lsbit(), lmvml(), lone(), loone(), lonew(), lonel();
X
Xint	pmove(), pcbch(), pdbcc(), pscc(), pcs(), pmovc(), pstop(), pexg();
Xint	pimed(), pmovp(), psbit(), pdbit(), pcs2(), pone(), ppea();
Xint	plea(), pdreg(), pmvml(), ptrap(), plink(), pareg(), podreg();
Xint	pqu(), pmqu(), ptreg(), pcmpm(), pomode(), pmshf(), pshf();
X
Xstruct	opstr	{
X	unsigned  short	 mask;
X	unsigned  short  match;
X	int	(*opsize)();
X	int	(*opprin)();
X	char	*prarg;
X} optab[] = {
X	0xf000, 0x2000, lmove, pmove, "l",
X	0xf000, 0x3000, lmove, pmove, "w",
X	0xf000, 0x1000, lmove, pmove, "b",
X	0xf000, 0x6000, lcbch, pcbch, 0,
X	0xffbf, 0x003c, l2,    pcs,   "or",
X	0xff00, 0x0000, limed, pimed, "or",
X	0xffbf, 0x023c, l2,    pcs,   "and",
X	0xff00, 0x0200, limed, pimed, "and",
X	0xff00, 0x0400, limed, pimed, "sub",
X	0xff00, 0x0600, limed, pimed, "add",
X	0xffbf, 0x0a3c, l2,    pcs,   "eor",
X	0xff00, 0x0a00, limed, pimed, "eor",
X	0xff00, 0x0c00, limed, pimed, "cmp",
X	0xf138, 0x0108, l2,    pmovp, 0,
X	0xff00, 0x0800, lsbit, psbit, 0,
X	0xf100, 0x0100, lonew, pdbit, 0,
X	0xffc0, 0x40c0, lonew, pcs2,  "sr",
X	0xff00, 0x4000, lone,  pone,  "negx",
X	0xff00, 0x4200, lone,  pone,  "clr",
X	0xffc0, 0x44c0, lonew, pcs2,  "cc",
X	0xff00, 0x4400, lone,  pone,  "neg",
X	0xffc0, 0x46c0, lonew, pcs2,  "sr",
X	0xff00, 0x4600, lone,  pone,  "not",
X	0xffc0, 0x4800, lonew, ppea,  "nbcd",
X	0xfff8, 0x4840, l1,    pdreg, "swap",
X	0xffc0, 0x4840, lonel, ppea,  "pea",
X	0xfff8, 0x4880, l1,    pdreg, "extw",
X	0xfff8, 0x48c0, l1,    pdreg, "extl",
X	0xfb80, 0x4880, lmvml, pmvml, 0,
X	0xffc0, 0x4ac0, lonew, ppea,  "tas",
X	0xff00, 0x4a00, lone,  pone,  "tst",
X	0xfff0, 0x4e40, l1,    ptrap, 0,
X	0xfff8, 0x4e50, l2,    plink, 0,
X	0xfff8, 0x4e58, l1,    pareg, "unlk\t%s",
X	0xfff8, 0x4e60, l1,    pareg, "movl\t%s,usp",
X	0xfff8, 0x4e68, l1,    pareg, "movl\tusp,%s",
X	0xffff, 0x4e70, l1,    pareg, "reset",
X	0xffff, 0x4e71, l1,    pareg, "nop",
X	0xffff, 0x4e72, l2,    pstop, 0,
X	0xffff, 0x4e73, el1,   pareg, "rte",
X	0xffff, 0x4e75, el1,   pareg, "rts",
X	0xffff, 0x4e76, l1,    pareg, "trapv",
X	0xffff, 0x4e77, el1,   pareg, "rtr",
X	0xfffe, 0x4e7a, l2,    pmovc, 0,
X	0xffc0, 0x4e80, jj,    ppea,  "jsr",
X	0xffc0, 0x4ec0, jj,    ppea,  "jmp",
X	0xf1c0, 0x4180, lonew, podreg,"chk",
X	0xf1c0, 0x41c0, lonel, plea,  0,
X	0xf0f8, 0x50c8, lcbch, pdbcc, 0,
X	0xf0c0, 0x50c0, lonew, pscc,  0,
X	0xf100, 0x5000, lone,  pqu,   "add",
X	0xf100, 0x5100, lone,  pqu,   "sub",
X	0xf100, 0x7000, l1,    pmqu,  0,
X	0xf1c0, 0x80c0, lonew, podreg,"divu",
X	0xf1c0, 0x81c0, lonew, podreg,"divs",
X	0xf1f0, 0x8100, l1,    ptreg, "sbcd",
X	0xf000, 0x8000, loone, pomode,"or",
X	0xf1f0, 0x9100, l1,    ptreg, "subxb",
X	0xf1f0, 0x9140, l1,    ptreg, "subxw",
X	0xf1f0, 0x9180, l1,    ptreg, "subxl",
X	0xf000, 0x9000, loone, pomode,"sub",
X	0xf1f8, 0xb108, l1,    pcmpm, "cmpmb",
X	0xf1f8, 0xb148, l1,    pcmpm, "cmpmw",
X	0xf1f8, 0xb188, l1,    pcmpm, "cmpml",
X	0xf100, 0xb000, loone, pomode,"cmp",
X	0xf1c0, 0xb1c0, loone, pomode,"cmp",
X	0xf100, 0xb100, loone, pomode,"eor",
X	0xf1c0, 0xc0c0, lonew, podreg,"mulu",
X	0xf1c0, 0xc1c0, lonew, podreg,"muls",
X	0xf1f0, 0xc100, l1,    ptreg, "abcd",
X	0xf130, 0xc100, l1,    pexg,  0,
X	0xf000, 0xc000, loone, pomode,"and",
X	0xf1f0, 0xd100, l1,    ptreg, "addxb",
X	0xf1f0, 0xd140, l1,    ptreg, "addxw",
X	0xf1f0, 0xd180, l1,    ptreg, "addxl",
X	0xf000, 0xd000, loone, pomode,"add",
X	0xf8c0, 0xe0c0, lonew, pmshf,  0,
X	0xf000, 0xe000, l1,    pshf,   0,
X	0
X};
X
Xchar	*areg[] = { "a0", "a1", "a2", "a3", "a4", "a5", "a6", "sp"};
Xchar	*cclist[] = { "hi", "ls", "cc", "cs", "ne", "eq", "vc", "vs",
X			"pl", "mi", "ge", "lt", "gt", "le"};
X	
Xchar	*shtype[] = { "as", "ls", "rox", "ro" };
Xchar	*bittyp[] = { "tst", "chg", "clr", "set" };
X
Xchar	*creg[] = { "sfc", "dfc", "usp", "vbr" };
X
X/*
X *	Length functions.
X */
X
Xint	l1()
X{
X	return	1;
X}
X
Xint	l2()
X{
X	return	2;
X}
X
Xint	el1(te)
Xt_entry	*te;
X{
X	te->t_bchtyp = T_UNBR;
X	return	1;
X}
X
Xint	lea(instr, size, pos)
Xunsigned  instr, size;
Xlong	pos;
X{
X	switch  ((instr >> 3) & 0x7)  {
X	case  0:
X	case  1:
X	case  2:
X	case  3:
X	case  4:
X		return	1;
X	case  5:
X	case  6:
X		return	2;
X	default:
X		switch  (instr & 0x7)  {
X		case  0:
X		case  2:
X		case  3:
X			return	2;
X		case  1:
X			mkdref(pos, size);
X			return	3;
X		case  4:
X			if  (size > 2)
X				return	3;
X			return	2;
X		default:
X			return	0;
X		}
X	}
X}
X
X/*
X *	Lengths of move instructions.
X */
X
Xint	lmove(te, pos)
Xt_entry	*te;
Xlong	pos;
X{
X	register  unsigned  tc  =  te->t_contents;
X	unsigned  sz  =  1;
X	int	lng, lng2;
X	
X	lng  = tc & 0xf000;
X	if  (lng == 0x3000)
X		sz = 2;
X	else  if  (lng == 0x2000)
X		sz = 4;
X	
X	if  ((lng = lea(tc, sz, pos+2)) <= 0)
X		return	0;
X	lng2 = lea(((tc>>3) & 0x38) | ((tc>>9) & 0x7), sz, pos+lng+lng);
X	if  (lng2 <= 0)
X		return	0;
X	return	lng + lng2 - 1;
X}
X
X/*
X *	Lengths for conditional branches and dbcc instructions.
X */
X
Xint	lcbch(te, pos)
Xt_entry	*te;
Xlong	pos;
X{
X	unsigned  tc  =  te->t_contents;
X	long	dest  =  pos + 2;
X	int	res   =  2;
X	
X	if  ((tc & 0xf000) == 0x5000  ||  (tc & 0xff) == 0)
X		dest += (short)gettw(&mainfile, pos+2, R_WORD);
X	else  {
X		dest += (char) tc;
X		res = 1;
X	}
X 	if ( dest < mainfile.ef_tbase 
X 		|| dest >= mainfile.ef_tbase+mainfile.ef_tsize 
X 		|| (dest & 1) != 0 )
X 		return 0;		/* Illegal branch destination */
X	if  ((tc & 0xff00) == 0x6000)
X		te->t_bchtyp = T_UNBR;
X	else  if  ((tc & 0xff00) == 0x6100)
X		te->t_bchtyp = T_JSR;
X	else
X		te->t_bchtyp = T_CONDBR;
X
X 	if ( (te->t_relsymb = textlab(dest, pos)) == NULL ) {
X 		te->t_bchtyp = T_NOBR;/* Branch to a continuation */
X 		return 0;
X 	}
X	return	res;
X}
X
Xint	jj(te, pos)
Xt_entry	*te;
Xlong	pos;
X{
X	unsigned  tc  =  te->t_contents;
X	t_entry	nextl;
X 	long dest;
X	
X	te->t_bchtyp = (tc & 0x40)? T_UNBR: T_JSR;
X	if  ((tc & 0x3f) == 0x39)  {
X		gette(&mainfile, pos+2, &nextl);
X		if  (nextl.t_relsymb == NULL)  {
X 			dest = gettw(&mainfile, pos + 2, R_LONG );
X 			if ( dest < mainfile.ef_tbase
X 				|| dest >= mainfile.ef_tbase+mainfile.ef_tsize
X 				|| (dest & 1) != 0 )
X 				return 0;	/* Illegal branch destination */
X 			if ( ( nextl.t_relsymb = textlab(dest, pos) ) == NULL )
X 			return 0;	/* Branch to a continuation */
X			putte(&mainfile, pos+2, &nextl);
X		}
X		te->t_relsymb = nextl.t_relsymb;	/*  Easy ref  */
X	}
X	return	lea(tc, 4, pos+2);
X}
X
Xint	limed(te, pos)
Xt_entry	*te;
Xlong	pos;
X{
X	unsigned  tc  =  te->t_contents;
X	int	lng;
X	
X	/*
X	 *	Specifically exclude byte address register operands,
X	 *	and ones which have lengths of 3.
X	 */
X
X	if  ((tc & 0xf8) == 0x08)
X		return  0;
X	
X	if  ((tc & 0xc0) >= 0x80)  {
X		if  (tc & 0x40)
X			return  0;
X		lng = lea(tc, 4, pos+6);
X		if  (lng > 0)
X			lng += 2;
X	}
X	else  {
X		lng = lea(tc, (unsigned)((tc & 0xc0)?2:1), pos+4);
X		if  (lng > 0)
X			lng++;
X	}
X	return	lng;
X}
X
Xint	lsbit(te, pos)
Xt_entry	*te;
Xlong	pos;
X{
X	int	lng = lea(te->t_contents, 1, pos+4);
X	
X	if  (lng > 0)
X		lng++;
X	return	lng;
X}
X
Xint	lmvml(te, pos)
Xt_entry	*te;
Xlong	pos;
X{
X	int	lng = lea(te->t_contents,
X			(unsigned)(te->t_contents&0x40? 4:2), pos+4);
X	
X	if  (lng > 0)
X		lng++;
X	return	lng;
X}
X
X/*
X *	Length depends on bits 6 and 7 of instruction.
X */
X
Xint	lone(te, pos)
Xt_entry	*te;
Xlong	pos;
X{
X	unsigned  tc  =  te->t_contents;
X	
X	return	lea(tc, 1 << ((tc >> 6) & 3), pos+2);
X}
X
X/*
X *	Length depends on bits 6-8 of instruction.
X */
X
Xint	loone(te, pos)
Xt_entry	*te;
Xlong	pos;
X{
X	unsigned  tc  =  te->t_contents;
X	
X	switch  ((tc >> 6) & 7)  {
X	case  0:
X	case  4:
X		return	lea(tc, 1, pos+2);
X	case  1:
X	case  3:
X	case  5:
X		return  lea(tc, 2, pos+2);
X	case  2:
X	case  6:
X	case  7:
X		return	lea(tc, 4, pos+2);
X	}
X	/*NOTREACHED*/
X}
X
Xint	lonew(te, pos)
Xt_entry	*te;
Xlong	pos;
X{
X	return	lea(te->t_contents, 2, pos+2);
X}
X
Xint	lonel(te, pos)
Xt_entry	*te;
Xlong	pos;
X{
X	return	lea(te->t_contents, 4, pos+2);
X}
X
X/*
X *	Print routines.
X */
X
Xint	findleng(tc)
Xunsigned  tc;
X{
X	switch  ((tc >> 6) & 3)  {
X	case  0:
X		return	'b';
X	case  1:
X		return	'w';
X	default:
X		return	'l';
X	}
X}
X
Xvoid	piword(disp)
Xunsigned  disp;
X{
X	int	szc;
X	
X	(void) printf("@(0x%x,", disp & 0xff);
X	if  (disp & 0x8000)
X		(void) printf("%s", areg[(disp >> 12) & 0x7]);
X	else
X		(void) printf("d%d", (disp >> 12) & 0x7);
X	szc = 'w';
X	if  (disp & (1 << 10))
X		szc = 'l';
X	(void) printf(":%c)", szc);
X}
X
Xvoid	paddr(pos)
Xlong	pos;
X{
X	t_entry	tent;
X	symbol	symb;
X	
X	gette(&mainfile, pos, &tent);
X	if  (tent.t_relsymb != NULL)  {
X		symb = tent.t_relsymb;
X		if  (symb->s_lsymb != 0)
X			(void) printf("%u$", symb->s_lsymb);
X		else
X			(void) printf("%s", symb->s_name);
X		if  (tent.t_reldisp != 0)
X			(void) printf("+0x%x", tent.t_reldisp);
X		return;
X	}
X	(void) printf("0x%x", gettw(&mainfile, pos, R_LONG));
X}
X
Xint	prea(ea, pos, sz)
Xunsigned  ea, sz;
Xlong	pos;			/*  Address of previous word to extn  */
X{
X	unsigned  reg  =  ea & 0x7;
X	long	disp;
X	
X	pos += 2;
X	
X	switch  ((ea >> 3) & 0x7)  {
X	case  0:
X		(void) printf("d%d", reg);
X		return	0;
X	case  1:
X		(void) printf("%s", areg[reg]);
X		return	0;
X	case  2:
X		(void) printf("%s@", areg[reg]);
X		return	0;
X	case  3:
X		(void) printf("%s@+", areg[reg]);
X		return	0;
X	case  4:
X		(void) printf("%s@-", areg[reg]);
X		return	0;
X	case  5:
X		disp = gettw(&mainfile, pos, R_WORD);
X		(void) printf("%s@(0x%x)", areg[reg], disp);
X		return	2;
X	case  6:
X		(void) printf("%s", areg[reg]);
X		piword((unsigned) gettw(&mainfile, pos, R_WORD));
X		return	2;
X	default:
X		switch  (reg)  {
X		case  0:
X			disp = gettw(&mainfile, pos, R_WORD);
X			(void) printf("0x%x:w", disp);
X			return	2;
X		case  1:
X			paddr(pos);
X			return	4;
X		case  2:
X			disp = gettw(&mainfile, pos, R_WORD);
X			(void) printf("pc@(0x%x)", disp);
X			return	2;
X		case  3:
X			(void) printf("pc");
X			piword((unsigned) gettw(&mainfile, pos, R_WORD));
X			return	2;
X		case  4:
X			(void) printf("#");
X			if  (sz < 4)
X				(void) printf("0x%x", gettw(&mainfile, pos, R_WORD));
X			else
X				paddr(pos);
X			return	sz;
X		default:
X			(void) fprintf(stderr, "Funny mode\n");
X			exit(220);
X		}
X	}
X	/*NOTREACHED*/
X}
X	
Xint	pmove(te, pos)
Xt_entry	*te;
Xlong	pos;
X{
X	unsigned  sz  =  2;
X	unsigned  tc  =  te->t_contents;
X	
X	(void) printf("mov%s\t", optab[te->t_iindex].prarg);
X	
X	if  ((tc & 0xf000) == 0x2000)
X		sz = 4;
X	
X	pos += prea(tc, pos, sz);
X	putchar(',');
X	(void) prea(((tc >> 9) & 0x7) | ((tc >> 3) & 0x38), pos, sz);
X}
X
Xint	pcbch(te)
Xt_entry	*te;
X{
X	int	cc = ((te->t_contents >> 8) & 0xf) - 2;
X	char	*msg;
X	register  symbol  ts;
X	
X	if  (cc < 0)
X		msg = cc < -1? "ra": "sr";
X	else
X		msg = cclist[cc];
X	(void) printf("b%s", msg);
X	if  (te->t_lng < 2)
X		(void) printf("s");
X	ts = te->t_relsymb;
X	if  (ts->s_lsymb != 0)
X		(void) printf("\t%u$", ts->s_lsymb);
X	else
X		(void) printf("\t%s", ts->s_name);
X}
X
Xint	pdbcc(te)
Xt_entry	*te;
X{
X	unsigned  tc  =  te->t_contents;
X	int	cc = ((tc >> 8) & 0xf) - 2;
X	char	*msg;
X	register  symbol  ts;
X	
X	if  (cc < 0)
X		msg = cc < -1? "t": "f";
X	else
X		msg = cclist[cc];
X	ts = te->t_relsymb;
X	(void) printf("db%s\td%d,", msg, tc & 0x7);
X	if  (ts->s_lsymb)
X		(void) printf("%u$", ts->s_lsymb);
X	else
X		(void) printf("%s", ts->s_name);
X}
X
Xint	pscc(te, pos)
Xt_entry	*te;
Xlong	pos;
X{
X	unsigned  tc  =  te->t_contents;
X	int	cc = ((tc >> 8) & 0xf) - 2;
X	char	*msg;
X	
X	if  (cc < 0)
X		msg = cc < -1? "t": "f";
X	else
X		msg = cclist[cc];
X	(void) printf("s%s\t", msg);
X	(void) prea(tc, pos, 1);
X}
X
Xint	pcs(te, pos)
Xt_entry	*te;
Xlong	pos;
X{
X	long	disp  =  gettw(&mainfile, pos+2, R_WORD);
X	
X	(void) printf("%s", optab[te->t_iindex].prarg);
X	if  ((te->t_contents & 0xc0) == 0)
X		(void) printf("b\t#0x%x,cc", disp);
X	else
X		(void) printf("w\t#0x%x,sr", disp);
X}
X
Xint	pmovc(te, pos)
Xt_entry	*te;
Xlong	pos;
X{
X	int	disp = gettw(&mainfile, pos+2, R_WORD);
X	int	ctrl = ((disp >> 10) & 2) | (disp & 1);
X
X	(void) printf("movec\t");
X	if  ((te->t_contents & 1) == 0)
X		(void) printf("%s,", creg[ctrl]);
X	if  (disp & 0x8000)
X		(void) printf("%s", areg[(disp >> 12) & 7]);
X	else
X		(void) printf("d%d", disp >> 12);
X	if  (te->t_contents & 1)
X		(void) printf(",%s", creg[ctrl]);
X}
X
Xint	pimed(te, pos)
Xt_entry	*te;
Xlong	pos;
X{
X	int	sz = findleng(te->t_contents);
X	
X	(void) printf("%s%c\t#", optab[te->t_iindex].prarg, sz);
X	if  (sz == 'l')  {
X		paddr(pos+2);
X		putchar(',');
X		(void) prea(te->t_contents, pos+4, 4);
X	}
X	else  {
X		(void) printf("0x%x,", gettw(&mainfile, pos+2, R_WORD));
X		(void) prea(te->t_contents, pos+2, 2);
X	}
X}
X
Xint	pmovp(te, pos)
Xt_entry	*te;
Xlong	pos;
X{
X	unsigned  tc  =  te->t_contents;
X	long	disp  =  gettw(&mainfile, pos+2, R_WORD);
X	int	dreg = tc >> 9;
X	char	*ar = areg[tc & 0x7];
X	
X	(void) printf("movep");
X	if  (tc & (1 << 6))
X		putchar('l');
X	else
X		putchar('w');
X
X	if  (tc & (1 << 7))
X		(void) printf("\td%d,%s@(0x%x)", dreg, ar, disp);
X	else
X		(void) printf("\t%s@(0x%x),d%d", ar, disp, dreg);
X}
X
Xint	psbit(te, pos)
Xt_entry	*te;
Xlong	pos;
X{
X	unsigned  tc  =  te->t_contents;
X	
X	(void) printf("b%s\t#%d,", bittyp[(tc >> 6) & 0x3], gettw(&mainfile, pos+2, R_WORD));
X	(void) prea(tc, pos+2, 1);
X}
X
X/*ARGSUSED*/
Xint	pstop(te, pos)
Xt_entry	*te;
Xlong	pos;
X{
X	(void) printf("stop\t#0x%x", gettw(&mainfile, pos+2, R_WORD));
X}
X
Xint	pdbit(te, pos)
Xt_entry	*te;
Xlong	pos;
X{
X	unsigned  tc  =  te->t_contents;
X	
X	(void) printf("b%s\td%d,", bittyp[(tc >> 6) & 0x3], (tc >> 9) & 0x7);
X	(void) prea(tc, pos, 1);
X}
X
Xint	pcs2(te, pos)
Xt_entry	*te;
Xlong	pos;
X{
X	unsigned  tc  =  te->t_contents;
X	
X	(void) printf("movw\t");
X	if  ((tc & 0xffc0) == 0x40c0)  {
X		(void) printf("sr,");
X		(void) prea(tc, pos, 2);
X	}
X	else  {
X		(void) prea(tc, pos, 2);
X		(void) printf(",%s", optab[te->t_iindex].prarg);
X	}
X}
X
Xint	pone(te, pos)
Xt_entry	*te;
Xlong	pos;
X{
X	unsigned  tc  =  te->t_contents;
X	int	sz = findleng(tc);
X	
X	(void) printf("%s%c\t", optab[te->t_iindex].prarg, sz);
X	(void) prea(tc, pos, (unsigned)(sz == 'l'? 4: 2));
X}
X
Xint	ppea(te, pos)	/*  nbcd, pea, tas, jmp, jsr  */
Xt_entry	*te;
Xlong	pos;
X{
X	(void) printf("%s\t", optab[te->t_iindex].prarg);
X	(void) prea(te->t_contents, pos, (unsigned)(te->t_lng > 2? 4: 2));
X}
X
X
Xint	plea(te, pos)
Xt_entry	*te;
Xlong	pos;
X{
X	(void) printf("lea\t");
X	(void) prea(te->t_contents, pos, 4);
X	(void) printf(",%s", areg[(te->t_contents >> 9) & 0x7]);
X}
X
Xint	pdreg(te)
Xt_entry	*te;
X{
X	(void) printf("%s\td%d", optab[te->t_iindex].prarg, te->t_contents & 7);
X}
X
X
Xint	pmvml(te, pos)
Xt_entry	*te;
Xlong	pos;
X{
X	unsigned  tc  =  te->t_contents;
X	register  unsigned  dw  =  gettw(&mainfile, pos+2, R_WORD);
X	unsigned  sz = 4;
X	int	sc = 'l';
X	register  int	i;
X	register  unsigned  bit;
X	
X	(void) printf("movem");
X	if  ((tc & 0x40) == 0)  {
X		sc = 'w';
X		sz = 2;
X	}
X	
X	(void) printf("%c\t", sc);
X	
X	if  (tc & 0x400)  {
X		(void) prea(tc, pos+2, sz);
X		(void) printf(",#0x%x", dw);
X	}
X	else  {
X		(void) printf("#0x%x,", dw);
X		(void) prea(tc, pos+2, sz);
X	}
X	
X	(void) printf("\t|");
X	
X	if  ((tc & 0x38) == 0x20)  {
X		bit = 0x8000;
X		for  (i = 0;  i < 8;  i++)  {
X			if  (dw & bit)
X				(void) printf(" d%d", i);
X			bit >>= 1;
X		}
X		for  (i = 0;  i < 8;  i++)  {
X			if  (dw & bit)
X				(void) printf(" %s", areg[i]);
X			bit >>= 1;
X		}
X	}
X	else  {
X		bit = 1;
X		for  (i = 0;  i < 8;  i++)  {
X			if  (dw & bit)
X				(void) printf(" d%d", i);
X			bit <<= 1;
X		}
X		for  (i = 0;  i < 8;  i++)  {
X			if  (dw & bit)
X				(void) printf(" %s", areg[i]);
X			bit <<= 1;
X		}
X	}
X}
X
Xint	ptrap(te)
Xt_entry	*te;
X{
X	(void) printf("trap\t#0x%x", te->t_contents & 0xf);
X}
X
Xint	plink(te, pos)
Xt_entry	*te;
Xlong	pos;
X{
X	(void) printf("link\t%s,#0x%x", areg[te->t_contents & 0x7],
X				gettw(&mainfile, pos+2, R_WORD));
X}
X
X
Xint	pareg(te)
Xt_entry	*te;
X{
X	(void) printf(optab[te->t_iindex].prarg, areg[te->t_contents & 0x7]);
X}
X
Xint	podreg(te, pos)
Xt_entry	*te;
Xlong	pos;
X{
X	unsigned  tc  =  te->t_contents;
X	
X	(void) printf("%s\t", optab[te->t_iindex].prarg);
X	(void) prea(tc, pos, 2);
X	(void) printf(",d%d", (tc >> 9) & 0x7);
X}
X
Xint	pqu(te, pos)
Xt_entry	*te;
Xlong	pos;
X{
X	unsigned  tc  =  te->t_contents;
X	int	sz  =  findleng(tc);
X	int	amt = (tc >> 9) & 0x7;
X	
X	if  (amt == 0)
X		amt = 8;
X	(void) printf("%sq%c\t#%d,", optab[te->t_iindex].prarg, sz, amt);
X	(void) prea(tc, pos, (unsigned)(sz == 'l'? 4: 2));
X}
X
Xint	pmqu(te)
Xt_entry	*te;
X{
X	unsigned  tc  =  te->t_contents;
X
X	(void) printf("moveq\t#0x%x,d%d", (char)tc, (tc >> 9) & 0x7);
X}
X
Xint	ptreg(te)
Xt_entry	*te;
X{
X	register  unsigned  tc  =  te->t_contents;
X	int	rx = (tc >> 9) & 0x7;
X	int	ry = tc & 0x7;
X
X	(void) printf("%s\t", optab[te->t_iindex].prarg);
X	if  (tc & 0x8)
X		(void) printf("%s@-,%s@-", areg[ry], areg[rx]);
X	else
X		(void) printf("d%d,d%d", ry, rx);
X}
X
Xint	pcmpm(te)
Xt_entry	*te;
X{
X	register  unsigned  tc  =  te->t_contents;
X
X	(void) printf("%s\t%s@+,%s@+", optab[te->t_iindex].prarg,
X		areg[tc & 7], areg[(tc >> 9) & 7]);
X}
X
Xint	pomode(te, pos)
Xt_entry	*te;
Xlong	pos;
X{
X	unsigned  tc  =  te->t_contents;
X	char	bef[4], aft[4];
X	int	sz;
X	int	reg = (tc >> 9) & 7;
X
X	bef[0] = aft[0] = '\0';
X	
X	switch  ((tc >> 6) & 7)  {
X	case  0:
X		sz = 'b';
X		goto  toreg;
X	case  1:
X		sz = 'w';
X		goto  toreg;
X	case  2:
X		sz = 'l';
X	toreg:
X		(void) sprintf(aft, ",d%d", reg);
X		break;
X	case  3:
X		sz = 'w';
X		goto  toareg;
X	case  7:
X		sz = 'l';
X	toareg:
X		(void) sprintf(aft, ",%s", areg[reg]);
X		break;
X	case  4:
X		sz = 'b';
X		goto  frreg;
X	case  5:
X		sz = 'w';
X		goto  frreg;
X	case  6:
X		sz = 'l';
X	frreg:
X		(void) sprintf(bef, "d%d,", reg);
X		break;
X	}
X
X	(void) printf("%s%c\t%s", optab[te->t_iindex].prarg, sz, bef);
X	(void) prea(tc, pos, (unsigned)(sz == 'l'? 4: 2));
X	(void) printf(aft);
X}
X
Xint	pexg(te)
Xt_entry	*te;
X{
X	unsigned  tc  =  te->t_contents;
X	int	r1 = (tc >> 9) & 7, r2 = tc & 7;
X
X	(void) printf("exg\t");
X	
X	if  ((tc & 0x00f8) == 0x0048)
X		(void) printf("%s,", areg[r1]);
X	else
X		(void) printf("d%d,", r1);
X	if  (tc & 0x8)
X		(void) printf("%s", areg[r2]);
X	else
X		(void) printf("d%d", r2);
X}
X	
Xint	pmshf(te, pos)
Xt_entry	*te;
Xlong	pos;
X{
X	unsigned  tc  =  te->t_contents;
X	
X	(void) printf("%s%cw\t", shtype[(tc >> 9) & 3], tc & 0x100? 'l': 'r');
X	(void) prea(tc, pos, 2);
X}
X
Xint	pshf(te)
Xt_entry	*te;
X{
X	unsigned  tc  =  te->t_contents;
X	int	sz  =  findleng(tc);
X	int	disp = (tc >> 9) & 7;
X
X	(void) printf("%s%c%c\t", shtype[(tc >> 3) & 3], tc & 0x100? 'l': 'r', sz);
X	if  (tc & 0x20)
X		(void) printf("d%d", disp);
X	else
X		(void) printf("#%d", disp == 0? 8: disp);
X	(void) printf(",d%d", tc & 7);
X}
X
X/*
X *	Find length etc of instruction.
X */
X
Xint	findinst(te, pos)
Xregister  t_entry  *te;
Xlong	pos;
X{
X	register  struct  opstr	*op;
X	unsigned  tc  =  te->t_contents;
X	int	lng = 0;
X	register  int	i;
X
X	te->t_type = T_BEGIN;
X	te->t_bchtyp = T_NOBR;
X	
X	for  (op = &optab[0];  op->mask;  op++)  {
X		if  ((tc & op->mask) == op->match)  {
X			te->t_iindex = op - optab;
X			lng = (op->opsize)(te, pos);
X			break;
X		}
X	}
X
X	for  (i = 1;  i < lng;  i++)  {
X		t_entry	ctent;
X		long	npos = pos+i+i;
X		
X		if  (npos >= endt)
X			goto  clearem;
X		gette(&mainfile, npos, &ctent);
X		if  (ctent.t_bdest || ctent.t_dref)  {
Xclearem:		for  (i--; i > 0; i--)  {
X				npos = pos + i + i;
X				gette(&mainfile, npos, &ctent);
X				ctent.t_type = T_UNKNOWN;
X				putte(&mainfile, npos, &ctent);
X			}
X			lng = 0;
X			goto  ginv;
X		}
X		ctent.t_type = T_CONT;
X		putte(&mainfile, npos, &ctent);
X	}
X	
X	if  (lng <= 0)  {
Xginv:		te->t_vins = 0;
X		te->t_lng = 1;
X		te->t_type = T_UNKNOWN;
X		te->t_bchtyp = T_NOBR;
X	}
X	else
X		te->t_lng = lng;
X	return	lng;
X}
X
X/*
X *	Print instruction.
X */
X
Xvoid	prinst(te, pos)
Xt_entry	*te;
Xlong	pos;
X{
X	putchar('\t');
X	(optab[te->t_iindex].opprin)(te, pos);
X	putchar('\n');
X}
END_OF_FILE
if test 20063 -ne `wc -c <'iset.c'`; then
    echo shar: \"'iset.c'\" unpacked with wrong size!
fi
# end of 'iset.c'
fi
echo shar: End of archive 1 \(of 2\).
cp /dev/null ark1isdone
MISSING=""
for I in 1 2 ; do
    if test ! -f ark${I}isdone ; then
	MISSING="${MISSING} ${I}"
    fi
done
if test "${MISSING}" = "" ; then
    echo You have unpacked both archives.
    echo "Read the README* files for more info"
    rm -f ark[1-9]isdone
else
    echo You still need to unpack the following archives:
    echo "        " ${MISSING}
fi
##  End of shell archive.
exit 0
-- 
Lenny Tropiano             ICUS Software Systems       [work] +1 (516) 582-5525
lenny@icus.islp.ny.us      Telex: 154232428 ICUS       [home] +1 (516) 968-8576
{talcott,boulder,hombre,pacbell,sbcs}!icus!lenny       attmail!icus!lenny
        ICUS Software Systems -- PO Box 1; Islip Terrace, NY  11752

lenny@icus.islp.ny.us (Lenny Tropiano) (09/27/88)

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@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, &ltent);
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,&sect);		/* text header */
X	    outf->ef_tbase = sect.s_vaddr;
X	    outf->ef_tsize = sect.s_size;
X
X	    ldshread(ldptr,2,&sect);		/* data header */
X	    outf->ef_dbase = sect.s_vaddr;
X	    outf->ef_dsize = sect.s_size;
X
X	    ldshread(ldptr,3,&sect);		/* 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@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

richard@uhccux.uhcc.hawaii.edu (Richard Foulk) (09/29/88)

Thanks for getting the ball rolling Lenny!

} Warning the program is awefully slow, and it does create large output files. 

I prof'ed unc and got this:

Name     %Time Seconds Cumsecs  #Calls   msec/call
read      48.0   61.82   61.82
write     25.2   32.51   94.33
lseek     15.3   19.77  114.09
_doprnt    2.5    3.23  117.33
...

I suspect that the reason it is so slow is because the ld library
does lseeks and reads for each reference or symbol (major yuk!).

So either some disk cacheing needs to be done, or more simply
and probably more effective, rewrite the ld routines so that
ldopen() reads the whole binary into memory to start with.

On a machine with 2 megs or more that should work okay.

Is anyone planning on doing the work to make it emit Motorola mnemonics?
I don't have much free time, but it's certainly a worthy project.

Richard