Article: 431 of alt.sources
From: pk@cs.few.eur.nl (Paul Kranenburg)
Newsgroups: alt.sources
Subject: unstrip a stripped dynamically linked executable.
Keywords: dynamic linking, debugging
Message-ID: <1992Jan22.161325.22872@cs.few.eur.nl>
Date: 22 Jan 92 16:13:25 GMT
Sender: news@cs.few.eur.nl
Reply-To: pk@cs.eur.nl
Organization: Erasmus University Rotterdam
Lines: 1319

Ever found the odd core file lying around in your root directory
and discovered that it was dropped by some system supplied daemon
which didn't even contained a name list?

If this happens on SunOS 4.x system (and it certainly does happen on
ours) and the executable is dynamically linked (as most of them are)
you may at least be able to get a decent traceback with adb(1)
after forcing the necessary symbolic information into the open
again.

This is the purpose of the enclosed programme, which takes advantage
of the fact that the run-time linker (ld.so) needs the same symbolic
information to perform its task and is therefore included in
the executable's text segment by its companion, ld(1).

Quote from README:

"Information for the run-time linker is stored in an executable's text
and data segment. This includes a symbol- and string table in standard
(a.out) format. Careful examination of the <link.h> header file and
tracing of some simple dynamically linked programs reveal the intrinsics
of the run-time link process, enabling the extraction of the symbol
table and putting it back on the spot where it used to be before
the executable was stripped."


Cheers, Paul.

