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