-------------------------------------------------------------------------
#! /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 1)."
# Contents:  Makefile README defs.h nm.c nmd.1 unstrip.1 unstrip.c
#   util.c
# Wrapped by pk@kaa on Wed Jan 22 16:35:51 1992
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'\" \(746 characters\)
sed "s/^X//" >'Makefile' <<'END_OF_FILE'
X#
X# @(#)Makefile	1.2 92/01/22
X#
XBINDIR=/usr/local/bin
XMANDIR=/usr/local/man/man1
XCC=cc
XCFLAGS=-O
XOBJS=util.o
XKIT=	Makefile README unstrip.1 nmd.1 defs.h util.c unstrip.c nm.c
X
Xall: nm unstrip
X
Xnm: nm.o $(OBJS)
X	$(CC) $(CFLAGS) -o $@ nm.o $(OBJS)
X
Xunstrip: unstrip.o $(OBJS)
X	$(CC) $(CFLAGS) -o $@ unstrip.o $(OBJS)
X
Xd2o: d2o.o $(OBJS)
X	$(CC) $(CFLAGS) -o $@ d2o.o $(OBJS)
X
Xinstall: nm unstrip
X	install -m 555 nm $(BINDIR)/nmd
X	install -m 555 unstrip $(BINDIR)
X
Xinstall.man: unstrip.1 nmd.1
X	install -m 444 unstrip.1 $(MANDIR)
X	install -m 444 nmd.1 $(MANDIR)
X
Xclean:
X	rm -f *.o a.out core nm unstrip d2o Part?? nm.tar.Z
X
Xkit: $(KIT)
X	makekit $(KIT)
X
Xtar: $(KIT)
X	tar cf - $(KIT) | compress > nm.tar.Z
X
Xnm.o: defs.h
Xunstrip.o: defs.h
Xd2o.o: defs.h
END_OF_FILE
if test 746 -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'\" \(1634 characters\)
sed "s/^X//" >'README' <<'END_OF_FILE'
X@(#)README	1.2 92/01/22
X
Xunstrip - restore symbols and relocation bits in a dynamically
X	  linked object file
X
Xnmd	- a nm(1) like programme that is capable of showing the name
X	  list and relocation information of dynamically linked executables
X
X
XInformation for the run-time linker is stored in an executable's text
Xand data segment. This includes a symbol- and string table in standard
X(a.out) format. Careful examination of the <link.h> header file and
Xtracing of some simple dynamically linked programs reveal the intrinsics
Xof the run-time link process, enabling the extraction of the symbol
Xtable and putting it back on the spot where it used to be before
Xthe executable was stripped.
X
XFortunately, the "internal" symbol table still includes entries
Xof symbols that were already resolved by the static linking process,
Xprovided they carry the "external" attribute.
X
XThe mechanisms employed by the dynamic linker have been declared
Xvolatile by Sun (cf. link(5)), so these programs may stop working
Xat any moment (perhaps even without upgrading your OS :-).
X
XHowever, the SVR4 SPARC ABI specifies many items related to dynamic
Xlinking and also documents the relocation types which are nowhere to
Xbe found in SunOS 4.1.x documentation (most notably the RELOC_JMP_SLOT
Xtype that appears to define the relation of a symbol to the Procedure
XLinkage Table). If this extrapolates to SunOS 4.1.x, some hacks in
Xthese programs could be cleaned up.
X
XA makefile and two quick manual pages are included in this distribution.
X
X
XAuthor:
X
X	P.Kranenburg
X	Deptartment of Computer Science
X	Erasmus University Rotterdam (NL)
X	email: pk@cs.few.eur.nl
END_OF_FILE
if test 1634 -ne `wc -c <'README'`; then
    echo shar: \"'README'\" unpacked with wrong size!
fi
# end of 'README'
fi
if test -f 'defs.h' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'defs.h'\"
else
echo shar: Extracting \"'defs.h'\" \(764 characters\)
sed "s/^X//" >'defs.h' <<'END_OF_FILE'
X/*
X * @(#)defs.h	1.2 92/01/22
X */
X
Xstruct execmap {
X	struct exec	*e_hdr;			/* exec header */
X	caddr_t		e_text;			/* text segment */
X	caddr_t		e_data;			/* data segment */
X	struct nlist	*e_nlist;		/* symbol table */
X	int		e_nnlist;		/* # of nlist */
X#ifdef sparc
X#define reloc_info	reloc_info_sparc
X#endif
X#ifdef mc68000
X#define reloc_info	reloc_info_68k
X#endif
X	struct reloc_info	*e_trel;	/* relocation tables */
X	struct reloc_info	*e_drel;
X	int		e_ntrel;		/* # of text relocations */
X	int		e_ndrel;		/* # of data relocations */
X	char		*e_sym;			/* string table */
X#ifdef sun
X	int		e_mlen;			/* size of mapped object */
X#endif
X};
X
Xstruct execmap *mapfile();
Xint unmapfile();
Xvoid prtsym(), prthdr(), prtrel();
Xint ncompare(), scompare(), rncompare(), rscompare();
END_OF_FILE
if test 764 -ne `wc -c <'defs.h'`; then
    echo shar: \"'defs.h'\" unpacked with wrong size!
fi
# end of 'defs.h'
fi
if test -f 'nm.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'nm.c'\"
else
echo shar: Extracting \"'nm.c'\" \(5881 characters\)
sed "s/^X//" >'nm.c' <<'END_OF_FILE'
X/*
X * @(#)nm.c	1.2 92/01/22	- display an a.out symbol table
X */
X
X#include <stdio.h>
X#include <sys/types.h>
X#include <a.out.h>
X#ifndef sun
X#include <nlist.h>
X#endif
X#ifdef sun
X#include <link.h>
X#endif
X#include "defs.h"
X
Xextern char *malloc();
X
Xstatic aflag, dflag, gflag, hflag, nflag, pflag, rflag, uflag, xflag;
X
Xmain(argc, argv)
Xint argc;
Xchar *argv[];
X{
X	int c, status = 0;
X	extern int optind;
X	extern char *optarg;
X
X	while ((c = getopt(argc, argv, "adghnprux")) != EOF) {
X		switch (c) {
X		case 'a':
X			aflag++;
X			break;
X		case 'n':
X			nflag++;
X			break;
X		case 'p':
X			pflag++;
X			break;
X		case 'h':
X			hflag++;
X			break;
X		case 'r':
X			rflag++;
X			break;
X		case 'u':
X			uflag++;
X			break;
X		case 'g':
X			gflag++;
X			break;
X		case 'x':
X			xflag++;
X			break;
X#ifdef sun
X		case 'd':
X			dflag++;
X			break;
X#endif
X		default:
X			fprintf(stderr, "Usage: %s file ...\n", argv[0]);
X			return -1;
X			break;
X		}
X	}
X	if (argc <= optind) {
X		status = nm("a.out") == -1;
X	} else if (argc == optind + 1) {
X		status = nm(argv[optind]) == -1;
X	} else {
X		for (; optind < argc; optind++) {
X			printf("\n%s:\n", argv[optind]);
X			status |= nm(argv[optind]) == -1;
X		}
X	}
X	return status;
X}
X
Xnm(file)
Xchar *file;
X{
X	int fd;
X	struct exec *hp;
X	struct execmap *mp;
X
X	if ((mp = mapfile(file)) == NULL) {
X		return -1;
X	}
X	hp = mp->e_hdr;
X	if (hflag || aflag) {
X		prthdr(hp);
X		if (!aflag) return 0;
X	}
X	if (hp->a_syms == 0 && !dflag) {
X		fprintf(stderr, "%s: no name list\n", file);
X		return -1;
X	}
X	if (hp->a_syms != 0 && (aflag || !dflag))
X		prtnlist(mp, aflag);
X
X	if (aflag || xflag) {
X		if (hp->a_trsize + hp->a_drsize != 0) {
X			prtarel(mp);
X		} else if (!aflag) {
X			fprintf(stderr, "%s: no relocation\n", file);
X			return -1;
X		}
X	}
X#ifdef sun
X	if (dflag || aflag)
X		prtdyn(mp);
X#endif
X
X	unmapfile(mp);
X	return 0;
X}
X
Xint
Xprtnlist(mp)
Xstruct execmap *mp;
X{
X	int n;
X	struct nlist *nlp;
X
X	n = mp->e_nnlist;
X	nlp = mp->e_nlist;
X	if (!pflag) {
X		nlp = (struct nlist *)malloc(n * sizeof(struct nlist));
X		bcopy((char *)mp->e_nlist, (char *)nlp, n*sizeof(struct nlist));
X		qsort((char *)nlp, n, sizeof(struct nlist),
X				nflag?
X					(rflag?rncompare:ncompare)
X				:
X					(rflag?rscompare:scompare));
X	}
X	for(; n; n--, nlp++) {
X		if (aflag ||
X			((nlp->n_type & N_STAB) == 0 && (
X				(!gflag && !uflag) ||
X				(uflag && (nlp->n_type & N_TYPE) == N_UNDF) ||
X				(gflag && (nlp->n_type & N_EXT))
X				)
X			)
X		) {
X			prtsym(nlp);
X			fputc('\n', stdout);
X		}
X	}
X	return 0;
X}
X
Xprtarel(mp)
Xstruct execmap *mp;
X{
X#ifdef sun
X	if (mp->e_hdr->a_trsize) {
X		printf("\nText relocations:\n");
X		prtrel(mp->e_trel, mp->e_ntrel, mp->e_nlist);
X	}
X	if (mp->e_hdr->a_drsize) {
X		printf("\nData relocations:\n");
X		prtrel(mp->e_drel, mp->e_ndrel, mp->e_nlist);
X	}
X#else
X	fprintf(stderr, "\nrelocations not done\n");
X#endif
X}
X
X#ifdef sun
Xint
Xprtdyn(mp)
Xstruct execmap *mp;
X{
X	struct link_dynamic *dynp;
X	struct link_dynamic_2 *ldp;
X	struct ld_debug *lddp;
X	struct link_object *lop = NULL;
X	char *d_rules = NULL;
X	struct nlist *nlp;
X	int i, nnlist, nrel, nplt, ngot;
X	char *strtab;
X	struct reloc_info *rlp;
X	long *got;
X	struct plt {
X		int X1, X2, X3;
X	} *plt;
X
X	if (!mp->e_hdr->a_dynamic) {
X		fprintf(stderr, "Not dynamic\n");
X		return -1;
X	}
X	/* By convention, __DYNAMIC is first data item */
X	dynp = (struct link_dynamic *)mp->e_data;
X	/*
X	 * Various tables and structures are imbedded in text and data segment
X	 * In text: relocation table, hash table, stab table, string table,
X	 *		needed link_objects, library search rules
X	 * In data: link_dynamic[-2], debugger iface, global offset table,
X	 * 		procedure linkage table
X	 */
X	 /* First, some relocations of our own */
X	ldp = (struct link_dynamic_2 *)
X		((long)dynp->ld_un.ld_2 - N_DATADDR(*(mp->e_hdr)) + (long)mp->e_data);
X	lddp = (struct ld_debug *)
X		((long)dynp->ldd - N_DATADDR(*(mp->e_hdr)) + (long)mp->e_data) ;
X	if (ldp->ld_need)
X		lop = (struct link_object *)(ldp->ld_need + mp->e_text);
X	if (ldp->ld_rules)
X		d_rules = (char *)(ldp->ld_rules + (long)mp->e_text);
X	got = (long *)(ldp->ld_got - N_DATADDR(*(mp->e_hdr)) + (long)mp->e_data);
X	ngot = (ldp->ld_plt - ldp->ld_got) / sizeof(long);
X
X	plt = (struct plt *)(ldp->ld_plt - N_DATADDR(*(mp->e_hdr)) + (long)mp->e_data);
X	nplt = ldp->ld_plt_sz / sizeof(struct plt);
X
X	rlp = (struct reloc_info *)(ldp->ld_rel + (long)mp->e_text);
X	nrel = (ldp->ld_hash - ldp->ld_rel) / sizeof(struct reloc_info);
X
X	nlp = (struct nlist *)(ldp->ld_stab + (long)mp->e_text);
X	nnlist = (ldp->ld_symbols - ldp->ld_stab) / sizeof(struct nlist);
X	strtab = (char *)((long)mp->e_text + ldp->ld_symbols);
X	for (i = 0; i < nnlist; i++) {
X		if (nlp[i].n_un.n_strx < ldp->ld_symb_size)
X			nlp[i].n_un.n_name = strtab + nlp[i].n_un.n_strx;
X		else
X			nlp[i].n_un.n_name = "sym_???";
X	}
X
X	printf("Dynamic name list (%u):\n", nnlist);
X	for(i = 0; i < nnlist; i++) {
X		prtsym(&nlp[i]);
X		fputc('\n', stdout);
X	}
X
X	printf("\nProcedure linkage table (%u):\n", nplt);
X	printf(" PLT  GOT  DYN\n");
X	/* first entry in the plt contains entry point for ld.so */
X	for(i = 1; i < nplt; i++) {
X		printf("%4x %4x %4x ", i*sizeof(struct plt),
X			i*sizeof(struct plt) + (char *)plt - (char *)got,
X			i*sizeof(struct plt) + (char *)plt - (char *)dynp);
X		prtrel(&rlp[(plt[i].X3 & 0xffff)], 1, nlp);
X	}
X
X	printf("\nGlobal offset table (%u):\n", ngot);
X	for(i = 0; i < ngot; i++) {
X		printf(" [got entry: %x]\n", got[i]);
X	}
X
X	if (aflag || xflag) {
X		printf("\nDynamic relocations (%u):\n", nrel);
X		prtrel(rlp, nrel, nlp);
X	}
X
X	if (lop) {
X		printf("\nNeeded libs:\n");
X		while (1) {
X			if (lop->lo_library)
X				printf("\tlib%s.so.%u.%u (SEARCHED)\n",
X					lop->lo_name + mp->e_text,
X					lop->lo_major, lop->lo_minor);
X			else
X				printf("\t%s\n", lop->lo_name + mp->e_text);
X			if (lop->lo_next == 0)
X				break;
X			lop = (struct link_object *)(lop->lo_next + mp->e_text);
X		}
X	}
X	if (d_rules)
X		printf("Search rules: %s\n", d_rules);
X	return 0;
X}
X#endif
END_OF_FILE
if test 5881 -ne `wc -c <'nm.c'`; then
    echo shar: \"'nm.c'\" unpacked with wrong size!
fi
# end of 'nm.c'
fi
if test -f 'nmd.1' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'nmd.1'\"
else
echo shar: Extracting \"'nmd.1'\" \(1966 characters\)
sed "s/^X//" >'nmd.1' <<'END_OF_FILE'
X.\" @(#)nmd.1	1.1 92/01/22
X.TH NMD 1 "January 1992"
X.SH NAME
Xnmd \- print symbol name list
X.SH SYNOPSIS
X.B nmd
X[
X.B \-dgnpruxa
X]
X[
X.RI [ " filename " "] .\|.\|."
X.SH DESCRIPTION
X.IX  "nmd command"  ""  "\fLnmd\fP \(em display name list"
X.IX  display "name list of object file or library \(em \fLnmd\fP"
X.IX  "programming tools"  nmd  ""  "\fLnm\fP \(em display name list"
X.B nmd
Xprints the name list (symbol table) of each object
X.I filename
Xin the argument list.
XIf no
X.I filename
Xis given, the symbols in
X.B a.out
Xare listed.
X.SS Output Format
X.LP
XEach symbol name is preceded by its value (blanks if undefined)
Xand one of the letters:
X.TP
X.B A
Xabsolute
X.TP
X.B B
Xbss segment symbol
X.TP
X.B C
Xcommon symbol
X.TP
X.B D
Xdata segment symbol
X.TP
X.B f
Xfilename
X.TP
X.B t
Xa static function symbol
X.TP
X.B  T
Xtext segment symbol
X.TP
X.B U
Xundefined
X.TP
X.B \-
Xdebug, giving symbol table entries (see
X.B \-a
Xbelow)
X.LP
XThe type letter is upper case if the symbol is external, and
Xlower case if it is local.  The output is sorted alphabetically.
X.SH OPTIONS
X.TP
X.B  \-a
XPrint all symbols.
X.TP
X.B  \-d
XPrint dynamic linker information. This includes
Xthe name list and Procedure Linkage Table entries.
X.TP
X.B  \-g
XPrint only global (external) symbols.
X.TP
X.B \-n
XSort numerically rather than alphabetically.
X.TP
X.B  \-o
XPrepend file or archive element name to
Xeach output line rather than only once.
X.TP
X.B  \-p
XDo not sort; print in symbol-table order.
X.TP
X.B  \-r
XSort in reverse order.
X.TP
X.B  \-x
XPrint relocation tables.
X.TP
X.B  \-u
XPrint only undefined symbols.
X.SH EXAMPLE
X.IP
X.B example% nmd
X.LP
Xprints the symbol list of the file named
X.BR  a.out ,
Xthe default output file for the
X.BR C ,
Xcompiler.
X.SH SEE ALSO
X.BR as (1),
X.BR cc (1V),
X.BR ld (1),
X.BR a.out (5),
X.SH BUGS
X.LP
XArchive files (see ar(1)) are not supported.
X.LP
XPrinting of relocation tables is not complete.
X.LP
XThe
X.B \-g,
X.B \-u,
X.B \-n,
Xand
X.B \-r
Xoptions do not apply when the
X.B \-d
Xoption is in effect.
END_OF_FILE
if test 1966 -ne `wc -c <'nmd.1'`; then
    echo shar: \"'nmd.1'\" unpacked with wrong size!
fi
# end of 'nmd.1'
fi
if test -f 'unstrip.1' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'unstrip.1'\"
else
echo shar: Extracting \"'unstrip.1'\" \(1386 characters\)
sed "s/^X//" >'unstrip.1' <<'END_OF_FILE'
X.\" @(#)unstrip.1	1.2 92/01/22
X.TH UNSTRIP 1 "January 1992"
X.SH NAME
Xunstrip \- restore symbols and relocation bits in a dynamically linked object file
X.SH SYNOPSIS
X.B unstrip [-h] [-n] [-r]
X.IR filename .\|.\|.
X.SH DESCRIPTION
X.IX  "unstrip command"  ""  "\fLunstrip\fP \(em restore symbols and relocation bits"
X.IX  "programming tools"  strip  ""  "\fLstrip\fP \(em restore symbols and relocation bits"
X.IX  "object file"  strip  ""  "\fLstrip\fP \(em restore symbols and relocation bits"
X.LP
X.B unstrip
Xexternalizes the symbol
Xtable and relocation bits ordinarily provided by the linker
Xin the data segment of a dynamically linked executable.
XThis is useful to debug a program after a it has been stripped to save space.
X.LP
X.B unstrip
Xfixes up the symbol table for the benefit of
X.B adb
Xin such a way as to show calls to functions in shared
Xobjects symbolically (eg. ``call printf'') as opposed to
Xindirections through the Procedure Linkage Table
X(such as ``call __DYNAMIC + 0x1234'').
X.SH OPTIONS
X.TP
X.BI \-h
XShow header information of newly created object file.
X.TP
X.BI \-n
XDo not fix up symbol table (leaves functions in shared objects show
Xas ``undefined'' when viewed with
X.BR nm (1)).
X.TP
X.BI \-r
XDo not pull up relocation information.
X.SH SEE ALSO
X.BR ld (1),
X.BR adb (1),
X.BR strip (1),
X.BR nm (1),
X.BR a.out (5),
X.BR link (5)
X.SH BUGS
X.LP
XOverwrites existing symbol table.
END_OF_FILE
if test 1386 -ne `wc -c <'unstrip.1'`; then
    echo shar: \"'unstrip.1'\" unpacked with wrong size!
fi
# end of 'unstrip.1'
fi
if test -f 'unstrip.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'unstrip.c'\"
else
echo shar: Extracting \"'unstrip.c'\" \(6328 characters\)
sed "s/^X//" >'unstrip.c' <<'END_OF_FILE'
X/*
X * @(#)unstrip.c	1.2 92/01/22	- put symbol table of stripped dynamically linked a.out back into place
X */
X
X#include <stdio.h>
X#include <sys/types.h>
X#include <string.h>
X#include <fcntl.h>
X#include <a.out.h>
X#include <sys/stat.h>
X#include <link.h>
X#include "defs.h"
X
Xextern char *malloc();
X
Xstatic hflag, nflag, rflag;
Xstruct execmap *makesymbols();
X
Xmain(argc, argv)
Xchar *argv[];
X{
X	int c, status = 0;
X	extern int optind;
X	extern char *optarg;
X
X	while ((c = getopt(argc, argv, "hnr")) != EOF) {
X		switch (c) {
X		case 'n':
X			nflag++;
X			break;
X		case 'h':
X			hflag++;
X			break;
X		case 'r':
X			rflag++;
X			break;
X		default:
X			fprintf(stderr, "Usage: %s [file ...]\n", argv[0]);
X			return -1;
X			break;
X		}
X	}
X	if (argc <= optind) {
X		status = unstrip("a.out") == -1;
X	} else if (argc == optind + 1) {
X		status = unstrip(argv[optind]) == -1;
X	} else {
X		for (; optind < argc; optind++) {
X			printf("\n%s:\n", argv[optind]);
X			status |= unstrip(argv[optind]) == -1;
X		}
X	}
X	return status;
X}
X
Xint
Xunstrip(file)
Xchar *file;
X{
X	int fd, res;
X	struct exec *hp;
X	struct execmap *mp, *nmp;
X
X	if ((mp = mapfile(file)) == NULL) {
X		return -1;
X	}
X	hp = mp->e_hdr;
X	if (!hp->a_dynamic) {
X		fprintf(stderr, "%s: Not dynamic\n", file);
X		(void)unmapfile(mp);
X		return -1;
X	}
X	if (hp->a_trsize != 0 || hp->a_drsize != 0) {
X		fprintf(stderr, "Warning: %s contains relocation table\n", file);
X		(void)unmapfile(mp);
X		return -1;
X	}
X	if ((nmp = makesymbols(mp)) == NULL) {
X		fprintf(stderr, "Couldn't get symbols from %s\n", file);
X		(void)unmapfile(mp);
X		return -1;
X	}
X	if ((fd = open(file, O_WRONLY|O_CREAT, 0666)) == -1) {
X		perror("open");
X		res = -1;
X		goto quit;
X	}
X
X	if (writemap(fd, nmp) < 0 || close(fd) < 0) {
X		perror("writemap");
X		res = -1;
X		goto quit;
X	}
X	res = 0;
X
X	if (hflag)
X		prthdr(nmp->e_hdr);
X
Xquit:
X	if (nmp->e_nlist) (void)free((char *)nmp->e_nlist);
X	if (nmp->e_sym) (void)free((char *)nmp->e_sym);
X	if (nmp->e_trel) (void)free((char *)nmp->e_trel);
X#if 0
X	(void)free((char *)nmp->e_hdr);
X#endif
X	(void)free((char *)nmp);
X	if (unmapfile(mp) < 0)
X		return -1;;
X	return res;
X}
X
Xint
Xwritemap(fd, mp)
Xstruct execmap *mp;
X{
X	struct exec *hp = mp->e_hdr;
X	unsigned long n;
X
X	if (write(fd, (char *)hp, sizeof(*hp)) < sizeof(*hp))
X		return -1;
X
X	if (lseek(fd, hp->a_text + hp->a_data + N_TXTOFF(*hp), 0) < 0)
X		return -1;
X
X	if (hp->a_trsize &&
X		write(fd, (char *)mp->e_trel, hp->a_trsize) < hp->a_trsize)
X		return -1;
X
X	if (hp->a_drsize &&
X		write(fd, (char *)mp->e_drel, hp->a_drsize) < hp->a_drsize)
X		return -1;
X
X	if (write(fd, (char *)mp->e_nlist, hp->a_syms) < hp->a_syms)
X		return -1;
X
X	bcopy(mp->e_sym, (char *)&n, sizeof n);
X	if (write(fd, mp->e_sym, n) < n)
X		return -1;
X
X	return 0;
X}
X
Xstruct execmap *
Xmakesymbols(mp)
Xstruct execmap *mp;
X{
X	struct execmap *nmp;
X	struct link_dynamic *dynp;
X	struct link_dynamic_2 *ldp;
X	struct ld_debug *lddp;
X	struct link_object *lop;
X	char *d_rules;
X	struct nlist *nlp;
X	char *strtab;
X	int i, nnlist, nrel, nplt, ngot;
X	struct reloc_info *rlp;
X	long *got;
X	struct plt {
X		int X1, X2, X3;
X	} *plt;
X
X	/* By convention, __DYNAMIC is first data item */
X	dynp = (struct link_dynamic *)mp->e_data;
X	/*
X	 * Various tables and structures are imbedded in text and data segment
X	 * In text: relocation table, hash table, stab table, string table
X	 * In data: link_dynamic[_2], debugger iface, global offset table,
X	 * 		procedure linkage table
X	 */
X	 /* First, some relocations of our own */
X	ldp = (struct link_dynamic_2 *)
X		((long)dynp->ld_un.ld_2 - N_DATADDR(*(mp->e_hdr)) + (long)mp->e_data);
X	lddp = (struct ld_debug *)
X		((long)dynp->ldd - N_DATADDR(*(mp->e_hdr)) + (long)mp->e_data) ;
X	lop = (struct link_object *)(ldp->ld_need + mp->e_text);
X	d_rules = (char *)(ldp->ld_rules + (long)mp->e_text);
X	got = (long *)(ldp->ld_got - N_DATADDR(*(mp->e_hdr)) + (long)mp->e_data);
X	ngot = (ldp->ld_plt - ldp->ld_got) / sizeof(long);
X
X	plt = (struct plt *)(ldp->ld_plt - N_DATADDR(*(mp->e_hdr)) + (long)mp->e_data);
X	nplt = ldp->ld_plt_sz / sizeof(struct plt);
X
X	rlp = (struct reloc_info *)(ldp->ld_rel + (long)mp->e_text);
X	nrel = (ldp->ld_hash - ldp->ld_rel) / sizeof(struct reloc_info);
X
X	nlp = (struct nlist *)(ldp->ld_stab + (long)mp->e_text);
X	nnlist = (ldp->ld_symbols - ldp->ld_stab) / sizeof(struct nlist);
X	strtab = (char *)((long)mp->e_text + ldp->ld_symbols);
X
X	/* allocate new map */
X	if ((nmp = (struct execmap *)calloc(1, sizeof(*nmp))) == NULL) {
X		fprintf(stderr, "No memory\n");
X		return NULL;
X	}
X	/* allocate new stab, symbol and reloc tables */
X	nmp->e_nlist = (struct nlist *)malloc(ldp->ld_symbols - ldp->ld_stab);
X
X	if (nmp->e_nlist == NULL) {
X		fprintf(stderr, "Out of memory\n");
X		return NULL;
X	}
X	bcopy((char *)nlp, (char *)nmp->e_nlist, ldp->ld_symbols - ldp->ld_stab);
X
X	for(i = 0; i < nnlist; i++) {
X		/* Fix up sym index */
X		nmp->e_nlist[i].n_un.n_strx += 4;
X	}
X	nmp->e_sym = malloc(ldp->ld_symb_size + 4);
X	if (nmp->e_sym == NULL) {
X		fprintf(stderr, "Out of memory\n");
X		return NULL;
X	}
X	*(long *)nmp->e_sym = ldp->ld_symb_size + 4;
X	bcopy(strtab, nmp->e_sym + 4, ldp->ld_symb_size);
X
X	nmp->e_trel = (struct reloc_info *)malloc((nplt-1)*sizeof(struct reloc_info));
X	if (nmp->e_trel == NULL) {
X		fprintf(stderr, "Out of memory\n");
X		return NULL;
X	}
X	/* first entry in the plt contains entry point for ld.so */
X	for(i = 1; i < nplt; i++) {
X		bcopy((char *)&rlp[(plt[i].X3 & 0xffff)],
X			(char *)&nmp->e_trel[i-1], sizeof(struct reloc_info));
X	}
X
X	/* Fix up nlist for adb */
X	if (!nflag)
X		for(i = 1; i < nplt; i++) {
X			struct reloc_info *rp = &rlp[(plt[i].X3 & 0xffff)];
X			struct nlist *np;
X
X			if (rp->r_extern == 0) {
X				fprintf(stderr, "Weird reloc\n");
X				continue;
X			}
X			np = &nmp->e_nlist[rp->r_index];
X			np->n_value = ldp->ld_plt + i*sizeof(*plt);
X			np->n_type = N_TEXT | (np->n_type & N_EXT);
X		}
X
X#if 0
X	if ((nmp->e_hdr = (struct exec *)calloc(1, sizeof *nmp->e_hdr)) == NULL) {
X		fprintf(stderr, "Out of memory\n");
X		return NULL;
X	}
X#endif
X	nmp->e_hdr = mp->e_hdr;
X
X	/* copy header, text, data and bss from old map */
X	nmp->e_text = mp->e_text;
X	nmp->e_data = mp->e_data;
X
X	/* Add symbols to a.out header */
X	nmp->e_hdr->a_syms = nnlist*sizeof(struct nlist);
X	if (rflag)
X		nmp->e_hdr->a_trsize = (nplt-1)*sizeof(struct reloc_info);
X	else
X		nmp->e_hdr->a_trsize = 0;
X
X	/* No data relocations */
X	nmp->e_hdr->a_drsize = 0;
X	return nmp;
X}
END_OF_FILE
if test 6328 -ne `wc -c <'unstrip.c'`; then
    echo shar: \"'unstrip.c'\" unpacked with wrong size!
fi
# end of 'unstrip.c'
fi
if test -f 'util.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'util.c'\"
else
echo shar: Extracting \"'util.c'\" \(7655 characters\)
sed "s/^X//" >'util.c' <<'END_OF_FILE'
X/*
X * @(#)util.c	1.2 92/01/22	- a.out & nlist related routines
X */
X
X#include <stdio.h>
X#include <sys/types.h>
X#include <string.h>
X#include <malloc.h>
X#include <fcntl.h>
X#include <a.out.h>
X#ifndef sun
X#include <nlist.h>
X#endif
X#include <sys/stat.h>
X#ifdef sun
X#include <sys/mman.h>
X#include <link.h>
X#endif
X#include "defs.h"
X
Xvoid
Xprthdr(hp)
Xstruct exec *hp;
X{
X#ifdef sun
X	(void)printf(hp->a_dynamic?"DYNAMIC":"STATIC");
X	(void)printf(" Magic %o Version %u Mach %o\n",
X			hp->a_magic, hp->a_toolversion,
X			hp->a_machtype);
X#else
X	(void)printf(" Magic %o\n", hp->a_magic);
X#endif
X	(void)printf("Text %u Data %u Bss %u Syms %u Entry %#x\n",
X		hp->a_text, hp->a_data, hp->a_bss, hp->a_syms, hp->a_entry);
X	(void)printf("Trsize %u Drsize %u\n", hp->a_trsize, hp->a_drsize);
X	return;
X}
X
Xint
Xncompare(nlp1, nlp2)
Xstruct nlist *nlp1, *nlp2;
X{
X	return nlp1->n_value - nlp2->n_value;
X}
X
Xint
Xscompare(nlp1, nlp2)
Xstruct nlist *nlp1, *nlp2;
X{
X	return strcmp(nlp1->n_un.n_name, nlp2->n_un.n_name);
X}
X
Xint
Xrncompare(nlp1, nlp2)
Xstruct nlist *nlp1, *nlp2;
X{
X	return nlp2->n_value - nlp1->n_value;
X}
X
Xint
Xrscompare(nlp1, nlp2)
Xstruct nlist *nlp1, *nlp2;
X{
X	return strcmp(nlp2->n_un.n_name, nlp1->n_un.n_name);
X}
X
Xvoid
Xprtsym(nlp)
Xstruct nlist *nlp;
X{
X	char c;
X
X	switch (nlp->n_type & N_TYPE) {
X	case N_UNDF:
X		if (nlp->n_value && (nlp->n_type & N_EXT))
X			c = 'C';
X		else
X			c = 'U';
X		break;
X	case N_ABS: c = 'A'; break;
X	case N_TEXT: c = 'T'; break;
X	case N_DATA: c = 'D'; break;
X	case N_BSS: c = 'B'; break;
X	case N_COMM: c = 'C'; break;
X	case N_FN: c = 'F'; break;
X	default: c = '?'; break;
X	}
X	if (!(nlp->n_type & N_EXT))
X		c = tolower(c);
X
X#ifdef DEBUG
X	(void)printf("type:%#x other:%#x desc:%#x",
X		nlp->n_type, nlp->n_other, nlp->n_desc);
X#endif
X	(void)printf(tolower(c)=='u'?"\t":N_FORMAT, nlp->n_value);
X	(void)printf(" %c", c);
X	(void)printf(" %s", nlp->n_un.n_name);
X
X	return;
X}
X
Xstatic char *
Xreltyp(v)
Xenum reloc_type v;
X{
X#ifdef sun
X#ifdef sparc
X	static struct {
X		enum reloc_type	v;
X		char	*s;
X	} *x, tab[] = {
X		RELOC_8,	"R_8",
X		RELOC_16,	"R_16",
X		RELOC_32,	"R_32",
X		RELOC_DISP8,	"DISP8",
X		RELOC_DISP16,	"DISP16",
X		RELOC_DISP32,	"DISP32",
X		RELOC_WDISP30,	"WDISP30",
X		RELOC_WDISP22,	"WDISP22",
X		RELOC_HI22,	"HI22",
X		RELOC_22,	"R_22",
X		RELOC_13,	"R_13",
X		RELOC_LO10,	"LO10",
X		RELOC_SFA_BASE,	"SFA_BASE",
X		RELOC_SFA_OFF13,	"SFA_OFF13",
X		RELOC_BASE10,	"BASE10",
X		RELOC_BASE13,	"BASE13",
X		RELOC_BASE22,	"BASE22",
X		RELOC_PC10,	"PC10",
X		RELOC_PC22,	"PC22",
X		RELOC_JMP_TBL,	"JMP_TBL",
X		RELOC_SEGOFF16,	"SEGOFF16",
X		RELOC_GLOB_DAT,	"GLOB_DAT",
X		RELOC_JMP_SLOT,	"JMP_SLOT",
X		RELOC_RELATIVE,	"RELATIVE",
X		(enum reloc_type)0,	NULL,
X	};
X
X	for (x=tab; x->s; x++) {
X		if (x->v == v)
X			return x->s;
X	}
X#endif /* sparc */
X#endif /* sun */
X	return "RELOC_???";
X}
X
X#ifdef sun
Xvoid
Xprtrel(rp, nrp, nlp)
Xstruct reloc_info *rp;
Xint nrp;
Xstruct nlist *nlp;
X{
X	for (; nrp; nrp--, rp++) {
X		(void)printf("%08x %s", rp->r_address, reltyp(rp->r_type));
X		if (rp->r_extern) {
X#ifdef DEBUG
X			(void)printf(" -- index %04x --", rp->r_index);
X#endif
X			(void)printf(" [");
X			(void)prtsym(nlp + rp->r_index, 0);
X			(void)printf("]", rp->r_index);
X		} else {
X			(void)printf(" ntype %x", rp->r_index);
X		}
X		(void)printf(" + %d (%1$x)\n", rp->r_addend);
X	}
X
X	return;
X}
X#endif
X
Xstruct execmap *
Xmapfile(file)
Xchar *file;
X{
X	struct execmap *mp;
X	struct exec *hp;
X	int fd;
X	unsigned long strsize;
X	struct nlist *nlp;
X	struct stat stb;
X	caddr_t addr;
X
X	if ((fd = open(file, O_RDONLY)) == -1) {
X		fprintf(stderr, "%s: ", file); perror("open");
X		return NULL;
X	}
X	if ((mp = (struct execmap *)calloc(1, sizeof(*mp))) == NULL) {
X		fprintf(stderr, "mapfile: no memory\n");
X		goto errx;
X	}
X#ifdef sun
X	if (fstat(fd, &stb) < 0) {
X		perror("stat");
X		goto errx;
X	}
X	if ((addr = mmap((caddr_t)0, stb.st_size, PROT_READ|PROT_WRITE, MAP_PRIVATE, fd, 0)) == (caddr_t)-1) {
X		perror("mmap");
X		goto errx;
X	}
X	mp->e_mlen = stb.st_size;
X	hp = mp->e_hdr = (struct exec *)addr;
X	if (N_BADMAG(*hp)) {
X		fprintf(stderr, "%s: bad format\n", file);
X		goto errx;
X	}
X	mp->e_text = addr + N_TXTOFF(*hp);
X	mp->e_data = addr + N_DATOFF(*hp);
X	if (hp->a_syms == 0) {
X		(void)close(fd);
X		return mp;
X	}
X
X	/* Symbol table */
X	mp->e_nnlist = hp->a_syms / sizeof(struct nlist);
X	mp->e_nlist = (struct nlist *)(addr + N_SYMOFF(*hp));
X	mp->e_sym = (char *)(addr + N_STROFF(*hp));
X	strsize = *((unsigned long *)mp->e_sym);
X	if (strsize < 4) {
X		fprintf(stderr, "Incorrect string table size.\n");
X		goto errx;
X	}
X	if (hp->a_text+hp->a_data+hp->a_syms+
X		hp->a_trsize+hp->a_drsize + strsize > mp->e_mlen) {
X		fprintf(stderr, "Giant string table.\n");
X		goto errx;
X	}
X
X	/* Relocation tables */
X	if (hp->a_trsize != 0) {
X		mp->e_ntrel = (hp->a_trsize) / sizeof(struct reloc_info);
X		mp->e_trel = (struct reloc_info *)(addr + N_TRELOFF(*hp));
X	}
X	if (hp->a_drsize != 0) {
X		mp->e_ndrel = (hp->a_drsize) / sizeof(struct reloc_info);
X		mp->e_drel = (struct reloc_info *)(addr + N_DRELOFF(*hp));
X	}
X
X#else sun
X
X	if ((hp = mp->e_hdr = (struct exec *)malloc(sizeof(struct exec))) == NULL) {
X		fprintf(stderr, "No memory for header.\n");
X		goto errx;
X	}
X	if (read(fd, (char *)hp, sizeof(struct exec)) < sizeof(struct exec)) {
X		perror("read");
X		goto errx;
X	}
X	if (N_BADMAG(*hp)) {
X		fprintf(stderr, "%s: bad format\n", file);
X		goto errx;
X	}
X	if (hp->a_syms == 0) {
X		(void)close(fd);
X		return mp;
X	}
X	mp->e_nnlist = hp->a_syms / sizeof(struct nlist);
X	if ((mp->e_nlist = (struct nlist *)malloc(hp->a_syms)) == NULL) {
X		fprintf(stderr, "No memory for nlist.\n");
X		goto errx;
X	}
X
X	/* read symbol table */
X	if (lseek(fd, N_SYMOFF(*hp), 0) < 0) {
X		perror("seek");
X		goto errx;
X	}
X	if (read(fd, (char *)mp->e_nlist, hp->a_syms) < hp->a_syms) {
X		perror("read nlist");
X		goto errx;
X	}
X	if (lseek(fd, N_STROFF(*hp), 0) < 0) {
X		perror("seek");
X		goto errx;
X	}
X	if (read(fd, (char *)&strsize, 4) < 4) {
X		perror("read strsize");
X		goto errx;
X	}
X	if (strsize < 4) {
X		fprintf(stderr, "Incorrect string table size.\n");
X		goto errx;
X	}
X	if (lseek(fd, -4, 1) < 0) {
X		perror("seek");
X		goto errx;
X	}
X	if ((mp->e_sym = malloc(strsize)) == NULL) {
X		fprintf(stderr, "No memory for strings.\n");
X		goto errx;
X	}
X	if (read(fd, mp->e_sym, strsize) < strsize) {
X		perror("read strings");
X		goto errx;
X	}
X
X	/* read relocation tables */
X	if (hp->a_trsize != 0) {
X		mp->e_ntrel = (hp->a_trsize) / sizeof(struct reloc_info);
X		if ((mp->e_trel = (struct reloc_info *)malloc(hp->a_trsize)) == 0) {
X			fprintf(stderr, "No memory for reloc_info.\n");
X			goto errx;
X		}
X		if (lseek(fd, N_TRELOFF(*hp), 0) < 0) {
X			perror("seek");
X			goto errx;
X		}
X		if (read(fd, (char *)mp->e_trel, hp->a_trsize) < hp->a_trsize) {
X			perror("read reloc_info");
X			goto errx;
X		}
X	}
X	if (hp->a_drsize != 0) {
X		mp->e_ndrel = (hp->a_drsize) / sizeof(struct reloc_info);
X		if ((mp->e_drel = (struct reloc_info *)malloc(hp->a_drsize)) == 0) {
X			fprintf(stderr, "No memory for reloc_info.\n");
X			goto errx;
X		}
X		if (lseek(fd, N_DRELOFF(*hp), 0) < 0) {
X			perror("seek");
X			goto errx;
X		}
X		if (read(fd, (char *)mp->e_drel, hp->a_drsize) < hp->a_drsize) {
X			perror("read reloc_info");
X			goto errx;
X		}
X	}
X#endif sun
X
X	(void)close(fd);
X	/* convert string table offset to char pointer, in situ */
X	for (nlp = mp->e_nlist; nlp < mp->e_nlist + mp->e_nnlist; nlp++) {
X		if (nlp->n_un.n_strx > 0 && nlp->n_un.n_strx < strsize)
X			nlp->n_un.n_name = mp->e_sym + nlp->n_un.n_strx;
X		else
X			nlp->n_un.n_name = "sym_???";
X	}
X	return mp;
X
Xerrx:
X	(void)close(fd);
X	return NULL;
X}
X
Xint
Xunmapfile(mp)
Xstruct execmap *mp;
X{
X#ifdef sun
X	if (munmap(mp->e_hdr, mp->e_mlen) < 0) {
X		perror("munmap");
X		return -1;
X	}
X#endif
X	(void)free((char *)mp);
X	return 0;
X}
X
END_OF_FILE
if test 7655 -ne `wc -c <'util.c'`; then
    echo shar: \"'util.c'\" unpacked with wrong size!
fi
# end of 'util.c'
fi
echo shar: End of archive 1 \(of 1\).
cp /dev/null ark1isdone
MISSING=""
for I in 1 ; do
    if test ! -f ark${I}isdone ; then
	MISSING="${MISSING} ${I}"
    fi
done
if test "${MISSING}" = "" ; then
    echo You have the archive.
    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


: To unbundle, sh this file
echo x - mksym.c 1>&2
sed 's/^X//' >mksym.c <<'@@@End of mksym.c'
X/* 
X * Copy just the symbol tables from an application for debugging.
X * (BSD format: must also copy "string table", the actual name entries).
X *
X * $Id: mksym.c,v 1.4 92/02/03 17:28:55 ian Exp $
X *
X * Run in makefile just BEFORE stripping.
X * usage: mksyms a.out # writes on a.out.sym
X * e.g.,
X *	$(CC) $(AEOBJS) $(AELIBS) $(SYSLIBS) -o ae_2.24
X *	mksyms ae_2.24 # creates ae_2.24.sym
X *	strip ae_2.24
X *
X */
X
X#include <stdio.h>
X#include <ctype.h>
X#include <sys/types.h>
X#include <sys/stat.h>
X#include <a.out.h>
X
X#define	MAXSTR	1000
X
Xint	debug;
Xstatic struct stat statbuf;
Xchar	*progname;
Xvoid	error(), exit();
Xvoid	closein(), closeout();
X
Xstatic char *txbuf, *dtbuf,	/* used to read text and data segments */
X	*symbuf, *strbuf,	/* symbols */
X	*txrldbuf,		/* text rld */
X	*dtrldbuf;		/* data rld */
Xlong symtabsize, strtabsize;	/* the only ones we need to compute */
Xlong pigsize;			/* pessimal assumption here... */
Xchar *malloc();
X
Xstatic int ifd, ofd;
Xstatic struct exec filhdr;
Xextern int errno;
X
X#define max(x,y) (x>y?x:y)
X
X/*
X * main - parse arguments and handle options
X */
Xmain(argc, argv)
Xint argc;
Xchar *argv[];
X{
X	int c, errflg = 0, keepem = 0;
X	extern int optind;
X	extern char *optarg;
X
X	progname = argv[0];
X
X	pigsize = getpagesize();
X
X	while ((c = getopt(argc, argv, "d")) != EOF)
X		switch (c) {
X		case 'd':
X			++debug;
X			break;
X		default:
X			errflg++;
X			break;
X		}
X	if (errflg) {
X		(void) fprintf(stderr, "usage: %s xxx [file] ...\n", progname);
X		exit(2);
X	}
X
X	if (argc <= optind) {
X		fprintf(stderr, "usage: %s a.out > a.syms\n", progname);
X		exit(3);
X	}
X
X	for (; optind < argc; optind++) {
X			if (stat(argv[optind], &statbuf) != 0) {
X				fprintf(stderr,
X					"can't fstat %s", argv[optind]);
X				continue;
X			}
X			if ((statbuf.st_mode & S_IFMT)==S_IFDIR) {
X				fprintf(stderr,
X					"%s is a directory!", argv[optind]);
X				continue;
X			}
X			process(argv[optind], debug, statbuf.st_size);
X		}
X
X	exit(0);
X}
X
Xprocess(inname, debug, fsize)
Xchar *inname;
Xint debug;
Xlong fsize;
X{
X	char outname[MAXSTR+1];
X	char *AllTheRest;
X	long LengthOfTheRest;
X
X	strncpy(outname, inname, MAXSTR);
X	strncat(outname, ".sym", MAXSTR);
X
X	/* PART ONE -- read the old format in, and convert */
X	openin(inname, fsize);	/* sets globals s* based on exec hdr */
X
X#define bufalloc(buf,bufsize) if ((buf = malloc((unsigned)bufsize)) == NULL) { \
X		fprintf(stderr, "%s: can't malloc memory for text/data\n", \
X			progname); \
X		exit(4); \
X		}
X
X	LengthOfTheRest = fsize - N_SYMOFF(filhdr);
X	bufalloc(AllTheRest, LengthOfTheRest);
X	if (lseek(ifd, N_SYMOFF(filhdr), 0) < 0) {
X		perror("lseek to start of symbol table on input");
X		exit(1);
X	}
X
X	{
X		long i = read(ifd, AllTheRest, LengthOfTheRest);
X
X		if (i != LengthOfTheRest) {
X			extern int errno;
X			int e = errno;
X
X			fprintf(stderr,
X			    "%s: %s: %ld bytes instead of %ld returned by ",
X			    progname, inname, i, LengthOfTheRest);
X			errno =e;
X			perror("read()");
X			exit(1);
X		}
X
X		closein();
X		openout(outname);
X
X		i = write(ofd, AllTheRest, LengthOfTheRest);
X
X		if (i != LengthOfTheRest) {
X			extern int errno;
X			int e = errno;
X
X			fprintf(stderr,
X			    "%s: %s: %ld bytes instead of %ld returned by ",
X			    progname, inname, i, LengthOfTheRest);
X			errno =e;
X			perror("write()");
X			exit(1);
X		}
X	}
X
X
X#if 0
X	bufalloc(symbuf,   symtabsize);
X	getsyms(symbuf);
X
X	bufalloc(strbuf,   strtabsize);
X	getstrs(strbuf);
X
X	closein();
X
X	/* PART TWO - write the output file */
X	openout();
X	putsyms(symbuf);
X	putstrs(strbuf);
X#endif
X	closeout();
X
X	/* CLEAN UP */
X	if (txbuf) free(txbuf);
X	if (dtbuf) free(dtbuf);
X	if (symbuf) free(symbuf);
X	if (strbuf) free(strbuf);
X	if (AllTheRest) free(AllTheRest);
X}
X
X
X/*
X * Open a a.out for input, read header, return sizes of the
X * (text, data, sym, trld, drld) segments so a buffer can be allocated.
X */
Xopenin(fn, filesize)
Xchar *fn;
Xlong filesize;
X{
X	int i;
X
X	if ((ifd = open(fn, 0)) <0) {
X		fprintf(stderr, "%s: error opening %s\n", progname, fn);
X		exit(101);
X	}
X
X	if ((i=read(ifd, (char *)&filhdr, sizeof filhdr)) != sizeof filhdr) {
X		int realerrno = errno;
X		fprintf(stderr,
X			"%s: read exec: errno %d, got %d bytes, wanted %d\n",
X			progname, realerrno, i, sizeof filhdr);
X		exit(102);
X	}
X
X	if (N_BADMAG(filhdr)) {
X		fprintf(stderr,
X			"%s: bad magic: magic number %ld\n",
X			progname, filhdr.a_magic);
X		exit(103);
X	}
X
X	/* Get symtabsize and strtabsize from the input file */
X
X	symtabsize = filhdr.a_syms;
X
X	lseek(ifd, N_STROFF(filhdr), 0);
X	if (sizeof strtabsize != read (ifd, &strtabsize, sizeof strtabsize)) {
X		fprintf(stderr, "can't get size of string table\n");
X		return;
X	}
X
X	if (debug) {
X		printf("Name:\t%s\n", fn);
X		printf("Fsize:\t%d\n", filesize);
X		printf("Txtsiz:\t%d\n", filhdr.a_magic);
X		printf("Symsiz:\t%d (from a_syms)\n", symtabsize);
X		printf("strsiz:\t%d (read from file)\n", strtabsize);
X		printf("symstart:\t%ld\n", N_SYMOFF(filhdr));
X	}
X
X	return;
X}
X
Xvoid
Xclosein()
X{
X	(void) close(ifd);
X}
X
Xopenout(outn)
Xchar *outn;
X{
X
X	ofd = creat(outn, 0644);
X	if (ofd<0) {
X		perror(outn);
X		exit(1);
X	}
X
X	if (write(ofd, &filhdr, sizeof filhdr) != sizeof(filhdr)) {
X		perror("write first header");
X		exit(1);
X	}
X
X	if (lseek(ofd, (long)N_SYMOFF(filhdr), 0) < 0) {
X		perror("lseek to start of symbol table on output");
X		exit(1);
X	}
X}
X
Xvoid
Xcloseout()
X{
X	(void) close(ofd);
X}
X
Xgettext(buf)
Xchar *buf;
X{
X	if (lseek(ifd, N_TXTOFF(filhdr), 0) <0) {
X		perror("gettext: lseek");
X		exit(1);
X	}
X	if (read(ifd, (char *)buf, filhdr.a_text) != filhdr.a_text) {
X		perror("gettext: read");
X		exit(1);
X	}
X	return;
X}
X
Xgetdata(buf)
Xchar *buf;
X{
X	if (lseek(ifd, N_DATOFF(filhdr), 0) <0) {
X		perror("getdata: lseek");
X		exit(1);
X	}
X	if (read(ifd, (char *)buf, filhdr.a_data) != filhdr.a_data) {
X		perror("getdata: read");
X		exit(1);
X	}
X	return;
X}
X
Xgetsyms(buf)
Xchar *buf;
X{
X	if (lseek(ifd, N_SYMOFF(filhdr)+sizeof strtabsize, 0) <0) {
X		perror("getsyms: lseek");
X		exit(1);
X	}
X	if (read(ifd, (char *)buf, symtabsize) != symtabsize) {
X		perror("getsyms: read");
X		exit(1);
X	}
X}
X
Xgetstrs(buf)
Xchar *buf;
X{
X	if (lseek(ifd, N_STROFF(filhdr), 0) <0) {
X		perror("getstrs: lseek");
X		exit(1);
X	}
X	if (read(ifd, (char *)buf, strtabsize) != strtabsize) {
X		perror("getstrs: read");
X		exit(1);
X	}
X}
X
Xputsyms(buf)
Xchar *buf;
X{
X	if (lseek(ofd, filhdr.a_text+filhdr.a_data, 0) < 0) {
X		perror("putsyms: seek");
X		exit(1);
X	}
X	if (write(ofd, (char *)buf, symtabsize) != symtabsize) {
X		perror("putsyms: write");
X		exit(1);
X	}
X}
X
Xputstrs(buf)
Xchar *buf;
X{
X	if (write(ofd, (char *)buf, strtabsize) != strtabsize) {
X		perror("putstrs: write");
X		exit(1);
X	}
X}
X
@@@End of mksym.c

