add directory gnu
This commit is contained in:
212
gnu/binutils/binutils.001/binutils/ChangeLog
Normal file
212
gnu/binutils/binutils.001/binutils/ChangeLog
Normal file
@@ -0,0 +1,212 @@
|
||||
Thu Dec 29 01:48:03 1988 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
|
||||
|
||||
* ld.c, ar.c: Don't define COFF_ENCAPSULATE automatically.
|
||||
The recommended Makefile change defines it.
|
||||
|
||||
* ld.c (alloca): If compiling with GCC, use __builtin_alloca.
|
||||
|
||||
* robotussin.c: New reformatted version with all variables renamed.
|
||||
|
||||
* ranlib.c: New file, just runs `ar rs' on each specified file.
|
||||
* Makefile: Special hack to tell ranlib where to find GNU ar.
|
||||
(LIBS): Recommend -lPW on USG; ld needs it for alloca (if not GCC).
|
||||
|
||||
Sat Dec 24 13:59:09 1988 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
|
||||
|
||||
* ld.c (error): Start with name of program running.
|
||||
(main): Set `progname' to that name.
|
||||
(digest_symbols): Fix punctuation and spelling in calls to `error'.
|
||||
|
||||
Tue Dec 20 21:49:46 1988 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
|
||||
|
||||
* robotussin.c (INPUT_MAGIC): New macro, has the magic number
|
||||
to expect in input files.
|
||||
(nounderscore): New macro; as in ld, define it to inhibit
|
||||
adding underscore to symbols.
|
||||
|
||||
* Makefile: Don't compile objdump on BSD; N_DATADDR causes trouble.
|
||||
|
||||
Tue Dec 20 14:57:38 1988 Pace Willisson (pace at prep.at.mit.edu)
|
||||
|
||||
* objdump.c: New program like the system 5 'dump' program.
|
||||
Documentation will follow...
|
||||
|
||||
* Makefile: Set up CFLAGS for USG systems. Added target
|
||||
libc.a to do robotussin conversion. Added objdump.
|
||||
|
||||
* libconvert: Wrote shell script to do robotussin conversion.
|
||||
|
||||
* ar.c, ld.c: Don't define COFF_ENCAPSULATE if it is already defined.
|
||||
|
||||
* ld.c: If i386, set a_machtype to M_386. Use a_flags instead
|
||||
of a_encap. Don't compute coff header if it isn't going to
|
||||
get written out.
|
||||
|
||||
* robotussin.c: Define COFF_ENCAPSULATE. Include a.out.encap.h
|
||||
instead of a.out.h. Check magic number of input
|
||||
file. Skip over optional header, if present. Don't ignore
|
||||
symbols with aux entries (they could be function definitions),
|
||||
instead, ignore symbols beginning with '.' (.text, etc).
|
||||
Don't prepend underscore to externals, since gcc doesn't do
|
||||
it now. Don't run past the end of symbols that are exactly
|
||||
eight characters long. Always write the string table size,
|
||||
even if it is empty. Change relocation types handled from
|
||||
R_PCRBYTE, etc, to R_DIR32 and R_PCRLONG (these are the
|
||||
only two emitted by the system 5 assembler.)
|
||||
|
||||
* size.c: Include <sys/types.h> so including sys/file.h will
|
||||
not get an error on USG systems. Include fcntl.h on usg systems.
|
||||
|
||||
* strip.c: Move inclusion of file.h to after types.h. Include
|
||||
fcntl.h. Add defintion of rename.
|
||||
|
||||
Fri Dec 16 13:55:11 1988 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
|
||||
|
||||
* size.c: Delete all ROBOTUSSIN conditionals and contents.
|
||||
Change SYSV conditionals to USG.
|
||||
COFF_ENCAPSULATE conditionals for headers.
|
||||
(do_one_file, read_header): Skip encapsulation headers if any.
|
||||
|
||||
* strip.c: Delete all ROBOTUSSIN conditionals and contents.
|
||||
Change SYSV conditionals to USG.
|
||||
COFF_ENCAPSULATE conditionals for headers.
|
||||
(file_open, read_header): Skip encapsulation headers if any.
|
||||
|
||||
* strip.c: Change most fatal errors to nonfatal.
|
||||
(file_open, read_header, read_{file,entry}_symbols):
|
||||
Now return 0 for success, -1 for failure.
|
||||
Failure means do no more for the current file.
|
||||
(modify_relocation): Now just warn if strip a symbol needed
|
||||
for relocation, and warn only once per file.
|
||||
(error_with_file): New function, replaces most fatal_with_file.
|
||||
Print filename first, as in most programs.
|
||||
(fatal_with_file): Deleted.
|
||||
(rewrite_file_symbols): Use perror_file when system call fails.
|
||||
|
||||
Tue Dec 13 17:16:39 1988 Jay Fenlason (hack at apple-gunkies.ai.mit.edu)
|
||||
|
||||
* ar.c: Changed pad character after odd-length archive member
|
||||
from \0 to \n so archives can be cmp'd with the output from /bin/ar
|
||||
Added fix for when ranlib is using ar to insert an __.SYMDEF member
|
||||
|
||||
Tue Dec 13 09:09:27 1988 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
|
||||
|
||||
* ar.c: conditional #includes for USG.
|
||||
* COFF_ENCAPSULATE conditionals for headers.
|
||||
(extract_member): Don't do fchmod if USG.
|
||||
Alternate USG code to set modtimes of extracted members.
|
||||
(write_archive): Don't do fsync if USG.
|
||||
(make_new_symdefs): Skip encapsulation headers if any.
|
||||
[USG] (bcopy, bzero, bcmp): New fns.
|
||||
|
||||
* nm.c: Delete all ROBOTUSSIN conditionals and contents.
|
||||
Include types.h.
|
||||
Change SYSV conditionals to USG.
|
||||
* COFF_ENCAPSULATE conditionals for headers.
|
||||
(do_one_file): Skip encapsulation headers if any.
|
||||
(read_header): Likewise.
|
||||
|
||||
* ld.c: Delete all ROBOTUSSIN conditionals and contents.
|
||||
Change SYSV conditionals to USG.
|
||||
Change HEADER_TYPE back to `struct exec'.
|
||||
(L_SET): Define it if headers don't.
|
||||
* COFF_ENCAPSULATE conditionals for headers.
|
||||
(main): Update text_size differently if encapsulating.
|
||||
(write_header): Write the encapsulation headers if nec.
|
||||
Don't end with padding if encapsulation being done.
|
||||
[USG] (bzero, bcopy, getpagesize): New fns.
|
||||
|
||||
Tue Dec 6 13:26:56 1988 Randall Smith (randy at apple-gunkies.ai.mit.edu)
|
||||
|
||||
* ld.c (do_file_warnings): Ignored text relocation entries that
|
||||
went through local symbols; any problems with lack of definitions
|
||||
etc. with them would have been caught by the compiler.
|
||||
|
||||
Mon Dec 5 16:13:22 1988 Jay Fenlason (hack at sugar-bombs.ai.mit.edu)
|
||||
|
||||
* ar.c (make_new_symdefs): On error, close the input files.
|
||||
|
||||
Thu Nov 10 18:15:07 1988 Randall Smith (randy at apple-gunkies.ai.mit.edu)
|
||||
|
||||
* ld.c: Put declaration of alloca inside an #ifdef so that it
|
||||
wouldn't mess up on the sparc.
|
||||
|
||||
* ld.c: Added #define CORE_ADDR for include of symseg.h from gdb
|
||||
and took out TARGET == SUN2 for sun2 INITIALIZE_HEADER.
|
||||
|
||||
Wed Nov 2 18:43:09 1988 Randall Smith (randy at gluteus.ai.mit.edu)
|
||||
|
||||
* ld.c: Merged in isi68k port. This included a kludge for symbols
|
||||
starting with _$ (#ifdef DOLLAR_KLUDGE) and addition of the
|
||||
STANDARD_SEARCH_DIRS macro to override the default if it's
|
||||
defined.
|
||||
|
||||
* ld.c: Added code for the N_WARNING symbol type. If a reference
|
||||
is found to a symbol in an input .o file which contains an
|
||||
N_WARNING symbol, a warning message (the name of the N_WARNING
|
||||
symbol) is printed. This name is treated as a printf format
|
||||
string; the name of the symbol referenced (which caused the
|
||||
warning) is supplied as a single argument to the print which
|
||||
interpets this string.
|
||||
|
||||
Tue Nov 1 16:57:00 1988 Randall Smith (randy at gluteus.ai.mit.edu)
|
||||
|
||||
* ld.c: Added code for Sun 2.
|
||||
|
||||
* ld.c: Modified access to the relocation information to be *much*
|
||||
more general; added in sparc support. This change is a minor
|
||||
performance hit; the perform_relocation routine uses about 0.1
|
||||
seconds more time on linking gdb than did the original ld.
|
||||
(perform_relocation is about 5% of the total time the loader
|
||||
spends). The price of generality.
|
||||
|
||||
Thu Aug 4 13:20:50 1988 Randy Smith (randy at rice-chex.ai.mit.edu)
|
||||
|
||||
* Modified ld.c to print only the first 10 unresolved references
|
||||
for each symbol, followed by a message indicating that there are
|
||||
more unresolved references that have not been printed (if indeed
|
||||
there are). Made default behaivior upon errors *not* writing any
|
||||
output file at all. Also added the -noinhibit-exec flag to force
|
||||
writing of an executable when that was desirable.
|
||||
|
||||
Tue Aug 2 12:04:01 1988 Randy Smith (randy at rice-chex.ai.mit.edu)
|
||||
|
||||
* Modified ld.c to give line numbers wherever possible on
|
||||
unreferenced symbols. Added a new symbol (N_DSLNE) to allow for
|
||||
the same mapping of data location to line number as is done for
|
||||
text segments by N_SLINE. Added code to sort the relocation
|
||||
entries when it is necessary to output these line numbers. The
|
||||
assumption was made that both N_SLINE and N_DSLNE symbols would
|
||||
always be in order by address.
|
||||
|
||||
Wed Jul 27 15:13:08 1988 Randy Smith (randy at rice-chex.ai.mit.edu)
|
||||
|
||||
* Modified ld.c to include a facility for equivalencing two
|
||||
symbols (translating one to another). Modified lib/a.out.h to
|
||||
include a definition of this new symbol. Modified nm.c to
|
||||
recognize this symbol and all of the set element and vector
|
||||
symbols I had added before.
|
||||
|
||||
Thu Jul 21 17:06:10 1988 Randy Smith (randy at rice-chex.ai.mit.edu)
|
||||
|
||||
* Modified ld.c to printout source file and line numbers for
|
||||
unresolved references whenever possible (ie. whenever the input
|
||||
file has debugger symbols and the reference is from the text area).
|
||||
|
||||
Wed Jul 13 17:21:33 1988 Randy Smith (randy at frosted-flakes.ai.mit.edu)
|
||||
|
||||
* Modified ld.c and a.out.h to handle new types of symbols; the
|
||||
loader can now create "sets" of symbols from entries in its input
|
||||
files. See a.out.h for more info. Also fixed a bug in ld in
|
||||
which references to common areas that we not defined in one pass
|
||||
of the loader caused errors on the next.
|
||||
|
||||
Sat Jul 2 00:05:44 1988 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
|
||||
|
||||
* ld.c (symdef_library): Error check was off by one.
|
||||
|
||||
Mon May 9 12:53:08 1988 Chris Hanson (cph at kleph)
|
||||
|
||||
* ar.c (replace_members): After updating map, write out
|
||||
`change_map->next' rather than `map', since the latter may be
|
||||
null.
|
||||
68
gnu/binutils/binutils.001/binutils/Makefile
Normal file
68
gnu/binutils/binutils.001/binutils/Makefile
Normal file
@@ -0,0 +1,68 @@
|
||||
# Makefile for GNU binary-file utilities
|
||||
# select a set of CFLAGS and PROGS, below, depending on the system type
|
||||
|
||||
GNUCC = gcc -O
|
||||
|
||||
# for BSD systems
|
||||
CFLAGS = -g
|
||||
# Don't add robotussin; it won't compile on BSD or GNU systems.
|
||||
# objdump also won't compile on most systems (trouble with N_DATADDR).
|
||||
PROGS = gprof ld size nm strip ar ranlib
|
||||
|
||||
# for USG systems using COFF_ENCAPSULATE
|
||||
# also, you will want to make the target libc.a (but it takes a long time)
|
||||
# Note that you should leave a copy of `ar' in this directory
|
||||
# after you install it, since `ranlib' will try to run it from here.
|
||||
#CFLAGS = -g -DUSG -DCOFF_ENCAPSULATE -DPORTAR -DNON_NATIVE -Dnounderscore
|
||||
#PROGS = ld size nm strip ar robotussin objdump ranlib
|
||||
#LIBS = -lPW
|
||||
|
||||
all: $(PROGS)
|
||||
|
||||
ld: ld.o
|
||||
# LIBS is used here since ld needs to use alloca.
|
||||
# Alternatively, compile it with GNU C--then the compiler handles alloca.
|
||||
$(CC) -o ld ld.o $(LIBS)
|
||||
|
||||
size: size.o
|
||||
$(CC) -o size size.o
|
||||
|
||||
nm: nm.o
|
||||
$(CC) -o nm nm.o
|
||||
|
||||
strip: strip.o
|
||||
$(CC) -o strip strip.o
|
||||
|
||||
ar: ar.o
|
||||
$(CC) -o ar ar.o
|
||||
|
||||
gprof: gprof.o
|
||||
$(GNUCC) -o gprof gprof.o
|
||||
gprof.o: gprof.c gmon.h
|
||||
$(GNUCC) -c $(CFLAGS) gprof.c
|
||||
|
||||
ranlib: ranlib.o
|
||||
$(CC) -o ranlib ranlib.o
|
||||
ranlib.o: ranlib.c
|
||||
$(CC) -c -g -DAR_PROG=\"`pwd`/ar\" ranlib.c
|
||||
|
||||
# Robotussin is NOT part of `all'.
|
||||
robotussin: robotussin.o
|
||||
$(CC) -o robotussin robotussin.o
|
||||
|
||||
libc.a: robotussin libconvert
|
||||
libconvert
|
||||
rm -rf tmp
|
||||
|
||||
clean:
|
||||
-rm -f *.o core
|
||||
-rm -f gprof ar nm size strip ld robotussin objdump ranlib
|
||||
|
||||
dist:
|
||||
-rm -rf binutils
|
||||
mkdir binutils
|
||||
-ln * binutils
|
||||
(cd binutils; rm -f GNUmakefile *~ "#*" log* binutils.tar*; make clean)
|
||||
tar cof binutils.tar binutils
|
||||
compress < binutils.tar > binutils.tar.Z
|
||||
rm -rf binutils
|
||||
37
gnu/binutils/binutils.001/binutils/README
Normal file
37
gnu/binutils/binutils.001/binutils/README
Normal file
@@ -0,0 +1,37 @@
|
||||
These files are some GNU utilities for operating on binary files.
|
||||
Note that GNU make, which used to be included here, is now distributed
|
||||
in a separate tar file.
|
||||
|
||||
Report bugs in these programs to bug-gnu-utils@prep.ai.mit.edu and use
|
||||
the date of the main source file as a "version number" for the
|
||||
program.
|
||||
|
||||
Define USG with `-DUSG' when compiling these programs to run on system V.
|
||||
|
||||
COFF is not supported, but we do support a way of encapsulating GNU
|
||||
executable files with COFF headers. Use -DCOFF_ENCAPSULATE when you
|
||||
compile, to enable this feature.
|
||||
|
||||
In order to use encapsulation, you must use entirely GNU tools,
|
||||
including these plus GAS, GCC and GDB. You will need to convert the
|
||||
system libraries to BSD object file format. Use the shell script
|
||||
libconvert (which uses robotussin) for that.
|
||||
|
||||
The GNU version of ld has some interesting features:
|
||||
|
||||
1. Undefined and multiply-defined global symbol errors
|
||||
are now associated with specific source files and line numbers,
|
||||
and printed in a format M-x next-error can parse.
|
||||
|
||||
2. Normally no output is written if there are serious errors.
|
||||
Use the option `-noinhibit-exec' if you want an output file anyway.
|
||||
|
||||
3. Global symbols can be defined by indirection to other symbols.
|
||||
See comments at definition of N_INDR in ld.c
|
||||
|
||||
4. LD can accumulate sets of related values from all the object files
|
||||
that are being linked together, and put them into a vector that can
|
||||
be accessed at run time. Thus, you can arrange for each file to have
|
||||
initializations to be run when your `main' function sees fit, without
|
||||
having to know the names of all the files that are linked together.
|
||||
See comments at definition of N_SETA, etc., in ld.c.
|
||||
115
gnu/binutils/binutils.001/binutils/a.out.encap.h
Normal file
115
gnu/binutils/binutils.001/binutils/a.out.encap.h
Normal file
@@ -0,0 +1,115 @@
|
||||
/* this file can be renamed 'a.out.h' someday */
|
||||
/*
|
||||
* another try at encapsulating bsd object files in coff
|
||||
* by Pace Willisson 12/9/88
|
||||
*
|
||||
* This time, we will only use the coff headers to tell the kernel
|
||||
* how to exec the file. Therefore, the only fields that need to
|
||||
* be filled in are the scnptr and vaddr for the text and data
|
||||
* sections, and the vaddr for the bss. As far as coff is concerned,
|
||||
* there is no symbol table, relocation, or line numbers.
|
||||
*
|
||||
* A normal bsd header (struct exec) is placed after the coff headers,
|
||||
* and before the real text. I defined a the new fields 'a_machtype'
|
||||
* and a_flags. If a_machtype is M_386, and a_flags & A_ENCAP is
|
||||
* true, then the bsd header is preceeded by a coff header. Macros
|
||||
* like N_TXTOFF and N_TXTADDR use this field to find the bsd header.
|
||||
*
|
||||
* The only problem is to track down the bsd exec header. The
|
||||
* macros HEADER_OFFSET, etc do this. Look at nm.c, dis.c, etc
|
||||
* for examples.
|
||||
*/
|
||||
|
||||
#include "a.out.gnu.h"
|
||||
|
||||
#define A_ENCAP 1 /* when true in a_flags, coff header preceeds bsd header */
|
||||
|
||||
/* Describe the COFF header used for encapsulation. */
|
||||
|
||||
struct coffheader
|
||||
{
|
||||
/* filehdr */
|
||||
unsigned short f_magic;
|
||||
unsigned short f_nscns;
|
||||
long f_timdat;
|
||||
long f_symptr;
|
||||
long f_nsyms;
|
||||
unsigned short f_opthdr;
|
||||
unsigned short f_flags;
|
||||
/* aouthdr */
|
||||
short magic;
|
||||
short vstamp;
|
||||
long tsize;
|
||||
long dsize;
|
||||
long bsize;
|
||||
long entry;
|
||||
long text_start;
|
||||
long data_start;
|
||||
struct coffscn
|
||||
{
|
||||
char s_name[8];
|
||||
long s_paddr;
|
||||
long s_vaddr;
|
||||
long s_size;
|
||||
long s_scnptr;
|
||||
long s_relptr;
|
||||
long s_lnnoptr;
|
||||
unsigned short s_nreloc;
|
||||
unsigned short s_nlnno;
|
||||
long s_flags;
|
||||
} scns[3];
|
||||
};
|
||||
|
||||
/* Describe some of the parameters of the encapsulation,
|
||||
including how to find the encapsulated BSD header. */
|
||||
|
||||
#ifdef i386
|
||||
#define COFF_MAGIC 0514 /* I386MAGIC */
|
||||
#endif
|
||||
|
||||
#if defined(i386)
|
||||
short __header_offset_temp;
|
||||
#define HEADER_OFFSET(f) \
|
||||
(__header_offset_temp = 0, \
|
||||
fread ((char *)&__header_offset_temp, sizeof (short), 1, (f)), \
|
||||
fseek ((f), -sizeof (short), 1), \
|
||||
__header_offset_temp==COFF_MAGIC ? sizeof(struct coffheader) : 0)
|
||||
|
||||
#define HEADER_OFFSET_FD(fd) \
|
||||
(__header_offset_temp = 0, \
|
||||
read ((fd), (char *)&__header_offset_temp, sizeof (short)), \
|
||||
lseek ((fd), -sizeof (short), 1), \
|
||||
__header_offset_temp==COFF_MAGIC ? sizeof(struct coffheader) : 0)
|
||||
|
||||
|
||||
#else
|
||||
#define HEADER_OFFSET(f) 0
|
||||
#define HEADER_OFFSET_FD(fd) 0
|
||||
#endif
|
||||
#define HEADER_SEEK(f) (fseek ((f), HEADER_OFFSET((f)), 1))
|
||||
#define HEADER_SEEK_FD(fd) (lseek ((fd), HEADER_OFFSET_FD((fd)), 1))
|
||||
|
||||
/* Describe the characteristics of the BSD header
|
||||
that appears inside the encapsulation. */
|
||||
|
||||
#undef N_BADMAG
|
||||
#define N_BADMAG(x) \
|
||||
(((x).a_magic)!=OMAGIC && ((x).a_magic)!=ZMAGIC)
|
||||
|
||||
#undef _N_HDROFF
|
||||
#undef N_TXTADDR
|
||||
#undef N_DATADDR
|
||||
|
||||
/* always 0 on real bsd systems */
|
||||
#define _N_HDROFF(x) ((x).a_flags & A_ENCAP ? sizeof (struct coffheader) : 0)
|
||||
|
||||
/* Address of text segment in memory after it is loaded. */
|
||||
#define N_TXTADDR(x) \
|
||||
(((x).a_flags & A_ENCAP) ? \
|
||||
sizeof (struct coffheader) + sizeof (struct exec) : 0)
|
||||
|
||||
#define SEGMENT_SIZE 0x400000
|
||||
#define N_DATADDR(x) \
|
||||
(((x).a_flags & A_ENCAP) ? \
|
||||
(SEGMENT_SIZE + ((N_TXTADDR(x)+(x).a_text-1) & ~(SEGMENT_SIZE-1))) : \
|
||||
(N_TXTADDR(x)+(x).a_text))
|
||||
155
gnu/binutils/binutils.001/binutils/a.out.gnu.h
Normal file
155
gnu/binutils/binutils.001/binutils/a.out.gnu.h
Normal file
@@ -0,0 +1,155 @@
|
||||
|
||||
struct exec
|
||||
{
|
||||
#ifdef COFF_ENCAPSULATE
|
||||
unsigned short a_magic;
|
||||
unsigned char a_machtype;
|
||||
unsigned char a_flags;
|
||||
#else
|
||||
long a_magic; /* number identifies as .o file and gives type of such. */
|
||||
#endif
|
||||
unsigned a_text; /* length of text, in bytes */
|
||||
unsigned a_data; /* length of data, in bytes */
|
||||
unsigned a_bss; /* length of uninitialized data area for file, in bytes */
|
||||
unsigned a_syms; /* length of symbol table data in file, in bytes */
|
||||
unsigned a_entry; /* start address */
|
||||
unsigned a_trsize; /* length of relocation info for text, in bytes */
|
||||
unsigned a_drsize; /* length of relocation info for data, in bytes */
|
||||
};
|
||||
|
||||
/* these go in the a_machtype field */
|
||||
#define M_68010 1 /* sun defined these */
|
||||
#define M_68020 2
|
||||
|
||||
#define M_386 100 /* skip a bunch so we don't conflict with sun's numbers */
|
||||
|
||||
/* Code indicating object file or impure executable. */
|
||||
#define OMAGIC 0407
|
||||
/* Code indicating pure executable. */
|
||||
#define NMAGIC 0410
|
||||
/* Code indicating demand-paged executable. */
|
||||
#define ZMAGIC 0413
|
||||
|
||||
#define N_BADMAG(x) \
|
||||
(((x).a_magic) != OMAGIC && ((x).a_magic) != NMAGIC \
|
||||
&& ((x).a_magic) != ZMAGIC)
|
||||
|
||||
#define _N_HDROFF(x) (1024 - sizeof (struct exec))
|
||||
|
||||
#define N_TXTOFF(x) \
|
||||
((x).a_magic == ZMAGIC ? _N_HDROFF((x)) + sizeof (struct exec) : sizeof (struct exec))
|
||||
|
||||
#define N_DATOFF(x) (N_TXTOFF(x) + (x).a_text)
|
||||
|
||||
#define N_TRELOFF(x) (N_DATOFF(x) + (x).a_data)
|
||||
|
||||
#define N_DRELOFF(x) (N_TRELOFF(x) + (x).a_trsize)
|
||||
|
||||
#define N_SYMOFF(x) (N_DRELOFF(x) + (x).a_drsize)
|
||||
|
||||
#define N_STROFF(x) (N_SYMOFF(x) + (x).a_syms)
|
||||
|
||||
/* Address of text segment in memory after it is loaded. */
|
||||
#define N_TXTADDR(x) 0
|
||||
|
||||
/* Address of data segment in memory after it is loaded.
|
||||
Note that it is up to you to define SEGMENT_SIZE
|
||||
on machines not listed here. */
|
||||
#ifdef vax
|
||||
#define SEGMENT_SIZE page_size
|
||||
#endif
|
||||
#ifdef is68k
|
||||
#define SEGMENT_SIZE 0x20000
|
||||
#endif
|
||||
|
||||
#ifndef N_DATADDR
|
||||
#define N_DATADDR(x) \
|
||||
(((x).a_magic==OMAGIC)? (N_TXTADDR(x)+(x).a_text) \
|
||||
: (SEGMENT_SIZE + ((N_TXTADDR(x)+(x).a_text-1) & ~(SEGMENT_SIZE-1))))
|
||||
#endif
|
||||
|
||||
/* Address of bss segment in memory after it is loaded. */
|
||||
#define N_BSSADDR(x) (N_DATADDR(x) + (x).a_data)
|
||||
|
||||
struct nlist {
|
||||
union {
|
||||
char *n_name;
|
||||
struct nlist *n_next;
|
||||
long n_strx;
|
||||
} n_un;
|
||||
char n_type;
|
||||
char n_other;
|
||||
short n_desc;
|
||||
unsigned n_value;
|
||||
};
|
||||
|
||||
#define N_UNDF 0
|
||||
#define N_ABS 2
|
||||
#define N_TEXT 4
|
||||
#define N_DATA 6
|
||||
#define N_BSS 8
|
||||
#define N_FN 15
|
||||
|
||||
#define N_EXT 1
|
||||
#define N_TYPE 036
|
||||
#define N_STAB 0340
|
||||
|
||||
/* The following type indicates the definition of a symbol as being
|
||||
an indirect reference to another symbol. The other symbol
|
||||
appears as an undefined reference, immediately following this symbol.
|
||||
|
||||
Indirection is asymmetrical. The other symbol's value will be used
|
||||
to satisfy requests for the indirect symbol, but not vice versa.
|
||||
If the other symbol does not have a definition, libraries will
|
||||
be searched to find a definition. */
|
||||
#define N_INDR 0xa
|
||||
|
||||
/* The following symbols refer to set elements.
|
||||
All the N_SET[ATDB] symbols with the same name form one set.
|
||||
Space is allocated for the set in the text section, and each set
|
||||
element's value is stored into one word of the space.
|
||||
The first word of the space is the length of the set (number of elements).
|
||||
|
||||
The address of the set is made into an N_SETV symbol
|
||||
whose name is the same as the name of the set.
|
||||
This symbol acts like a N_TEXT global symbol
|
||||
in that it can satisfy undefined external references. */
|
||||
|
||||
/* These appear as input to LD, in a .o file. */
|
||||
#define N_SETA 0x14 /* Absolute set element symbol */
|
||||
#define N_SETT 0x16 /* Text set element symbol */
|
||||
#define N_SETD 0x18 /* Data set element symbol */
|
||||
#define N_SETB 0x1A /* Bss set element symbol */
|
||||
|
||||
/* This is output from LD. */
|
||||
#define N_SETV 0x1C /* Pointer to set vector in text area. */
|
||||
|
||||
/* This structure describes a single relocation to be performed.
|
||||
The text-relocation section of the file is a vector of these structures,
|
||||
all of which apply to the text section.
|
||||
Likewise, the data-relocation section applies to the data section. */
|
||||
|
||||
struct relocation_info
|
||||
{
|
||||
/* Address (within segment) to be relocated. */
|
||||
int r_address;
|
||||
/* The meaning of r_symbolnum depends on r_extern. */
|
||||
unsigned int r_symbolnum:24;
|
||||
/* Nonzero means value is a pc-relative offset
|
||||
and it should be relocated for changes in its own address
|
||||
as well as for changes in the symbol or section specified. */
|
||||
unsigned int r_pcrel:1;
|
||||
/* Length (as exponent of 2) of the field to be relocated.
|
||||
Thus, a value of 2 indicates 1<<2 bytes. */
|
||||
unsigned int r_length:2;
|
||||
/* 1 => relocate with value of symbol.
|
||||
r_symbolnum is the index of the symbol
|
||||
in file's the symbol table.
|
||||
0 => relocate with the address of a segment.
|
||||
r_symbolnum is N_TEXT, N_DATA, N_BSS or N_ABS
|
||||
(the N_EXT bit may be set also, but signifies nothing). */
|
||||
unsigned int r_extern:1;
|
||||
/* Four bits that aren't used, but when writing an object file
|
||||
it is desirable to clear them. */
|
||||
unsigned int r_pad:4;
|
||||
};
|
||||
1804
gnu/binutils/binutils.001/binutils/ar.c
Normal file
1804
gnu/binutils/binutils.001/binutils/ar.c
Normal file
File diff suppressed because it is too large
Load Diff
48
gnu/binutils/binutils.001/binutils/gmon.h
Normal file
48
gnu/binutils/binutils.001/binutils/gmon.h
Normal file
@@ -0,0 +1,48 @@
|
||||
/* Format of gmon.out file. */
|
||||
|
||||
/* This header appears at the beginning of the gmon.out file.
|
||||
LOW and HIGH are low and high water marks for the program counter
|
||||
during the creation of the gmon.out file.
|
||||
LOW is also the offset where the histogram table starts in the
|
||||
text (code) segment.
|
||||
NBYTES is the number of bytes in this header plus the histogram itself,
|
||||
which immediately follows the header in the file.
|
||||
|
||||
Therefore, the number of histogram entries is
|
||||
(NBYTES - sizeof (struct gm_header)) / (sizeof (CHUNK)).
|
||||
|
||||
Each entry applies to a range of PC values.
|
||||
The first entry applies to PC values starting at LOW.
|
||||
The last entry applies to PC values ending at HIGH.
|
||||
Therefore, the span of each entry's range is
|
||||
(HIGH - LOW) / number-of-entries
|
||||
Usually this value is 4.
|
||||
*/
|
||||
|
||||
struct gm_header {
|
||||
unsigned long low;
|
||||
unsigned long high;
|
||||
long nbytes;
|
||||
};
|
||||
|
||||
/* Data type of an entry in the PC histogram. */
|
||||
#define CHUNK short
|
||||
|
||||
/* After the histogram cone the function call count entries.
|
||||
They fill all the rest of the file.
|
||||
Each count entry records the number of calls to one function
|
||||
from one pc value.
|
||||
|
||||
FROM describes the caller pc, as an offset into the text segment.
|
||||
TO is the address of the called function.
|
||||
NCALLS is the number of calls counted from FROM to TO.
|
||||
|
||||
Note that if a function A is called from several places in B,
|
||||
there are separate call count entries for each call, with different FROM.
|
||||
All of them together count the number of calls from B to A. */
|
||||
|
||||
struct gm_call {
|
||||
unsigned long from;
|
||||
unsigned long to;
|
||||
unsigned long ncalls;
|
||||
};
|
||||
2760
gnu/binutils/binutils.001/binutils/gprof.c
Normal file
2760
gnu/binutils/binutils.001/binutils/gprof.c
Normal file
File diff suppressed because it is too large
Load Diff
933
gnu/binutils/binutils.001/binutils/gprof.texinfo
Normal file
933
gnu/binutils/binutils.001/binutils/gprof.texinfo
Normal file
@@ -0,0 +1,933 @@
|
||||
\input texinfo @c -*-texinfo-*-
|
||||
@setfilename gprof
|
||||
@settitle gprof
|
||||
@ifinfo
|
||||
This file documents the gprof profiler of the GNU system.
|
||||
|
||||
Copyright (C) 1988 Free Software Foundation, Inc.
|
||||
|
||||
Permission is granted to make and distribute verbatim copies of
|
||||
this manual provided the copyright notice and this permission notice
|
||||
are preserved on all copies.
|
||||
|
||||
@ignore
|
||||
Permission is granted to process this file through Tex and print the
|
||||
results, provided the printed document carries copying permission
|
||||
notice identical to this one except for the removal of this paragraph
|
||||
(this paragraph not being relevant to the printed manual).
|
||||
|
||||
@end ignore
|
||||
Permission is granted to copy and distribute modified versions of this
|
||||
manual under the conditions for verbatim copying, provided that the entire
|
||||
resulting derived work is distributed under the terms of a permission
|
||||
notice identical to this one.
|
||||
|
||||
Permission is granted to copy and distribute translations of this manual
|
||||
into another language, under the above conditions for modified versions.
|
||||
@end ifinfo
|
||||
|
||||
@titlepage
|
||||
@center @titlefont{gprof}
|
||||
@sp 1
|
||||
@center The GNU Profiler
|
||||
@sp 2
|
||||
@center Jay Fenlason and Richard Stallman
|
||||
@sp 4
|
||||
This manual describes the GNU profiler, @code{gprof}, and how you can use
|
||||
it to determine which parts of a program are taking most of the execution
|
||||
time. We assume that you know how to write, compile, and execute programs.
|
||||
GNU @code{gprof} was written by Jay Fenlason.
|
||||
@sp 8
|
||||
Copyright @copyright{} 1988 Free Software Foundation, Inc.
|
||||
|
||||
Permission is granted to make and distribute verbatim copies of
|
||||
this manual provided the copyright notice and this permission notice
|
||||
are preserved on all copies.
|
||||
|
||||
@ignore
|
||||
Permission is granted to process this file through Tex and print the
|
||||
results, provided the printed document carries copying permission
|
||||
notice identical to this one except for the removal of this paragraph
|
||||
(this paragraph not being relevant to the printed manual).
|
||||
|
||||
@end ignore
|
||||
Permission is granted to copy and distribute modified versions of this
|
||||
manual under the conditions for verbatim copying, provided that the entire
|
||||
resulting derived work is distributed under the terms of a permission
|
||||
notice identical to this one.
|
||||
|
||||
Permission is granted to copy and distribute translations of this manual
|
||||
into another language, under the same conditions as for modified versions.
|
||||
|
||||
@end titlepage
|
||||
|
||||
@ifinfo
|
||||
@node Top, Why, Top, (dir)
|
||||
@ichapter Profiling a Program: Where Does It Spend Its Time?
|
||||
|
||||
This manual describes the GNU profiler @code{gprof}, and how you can use it
|
||||
to determine which parts of a program are taking most of the execution
|
||||
time. We assume that you know how to write, compile, and execute programs.
|
||||
GNU @code{gprof} was written by Jay Fenlason.
|
||||
|
||||
@menu
|
||||
* Why:: What profiling means, and why it is useful.
|
||||
* Compiling:: How to compile your program for profiling.
|
||||
* Executing:: How to execute your program to generate the
|
||||
profile data file @file{gmon.out}.
|
||||
* Analyzing:: How to run @code{gprof}, and how to specify
|
||||
options for it.
|
||||
|
||||
* Flat Profile:: The flat profile shows how much time was spent
|
||||
executing directly in each function.
|
||||
* Call Graph:: The call graph shows which functions called which
|
||||
others, and how much time each function used
|
||||
when its subroutine calls are included.
|
||||
|
||||
* Implementation:: How the profile data is recorded and written.
|
||||
* Sampling Error:: Statistical margins of error.
|
||||
How to accumulate data from several runs
|
||||
to make it more accurate.
|
||||
|
||||
* Assumptions:: Some of @code{gprof}'s measurements are based
|
||||
on assumptions about your program
|
||||
that could be very wrong.
|
||||
|
||||
* Incompatibilities:: (between GNU @code{gprof} and Unix @code{gprof}.)
|
||||
@end menu
|
||||
@end ifinfo
|
||||
|
||||
@node Why, Compiling, Top, Top
|
||||
@chapter Why Profile
|
||||
|
||||
Profiling allows you to learn where your program spent its time and which
|
||||
functions called which other functions while it was executing. This
|
||||
information can show you which pieces of your program are slower than you
|
||||
expected, and might be candidates for rewriting to make your program
|
||||
execute faster. It can also tell you which functions are being called more
|
||||
or less often than you expected. This may help you spot bugs that had
|
||||
otherwise been unnoticed.
|
||||
|
||||
Since the profiler uses information collected during the actual execution
|
||||
of your program, it can be used on programs that are too large or too
|
||||
complex to analyze by reading the source. However, how your program is run
|
||||
will affect the information that shows up in the profile data. If you
|
||||
don't use some feature of your program while it is being profiled, no
|
||||
profile information will be generated for that feature.
|
||||
|
||||
Profiling has several steps:
|
||||
|
||||
@itemize @bullet
|
||||
@item
|
||||
You must compile and link your program with profiling enabled.
|
||||
@xref{Compiling}.
|
||||
|
||||
@item
|
||||
You must execute your program to generate a profile data file.
|
||||
@xref{Executing}.
|
||||
|
||||
@item
|
||||
You must run @code{gprof} to analyze the profile data.
|
||||
@xref{Analyzing}.
|
||||
@end itemize
|
||||
|
||||
The next three chapters explain these steps in greater detail.
|
||||
|
||||
The result of the analysis is a file containing two tables, the
|
||||
@dfn{flat profile} and the @dfn{call graph} (plus blurbs which briefly
|
||||
explain the contents of these tables).
|
||||
|
||||
The flat profile shows how much time your program spent in each function,
|
||||
and how many times that function was called. If you simply want to know
|
||||
which functions burn most of the cycles, it is stated concisely here.
|
||||
@xref{Flat Profile}.
|
||||
|
||||
The call graph, shows, for each function, which functions called it, which
|
||||
other functions it called, and how many times. There is also an estimate
|
||||
of how much time was spent in the subroutines of each function. This can
|
||||
suggest places where you might try to eliminate function calls that use a
|
||||
lot of time. @xref{Call Graph}.
|
||||
|
||||
@node Compiling, Executing, Why, Top
|
||||
@chapter Compiling a Program for Profiling
|
||||
|
||||
The first step in generating profile information for your program is
|
||||
to compile and link it with profiling enabled.
|
||||
|
||||
To compile a source file for profiling, specify the @samp{-pg} option when
|
||||
you run the compiler. (This is in addition to the options you normally
|
||||
use.)
|
||||
|
||||
To link the program for profiling, if you use a compiler such as @code{cc}
|
||||
to do the linking, simply specify @samp{-pg} in addition to your usual
|
||||
options. The same option, @samp{-pg}, alters either compilation or linking
|
||||
to do what is necessary for profiling. Here are examples:
|
||||
|
||||
@example
|
||||
cc -g myprog.c utils.c -pg
|
||||
cc -o myprog myprog.o utils.o -pg
|
||||
@end example
|
||||
|
||||
The @samp{-pg} option also works with a command that both compiles and links:
|
||||
|
||||
@example
|
||||
cc -o myprog myprog.c utils.c -g -pg
|
||||
@end example
|
||||
|
||||
If you run the linker @code{ld} directly instead of through a compiler such
|
||||
as @code{cc}, you must specify the profiling startup file
|
||||
@file{/lib/gcrt0.o} as the first input file instead of the usual startup
|
||||
file @file{/lib/crt0.o}. In addition, you would probably want to specify
|
||||
the profiling C library, @file{/usr/lib/libc_p.a}, by writing @samp{-lc_p}
|
||||
instead of the usual @samp{-lc}. This is not absolutely necessary, but doing
|
||||
this gives you number-of-calls information for standard library functions such
|
||||
as @code{read} and @code{open}. For example:
|
||||
|
||||
@example
|
||||
ld -o myprog /lib/gcrt0.o myprog.o utils.o -lc_p
|
||||
@end example
|
||||
|
||||
If you compile only some of the modules of the program with @samp{-pg}, you
|
||||
can still profile the program, but you won't get complete information about
|
||||
the modules that were compiled without @samp{-pg}. The only information
|
||||
you get for the functions in those modules is the total time spent in them;
|
||||
there is no record of how many times they were called, or from where. This
|
||||
will not affect the flat profile (except that the @code{calls} field for
|
||||
the functions will be blank), but will greatly reduce the usefulness of the
|
||||
call graph.
|
||||
|
||||
So far GNU @code{gprof} has been tested only with C programs, but it ought
|
||||
to work with any language in which programs are compiled and linked to form
|
||||
executable files. If it does not, please let us know.
|
||||
|
||||
@node Executing, Analyzing, Compiling, Top
|
||||
@chapter Executing the Program to Generate Profile Data
|
||||
|
||||
Once the program is compiled for profiling, you must run it in order to
|
||||
generate the information that @code{gprof} needs. Simply run the program
|
||||
as usual, using the normal arguments, file names, etc. The program should
|
||||
run normally, producing the same output as usual. It will, however, run
|
||||
somewhat slower than normal because of the time spent collecting and the
|
||||
writing the profile data.
|
||||
|
||||
The way you run the program---the arguments and input that you give
|
||||
it---may have a dramatic effect on what the profile information shows. The
|
||||
profile data will describe the parts of the program that were activated for
|
||||
the particular input you use. For example, if the first command you give
|
||||
to your program is to quit, the profile data will show the time used in
|
||||
initialization and in cleanup, but not much else.
|
||||
|
||||
You program will write the profile data into a file called @file{gmon.out}
|
||||
just before exiting. If there is already a file called @file{gmon.out},
|
||||
its contents are overwritten. There is currently no way to tell the
|
||||
program to write the profile data under a different name, but you can rename
|
||||
the file afterward if you are concerned that it may be overwritten.
|
||||
|
||||
In order to write the @file{gmon.out} file properly, your program must exit
|
||||
normally: by returning from @code{main} or by calling @code{exit}. Calling
|
||||
the low-level function @code{_exit} does not write the profile data, and
|
||||
neither does abnormal termination due to an unhandled signal.
|
||||
|
||||
The @file{gmon.out} file is written in the program's @emph{current working
|
||||
directory} at the time it exits. This means that if your program calls
|
||||
@code{chdir}, the @file{gmon.out} file will be left in the last directory
|
||||
your program @code{chdir}'d to. If you don't have permission to write in
|
||||
this directory, the file is not written. You may get a confusing error
|
||||
message if this happens. (We have not yet replaced the part of Unix
|
||||
responsible for this; when we do, we will make the error message
|
||||
comprehensible.)
|
||||
|
||||
@node Analyzing, Flat Profile, Executing, Top
|
||||
@chapter Analyzing the Profile Data: @code{gprof} Command Summary
|
||||
|
||||
After you have a profile data file @file{gmon.out}, you can run @code{gprof}
|
||||
to interpret the information in it. The @code{gprof} program prints a
|
||||
flat profile and a call graph on standard output. Typically you would
|
||||
redirect the output of @code{gprof} into a file with @samp{>}.
|
||||
|
||||
You run @code{gprof} like this:
|
||||
|
||||
@example
|
||||
gprof @var{options} [@var{executable-file} [@var{profile-data-files}@dots{}]] [> @var{outfile}]
|
||||
@end example
|
||||
|
||||
@noindent
|
||||
Here square-brackets indicate optional arguments.
|
||||
|
||||
If you omit the executable file name, the file @file{a.out} is used. If
|
||||
you give no profile data file name, the file @file{gmon.out} is used. If
|
||||
any file is not in the proper format, or if the profile data file does not
|
||||
appear to belong to the executable file, an error message is printed.
|
||||
|
||||
You can give more than one profile data file by entering all their names
|
||||
after the executable file name; then the statistics in all the data files
|
||||
are summed together.
|
||||
|
||||
The following options may be used to selectively include or exclude
|
||||
functions in the output:
|
||||
|
||||
@table @code
|
||||
@item -a
|
||||
The @code{-a} option causes @code{gprof} to ignore static (private)
|
||||
functions. (These are functions whose names are not listed as global,
|
||||
and which are not visible outside the file/function/block where they
|
||||
were defined.) Time spent in these functions, calls to/from them,
|
||||
etc, will all be attributed to the function that was loaded directly
|
||||
before it in the executable file. This is compatible with Unix
|
||||
@code{gprof}, but a bad idea. This option affects both the flat
|
||||
profile and the call graph.
|
||||
|
||||
@item -e @var{function_name}
|
||||
The @code{-e @var{function}} option tells @code{gprof} to not print
|
||||
information about the function (and its children@dots{}) in the call
|
||||
graph. The function will still be listed as a child of any functions
|
||||
that call it, but its index number will be shown as @samp{[not
|
||||
printed]}.
|
||||
|
||||
@item -E @var{function_name}
|
||||
The @code{-E @var{function}} option works like the @code{-e} option,
|
||||
but time spent in the function (and children who were not called from
|
||||
anywhere else), will not be used to compute the percentages-of-time
|
||||
for the call graph.
|
||||
|
||||
@item -f @var{function_name}
|
||||
The @code{-f @var{function}} option causes @code{gprof} to limit the
|
||||
call graph to the function and its children (and their
|
||||
children@dots{}).
|
||||
|
||||
@item -F @var{function_name}
|
||||
The @code{-F @var{function}} option works like the @code{-f} option,
|
||||
but only time spent in the function and its children (and their
|
||||
children@dots{}) will be used to determine total-time and
|
||||
percentages-of-time for the call graph.
|
||||
|
||||
@item -z
|
||||
If you give the @code{-z} option, @code{gprof} will mention all
|
||||
functions in the flat profile, even those that were never called, and
|
||||
that had no time spent in them.
|
||||
@end table
|
||||
|
||||
The order of these options does not matter.
|
||||
|
||||
Note that only one function can be specified with each @code{-e},
|
||||
@code{-E}, @code{-f} or @code{-F} option. To specify more than one
|
||||
function, use multiple options. For example, this command:
|
||||
|
||||
@example
|
||||
gprof -e boring -f foo -f bar myprogram > gprof.output
|
||||
@end example
|
||||
|
||||
@noindent
|
||||
lists in the call graph all functions that were reached from either
|
||||
@code{foo} or @code{bar} and were not reachable from @code{boring}.
|
||||
|
||||
There are two other useful @code{gprof} options:
|
||||
|
||||
@table @code
|
||||
@item -b
|
||||
If the @code{-b} option is given, @code{gprof} doesn't print the
|
||||
verbose blurbs that try to explain the meaning of all of the fields in
|
||||
the tables. This is useful if you intend to print out the output, or
|
||||
are tired of seeing the blurbs.
|
||||
|
||||
@item -s
|
||||
The @code{-s} option causes @code{gprof} to summarize the information
|
||||
in the profile data files it read in, and write out a profile data
|
||||
file called @file{gmon.sum}, which contains all the information from
|
||||
the profile data files that @code{gprof} read in. The file @file{gmon.sum}
|
||||
may be one of the specified input files; the effect of this is to
|
||||
merge the data in the other input files into @file{gmon.sum}.
|
||||
@xref{Sampling Error}.
|
||||
|
||||
Eventually you can run @code{gprof} again without @samp{-s} to analyze the
|
||||
cumulative data in the file @file{gmon.sum}.
|
||||
@end table
|
||||
|
||||
@node Flat Profile, Call Graph, Analyzing, Top
|
||||
@chapter How to Understand the Flat Profile
|
||||
@cindex flat profile
|
||||
|
||||
The @dfn{flat profile} shows the total amount of time your program
|
||||
spent executing each function. Unless the @samp{-z} option is given,
|
||||
functions with no apparent time spent in them, and no apparent calls
|
||||
to them, are not mentioned. Note that if a function was not compiled
|
||||
for profiling, and didn't run long enough to show up on the program
|
||||
counter histogram, it will be indistinguishable from a function that
|
||||
was never called.
|
||||
@c???
|
||||
|
||||
Here is a sample flat profile for a small program:
|
||||
|
||||
@example
|
||||
Each sample counts as 0.01 seconds.
|
||||
|
||||
% time seconds cumsec calls function
|
||||
79.17 0.19 0.19 6 a
|
||||
16.67 0.04 0.23 1 main
|
||||
4.17 0.01 0.24 mcount
|
||||
0.00 0 0.24 1 profil
|
||||
@end example
|
||||
|
||||
@noindent
|
||||
The functions are sorted by decreasing run-time spent in them. The
|
||||
functions @code{mcount} and @code{profil} are part of the profiling
|
||||
aparatus and appear in every flat profile; their time gives a measure of
|
||||
the amount of overhead due to profiling. (These internal functions are
|
||||
omitted from the call graph.)
|
||||
|
||||
The sampling period estimates the margin of error in each of the time
|
||||
figures. A time figure that is not much larger than this is not reliable.
|
||||
In this example, the @code{seconds} field for @code{mcount} might well be 0
|
||||
or 0.02 in another run. @xref{Sampling Error}, for a complete discussion.
|
||||
|
||||
Here is what the fields in each line mean:
|
||||
|
||||
@table @code
|
||||
@item % time
|
||||
This is the percentage of the total execution time your program spent
|
||||
in this function. These should all add up to 100%.
|
||||
|
||||
@item seconds
|
||||
This is the total number of seconds the computer spent executing the
|
||||
user code of this function.
|
||||
|
||||
@item cumsec
|
||||
This is the cumulative total number of seconds the computer spent
|
||||
executing this functions, plus the time spent in all the functions
|
||||
above this one in this table.
|
||||
|
||||
@item calls
|
||||
This is the total number of times the function was called. If the
|
||||
function was never called, or the number of times it was called cannot
|
||||
be determined (probably because the function was not compiled with
|
||||
profiling enabled), the @dfn{calls} field is blank.
|
||||
|
||||
@item function
|
||||
This is the name of the function.
|
||||
@end table
|
||||
|
||||
@node Call Graph, Implementation, Flat Profile, Top
|
||||
@chapter How to Read the Call Graph
|
||||
|
||||
@cindex call graph
|
||||
The @dfn{call graph} shows how much time was spent in each function
|
||||
and its children. From this information, you can find functions that,
|
||||
while they themselves may not have used much time, called other
|
||||
functions that did use unusual amounts of time.
|
||||
|
||||
Here is a sample call from a small program. This call came from the
|
||||
same @code{gprof} run as the flat profile example in the previous
|
||||
chapter.
|
||||
|
||||
@example
|
||||
index % time self children called name
|
||||
<spontaneous>
|
||||
[1] 100.00 0 0.23 0 start [1]
|
||||
0.04 0.19 1/1 main [2]
|
||||
----------------------------------------
|
||||
0.04 0.19 1/1 start [1]
|
||||
[2] 100.00 0.04 0.19 1 main [2]
|
||||
0.19 0 1/1 a [3]
|
||||
----------------------------------------
|
||||
0.19 0 1/1 main [2]
|
||||
[3] 82.61 0.19 0 1+5 a [3]
|
||||
----------------------------------------
|
||||
@end example
|
||||
|
||||
The lines full of dashes divide this table into @dfn{entries}, one for each
|
||||
function. Each entry has one or more lines.
|
||||
|
||||
In each entry, the primary line is the one that starts with an index number
|
||||
in square brackets. The end of this line says which function the entry is
|
||||
for. The preceding lines in the entry describe the callers of this
|
||||
function and the following lines describe its subroutines (also called
|
||||
@dfn{children} when we speak of the call graph).
|
||||
|
||||
The entries are sorted by time spent in the function and its subroutines.
|
||||
|
||||
The internal profiling functions @code{mcount} and @code{profil}
|
||||
(@pxref{Flat Profile}) are never mentioned in the call graph.
|
||||
|
||||
@menu
|
||||
* Primary:: Details of the primary line's contents.
|
||||
* Callers:: Details of caller-lines' contents.
|
||||
* Subroutines:: Details of subroutine-lines' contents.
|
||||
* Cycles:: When there are cycles of recursion,
|
||||
such as @code{a} calls @code{b} calls @code{a}@dots{}
|
||||
@end menu
|
||||
|
||||
@node Primary, Callers, Call Graph, Call Graph
|
||||
@section The Primary Line
|
||||
|
||||
The @dfn{primary line} in a call graph entry is the line that
|
||||
describes the function which the entry is about and gives the overall
|
||||
statistics for this function.
|
||||
|
||||
For reference, we repeat the primary line from the entry for function
|
||||
@code{a} in our main example, together with the heading line that shows the
|
||||
names of the fields:
|
||||
|
||||
@example
|
||||
index % time self children called name
|
||||
@dots{}
|
||||
[3] 82.61 0.19 0 1+5 a [3]
|
||||
@end example
|
||||
|
||||
Here is what the fields in the primary line mean:
|
||||
|
||||
@table @code
|
||||
@item index
|
||||
Entries are numbered with consecutive integers. Each function
|
||||
therefore has an index number, which appears at the beginning of its
|
||||
primary line.
|
||||
|
||||
Each cross-reference to a function, as a caller or subroutine of
|
||||
another, gives its index number as well as its name. The index number
|
||||
guides you if you wish to look for the entry for that function.
|
||||
|
||||
@item % time
|
||||
This is the percentage of the total time that was spent in this
|
||||
function, including time spent in subroutines called from this
|
||||
function.
|
||||
|
||||
The time spent in this function is counted again for the callers of
|
||||
this function. Therefore, adding up these percentages is meaningless.
|
||||
|
||||
@item self
|
||||
This is the total amount of time spent in this function. This
|
||||
should be identical to the number printed in the @code{seconds} field
|
||||
for this function in the flat profile.
|
||||
|
||||
@item children
|
||||
This is the total amount of time spent in the subroutine calls made by
|
||||
this function. This should be equal to the sum of all the @code{self}
|
||||
and @code{children} entries of the children listed directly below this
|
||||
function.
|
||||
|
||||
@item called
|
||||
This is the number of times the function was called.
|
||||
|
||||
If the function called itself recursively, there are two numbers,
|
||||
separated by a @samp{+}. The first number counts non-recursive calls,
|
||||
and the second counts recursive calls.
|
||||
|
||||
In the example above, the function @code{a} called itself five times,
|
||||
and was called once from @code{main}.
|
||||
|
||||
@item name
|
||||
This is the name of the current function. The index number is
|
||||
repeated after it.
|
||||
|
||||
If the function is part of a cycle of recursion, the cycle number is
|
||||
printed between the function's name and the index number
|
||||
(@pxref{Cycles}). For example, if function @code{gnurr} is part of
|
||||
cycle number one, and has index number twelve, its primary line would
|
||||
be end like this:
|
||||
|
||||
@example
|
||||
gnurr <cycle 1> [12]
|
||||
@end example
|
||||
@end table
|
||||
|
||||
@node Callers, Subroutines, Primary, Call Graph
|
||||
@section Lines for a Function's Callers
|
||||
|
||||
A function's entry has a line for each function it was called by.
|
||||
These lines' fields correspond to the fields of the primary line, but
|
||||
their meanings are different because of the difference in context.
|
||||
|
||||
For reference, we repeat two lines from the entry for the function
|
||||
@code{a}, the primary line and one caller-line preceding it, together
|
||||
with the heading line that shows the names of the fields:
|
||||
|
||||
@example
|
||||
index % time self children called name
|
||||
@dots{}
|
||||
0.19 0 1/1 main [2]
|
||||
[3] 82.61 0.19 0 1+5 a [3]
|
||||
@end example
|
||||
|
||||
Here are the meanings of the fields in the caller-line for @code{a}
|
||||
called from @code{main}:
|
||||
|
||||
@table @code
|
||||
@item self
|
||||
An estimate of the amount of time spent in @code{a} itself when it was
|
||||
called from @code{main}.
|
||||
|
||||
@item children
|
||||
An estimate of the amount of time spent in @code{a}'s subroutines when
|
||||
@code{a} was called from @code{main}.
|
||||
|
||||
The sum of the @code{self} and @code{children} fields is an estimate
|
||||
of the amount of time spent within calls to @code{a} from @code{main}.
|
||||
|
||||
@item called
|
||||
Two numbers: the number of times @code{a} was called from @code{main},
|
||||
followed by the total number of nonrecursive calls to @code{a} from
|
||||
all its callers.
|
||||
|
||||
@item name and index number
|
||||
The name of the caller of @code{a} to which this line applies,
|
||||
followed by the caller's index number.
|
||||
|
||||
Not all functions have entries in the call graph; some
|
||||
options to @code{gprof} request the omission of certain functions.
|
||||
When a caller has no entry of its own, it still has caller-lines
|
||||
in the entries of the functions it calls. Since this caller
|
||||
has no index number, the string @samp{[not printed]} is used
|
||||
instead of one.
|
||||
|
||||
If the caller is part of a recursion cycle, the cycle number is
|
||||
printed between the name and the index number.
|
||||
@end table
|
||||
|
||||
If the identity of the callers of a function cannot be determined, a
|
||||
dummy caller-line is printed which has @samp{<spontaneous>} as the
|
||||
``caller's name'' and all other fields blank. This can happen for
|
||||
signal handlers.
|
||||
@c What if some calls have determinable callers' names but not all?
|
||||
|
||||
@node Subroutines, Cycles, Callers, Call Graph
|
||||
@section Lines for a Function's Subroutines
|
||||
|
||||
A function's entry has a line for each of its subroutines---in other
|
||||
words, a line for each other function that it called. These lines'
|
||||
fields correspond to the fields of the primary line, but their meanings
|
||||
are different because of the difference in context.
|
||||
|
||||
For reference, we repeat two lines from the entry for the function
|
||||
@code{main}, the primary line and a line for a subroutine, together
|
||||
with the heading line that shows the names of the fields:
|
||||
|
||||
@example
|
||||
index % time self children called name
|
||||
@dots{}
|
||||
[2] 100.00 0.04 0.19 1 main [2]
|
||||
0.19 0 1/1 a [3]
|
||||
@end example
|
||||
|
||||
Here are the meanings of the fields in the subroutine-line for @code{main}
|
||||
calling @code{a}:
|
||||
|
||||
@table @code
|
||||
@item self
|
||||
An estimate of the amount of time spent directly within @code{a}
|
||||
when @code{a} was called from @code{main}.
|
||||
|
||||
@item children
|
||||
An estimate of the amount of time spent in subroutines of @code{a}
|
||||
when @code{a} was called from @code{main}.
|
||||
|
||||
The sum of the @code{self} and @code{children} fields is an estimate
|
||||
of the total time spent in calls to @code{a} from @code{main}.
|
||||
|
||||
@item called
|
||||
Two numbers, the number of calls to @code{a} from @code{main}
|
||||
followed by the total number of nonrecursive calls to @code{a}.
|
||||
|
||||
@item name
|
||||
The name of the subroutine of @code{a} to which this line applies,
|
||||
followed by the subroutine's index number. If the subroutine is
|
||||
a function omitted from the call graph, it has no index number,
|
||||
so @samp{[not printed]} appears instead.
|
||||
|
||||
If the caller is part of a recursion cycle, the cycle number is
|
||||
printed between the name and the index number.
|
||||
@end table
|
||||
|
||||
@node Cycles,, Subroutines, Call Graph
|
||||
@section How Mutually Recursive Functions Are Described
|
||||
@cindex cycle
|
||||
@cindex recursion cycle
|
||||
|
||||
The graph may be complicated by the presence of @dfn{cycles of
|
||||
recursion} in the call graph. A cycle exists if a function calls
|
||||
another function that (directly or indirectly) calls (or appears to
|
||||
call) the original function. For example: if @code{a} calls @code{b},
|
||||
and @code{b} calls @code{a}, then @code{a} and @code{b} form a cycle.
|
||||
|
||||
Whenever there are call-paths both ways between a pair of functions, they
|
||||
belong to the same cycle. If @code{a} and @code{b} call each other and
|
||||
@code{b} and @code{c} call each other, all three make one cycle. Note that
|
||||
even if @code{b} only calls @code{a} if it was not called from @code{a},
|
||||
@code{gprof} cannot determine this, so @code{a} and @code{b} are still
|
||||
considered a cycle.
|
||||
|
||||
The cycles are numbered with consecutive integers. When a function
|
||||
belongs to a cycle, each time the function name appears in the call graph
|
||||
it is followed by @samp{<cycle @var{number}>}.
|
||||
|
||||
The reason cycles matter is that they make the time values in the call
|
||||
graph paradoxical. The ``time spent in children'' of @code{a} should
|
||||
include the time spent in its subroutine @code{b} and in @code{b}'s
|
||||
subroutines---but one of @code{b}'s subroutines is @code{a}! How much of
|
||||
@code{a}'s time should be included in the children of @code{a}, when
|
||||
@code{a} is indirectly recursive?
|
||||
|
||||
The way @code{gprof} resolves this paradox is by creating a single entry
|
||||
for the cycle as a whole. The primary line of this entry describes the
|
||||
total time spent directly in the functions of the cycle. The
|
||||
``subroutines'' of the cycle are the individual functions of the cycle, and
|
||||
all other functions that were called directly by them. The ``callers'' of
|
||||
the cycle are the functions, outside the cycle, that called functions in
|
||||
the cycle.
|
||||
|
||||
Here is a portion of the call graph which shows a cycle containing
|
||||
functions @code{a} and @code{b}. The cycle was entered by a call to
|
||||
@code{a} from @code{main}; both @code{a} and @code{b} called @code{c}.@refill
|
||||
|
||||
@example
|
||||
index % time self children called name
|
||||
----------------------------------------
|
||||
1.77 0 1/1 main [2]
|
||||
[3] 91.71 1.77 0 1+5 <cycle 1 as a whole> [3]
|
||||
1.02 0 3 b <cycle 1> [4]
|
||||
0.75 0 2 a <cycle 1> [5]
|
||||
----------------------------------------
|
||||
3 a <cycle 1> [5]
|
||||
[4] 52.85 1.02 0 0 b <cycle 1> [4]
|
||||
2 a <cycle 1> [5]
|
||||
0 0 3/6 c [6]
|
||||
----------------------------------------
|
||||
1.77 0 1/1 main [2]
|
||||
2 b <cycle 1> [4]
|
||||
[5] 38.86 0.75 0 1 a <cycle 1> [5]
|
||||
3 b <cycle 1> [4]
|
||||
0 0 3/6 c [6]
|
||||
----------------------------------------
|
||||
@end example
|
||||
|
||||
@noindent
|
||||
(The entire call graph for this program contains in addition an entry for
|
||||
@code{main}, which calls @code{a}, and an entry for @code{c}, with callers
|
||||
@code{a} and @code{b}.)
|
||||
|
||||
@example
|
||||
index % time self children called name
|
||||
<spontaneous>
|
||||
[1] 100.00 0 1.93 0 start [1]
|
||||
0.16 1.77 1/1 main [2]
|
||||
----------------------------------------
|
||||
0.16 1.77 1/1 start [1]
|
||||
[2] 100.00 0.16 1.77 1 main [2]
|
||||
1.77 0 1/1 a <cycle 1> [5]
|
||||
----------------------------------------
|
||||
1.77 0 1/1 main [2]
|
||||
[3] 91.71 1.77 0 1+5 <cycle 1 as a whole> [3]
|
||||
1.02 0 3 b <cycle 1> [4]
|
||||
0.75 0 2 a <cycle 1> [5]
|
||||
0 0 6/6 c [6]
|
||||
----------------------------------------
|
||||
3 a <cycle 1> [5]
|
||||
[4] 52.85 1.02 0 0 b <cycle 1> [4]
|
||||
2 a <cycle 1> [5]
|
||||
0 0 3/6 c [6]
|
||||
----------------------------------------
|
||||
1.77 0 1/1 main [2]
|
||||
2 b <cycle 1> [4]
|
||||
[5] 38.86 0.75 0 1 a <cycle 1> [5]
|
||||
3 b <cycle 1> [4]
|
||||
0 0 3/6 c [6]
|
||||
----------------------------------------
|
||||
0 0 3/6 b <cycle 1> [4]
|
||||
0 0 3/6 a <cycle 1> [5]
|
||||
[6] 0.00 0 0 6 c [6]
|
||||
----------------------------------------
|
||||
@end example
|
||||
|
||||
The @code{self} field of the cycle's primary line is the total time
|
||||
spent in all the functions of the cycle. It equals the sum of the
|
||||
@code{self} fields for the individual functions in the cycle, found
|
||||
in the entry in the subroutine lines for these functions.
|
||||
|
||||
The @code{children} fields of the cycle's primary line and subroutine lines
|
||||
count only subroutines outside the cycle. Even though @code{a} calls
|
||||
@code{b}, the time spent in those calls to @code{b} is not counted in
|
||||
@code{a}'s @code{children} time. Thus, we do not encounter the problem of
|
||||
what to do when the time in those calls to @code{b} includes indirect
|
||||
recursive calls back to @code{a}.
|
||||
|
||||
The @code{children} field of a caller-line in the cycle's entry estimates
|
||||
the amount of time spent @emph{in the whole cycle}, and its other
|
||||
subroutines, on the times when that caller called a function in the cycle.
|
||||
|
||||
The @code{calls} field in the primary line for the cycle has two numbers:
|
||||
first, the number of times functions in the cycle were called by functions
|
||||
outside the cycle; second, the number of times they were called by
|
||||
functions in the cycle (including times when a function in the cycle calls
|
||||
itself). This is a generalization of the usual split into nonrecursive and
|
||||
recursive calls.
|
||||
|
||||
The @code{calls} field of a subroutine-line for a cycle member in the
|
||||
cycle's entry says how many time that function was called from functions in
|
||||
the cycle. The total of all these is the second number in the primary line's
|
||||
@code{calls} field.
|
||||
|
||||
In the individual entry for a function in a cycle, the other functions in
|
||||
the same cycle can appear as subroutines and as callers. These lines show
|
||||
how many times each function in the cycle called or was called from each other
|
||||
function in the cycle. The @code{self} and @code{children} fields in these
|
||||
lines are blank because of the difficulty of defining meanings for them
|
||||
when recursion is going on.
|
||||
|
||||
@node Implementation, Sampling Error, Call Graph, Top
|
||||
@chapter Implementation of Profiling
|
||||
|
||||
Profiling works by changing how every function in your program is compiled
|
||||
so that when it is called, it will stash away some information about where
|
||||
it was called from. From this, the profiler can figure out what function
|
||||
called it, and can count how many times it was called. This change is made
|
||||
by the compiler when your program is compiled with the @samp{-pg} option.
|
||||
|
||||
Profiling also involves watching your program as it runs, and keeping a
|
||||
histogram of where the program counter happens to be every now and then.
|
||||
Typically the program counter is looked at around 100 times per second of
|
||||
run time, but the exact frequency may vary from system to system.
|
||||
|
||||
A special startup routine allocates memory for the histogram and sets up a
|
||||
clock signal handler to make entries in it. Use of this special startup
|
||||
routine is one of the effects of using @samp{cc -pg} to link. The startup
|
||||
file also includes an @code{exit} function which is responsible for writing
|
||||
the file @file{gmon.out}.
|
||||
|
||||
Number-of-calls information for library routines is collected by using a
|
||||
special version of the C library. The programs in it are the same as in
|
||||
the usual C library, but they were compiled with @samp{-pg}. If you link
|
||||
your program with @samp{cc -pg}, it automatically uses the profiling
|
||||
version of the library.
|
||||
|
||||
The output @code{gprof} gives no indication of parts of your program that
|
||||
are limited by I/O or swapping bandwidth. This is because samples of the
|
||||
program counter are taken at fixed intervals of run time. Therefore, the
|
||||
time measurements in @code{gprof} output say nothing about time that your
|
||||
program was not running. For example, a part of the program that creates
|
||||
so much data that it cannot all fit in physical memory at once may run very
|
||||
slowly due to thrashing, but @code{gprof} will say it uses little time. On
|
||||
the other hand, sampling by run time has the advantage that the amount of
|
||||
load due to other users won't directly affect the output you get.
|
||||
|
||||
@node Sampling Error, Assumptions, Implementation, Top
|
||||
@chapter Statistical Inaccuracy of @code{gprof} Output
|
||||
|
||||
The run-time figures that @code{gprof} gives you are based on a sampling
|
||||
process, so they are subject to statistical inaccuracy. If a function runs
|
||||
only a small amount of time, so that on the average the sampling process
|
||||
ought to catch that function in the act only once, there is a pretty good
|
||||
chance it will actually find that function zero times, or twice.
|
||||
|
||||
By contrast, the number-of-calls figures are derived by counting, not
|
||||
sampling. They are completely accurate and will not vary from run to run
|
||||
if your program is deterministic.
|
||||
|
||||
The @dfn{sampling period} that is printed at the beginning of the flat
|
||||
profile says how often samples are taken. The rule of thumb is that a
|
||||
run-time figure is accurate if it is considerably bigger than the sampling
|
||||
period.
|
||||
|
||||
The actual amount of error is usually more than one sampling period. In
|
||||
fact, if a value is @var{n} times the sampling period, the @emph{expected}
|
||||
error in it is the square-root of @var{n} sampling periods. If the
|
||||
sampling period is 0.01 seconds and @code{foo}'s run-time is 1 second, the
|
||||
expected error in @code{foo}'s run-time is 0.1 seconds. It is likely to
|
||||
vary this much @emph{on the average} from one profiling run to the next.
|
||||
(@emph{Sometimes} it will vary more.)
|
||||
|
||||
This does not mean that a small run-time figure is devoid of information.
|
||||
If the program's @emph{total} run-time is large, a small run-time for one
|
||||
function does tell you that that function used an insignificant fraction of
|
||||
the whole program's time. Usually this means it is not worth optimizing.
|
||||
|
||||
One way to get more accuracy is to give your program more (but similar)
|
||||
input data so it will take longer. Another way is to combine the data from
|
||||
several runs, using the @samp{-s} option of @code{gprof}. Here is how:
|
||||
|
||||
@enumerate
|
||||
@item
|
||||
Run your program once.
|
||||
|
||||
@item
|
||||
Issue the command @samp{mv gmon.out gmon.sum}.
|
||||
|
||||
@item
|
||||
Run your program again, the same as before.
|
||||
|
||||
@item
|
||||
Merge the new data in @file{gmon.out} into @file{gmon.sum} with this command:
|
||||
|
||||
@example
|
||||
gprof -s @var{executable-file} gmon.out gmon.sum
|
||||
@end example
|
||||
|
||||
@item
|
||||
Repeat the last two steps as often as you wish.
|
||||
|
||||
@item
|
||||
Analyze the cumulative data using this command:
|
||||
|
||||
@example
|
||||
gprof @var{executable-file} gmon.sum > @var{output-file}
|
||||
@end example
|
||||
@end enumerate
|
||||
|
||||
@node Assumptions, Incompatibilities, Sampling Error, Top
|
||||
@chapter Estimating @code{children} Times Uses an Assumption
|
||||
|
||||
Some of the figures in the call graph are estimates---for example, the
|
||||
@code{children} time values and all the the time figures in caller and
|
||||
subroutine lines.
|
||||
|
||||
There is no direct information about these measurements in the profile
|
||||
data itself. Instead, @code{gprof} estimates them by making an assumption
|
||||
about your program that might or might not be true.
|
||||
|
||||
The assumption made is that the average time spent in each call to any
|
||||
function @code{foo} is not correlated with who called @code{foo}. If
|
||||
@code{foo} used 5 seconds in all, and 2/5 of the calls to @code{foo} came
|
||||
from @code{a}, then @code{foo} contributes 2 seconds to @code{a}'s
|
||||
@code{children} time, by assumption.
|
||||
|
||||
This assumption is usually true enough, but for some programs it is far
|
||||
from true. Suppose that @code{foo} returns very quickly when its argument
|
||||
is zero; suppose that @code{a} always passes zero as an argument, while
|
||||
other callers of @code{foo} pass other arguments. In this program, all the
|
||||
time spent in @code{foo} is in the calls from callers other than @code{a}.
|
||||
But @code{gprof} has no way of knowing this; it will blindly and
|
||||
incorrectly charge 2 seconds of time in @code{foo} to the children of
|
||||
@code{a}.
|
||||
|
||||
We hope some day to put more complete data into @file{gmon.out}, so that
|
||||
this assumption is no longer needed, if we can figure out how. For the
|
||||
nonce, the estimated figures are usually more useful than misleading.
|
||||
|
||||
@node Incompatibilities, , Assumptions, Top
|
||||
@chapter Incompatibilities with Unix @code{gprof}
|
||||
|
||||
GNU @code{gprof} and Berkeley Unix @code{gprof} use the same data file
|
||||
@file{gmon.out}, and provide essentially the same information. But there a
|
||||
few differences.@refill
|
||||
|
||||
GNU @code{gprof} does not support the @samp{-c} option which prints a
|
||||
static call graph based on reading the machine language of your
|
||||
program. We think that program cross-references ought to be based on
|
||||
the source files, which can be analyzed in a machine-independent
|
||||
fashion.@refill
|
||||
|
||||
For a recursive function, Unix @code{gprof} lists the function as a parent
|
||||
and as a child, with a @code{calls} field that lists the number of
|
||||
recursive calls. GNU @code{gprof} omits these lines and puts the number of
|
||||
recursive calls in the primary line.
|
||||
|
||||
When a function is suppressed from the call graph with @samp{-e}, GNU
|
||||
@code{gprof} still lists it as a subroutine of functions that call it.
|
||||
|
||||
The function names printed in GNU @code{gprof} output do not include
|
||||
the leading underscores that are added internally to the front of all
|
||||
C identifiers on many operating systems.
|
||||
|
||||
The blurbs, field widths, and output formats are different. GNU
|
||||
@code{gprof} prints blurbs after the tables, so that you can see the
|
||||
tables without skipping the blurbs.
|
||||
|
||||
@contents
|
||||
@bye
|
||||
4314
gnu/binutils/binutils.001/binutils/ld.c
Normal file
4314
gnu/binutils/binutils.001/binutils/ld.c
Normal file
File diff suppressed because it is too large
Load Diff
23
gnu/binutils/binutils.001/binutils/libconvert
Normal file
23
gnu/binutils/binutils.001/binutils/libconvert
Normal file
@@ -0,0 +1,23 @@
|
||||
#! /bin/sh
|
||||
#
|
||||
# Convert coff libc to a coff-encapsulated libc
|
||||
# suitable for linking with the GNU linker.
|
||||
#
|
||||
# Extract all members of /lib/libc.a (using coff ar).
|
||||
# Convert each using robotussin.
|
||||
# Create new libc (using gnu ar) with members in the same order as coff libc.
|
||||
|
||||
# set -e makes this script exit if any command gets an error
|
||||
|
||||
set -e
|
||||
mkdir tmp
|
||||
cd tmp
|
||||
/bin/ar x /lib/libc.a
|
||||
for i in *.o
|
||||
do
|
||||
../robotussin $i x
|
||||
mv x $i
|
||||
done
|
||||
rm -f ../libc.a
|
||||
../ar rs ../libc.a `/bin/ar t /lib/libc.a`
|
||||
cd ..
|
||||
1054
gnu/binutils/binutils.001/binutils/nm.c
Normal file
1054
gnu/binutils/binutils.001/binutils/nm.c
Normal file
File diff suppressed because it is too large
Load Diff
272
gnu/binutils/binutils.001/binutils/objdump.c
Normal file
272
gnu/binutils/binutils.001/binutils/objdump.c
Normal file
@@ -0,0 +1,272 @@
|
||||
/*
|
||||
* objdump
|
||||
*
|
||||
* dump information about an object file. Until there is other documentation,
|
||||
* refer to the manual page dump(1) in the system 5 program's reference manual
|
||||
*/
|
||||
#include <stdio.h>
|
||||
|
||||
#ifndef COFF_ENCAPSULATE
|
||||
#include "a.out.gnu.h"
|
||||
#else
|
||||
#include "a.out.encap.h"
|
||||
#endif
|
||||
|
||||
char *malloc();
|
||||
int nsyms;
|
||||
struct nlist *symtbl;
|
||||
char *strtbl;
|
||||
int strsize;
|
||||
|
||||
read_symbols (execp, f)
|
||||
struct exec *execp;
|
||||
FILE *f;
|
||||
{
|
||||
int i;
|
||||
struct nlist *sp;
|
||||
if (symtbl)
|
||||
return;
|
||||
nsyms = execp->a_syms / sizeof (struct nlist);
|
||||
if (nsyms == 0)
|
||||
return;
|
||||
|
||||
symtbl = (struct nlist *)malloc (nsyms * sizeof (struct nlist));
|
||||
if (symtbl == NULL) {
|
||||
fprintf (stderr, "can't malloc for %d symbols\n",
|
||||
nsyms);
|
||||
exit (1);
|
||||
}
|
||||
|
||||
fseek (f, N_STROFF(*execp), 0);
|
||||
if (fread ((char *)&strsize, sizeof strsize, 1, f) != 1) {
|
||||
fprintf (stderr, "can't get string table size\n");
|
||||
exit (1);
|
||||
}
|
||||
strtbl = malloc (strsize);
|
||||
if (strtbl == NULL) {
|
||||
fprintf (stderr, "can't malloc %d bytes for string table\n");
|
||||
exit (1);
|
||||
}
|
||||
fseek (f, N_STROFF (*execp), 0);
|
||||
if (fread (strtbl, 1, strsize, f) != strsize) {
|
||||
fprintf (stderr, "error reading string table\n");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
fseek (f, N_SYMOFF (*execp), 0);
|
||||
if (fread ((char *)symtbl, sizeof (struct nlist), nsyms, f) != nsyms) {
|
||||
fprintf (stderr, "error reading symbol table\n");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
for (i = 0, sp = symtbl; i < nsyms; i++, sp++) {
|
||||
if (sp->n_un.n_strx < 0 || sp->n_un.n_strx > strsize)
|
||||
sp->n_un.n_name = "<bad string table index>";
|
||||
else
|
||||
sp->n_un.n_name = strtbl + sp->n_un.n_strx;
|
||||
}
|
||||
}
|
||||
|
||||
free_symbols ()
|
||||
{
|
||||
if (symtbl)
|
||||
free (symtbl);
|
||||
symtbl = NULL;
|
||||
if (strtbl)
|
||||
free (strtbl);
|
||||
strtbl = NULL;
|
||||
}
|
||||
|
||||
|
||||
usage ()
|
||||
{
|
||||
fprintf (stderr, "usage: dump [-h] [-n] [-r] [-t] obj ...\n");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
int hflag;
|
||||
int nflag;
|
||||
int rflag;
|
||||
int tflag;
|
||||
|
||||
main (argc, argv)
|
||||
char **argv;
|
||||
{
|
||||
int c;
|
||||
extern char *optarg;
|
||||
extern int optind;
|
||||
int seenflag = 0;
|
||||
|
||||
while ((c = getopt (argc, argv, "hnrt")) != EOF) {
|
||||
seenflag = 1;
|
||||
switch (c) {
|
||||
case 't': tflag = 1; break;
|
||||
case 'r': rflag = 1; break;
|
||||
case 'n': nflag = 1; break;
|
||||
case 'h': hflag = 1; break;
|
||||
default:
|
||||
usage ();
|
||||
}
|
||||
}
|
||||
|
||||
if (seenflag == 0 || optind == argc)
|
||||
usage ();
|
||||
|
||||
while (optind < argc)
|
||||
doit (argv[optind++]);
|
||||
}
|
||||
|
||||
doit (name)
|
||||
char *name;
|
||||
{
|
||||
FILE *f;
|
||||
struct exec exec;
|
||||
printf ("%s:\n", name);
|
||||
f = fopen (name, "r");
|
||||
if (f == NULL) {
|
||||
fprintf (stderr, "can't open %s\n", name);
|
||||
return;
|
||||
}
|
||||
#ifdef HEADER_SEEK
|
||||
HEADER_SEEK (f);
|
||||
#endif
|
||||
if (fread ((char *)&exec, sizeof exec, 1, f) != 1) {
|
||||
fprintf (stderr, "can't read header for %s\n", name);
|
||||
return;
|
||||
}
|
||||
|
||||
if (N_BADMAG (exec)) {
|
||||
fprintf (stderr, "%s is not an object file\n", name);
|
||||
return;
|
||||
}
|
||||
|
||||
if (hflag)
|
||||
dump_header (&exec);
|
||||
|
||||
if (nflag)
|
||||
dump_nstuff (&exec);
|
||||
|
||||
if (tflag)
|
||||
dump_sym (&exec, f);
|
||||
|
||||
if (rflag)
|
||||
dump_reloc (&exec, f);
|
||||
|
||||
free_symbols ();
|
||||
|
||||
}
|
||||
|
||||
dump_header (execp)
|
||||
struct exec *execp;
|
||||
{
|
||||
int x;
|
||||
|
||||
printf ("magic: 0x%x (%o) ", execp->a_magic, execp->a_magic & 0xffff);
|
||||
#ifdef COFF_ENCAPSULATE
|
||||
printf ("machtype: %d ", execp->a_machtype);
|
||||
printf ("flags: 0x%x ", execp->a_flags);
|
||||
#endif
|
||||
printf ("text 0x%x ", execp->a_text);
|
||||
printf ("data 0x%x ", execp->a_data);
|
||||
printf ("bss 0x%x\n", execp->a_bss);
|
||||
printf ("nsyms %d", execp->a_syms / sizeof (struct nlist));
|
||||
x = execp->a_syms % sizeof (struct nlist);
|
||||
if (x)
|
||||
printf (" (+ %d bytes)", x);
|
||||
printf (" entry 0x%x ", execp->a_entry);
|
||||
printf ("trsize 0x%x ", execp->a_trsize);
|
||||
printf ("drsize 0x%x\n", execp->a_drsize);
|
||||
}
|
||||
|
||||
dump_nstuff (execp)
|
||||
struct exec *execp;
|
||||
{
|
||||
printf ("N_BADMAG %d\n", N_BADMAG (*execp));
|
||||
printf ("N_TXTOFF 0x%x\n", N_TXTOFF (*execp));
|
||||
printf ("N_SYMOFF 0x%x\n", N_SYMOFF (*execp));
|
||||
printf ("N_STROFF 0x%x\n", N_STROFF (*execp));
|
||||
printf ("N_TXTADDR 0x%x\n", N_TXTADDR (*execp));
|
||||
printf ("N_DATADDR 0x%x\n", N_DATADDR (*execp));
|
||||
}
|
||||
|
||||
dump_sym (execp, f)
|
||||
struct exec *execp;
|
||||
FILE *f;
|
||||
{
|
||||
int i;
|
||||
struct nlist *sp;
|
||||
|
||||
read_symbols (execp, f);
|
||||
if (nsyms == 0) {
|
||||
printf ("no symbols\n");
|
||||
return;
|
||||
}
|
||||
|
||||
printf ("%3s: %4s %5s %4s %8s\n",
|
||||
"#", "type", "other", "desc", "val");
|
||||
for (i = 0, sp = symtbl; i < nsyms; i++, sp++) {
|
||||
printf ("%3d: %4x %5x %4x %8x %s\n",
|
||||
i, sp->n_type, sp->n_other, sp->n_desc, sp->n_value,
|
||||
sp->n_un.n_name);
|
||||
}
|
||||
}
|
||||
|
||||
dump_reloc (execp, f)
|
||||
struct exec *execp;
|
||||
FILE *f;
|
||||
{
|
||||
read_symbols (execp, f);
|
||||
if (execp->a_trsize) {
|
||||
printf ("text reloc\n");
|
||||
dump_reloc1 (execp, f, N_TRELOFF (*execp), execp->a_trsize);
|
||||
}
|
||||
if (execp->a_drsize) {
|
||||
printf ("data reloc\n");
|
||||
dump_reloc1 (execp, f, N_DRELOFF (*execp), execp->a_drsize);
|
||||
}
|
||||
}
|
||||
|
||||
dump_reloc1 (execp, f, off, size)
|
||||
struct exec *execp;
|
||||
FILE *f;
|
||||
{
|
||||
int nreloc;
|
||||
struct relocation_info reloc;
|
||||
int i;
|
||||
|
||||
nreloc = size / sizeof (struct relocation_info);
|
||||
|
||||
printf ("%3s: %3s %8s %4s\n", "#", "len", "adr", "sym");
|
||||
fseek (f, off, 0);
|
||||
for (i = 0; i < nreloc; i++) {
|
||||
if (fread ((char *)&reloc, sizeof reloc, 1, f) != 1) {
|
||||
fprintf (stderr, "error reading reloc\n");
|
||||
return;
|
||||
}
|
||||
printf ("%3d: %3d %8x ", i, 1 << reloc.r_length,
|
||||
reloc.r_address);
|
||||
|
||||
if (reloc.r_extern) {
|
||||
printf ("%4d ", reloc.r_symbolnum);
|
||||
if (reloc.r_symbolnum < nsyms)
|
||||
printf ("%s ",
|
||||
symtbl[reloc.r_symbolnum].n_un.n_name);
|
||||
} else {
|
||||
printf (" ");
|
||||
switch (reloc.r_symbolnum & ~N_EXT) {
|
||||
case N_TEXT: printf (".text "); break;
|
||||
case N_DATA: printf (".data "); break;
|
||||
case N_BSS: printf (".bss "); break;
|
||||
case N_ABS: printf (".abs "); break;
|
||||
default: printf ("base %x ", reloc.r_symbolnum); break;
|
||||
}
|
||||
}
|
||||
if (reloc.r_pcrel) printf ("PCREL ");
|
||||
#if 0
|
||||
if (reloc.r_pad) printf ("PAD %x ", reloc.r_pad);
|
||||
#endif
|
||||
printf ("\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
26
gnu/binutils/binutils.001/binutils/ranlib.c
Normal file
26
gnu/binutils/binutils.001/binutils/ranlib.c
Normal file
@@ -0,0 +1,26 @@
|
||||
/* Dummy ranlib program for GNU. All it does is
|
||||
`ar rs LIBRARY' for each library specified. */
|
||||
|
||||
/* The makefile generates a -D switch to define AR_PROG
|
||||
as the location of the GNU AR program. */
|
||||
|
||||
char *prog = AR_PROG;
|
||||
|
||||
main (argc, argv)
|
||||
int argc;
|
||||
char **argv;
|
||||
{
|
||||
int i;
|
||||
for (i = 1; i < argc; i++)
|
||||
{
|
||||
int pid = fork ();
|
||||
if (pid == 0)
|
||||
{
|
||||
execl (prog, prog, "rs", argv[i], 0);
|
||||
perror (prog);
|
||||
exit (1);
|
||||
}
|
||||
wait (0);
|
||||
}
|
||||
exit (0);
|
||||
}
|
||||
17
gnu/binutils/binutils.001/binutils/ranlib.h
Normal file
17
gnu/binutils/binutils.001/binutils/ranlib.h
Normal file
@@ -0,0 +1,17 @@
|
||||
/* ranlib.h 4.1 83/05/03 */
|
||||
|
||||
/*
|
||||
* Structure of the __.SYMDEF table of contents for an archive.
|
||||
* __.SYMDEF begins with a word giving the number of ranlib structures
|
||||
* which immediately follow, and then continues with a string
|
||||
* table consisting of a word giving the number of bytes of strings
|
||||
* which follow and then the strings themselves.
|
||||
* The ran_strx fields index the string table whose first byte is numbered 0.
|
||||
*/
|
||||
struct ranlib {
|
||||
union {
|
||||
off_t ran_strx; /* string table index of */
|
||||
char *ran_name; /* symbol defined by */
|
||||
} ran_un;
|
||||
off_t ran_off; /* library member at this offset */
|
||||
};
|
||||
610
gnu/binutils/binutils.001/binutils/robotussin.c
Normal file
610
gnu/binutils/binutils.001/binutils/robotussin.c
Normal file
@@ -0,0 +1,610 @@
|
||||
/* Convert COFF-format object file to BSD format.
|
||||
Used for converting the system libraries so GNU ld can link them.
|
||||
Copyright (C) 1988 Free Software Foundation, Inc.
|
||||
|
||||
NO WARRANTY
|
||||
|
||||
BECAUSE THIS PROGRAM IS LICENSED FREE OF CHARGE, WE PROVIDE ABSOLUTELY
|
||||
NO WARRANTY, TO THE EXTENT PERMITTED BY APPLICABLE STATE LAW. EXCEPT
|
||||
WHEN OTHERWISE STATED IN WRITING, FREE SOFTWARE FOUNDATION, INC,
|
||||
RICHARD M. STALLMAN AND/OR OTHER PARTIES PROVIDE THIS PROGRAM "AS IS"
|
||||
WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
|
||||
BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY
|
||||
AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE
|
||||
DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR
|
||||
CORRECTION.
|
||||
|
||||
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW WILL RICHARD M.
|
||||
STALLMAN, THE FREE SOFTWARE FOUNDATION, INC., AND/OR ANY OTHER PARTY
|
||||
WHO MAY MODIFY AND REDISTRIBUTE THIS PROGRAM AS PERMITTED BELOW, BE
|
||||
LIABLE TO YOU FOR DAMAGES, INCLUDING ANY LOST PROFITS, LOST MONIES, OR
|
||||
OTHER SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
|
||||
USE OR INABILITY TO USE (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR
|
||||
DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY THIRD PARTIES OR
|
||||
A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS) THIS
|
||||
PROGRAM, EVEN IF YOU HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH
|
||||
DAMAGES, OR FOR ANY CLAIM BY ANY OTHER PARTY.
|
||||
|
||||
GENERAL PUBLIC LICENSE TO COPY
|
||||
|
||||
1. You may copy and distribute verbatim copies of this source file
|
||||
as you receive it, in any medium, provided that you conspicuously
|
||||
and appropriately publish on each copy a valid copyright notice
|
||||
"Copyright (C) 1988 Free Software Foundation, Inc.", and include
|
||||
following the copyright notice a verbatim copy of the above disclaimer
|
||||
of warranty and of this License.
|
||||
|
||||
2. You may modify your copy or copies of this source file or
|
||||
any portion of it, and copy and distribute such modifications under
|
||||
the terms of Paragraph 1 above, provided that you also do the following:
|
||||
|
||||
a) cause the modified files to carry prominent notices stating
|
||||
that you changed the files and the date of any change; and
|
||||
|
||||
b) cause the whole of any work that you distribute or publish,
|
||||
that in whole or in part contains or is a derivative of this
|
||||
program or any part thereof, to be licensed at no charge to all
|
||||
third parties on terms identical to those contained in this
|
||||
License Agreement (except that you may choose to grant more extensive
|
||||
warranty protection to some or all third parties, at your option).
|
||||
|
||||
c) You may charge a distribution fee for the physical act of
|
||||
transferring a copy, and you may at your option offer warranty
|
||||
protection in exchange for a fee.
|
||||
|
||||
Mere aggregation of another unrelated program with this program (or its
|
||||
derivative) on a volume of a storage or distribution medium does not bring
|
||||
the other program under the scope of these terms.
|
||||
|
||||
3. You may copy and distribute this program (or a portion or derivative
|
||||
of it, under Paragraph 2) in object code or executable form under the terms
|
||||
of Paragraphs 1 and 2 above provided that you also do one of the following:
|
||||
|
||||
a) accompany it with the complete corresponding machine-readable
|
||||
source code, which must be distributed under the terms of
|
||||
Paragraphs 1 and 2 above; or,
|
||||
|
||||
b) accompany it with a written offer, valid for at least three
|
||||
years, to give any third party free (except for a nominal
|
||||
shipping charge) a complete machine-readable copy of the
|
||||
corresponding source code, to be distributed under the terms of
|
||||
Paragraphs 1 and 2 above; or,
|
||||
|
||||
c) accompany it with the information you received as to where the
|
||||
corresponding source code may be obtained. (This alternative is
|
||||
allowed only for noncommercial distribution and only if you
|
||||
received the program in object code or executable form alone.)
|
||||
|
||||
For an executable file, complete source code means all the source code for
|
||||
all modules it contains; but, as a special exception, it need not include
|
||||
source code for modules which are standard libraries that accompany the
|
||||
operating system on which the executable file runs.
|
||||
|
||||
4. You may not copy, sublicense, distribute or transfer this program
|
||||
except as expressly provided under this License Agreement. Any attempt
|
||||
otherwise to copy, sublicense, distribute or transfer this program is void and
|
||||
your rights to use the program under this License agreement shall be
|
||||
automatically terminated. However, parties who have received computer
|
||||
software programs from you with this License Agreement will not have
|
||||
their licenses terminated so long as such parties remain in full compliance.
|
||||
|
||||
5. If you wish to incorporate parts of this program into other free
|
||||
programs whose distribution conditions are different, write to the Free
|
||||
Software Foundation at 675 Mass Ave, Cambridge, MA 02139. We have not yet
|
||||
worked out a simple rule that can be stated here, but we will often permit
|
||||
this. We will be guided by the two goals of preserving the free status of
|
||||
all derivatives of our free software and of promoting the sharing and reuse of
|
||||
software.
|
||||
|
||||
In other words, you are welcome to use, share and improve this program.
|
||||
You are forbidden to forbid anyone else to use, share and improve
|
||||
what you give them. Help stamp out software-hoarding! */
|
||||
|
||||
/*
|
||||
** Robotussin - convert COFF format object files to BSD format.
|
||||
**
|
||||
** written by Jeff Lewis, donated to the Free Software Foundation.
|
||||
**
|
||||
** BUGS:
|
||||
** Should do more to verify that the input COFF file meets our
|
||||
** expectations.
|
||||
** On machines where the structure of the COFF data in the file does not
|
||||
** match the structure of the COFF data declared (when, for example
|
||||
** sizeof (struct filhdr) != FILHSZ), this program will fail. (Don't
|
||||
** ask me why this is ever allowed to come about). Accessor functions/
|
||||
** macros that painstakingly extract the data out of the file and stuff
|
||||
** it in the memory struct should be written to fix this on such machines.
|
||||
**
|
||||
** CAVEATS:
|
||||
** This program cannot claim correctness, however, it does appear
|
||||
** to work on my fairly vanilla Sys5r2 machine. Someone with the time
|
||||
** and a fine tooth comb (not to mention some documentation on COFF)
|
||||
** should correct this!
|
||||
*/
|
||||
|
||||
#ifndef COFF_ENCAPSULATE
|
||||
#define COFF_ENCAPSULATE
|
||||
#endif
|
||||
|
||||
/* Customization for a particular machine. */
|
||||
#define INPUT_MAGIC I386MAGIC
|
||||
#define nounderscore
|
||||
|
||||
#include <stdio.h>
|
||||
#include <varargs.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#include "a.out.encap.h"
|
||||
#define N_ABSOLUTE N_ABS /* N_ABS will be redefined in syms.h */
|
||||
#undef N_ABS
|
||||
|
||||
#include <filehdr.h>
|
||||
#include <aouthdr.h>
|
||||
#include <scnhdr.h>
|
||||
#include <syms.h>
|
||||
#include <reloc.h>
|
||||
/* Because of struct alignment on dwords sizeof (struct syment) is different
|
||||
than the syments stored in the file. Therefore, we must kludge: */
|
||||
#define sizeof_syment (SYMESZ)
|
||||
#define sizeof_reloc (RELSZ)
|
||||
#define sizeof_section (SCNHSZ)
|
||||
#define sizeof_coff_header (FILHSZ)
|
||||
|
||||
extern long lseek ();
|
||||
extern void exit ();
|
||||
extern char *memcpy ();
|
||||
extern int errno;
|
||||
|
||||
void error (), sys_error ();
|
||||
static void reloc_segment ();
|
||||
char *mem_alloc ();
|
||||
|
||||
int fd_in, fd_out; /* input and output file descriptors */
|
||||
|
||||
struct filehdr coff_header; /* file header from the input file */
|
||||
struct exec bsd_header; /* file header for the output file */
|
||||
|
||||
struct syment *coff_sym_listp; /* list of symbols from the input */
|
||||
int *symbol_map; /* mapping of input symbol #'s to
|
||||
output symbol numbers */
|
||||
char *text_and_data; /* space for text & data section data */
|
||||
char *relocations; /* space for output reloc entries */
|
||||
int verbose_flag; /* flag for debugging */
|
||||
|
||||
struct scnhdr coff_text_header; /* COFF text section header */
|
||||
struct scnhdr coff_data_header; /* COFF data section header */
|
||||
struct scnhdr coff_bss_header; /* COFF bss section header */
|
||||
int text_sect_num; /* COFF section # for text */
|
||||
int data_sect_num; /* COFF section # for data */
|
||||
int bss_sect_num; /* COFF section # for bss */
|
||||
|
||||
int
|
||||
main (argc, argv)
|
||||
int argc;
|
||||
char **argv;
|
||||
{
|
||||
int i, j;
|
||||
char *coff_string_table, *bsd_string_table;
|
||||
register char *pc, *pc2;
|
||||
int string_table_len;
|
||||
int symbol_count;
|
||||
struct scnhdr section;
|
||||
struct nlist name;
|
||||
|
||||
if (argc < 3)
|
||||
error ("usage: %s cofffile bsdfile", argv[0]);
|
||||
if (argc > 3)
|
||||
verbose_flag = 1;
|
||||
|
||||
fd_in = open (argv[1], O_RDONLY);
|
||||
if (fd_in < 0)
|
||||
sys_error ("can't open %s", argv[1]);
|
||||
|
||||
fd_out = open (argv[2], O_WRONLY | O_CREAT | O_TRUNC, 0666);
|
||||
if (fd_out < 0)
|
||||
sys_error ("can't open %s", argv[2]);
|
||||
|
||||
/*
|
||||
** Read in the file header and all section headers searching
|
||||
** for text, data and bss. We note the section #'s of these
|
||||
** sections for use when examining symbols.
|
||||
*/
|
||||
|
||||
if (read (fd_in, &coff_header, sizeof_coff_header) != sizeof_coff_header)
|
||||
error ("can't read file header");
|
||||
|
||||
if (coff_header.f_magic != INPUT_MAGIC)
|
||||
error ("bad magic number in coff file\n");
|
||||
|
||||
lseek (fd_in, sizeof_coff_header + coff_header.f_opthdr, 0);
|
||||
|
||||
for (i = 1; i <= coff_header.f_nscns; ++i)
|
||||
{
|
||||
if (read (fd_in, §ion, sizeof_section) != sizeof_section)
|
||||
error ("can't read section header #%d", i);
|
||||
if (strcmp (section.s_name, _TEXT) == 0)
|
||||
{
|
||||
text_sect_num = i;
|
||||
memcpy (&coff_text_header, §ion, sizeof section);
|
||||
}
|
||||
else if (strcmp (section.s_name, _DATA) == 0)
|
||||
{
|
||||
data_sect_num = i;
|
||||
memcpy (&coff_data_header, §ion, sizeof section);
|
||||
}
|
||||
else if (strcmp (section.s_name, _BSS) == 0)
|
||||
{
|
||||
bss_sect_num = i;
|
||||
memcpy (&coff_bss_header, §ion, sizeof section);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** Pass1 thru the symbol table - count usable symbols and map
|
||||
** old symbol #'s into new ones (as used by relocation
|
||||
** info). We're only interested in keeping the kinds of symbols
|
||||
** we'd expect to find in a BSD library object file: no debug
|
||||
** symbols, file names, section definition symbols, etc.
|
||||
** Section definition symbols are referenced by reloc entries
|
||||
** in the COFF file, so we note their position with a negative
|
||||
** symbol number indicating the section. -1 is used to flag
|
||||
** symbols we're not interested in, yielding an unexpected error
|
||||
** if we find any reloc entries referencing them.
|
||||
*/
|
||||
|
||||
coff_sym_listp =
|
||||
(struct syment *) mem_alloc (coff_header.f_nsyms * sizeof (struct syment));
|
||||
symbol_map = (int *) mem_alloc (coff_header.f_nsyms * sizeof *symbol_map);
|
||||
if (lseek (fd_in, coff_header.f_symptr, 0) < 0L)
|
||||
sys_error ("can't seek to COFF symbols");
|
||||
for (i = 0; i < coff_header.f_nsyms; ++i)
|
||||
{
|
||||
if (read (fd_in, coff_sym_listp + i, sizeof_syment) != sizeof_syment)
|
||||
error ("can't read COFF symbols");
|
||||
}
|
||||
symbol_count = 0;
|
||||
for (i = 0; i < coff_header.f_nsyms; ++i)
|
||||
{
|
||||
if (coff_sym_listp[i].n_scnum != N_DEBUG
|
||||
&& coff_sym_listp[i].n_name[0] != '.')
|
||||
{
|
||||
if (verbose_flag)
|
||||
printf ("map %d to %d\n", i, symbol_count);
|
||||
symbol_map[i] = symbol_count++;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (coff_sym_listp[i].n_sclass == C_STAT)
|
||||
{
|
||||
if (strcmp (coff_sym_listp[i].n_name, _TEXT) == 0)
|
||||
symbol_map[i] = -N_TEXT;
|
||||
else if (strcmp (coff_sym_listp[i].n_name, _DATA) == 0)
|
||||
symbol_map[i] = -N_DATA;
|
||||
else if (strcmp (coff_sym_listp[i].n_name, _BSS) == 0)
|
||||
symbol_map[i] = -N_BSS;
|
||||
else
|
||||
symbol_map[i] = -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
symbol_map[i] = -1;
|
||||
}
|
||||
}
|
||||
/* skip auxillary entries */
|
||||
j = coff_sym_listp[i].n_numaux;
|
||||
if (j != 0)
|
||||
{
|
||||
if (j < 0)
|
||||
error ("invalid numaux");
|
||||
if (j != 1)
|
||||
fprintf (stderr, "unlikely numaux value\n");
|
||||
while (--j >= 0)
|
||||
++i;
|
||||
}
|
||||
}
|
||||
|
||||
/* now we know enough to write the output file header */
|
||||
|
||||
bsd_header.a_magic = OMAGIC;
|
||||
bsd_header.a_text = coff_text_header.s_size;
|
||||
bsd_header.a_data = coff_data_header.s_size;
|
||||
bsd_header.a_bss = coff_bss_header.s_size;
|
||||
bsd_header.a_syms = symbol_count * sizeof (struct nlist);
|
||||
bsd_header.a_entry = 0;
|
||||
bsd_header.a_trsize = coff_text_header.s_nreloc * sizeof (struct relocation_info);
|
||||
bsd_header.a_drsize = coff_data_header.s_nreloc * sizeof (struct relocation_info);
|
||||
if (write (fd_out, &bsd_header, sizeof bsd_header) != sizeof bsd_header)
|
||||
sys_error ("can't write BSD header");
|
||||
|
||||
/*
|
||||
** Read in and save text and data sections - some data in
|
||||
** these sections may need to be altered due to relocations.
|
||||
*/
|
||||
|
||||
text_and_data = (char *) mem_alloc (coff_text_header.s_size + coff_data_header.s_size);
|
||||
if (lseek (fd_in, coff_text_header.s_scnptr, 0) < 0L)
|
||||
sys_error ("can't seek to text section");
|
||||
if (read (fd_in, text_and_data, coff_text_header.s_size) != coff_text_header.s_size)
|
||||
error ("can't read text section");
|
||||
if (lseek (fd_in, coff_data_header.s_scnptr, 0) < 0L)
|
||||
sys_error ("can't seek to data section");
|
||||
if (read (fd_in, text_and_data + coff_text_header.s_size, coff_data_header.s_size) != coff_data_header.s_size)
|
||||
error ("can't read data section");
|
||||
|
||||
/*
|
||||
** Convert the relocation entries and do any text or data
|
||||
** modifications necessary.
|
||||
*/
|
||||
|
||||
relocations = (char *) mem_alloc (bsd_header.a_trsize + bsd_header.a_drsize);
|
||||
reloc_segment (&coff_text_header, relocations);
|
||||
reloc_segment (&coff_data_header, relocations + bsd_header.a_trsize);
|
||||
|
||||
if (write (fd_out, text_and_data, coff_text_header.s_size + coff_data_header.s_size)
|
||||
!= coff_text_header.s_size + coff_data_header.s_size)
|
||||
sys_error ("can't write text and data sections");
|
||||
/* ZZ - are there any alignment considerations?? */
|
||||
if ((coff_text_header.s_size & 1) || (coff_data_header.s_size & 1))
|
||||
fprintf (stderr, "non-aligned text or data section\n");
|
||||
if (write (fd_out, relocations, bsd_header.a_trsize + bsd_header.a_drsize)
|
||||
!= bsd_header.a_trsize + bsd_header.a_drsize)
|
||||
sys_error ("can't write relocation entries");
|
||||
|
||||
/*
|
||||
** Second pass thru the symbol table.
|
||||
** a COFF symbol entry may contain up to 8 chars of symbol name
|
||||
** in the entry itself - symbol names > 8 go into the string table,
|
||||
** whereas the BSD entry puts all symbol names into the string
|
||||
** table.
|
||||
*/
|
||||
|
||||
if (lseek (fd_in, coff_header.f_symptr + coff_header.f_nsyms * sizeof_syment, 0) < 0L)
|
||||
error ("can't seek to string table");
|
||||
|
||||
i = read (fd_in, &string_table_len, sizeof string_table_len);
|
||||
if (i == sizeof string_table_len)
|
||||
{
|
||||
coff_string_table = mem_alloc (string_table_len);
|
||||
string_table_len -= sizeof string_table_len;
|
||||
i = read (fd_in, coff_string_table + sizeof string_table_len, string_table_len);
|
||||
if (i < 0)
|
||||
error ("can't read string table");
|
||||
if (i != string_table_len)
|
||||
error ("truncated string table - expected %d, got %d",
|
||||
string_table_len, i);
|
||||
}
|
||||
else
|
||||
{
|
||||
string_table_len = 0;
|
||||
}
|
||||
bsd_string_table = mem_alloc (string_table_len + coff_header.f_nsyms * (SYMNMLEN + 1));
|
||||
pc = bsd_string_table + sizeof string_table_len;
|
||||
for (i = 0; i < coff_header.f_nsyms; ++i)
|
||||
{
|
||||
if (coff_sym_listp[i].n_scnum != N_DEBUG
|
||||
&& coff_sym_listp[i].n_name[0] != '.')
|
||||
{
|
||||
if (coff_sym_listp[i].n_zeroes == 0)
|
||||
{
|
||||
j = pc - bsd_string_table;
|
||||
#ifndef nounderscore
|
||||
if (coff_sym_listp[i].n_sclass == C_EXT
|
||||
|| coff_sym_listp[i].n_sclass == C_STAT)
|
||||
*pc++ = '_';
|
||||
#endif
|
||||
pc2 = coff_string_table + coff_sym_listp[i].n_offset;
|
||||
while (*pc++ = *pc2++)
|
||||
/* null */ ;
|
||||
name.n_un.n_strx = j;
|
||||
}
|
||||
else
|
||||
{
|
||||
pc2 = &coff_sym_listp[i].n_name[0];
|
||||
j = pc - bsd_string_table;
|
||||
#ifndef nounderscore
|
||||
if (coff_sym_listp[i].n_sclass == C_EXT
|
||||
|| coff_sym_listp[i].n_sclass == C_STAT)
|
||||
*pc++ = '_';
|
||||
#endif
|
||||
{
|
||||
int x;
|
||||
for (x = 0; x < SYMNMLEN; x++)
|
||||
{
|
||||
if (*pc2 == 0)
|
||||
break;
|
||||
*pc++ = *pc2++;
|
||||
}
|
||||
*pc++ = 0;
|
||||
}
|
||||
name.n_un.n_strx = j;
|
||||
}
|
||||
switch (coff_sym_listp[i].n_scnum)
|
||||
{
|
||||
case N_ABS:
|
||||
name.n_type = N_ABSOLUTE;
|
||||
break;
|
||||
case N_UNDEF:
|
||||
name.n_type = N_UNDF;
|
||||
break;
|
||||
default:
|
||||
if (coff_sym_listp[i].n_scnum == text_sect_num)
|
||||
name.n_type = N_TEXT;
|
||||
else if (coff_sym_listp[i].n_scnum == data_sect_num)
|
||||
name.n_type = N_DATA;
|
||||
else if (coff_sym_listp[i].n_scnum == bss_sect_num)
|
||||
name.n_type = N_BSS;
|
||||
break;
|
||||
}
|
||||
if (coff_sym_listp[i].n_sclass == C_EXT)
|
||||
name.n_type |= N_EXT;
|
||||
name.n_other = 0;
|
||||
name.n_desc = 0;
|
||||
name.n_value = coff_sym_listp[i].n_value;
|
||||
|
||||
if (write (fd_out, &name, sizeof name) != sizeof name)
|
||||
sys_error ("can't write symbol");
|
||||
}
|
||||
/* skip auxillary entries */
|
||||
j = coff_sym_listp[i].n_numaux;
|
||||
if (j != 0)
|
||||
{
|
||||
while (--j >= 0)
|
||||
++i;
|
||||
}
|
||||
}
|
||||
i = *((int *) bsd_string_table) = pc - bsd_string_table;
|
||||
if (write (fd_out, bsd_string_table, i) != i)
|
||||
error ("can't write string table");
|
||||
|
||||
close (fd_in);
|
||||
close (fd_out);
|
||||
exit (0);
|
||||
}
|
||||
|
||||
/*
|
||||
** Convert the relocation entries and do any text or data
|
||||
** modifications necessary.
|
||||
*/
|
||||
|
||||
static void
|
||||
reloc_segment (section_headerp, reloc_infop)
|
||||
struct scnhdr *section_headerp;
|
||||
struct relocation_info *reloc_infop;
|
||||
{
|
||||
struct reloc coff_reloc;
|
||||
int i;
|
||||
|
||||
if (lseek (fd_in, section_headerp->s_relptr, 0) < 0L)
|
||||
error ("can't seek to relocation entries");
|
||||
for (i = 0; i < section_headerp->s_nreloc; ++i)
|
||||
{
|
||||
if (read (fd_in, &coff_reloc, sizeof_reloc) != sizeof_reloc)
|
||||
error ("can't read relocation entry");
|
||||
if (verbose_flag)
|
||||
printf ("vaddr = 0x%x, symndx = %d\n", coff_reloc.r_vaddr, coff_reloc.r_symndx);
|
||||
/*
|
||||
** The reloc references a symbol declared common, thus the
|
||||
** value of the symbol holds its size (in bytes). In COFF,
|
||||
** apparently this info is also put into the binary -
|
||||
** BSD doesn't like this, so we subtract it out.
|
||||
*/
|
||||
if (coff_sym_listp[coff_reloc.r_symndx].n_scnum == N_UNDEF)
|
||||
{
|
||||
if (coff_sym_listp[coff_reloc.r_symndx].n_value != 0)
|
||||
{
|
||||
if (verbose_flag)
|
||||
printf ("adjust common 0x%x (%d)\n",
|
||||
coff_sym_listp[coff_reloc.r_symndx].n_value,
|
||||
coff_sym_listp[coff_reloc.r_symndx].n_value);
|
||||
switch (coff_reloc.r_type)
|
||||
{
|
||||
case R_RELBYTE:
|
||||
*((char *) (text_and_data + coff_reloc.r_vaddr))
|
||||
-= coff_sym_listp[coff_reloc.r_symndx].n_value;
|
||||
break;
|
||||
case R_RELWORD:
|
||||
*((short *) (text_and_data + coff_reloc.r_vaddr))
|
||||
-= coff_sym_listp[coff_reloc.r_symndx].n_value;
|
||||
break;
|
||||
case R_RELLONG:
|
||||
case R_DIR32: /* these are the only two that really show up */
|
||||
case R_PCRLONG:
|
||||
*((int *) (text_and_data + coff_reloc.r_vaddr))
|
||||
-= coff_sym_listp[coff_reloc.r_symndx].n_value;
|
||||
break;
|
||||
default:
|
||||
error ("unknown relocation type 0%o", coff_reloc.r_type);
|
||||
}
|
||||
}
|
||||
}
|
||||
/*
|
||||
** >= 0 means its an extern - value is the output symbol #.
|
||||
** < 0 means its an intern - value is N_TEXT, N_DATA or N_BSS.
|
||||
*/
|
||||
if (symbol_map[coff_reloc.r_symndx] >= 0)
|
||||
{
|
||||
reloc_infop->r_symbolnum = symbol_map[coff_reloc.r_symndx];
|
||||
reloc_infop->r_extern = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (symbol_map[coff_reloc.r_symndx] == -1)
|
||||
error ("Oops! possible bug - reloc reference to ignored symbol");
|
||||
reloc_infop->r_symbolnum = -symbol_map[coff_reloc.r_symndx];
|
||||
reloc_infop->r_extern = 0;
|
||||
}
|
||||
/*
|
||||
** COFF address includes the section address - BSD doesn't, so
|
||||
** subtract it out.
|
||||
*/
|
||||
reloc_infop->r_address = coff_reloc.r_vaddr - section_headerp->s_vaddr;
|
||||
switch (coff_reloc.r_type)
|
||||
{
|
||||
case R_PCRLONG:
|
||||
reloc_infop->r_pcrel = 1;
|
||||
reloc_infop->r_length = 2; /* 4 bytes */
|
||||
break;
|
||||
case R_DIR32:
|
||||
reloc_infop->r_pcrel = 0;
|
||||
reloc_infop->r_length = 2;
|
||||
break;
|
||||
default:
|
||||
error ("can't handle coff reloction type 0%o", coff_reloc.r_type);
|
||||
}
|
||||
|
||||
if (verbose_flag)
|
||||
printf ("reloc: addr = 0x%x, synum = %d\n",
|
||||
reloc_infop->r_address, reloc_infop->r_symbolnum);
|
||||
reloc_infop->r_pad = 0;
|
||||
++reloc_infop;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
error (format, va_alist)
|
||||
char *format;
|
||||
va_dcl
|
||||
{
|
||||
va_list args;
|
||||
|
||||
va_start (args);
|
||||
fprintf (stderr, "robotussin: ");
|
||||
vfprintf (stderr, format, args);
|
||||
putc ('\n', stderr);
|
||||
va_end (args);
|
||||
exit (1);
|
||||
}
|
||||
|
||||
extern char *sys_errlist[];
|
||||
extern int errno;
|
||||
|
||||
void
|
||||
sys_error (format, va_alist)
|
||||
char *format;
|
||||
va_dcl
|
||||
{
|
||||
va_list args;
|
||||
|
||||
va_start (args);
|
||||
fprintf (stderr, "robotussin: ");
|
||||
vfprintf (stderr, format, args);
|
||||
fprintf (stderr, ": %s\n", sys_errlist[errno]);
|
||||
va_end (args);
|
||||
exit (1);
|
||||
}
|
||||
|
||||
extern char *malloc ();
|
||||
|
||||
char *
|
||||
mem_alloc (size)
|
||||
int size;
|
||||
{
|
||||
char *pc;
|
||||
|
||||
if ((pc = malloc (size)) == NULL)
|
||||
error ("memory exhausted!");
|
||||
return pc;
|
||||
}
|
||||
|
||||
/* end */
|
||||
428
gnu/binutils/binutils.001/binutils/size.c
Normal file
428
gnu/binutils/binutils.001/binutils/size.c
Normal file
@@ -0,0 +1,428 @@
|
||||
/* Size of rel file utility (`size') for GNU.
|
||||
Copyright (C) 1986 Free Software Foundation, Inc.
|
||||
|
||||
NO WARRANTY
|
||||
|
||||
BECAUSE THIS PROGRAM IS LICENSED FREE OF CHARGE, WE PROVIDE ABSOLUTELY
|
||||
NO WARRANTY, TO THE EXTENT PERMITTED BY APPLICABLE STATE LAW. EXCEPT
|
||||
WHEN OTHERWISE STATED IN WRITING, FREE SOFTWARE FOUNDATION, INC,
|
||||
RICHARD M. STALLMAN AND/OR OTHER PARTIES PROVIDE THIS PROGRAM "AS IS"
|
||||
WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
|
||||
BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY
|
||||
AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE
|
||||
DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR
|
||||
CORRECTION.
|
||||
|
||||
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW WILL RICHARD M.
|
||||
STALLMAN, THE FREE SOFTWARE FOUNDATION, INC., AND/OR ANY OTHER PARTY
|
||||
WHO MAY MODIFY AND REDISTRIBUTE THIS PROGRAM AS PERMITTED BELOW, BE
|
||||
LIABLE TO YOU FOR DAMAGES, INCLUDING ANY LOST PROFITS, LOST MONIES, OR
|
||||
OTHER SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
|
||||
USE OR INABILITY TO USE (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR
|
||||
DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY THIRD PARTIES OR
|
||||
A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS) THIS
|
||||
PROGRAM, EVEN IF YOU HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH
|
||||
DAMAGES, OR FOR ANY CLAIM BY ANY OTHER PARTY.
|
||||
|
||||
GENERAL PUBLIC LICENSE TO COPY
|
||||
|
||||
1. You may copy and distribute verbatim copies of this source file
|
||||
as you receive it, in any medium, provided that you conspicuously
|
||||
and appropriately publish on each copy a valid copyright notice
|
||||
"Copyright (C) 1986 Free Software Foundation, Inc.", and include
|
||||
following the copyright notice a verbatim copy of the above disclaimer
|
||||
of warranty and of this License.
|
||||
|
||||
2. You may modify your copy or copies of this source file or
|
||||
any portion of it, and copy and distribute such modifications under
|
||||
the terms of Paragraph 1 above, provided that you also do the following:
|
||||
|
||||
a) cause the modified files to carry prominent notices stating
|
||||
that you changed the files and the date of any change; and
|
||||
|
||||
b) cause the whole of any work that you distribute or publish,
|
||||
that in whole or in part contains or is a derivative of this
|
||||
program or any part thereof, to be licensed at no charge to all
|
||||
third parties on terms identical to those contained in this
|
||||
License Agreement (except that you may choose to grant more extensive
|
||||
warranty protection to some or all third parties, at your option).
|
||||
|
||||
c) You may charge a distribution fee for the physical act of
|
||||
transferring a copy, and you may at your option offer warranty
|
||||
protection in exchange for a fee.
|
||||
|
||||
Mere aggregation of another unrelated program with this program (or its
|
||||
derivative) on a volume of a storage or distribution medium does not bring
|
||||
the other program under the scope of these terms.
|
||||
|
||||
3. You may copy and distribute this program (or a portion or derivative
|
||||
of it, under Paragraph 2) in object code or executable form under the terms
|
||||
of Paragraphs 1 and 2 above provided that you also do one of the following:
|
||||
|
||||
a) accompany it with the complete corresponding machine-readable
|
||||
source code, which must be distributed under the terms of
|
||||
Paragraphs 1 and 2 above; or,
|
||||
|
||||
b) accompany it with a written offer, valid for at least three
|
||||
years, to give any third party free (except for a nominal
|
||||
shipping charge) a complete machine-readable copy of the
|
||||
corresponding source code, to be distributed under the terms of
|
||||
Paragraphs 1 and 2 above; or,
|
||||
|
||||
c) accompany it with the information you received as to where the
|
||||
corresponding source code may be obtained. (This alternative is
|
||||
allowed only for noncommercial distribution and only if you
|
||||
received the program in object code or executable form alone.)
|
||||
|
||||
For an executable file, complete source code means all the source code for
|
||||
all modules it contains; but, as a special exception, it need not include
|
||||
source code for modules which are standard libraries that accompany the
|
||||
operating system on which the executable file runs.
|
||||
|
||||
4. You may not copy, sublicense, distribute or transfer this program
|
||||
except as expressly provided under this License Agreement. Any attempt
|
||||
otherwise to copy, sublicense, distribute or transfer this program is void and
|
||||
your rights to use the program under this License agreement shall be
|
||||
automatically terminated. However, parties who have received computer
|
||||
software programs from you with this License Agreement will not have
|
||||
their licenses terminated so long as such parties remain in full compliance.
|
||||
|
||||
5. If you wish to incorporate parts of this program into other free
|
||||
programs whose distribution conditions are different, write to the Free
|
||||
Software Foundation at 675 Mass Ave, Cambridge, MA 02139. We have not yet
|
||||
worked out a simple rule that can be stated here, but we will often permit
|
||||
this. We will be guided by the two goals of preserving the free status of
|
||||
all derivatives of our free software and of promoting the sharing and reuse of
|
||||
software.
|
||||
|
||||
In other words, you are welcome to use, share and improve this program.
|
||||
You are forbidden to forbid anyone else to use, share and improve
|
||||
what you give them. Help stamp out software-hoarding! */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <ar.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/file.h>
|
||||
|
||||
#ifdef COFF_ENCAPSULATE
|
||||
#include "a.out.encap.h"
|
||||
#else
|
||||
/* On native BSD systems, use the system's own a.out.h. */
|
||||
#include <a.out.h>
|
||||
#endif
|
||||
|
||||
#ifdef USG
|
||||
#include <fcntl.h>
|
||||
#include <string.h>
|
||||
#else
|
||||
#include <strings.h>
|
||||
#endif
|
||||
|
||||
/* Struct or union for header of object file. */
|
||||
|
||||
#define HEADER_TYPE struct exec
|
||||
|
||||
/* Number of input file names specified. */
|
||||
|
||||
int number_of_files;
|
||||
|
||||
/* Current file's name */
|
||||
|
||||
char *input_name;
|
||||
|
||||
/* Current member's name, or 0 if processing a non-library file. */
|
||||
|
||||
char *input_member;
|
||||
|
||||
/* Offset within archive of the current member,
|
||||
if we are processing an archive. */
|
||||
|
||||
int member_offset;
|
||||
|
||||
void do_one_file (), do_one_rel_file ();
|
||||
char *concat ();
|
||||
|
||||
main (argc, argv)
|
||||
char **argv;
|
||||
int argc;
|
||||
{
|
||||
int i;
|
||||
|
||||
number_of_files = argc - 1;
|
||||
|
||||
printf ("text\tdata\tbss\tdec\thex\n");
|
||||
|
||||
/* Now scan and describe the files. */
|
||||
|
||||
if (number_of_files == 0)
|
||||
do_one_file ("a.out");
|
||||
else
|
||||
for (i = 1; i < argc; i++)
|
||||
do_one_file (argv[i]);
|
||||
}
|
||||
|
||||
/* Print the filename of the current file on 'outfile' (a stdio stream). */
|
||||
|
||||
print_file_name (outfile)
|
||||
FILE *outfile;
|
||||
{
|
||||
fprintf (outfile, "%s", input_name);
|
||||
if (input_member)
|
||||
fprintf (outfile, "(%s)", input_member);
|
||||
}
|
||||
|
||||
/* process one input file */
|
||||
void scan_library ();
|
||||
|
||||
void
|
||||
do_one_file (name)
|
||||
char *name;
|
||||
{
|
||||
int len, magicnum, desc;
|
||||
|
||||
desc = open (name, O_RDONLY, 0);
|
||||
|
||||
if (desc < 0)
|
||||
{
|
||||
perror_name (name);
|
||||
return;
|
||||
}
|
||||
|
||||
input_name = name;
|
||||
input_member = 0;
|
||||
|
||||
#ifdef HEADER_SEEK_FD
|
||||
/* Skip the headers that encapsulate our data in some other format
|
||||
such as COFF. */
|
||||
HEADER_SEEK_FD (desc);
|
||||
#endif
|
||||
len = read (desc, &magicnum, sizeof magicnum);
|
||||
if (len != sizeof magicnum)
|
||||
error_with_file ("failure reading header");
|
||||
else if (!N_BADMAG (*((struct exec *)&magicnum)))
|
||||
do_one_rel_file (desc, 0);
|
||||
else
|
||||
{
|
||||
char armag[SARMAG];
|
||||
|
||||
lseek (desc, 0, 0);
|
||||
if (SARMAG != read (desc, armag, SARMAG) || strncmp (armag, ARMAG, SARMAG))
|
||||
error_with_file ("malformed input file (not rel or archive)");
|
||||
else
|
||||
scan_library (desc);
|
||||
}
|
||||
|
||||
close (desc);
|
||||
}
|
||||
|
||||
/* Read in the archive data about one member.
|
||||
subfile_offset is the address within the archive of the start of that data.
|
||||
The value returned is the length of the member's contents, which does
|
||||
not include the archive data about the member.
|
||||
|
||||
If there are no more valid members, zero is returned. */
|
||||
|
||||
int
|
||||
decode_library_subfile (desc, subfile_offset)
|
||||
int desc;
|
||||
int subfile_offset;
|
||||
{
|
||||
int bytes_read;
|
||||
int namelen;
|
||||
int member_length;
|
||||
char *name;
|
||||
struct ar_hdr hdr1;
|
||||
|
||||
lseek (desc, subfile_offset, 0);
|
||||
|
||||
bytes_read = read (desc, &hdr1, sizeof hdr1);
|
||||
if (!bytes_read)
|
||||
; /* end of archive */
|
||||
|
||||
else if (sizeof hdr1 != bytes_read)
|
||||
error_with_file ("malformed library archive");
|
||||
|
||||
else if (sscanf (hdr1.ar_size, "%d", &member_length) != 1)
|
||||
error_with_file ("malformatted header of archive member");
|
||||
|
||||
else
|
||||
{
|
||||
for (namelen = 0;
|
||||
hdr1.ar_name[namelen] != 0
|
||||
&& hdr1.ar_name[namelen] != ' '
|
||||
&& hdr1.ar_name[namelen] != '/';
|
||||
namelen++)
|
||||
;
|
||||
name = (char *) xmalloc (namelen+1);
|
||||
strncpy (name, hdr1.ar_name, namelen);
|
||||
*(name + namelen) = 0;
|
||||
|
||||
input_member = name;
|
||||
|
||||
return member_length;
|
||||
}
|
||||
return 0; /* tell caller to exit loop */
|
||||
}
|
||||
|
||||
/* Scan a library and describe each member. */
|
||||
|
||||
void
|
||||
scan_library (desc)
|
||||
int desc;
|
||||
{
|
||||
int this_subfile_offset = SARMAG;
|
||||
int member_length;
|
||||
|
||||
while (member_length = decode_library_subfile (desc, this_subfile_offset))
|
||||
{
|
||||
/* describe every member except the ranlib data if any */
|
||||
if (strcmp (input_member, "__.SYMDEF"))
|
||||
do_one_rel_file (desc, this_subfile_offset + sizeof (struct ar_hdr));
|
||||
|
||||
this_subfile_offset += ((member_length + sizeof (struct ar_hdr)) + 1) & -2;
|
||||
}
|
||||
}
|
||||
|
||||
void read_header ();
|
||||
|
||||
void
|
||||
do_one_rel_file (desc, offset)
|
||||
int desc;
|
||||
int offset;
|
||||
{
|
||||
HEADER_TYPE header; /* file header read in here */
|
||||
int total;
|
||||
|
||||
header.a_magic = 0;
|
||||
|
||||
read_header (desc, &header, offset);
|
||||
|
||||
if (N_BADMAG (header))
|
||||
{
|
||||
error_with_file ("bad magic number");
|
||||
return;
|
||||
}
|
||||
|
||||
{
|
||||
int tsize, dsize, bsize;
|
||||
|
||||
tsize = header.a_text;
|
||||
dsize = header.a_data;
|
||||
bsize = header.a_bss;
|
||||
total = tsize + dsize + bsize;
|
||||
printf ("%d\t%d\t%d\t%d\t%x", tsize, dsize, bsize, total, total);
|
||||
}
|
||||
|
||||
if (number_of_files > 1 || input_member)
|
||||
{
|
||||
printf ("\t");
|
||||
print_file_name (stdout);
|
||||
}
|
||||
printf ("\n");
|
||||
}
|
||||
|
||||
|
||||
/* read a file's header */
|
||||
|
||||
void
|
||||
read_header (desc, loc, offset)
|
||||
int desc;
|
||||
HEADER_TYPE *loc;
|
||||
int offset;
|
||||
{
|
||||
int len;
|
||||
|
||||
lseek (desc, offset, 0);
|
||||
#ifdef HEADER_SEEK_FD
|
||||
/* Skip the headers that encapsulate our data in some other format
|
||||
such as COFF. */
|
||||
HEADER_SEEK_FD (desc);
|
||||
#endif
|
||||
len = read (desc, loc, sizeof (struct exec));
|
||||
if (len != sizeof (struct exec))
|
||||
error_with_file ("failure reading header");
|
||||
}
|
||||
|
||||
/* Report a fatal error.
|
||||
STRING is a printf format string and ARG is one arg for it. */
|
||||
|
||||
fatal (string, arg)
|
||||
char *string, *arg;
|
||||
{
|
||||
fprintf (stderr, "size: ");
|
||||
fprintf (stderr, string, arg);
|
||||
fprintf (stderr, "\n");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
/* Report a nonfatal error.
|
||||
STRING is a printf format string and ARG is one arg for it. */
|
||||
|
||||
error (string, arg)
|
||||
char *string, *arg;
|
||||
{
|
||||
fprintf (stderr, "size: ");
|
||||
fprintf (stderr, string, arg);
|
||||
fprintf (stderr, "\n");
|
||||
}
|
||||
|
||||
/* Report a nonfatal error.
|
||||
STRING is printed, followed by the current file name. */
|
||||
|
||||
error_with_file (string)
|
||||
char *string;
|
||||
{
|
||||
fprintf (stderr, "size: ");
|
||||
print_file_name (stderr);
|
||||
fprintf (stderr, ": ");
|
||||
fprintf (stderr, string);
|
||||
fprintf (stderr, "\n");
|
||||
}
|
||||
|
||||
/* Report an error using the message for the last failed system call,
|
||||
followed by the string NAME. */
|
||||
|
||||
perror_name (name)
|
||||
char *name;
|
||||
{
|
||||
extern int errno, sys_nerr;
|
||||
extern char *sys_errlist[];
|
||||
char *s;
|
||||
|
||||
if (errno < sys_nerr)
|
||||
s = concat (name, ": ", sys_errlist[errno]);
|
||||
else
|
||||
s = concat (name, ": ", "unknown error");
|
||||
error (s, name);
|
||||
}
|
||||
|
||||
/* Like malloc but get fatal error if memory is exhausted. */
|
||||
|
||||
int
|
||||
xmalloc (size)
|
||||
int size;
|
||||
{
|
||||
int result = malloc (size);
|
||||
if (!result)
|
||||
fatal ("virtual memory exhausted", 0);
|
||||
return result;
|
||||
}
|
||||
|
||||
/* Return a newly-allocated string
|
||||
whose contents concatenate those of S1, S2, S3. */
|
||||
|
||||
char *
|
||||
concat (s1, s2, s3)
|
||||
char *s1, *s2, *s3;
|
||||
{
|
||||
int len1 = strlen (s1), len2 = strlen (s2), len3 = strlen (s3);
|
||||
char *result = (char *) xmalloc (len1 + len2 + len3 + 1);
|
||||
|
||||
strcpy (result, s1);
|
||||
strcpy (result + len1, s2);
|
||||
strcpy (result + len1 + len2, s3);
|
||||
*(result + len1 + len2 + len3) = 0;
|
||||
|
||||
return result;
|
||||
}
|
||||
201
gnu/binutils/binutils.001/binutils/stab.def
Normal file
201
gnu/binutils/binutils.001/binutils/stab.def
Normal file
@@ -0,0 +1,201 @@
|
||||
/* Table of DBX symbol codes for the GNU system.
|
||||
Copyright (C) 1988 Free Software Foundation, Inc.
|
||||
|
||||
NO WARRANTY
|
||||
|
||||
BECAUSE THIS PROGRAM IS LICENSED FREE OF CHARGE, WE PROVIDE ABSOLUTELY
|
||||
NO WARRANTY, TO THE EXTENT PERMITTED BY APPLICABLE STATE LAW. EXCEPT
|
||||
WHEN OTHERWISE STATED IN WRITING, FREE SOFTWARE FOUNDATION, INC,
|
||||
RICHARD M. STALLMAN AND/OR OTHER PARTIES PROVIDE THIS PROGRAM "AS IS"
|
||||
WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
|
||||
BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY
|
||||
AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE
|
||||
DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR
|
||||
CORRECTION.
|
||||
|
||||
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW WILL RICHARD M.
|
||||
STALLMAN, THE FREE SOFTWARE FOUNDATION, INC., AND/OR ANY OTHER PARTY
|
||||
WHO MAY MODIFY AND REDISTRIBUTE THIS PROGRAM AS PERMITTED BELOW, BE
|
||||
LIABLE TO YOU FOR DAMAGES, INCLUDING ANY LOST PROFITS, LOST MONIES, OR
|
||||
OTHER SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
|
||||
USE OR INABILITY TO USE (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR
|
||||
DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY THIRD PARTIES OR
|
||||
A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS) THIS
|
||||
PROGRAM, EVEN IF YOU HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH
|
||||
DAMAGES, OR FOR ANY CLAIM BY ANY OTHER PARTY.
|
||||
|
||||
GENERAL PUBLIC LICENSE TO COPY
|
||||
|
||||
1. You may copy and distribute verbatim copies of this source file
|
||||
as you receive it, in any medium, provided that you conspicuously and
|
||||
appropriately publish on each copy a valid copyright notice "Copyright
|
||||
(C) 1988 Free Software Foundation, Inc."; and include following the
|
||||
copyright notice a verbatim copy of the above disclaimer of warranty
|
||||
and of this License. You may charge a distribution fee for the
|
||||
physical act of transferring a copy.
|
||||
|
||||
2. You may modify your copy or copies of this source file or
|
||||
any portion of it, and copy and distribute such modifications under
|
||||
the terms of Paragraph 1 above, provided that you also do the following:
|
||||
|
||||
a) cause the modified files to carry prominent notices stating
|
||||
that you changed the files and the date of any change; and
|
||||
|
||||
b) cause the whole of any work that you distribute or publish,
|
||||
that in whole or in part contains or is a derivative of this
|
||||
program or any part thereof, to be licensed at no charge to all
|
||||
third parties on terms identical to those contained in this
|
||||
License Agreement (except that you may choose to grant more extensive
|
||||
warranty protection to some or all third parties, at your option).
|
||||
|
||||
c) You may charge a distribution fee for the physical act of
|
||||
transferring a copy, and you may at your option offer warranty
|
||||
protection in exchange for a fee.
|
||||
|
||||
Mere aggregation of another unrelated program with this program (or its
|
||||
derivative) on a volume of a storage or distribution medium does not bring
|
||||
the other program under the scope of these terms.
|
||||
|
||||
3. You may copy and distribute this program or any portion of it in
|
||||
compiled, executable or object code form under the terms of Paragraphs
|
||||
1 and 2 above provided that you do the following:
|
||||
|
||||
a) accompany it with the complete corresponding machine-readable
|
||||
source code, which must be distributed under the terms of
|
||||
Paragraphs 1 and 2 above; or,
|
||||
|
||||
b) accompany it with a written offer, valid for at least three
|
||||
years, to give any third party free (except for a nominal
|
||||
shipping charge) a complete machine-readable copy of the
|
||||
corresponding source code, to be distributed under the terms of
|
||||
Paragraphs 1 and 2 above; or,
|
||||
|
||||
c) accompany it with the information you received as to where the
|
||||
corresponding source code may be obtained. (This alternative is
|
||||
allowed only for noncommercial distribution and only if you
|
||||
received the program in object code or executable form alone.)
|
||||
|
||||
For an executable file, complete source code means all the source code for
|
||||
all modules it contains; but, as a special exception, it need not include
|
||||
source code for modules which are standard libraries that accompany the
|
||||
operating system on which the executable file runs.
|
||||
|
||||
4. You may not copy, sublicense, distribute or transfer this program
|
||||
except as expressly provided under this License Agreement. Any attempt
|
||||
otherwise to copy, sublicense, distribute or transfer this program is void and
|
||||
your rights to use the program under this License agreement shall be
|
||||
automatically terminated. However, parties who have received computer
|
||||
software programs from you with this License Agreement will not have
|
||||
their licenses terminated so long as such parties remain in full compliance.
|
||||
|
||||
5. If you wish to incorporate parts of this program into other free
|
||||
programs whose distribution conditions are different, write to the Free
|
||||
Software Foundation at 675 Mass Ave, Cambridge, MA 02139. We have not yet
|
||||
worked out a simple rule that can be stated here, but we will often permit
|
||||
this. We will be guided by the two goals of preserving the free status of
|
||||
all derivatives our free software and of promoting the sharing and reuse of
|
||||
software.
|
||||
|
||||
|
||||
In other words, you are welcome to use, share and improve this program.
|
||||
You are forbidden to forbid anyone else to use, share and improve
|
||||
what you give them. Help stamp out software-hoarding! */
|
||||
|
||||
/* Global variable. Only the name is significant.
|
||||
To find the address, look in the corresponding external symbol. */
|
||||
__define_stab (N_GSYM, 0x20, "GSYM")
|
||||
|
||||
/* Function name for BSD Fortran. Only the name is significant.
|
||||
To find the address, look in the corresponding external symbol. */
|
||||
__define_stab (N_FNAME, 0x22, "FNAME")
|
||||
|
||||
/* Function name or text-segment variable for C. Value is its address.
|
||||
Desc is supposedly starting line number, but GCC doesn't set it
|
||||
and DBX seems not to miss it. */
|
||||
__define_stab (N_FUN, 0x24, "FUN")
|
||||
|
||||
/* Data-segment variable with internal linkage. Value is its address. */
|
||||
__define_stab (N_STSYM, 0x26, "STSYM")
|
||||
|
||||
/* BSS-segment variable with internal linkage. Value is its address. */
|
||||
__define_stab (N_LCSYM, 0x28, "LCSYM")
|
||||
|
||||
/* Name of main routine. Only the name is significant.
|
||||
This is not used in C. */
|
||||
__define_stab (N_MAIN, 0x2a, "MAIN")
|
||||
|
||||
/* Register variable. Value is number of register. */
|
||||
__define_stab (N_RSYM, 0x40, "RSYM")
|
||||
|
||||
/* Structure or union element. Value is offset in the structure. */
|
||||
__define_stab (N_SSYM, 0x60, "SSYM")
|
||||
|
||||
/* Parameter variable. Value is offset from argument pointer.
|
||||
(On most machines the argument pointer is the same as the frame pointer. */
|
||||
__define_stab (N_PSYM, 0xa0, "PSYM")
|
||||
|
||||
/* Automatic variable in the stack. Value is offset from frame pointer. */
|
||||
__define_stab (N_LSYM, 0x80, "LSYM")
|
||||
|
||||
/* Alternate entry point. Value is its address. */
|
||||
__define_stab (N_ENTRY, 0xa4, "ENTRY")
|
||||
|
||||
/* Name of main source file.
|
||||
Value is starting text address of the compilation. */
|
||||
__define_stab (N_SO, 0x64, "SO")
|
||||
|
||||
/* Name of sub-source file.
|
||||
Value is starting text address of the compilation. */
|
||||
__define_stab (N_SOL, 0x84, "SOL")
|
||||
|
||||
/* Line number in text segment. Desc is the line number;
|
||||
value is corresponding address. */
|
||||
__define_stab (N_SLINE, 0x44, "SLINE")
|
||||
/* Similar, for data segment. */
|
||||
__define_stab (N_DSLINE, 0x46, "DSLINE")
|
||||
/* Similar, for bss segment. */
|
||||
__define_stab (N_BSLINE, 0x48, "BSLINE")
|
||||
|
||||
/* Beginning of an include file. Only Sun uses this.
|
||||
In an object file, only the name is significant.
|
||||
The Sun linker puts data into some of the other fields. */
|
||||
__define_stab (N_BINCL, 0x82, "BINCL")
|
||||
/* End of an include file. No name.
|
||||
These two act as brackets around the file's output.
|
||||
In an object file, there is no significant data in this entry.
|
||||
The Sun linker puts data into some of the fields. */
|
||||
__define_stab (N_EINCL, 0xa2, "EINCL")
|
||||
/* Place holder for deleted include file.
|
||||
This appears only in output from the Sun linker. */
|
||||
__define_stab (N_EXCL, 0xc2, "EXCL")
|
||||
|
||||
/* Beginning of lexical block.
|
||||
The desc is the nesting level in lexical blocks.
|
||||
The value is the address of the start of the text for the block.
|
||||
The variables declared inside the block *precede* the N_LBRAC symbol. */
|
||||
__define_stab (N_LBRAC, 0xc0, "LBRAC")
|
||||
/* End of a lexical block. Desc matches the N_LBRAC's desc.
|
||||
The value is the address of the end of the text for the block. */
|
||||
__define_stab (N_RBRAC, 0xe0, "RBRAC")
|
||||
|
||||
/* Begin named common block. Only the name is significant. */
|
||||
__define_stab (N_BCOMM, 0xe2, "BCOMM")
|
||||
/* Begin named common block. Only the name is significant
|
||||
(and it should match the N_BCOMM). */
|
||||
__define_stab (N_ECOMM, 0xe4, "ECOMM")
|
||||
/* End common (local name): value is address.
|
||||
I'm not sure how this is used. */
|
||||
__define_stab (N_ECOML, 0xe8, "ECOML")
|
||||
/* Second symbol entry containing a length-value for the preceding entry.
|
||||
The value is the length. */
|
||||
__define_stab (N_LENG, 0xfe, "LENG")
|
||||
|
||||
/* Global symbol in Pascal.
|
||||
Supposedly the value is its line number; I'm skeptical. */
|
||||
__define_stab (N_PC, 0x30, "PC")
|
||||
|
||||
/* Modula-2 compilation unit. Can someone say what info it contains? */
|
||||
__define_stab (N_M2C, 0x42, "M2C")
|
||||
/* Modula-2 scope information. Can someone say what info it contains? */
|
||||
__define_stab (N_SCOPE, 0xc4, "SCOPE")
|
||||
16
gnu/binutils/binutils.001/binutils/stab.h
Normal file
16
gnu/binutils/binutils.001/binutils/stab.h
Normal file
@@ -0,0 +1,16 @@
|
||||
#ifndef __GNU_STAB__
|
||||
|
||||
/* Indicate the GNU stab.h is in use. */
|
||||
|
||||
#define __GNU_STAB__
|
||||
|
||||
#define __define_stab(NAME, CODE, STRING) NAME=CODE,
|
||||
|
||||
enum __stab_debug_code
|
||||
{
|
||||
#include "stab.def"
|
||||
};
|
||||
|
||||
#undef __define_stab
|
||||
|
||||
#endif /* __GNU_STAB_ */
|
||||
789
gnu/binutils/binutils.001/binutils/strip.c
Normal file
789
gnu/binutils/binutils.001/binutils/strip.c
Normal file
@@ -0,0 +1,789 @@
|
||||
/* strip certain symbols from a rel file.
|
||||
Copyright (C) 1986 Free Software Foundation, Inc.
|
||||
|
||||
NO WARRANTY
|
||||
|
||||
BECAUSE THIS PROGRAM IS LICENSED FREE OF CHARGE, WE PROVIDE ABSOLUTELY
|
||||
NO WARRANTY, TO THE EXTENT PERMITTED BY APPLICABLE STATE LAW. EXCEPT
|
||||
WHEN OTHERWISE STATED IN WRITING, FREE SOFTWARE FOUNDATION, INC,
|
||||
RICHARD M. STALLMAN AND/OR OTHER PARTIES PROVIDE THIS PROGRAM "AS IS"
|
||||
WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
|
||||
BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY
|
||||
AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE
|
||||
DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR
|
||||
CORRECTION.
|
||||
|
||||
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW WILL RICHARD M.
|
||||
STALLMAN, THE FREE SOFTWARE FOUNDATION, INC., AND/OR ANY OTHER PARTY
|
||||
WHO MAY MODIFY AND REDISTRIBUTE THIS PROGRAM AS PERMITTED BELOW, BE
|
||||
LIABLE TO YOU FOR DAMAGES, INCLUDING ANY LOST PROFITS, LOST MONIES, OR
|
||||
OTHER SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
|
||||
USE OR INABILITY TO USE (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR
|
||||
DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY THIRD PARTIES OR
|
||||
A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS) THIS
|
||||
PROGRAM, EVEN IF YOU HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH
|
||||
DAMAGES, OR FOR ANY CLAIM BY ANY OTHER PARTY.
|
||||
|
||||
GENERAL PUBLIC LICENSE TO COPY
|
||||
|
||||
1. You may copy and distribute verbatim copies of this source file
|
||||
as you receive it, in any medium, provided that you conspicuously
|
||||
and appropriately publish on each copy a valid copyright notice
|
||||
"Copyright (C) 1986 Free Software Foundation, Inc.", and include
|
||||
following the copyright notice a verbatim copy of the above disclaimer
|
||||
of warranty and of this License.
|
||||
|
||||
2. You may modify your copy or copies of this source file or
|
||||
any portion of it, and copy and distribute such modifications under
|
||||
the terms of Paragraph 1 above, provided that you also do the following:
|
||||
|
||||
a) cause the modified files to carry prominent notices stating
|
||||
that you changed the files and the date of any change; and
|
||||
|
||||
b) cause the whole of any work that you distribute or publish,
|
||||
that in whole or in part contains or is a derivative of this
|
||||
program or any part thereof, to be licensed at no charge to all
|
||||
third parties on terms identical to those contained in this
|
||||
License Agreement (except that you may choose to grant more extensive
|
||||
warranty protection to some or all third parties, at your option).
|
||||
|
||||
c) You may charge a distribution fee for the physical act of
|
||||
transferring a copy, and you may at your option offer warranty
|
||||
protection in exchange for a fee.
|
||||
|
||||
Mere aggregation of another unrelated program with this program (or its
|
||||
derivative) on a volume of a storage or distribution medium does not bring
|
||||
the other program under the scope of these terms.
|
||||
|
||||
3. You may copy and distribute this program (or a portion or derivative
|
||||
of it, under Paragraph 2) in object code or executable form under the terms
|
||||
of Paragraphs 1 and 2 above provided that you also do one of the following:
|
||||
|
||||
a) accompany it with the complete corresponding machine-readable
|
||||
source code, which must be distributed under the terms of
|
||||
Paragraphs 1 and 2 above; or,
|
||||
|
||||
b) accompany it with a written offer, valid for at least three
|
||||
years, to give any third party free (except for a nominal
|
||||
shipping charge) a complete machine-readable copy of the
|
||||
corresponding source code, to be distributed under the terms of
|
||||
Paragraphs 1 and 2 above; or,
|
||||
|
||||
c) accompany it with the information you received as to where the
|
||||
corresponding source code may be obtained. (This alternative is
|
||||
allowed only for noncommercial distribution and only if you
|
||||
received the program in object code or executable form alone.)
|
||||
|
||||
For an executable file, complete source code means all the source code for
|
||||
all modules it contains; but, as a special exception, it need not include
|
||||
source code for modules which are standard libraries that accompany the
|
||||
operating system on which the executable file runs.
|
||||
|
||||
4. You may not copy, sublicense, distribute or transfer this program
|
||||
except as expressly provided under this License Agreement. Any attempt
|
||||
otherwise to copy, sublicense, distribute or transfer this program is void and
|
||||
your rights to use the program under this License agreement shall be
|
||||
automatically terminated. However, parties who have received computer
|
||||
software programs from you with this License Agreement will not have
|
||||
their licenses terminated so long as such parties remain in full compliance.
|
||||
|
||||
5. If you wish to incorporate parts of this program into other free
|
||||
programs whose distribution conditions are different, write to the Free
|
||||
Software Foundation at 675 Mass Ave, Cambridge, MA 02139. We have not yet
|
||||
worked out a simple rule that can be stated here, but we will often permit
|
||||
this. We will be guided by the two goals of preserving the free status of
|
||||
all derivatives of our free software and of promoting the sharing and reuse of
|
||||
software.
|
||||
|
||||
In other words, you are welcome to use, share and improve this program.
|
||||
You are forbidden to forbid anyone else to use, share and improve
|
||||
what you give them. Help stamp out software-hoarding! */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/file.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#ifdef USG
|
||||
#include <fcntl.h>
|
||||
#include <string.h>
|
||||
#else
|
||||
#include <strings.h>
|
||||
#endif
|
||||
|
||||
#ifdef COFF_ENCAPSULATE
|
||||
#include "a.out.encap.h"
|
||||
#else
|
||||
/* On native BSD systems, use the system's own a.out.h. */
|
||||
#include <a.out.h>
|
||||
#endif
|
||||
|
||||
/* If BSD, we can use `ftruncate'. */
|
||||
|
||||
#ifndef USG
|
||||
#define HAVE_FTRUNCATE
|
||||
#endif
|
||||
|
||||
/* Struct or union for header of object file. */
|
||||
|
||||
#define HEADER_TYPE struct exec
|
||||
|
||||
/* Count the number of nlist entries that are for local symbols. */
|
||||
int local_sym_count;
|
||||
|
||||
/* Count number of nlist entries that are for local symbols
|
||||
whose names don't start with L. */
|
||||
int non_L_local_sym_count;
|
||||
|
||||
/* Count the number of nlist entries for debugger info. */
|
||||
int debugger_sym_count;
|
||||
|
||||
/* Count the number of global symbols referenced or defined. */
|
||||
int global_sym_count;
|
||||
|
||||
/* Total number of symbols to be preserved in the current file. */
|
||||
int nsyms;
|
||||
|
||||
/* Number of files specified in the command line. */
|
||||
|
||||
int number_of_files;
|
||||
|
||||
/* Each specified file has a file_entry structure for it.
|
||||
These are contained in the vector which file_table points to. */
|
||||
|
||||
struct file_entry {
|
||||
char *filename;
|
||||
HEADER_TYPE header; /* the file's header */
|
||||
int ss_size; /* size, in bytes, of symbols_and_strings data */
|
||||
struct nlist *symbols_and_strings;
|
||||
};
|
||||
|
||||
struct file_entry *file_table;
|
||||
|
||||
/* Descriptor on which current file is open. */
|
||||
|
||||
int input_desc;
|
||||
|
||||
/* Stream for writing that file using stdio. */
|
||||
|
||||
FILE *outstream;
|
||||
|
||||
/* 1 => strip all symbols; 2 => strip all debugger symbols */
|
||||
int strip_symbols;
|
||||
|
||||
/* 1 => discard locals starting with L; 2 => discard all locals */
|
||||
int discard_locals;
|
||||
|
||||
void strip_file ();
|
||||
int file_open ();
|
||||
void rewrite_file_symbols(), file_close();
|
||||
int read_header (), read_entry_symbols (), read_file_symbols ();
|
||||
void count_file_symbols ();
|
||||
char *concat ();
|
||||
|
||||
main (argc, argv)
|
||||
char **argv;
|
||||
int argc;
|
||||
{
|
||||
int c;
|
||||
extern int optind;
|
||||
struct file_entry *p;
|
||||
int i;
|
||||
|
||||
strip_symbols = 0; /* default is to strip everything. */
|
||||
discard_locals = 0;
|
||||
|
||||
while ((c = getopt (argc, argv, "sSxX")) != EOF)
|
||||
switch (c)
|
||||
{
|
||||
case 's':
|
||||
strip_symbols = 1;
|
||||
break;
|
||||
case 'S':
|
||||
strip_symbols = 2;
|
||||
break;
|
||||
case 'x':
|
||||
discard_locals = 2;
|
||||
break;
|
||||
case 'X':
|
||||
discard_locals = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Default is to strip all symbols. */
|
||||
if (strip_symbols == 0 && discard_locals == 0)
|
||||
strip_symbols = 1;
|
||||
|
||||
number_of_files = argc - optind;
|
||||
|
||||
if (!number_of_files)
|
||||
fatal ("no files specified", 0);
|
||||
|
||||
p = file_table
|
||||
= (struct file_entry *) xmalloc (number_of_files * sizeof (struct file_entry));
|
||||
|
||||
/* Now fill in file_table */
|
||||
|
||||
for (i = 0; i < number_of_files; i++)
|
||||
{
|
||||
p->filename = argv[i + optind];
|
||||
p->symbols_and_strings = 0;
|
||||
p++;
|
||||
}
|
||||
|
||||
for (i = 0; i < number_of_files; i++)
|
||||
strip_file (&file_table[i]);
|
||||
}
|
||||
|
||||
/* process one input file */
|
||||
|
||||
void
|
||||
strip_file (entry)
|
||||
struct file_entry *entry;
|
||||
{
|
||||
int val;
|
||||
|
||||
local_sym_count = 0;
|
||||
non_L_local_sym_count = 0;
|
||||
debugger_sym_count = 0;
|
||||
global_sym_count = 0;
|
||||
|
||||
val = file_open (entry);
|
||||
if (val < 0)
|
||||
return;
|
||||
|
||||
if (strip_symbols != 1)
|
||||
/* Read in the existing symbols unless we are discarding everything. */
|
||||
{
|
||||
if (read_file_symbols (entry) < 0)
|
||||
return;
|
||||
}
|
||||
|
||||
rewrite_file_symbols (entry);
|
||||
if (strip_symbols != 1)
|
||||
free (entry->symbols_and_strings);
|
||||
|
||||
file_close ();
|
||||
}
|
||||
|
||||
/** Convenient functions for operating on one or all files being processed. */
|
||||
|
||||
/* Close the file that is now open. */
|
||||
|
||||
void
|
||||
file_close ()
|
||||
{
|
||||
close (input_desc);
|
||||
input_desc = 0;
|
||||
}
|
||||
|
||||
/* Open the file specified by 'entry', and return a descriptor.
|
||||
The descriptor is also saved in input_desc. */
|
||||
|
||||
/* JF this also makes sure the file is in rel format */
|
||||
|
||||
int
|
||||
file_open (entry)
|
||||
struct file_entry *entry;
|
||||
{
|
||||
int desc;
|
||||
int len, magicnum;
|
||||
|
||||
desc = open (entry->filename, O_RDWR, 0);
|
||||
|
||||
if (desc > 0)
|
||||
{
|
||||
input_desc = desc;
|
||||
#ifdef HEADER_SEEK_FD
|
||||
/* Skip the headers that encapsulate our data in some other format
|
||||
such as COFF. */
|
||||
HEADER_SEEK_FD (desc);
|
||||
#endif
|
||||
len = read (input_desc, (char *)&magicnum, sizeof magicnum);
|
||||
if (len != sizeof magicnum)
|
||||
{
|
||||
error_with_file ("failure reading header", entry);
|
||||
return -1;
|
||||
}
|
||||
if (N_BADMAG (*((struct exec *)&magicnum)))
|
||||
{
|
||||
error_with_file ("malformed input file (not an object file)", entry);
|
||||
return -1;
|
||||
}
|
||||
if (read_header (desc, &entry->header, entry) < 0)
|
||||
return -1;
|
||||
return desc;
|
||||
}
|
||||
|
||||
perror_file (entry);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Print the filename of ENTRY on OUTFILE (a stdio stream), then a newline. */
|
||||
|
||||
prline_file_name (entry, outfile)
|
||||
struct file_entry *entry;
|
||||
FILE *outfile;
|
||||
{
|
||||
print_file_name (entry, outfile);
|
||||
fprintf (outfile, "\n");
|
||||
}
|
||||
|
||||
/* Print the filename of ENTRY on OUTFILE (a stdio stream). */
|
||||
|
||||
print_file_name (entry, outfile)
|
||||
struct file_entry *entry;
|
||||
FILE *outfile;
|
||||
{
|
||||
fprintf (outfile, "%s", entry->filename);
|
||||
}
|
||||
|
||||
/* Validate file ENTRY and read its symbol and string sections into core. */
|
||||
|
||||
int
|
||||
read_file_symbols (entry)
|
||||
struct file_entry *entry;
|
||||
{
|
||||
if (read_entry_symbols (input_desc, entry) < 0)
|
||||
return -1;
|
||||
count_file_symbols (entry);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Read a file's header into the proper place in the file_entry.
|
||||
Return -1 on failure. */
|
||||
|
||||
int
|
||||
read_header (desc, loc, entry)
|
||||
int desc;
|
||||
struct exec *loc;
|
||||
struct file_entry *entry;
|
||||
{
|
||||
int len;
|
||||
lseek (desc, 0, 0);
|
||||
#ifdef HEADER_SEEK_FD
|
||||
/* Skip the headers that encapsulate our data in some other format
|
||||
such as COFF. */
|
||||
HEADER_SEEK_FD (desc);
|
||||
#endif
|
||||
len = read (desc, loc, sizeof (struct exec));
|
||||
if (len != sizeof (struct exec))
|
||||
{
|
||||
error_with_file ("failure reading header", entry);
|
||||
return -1;
|
||||
}
|
||||
if (N_BADMAG (*loc))
|
||||
{
|
||||
error_with_file ("bad magic number", entry);
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Read the symbols and strings of file ENTRY into core.
|
||||
Assume it is already open, on descriptor DESC.
|
||||
Return -1 on failure. */
|
||||
|
||||
int
|
||||
read_entry_symbols (desc, entry)
|
||||
struct file_entry *entry;
|
||||
int desc;
|
||||
{
|
||||
int string_size;
|
||||
|
||||
lseek (desc, N_STROFF (entry->header), 0);
|
||||
if (sizeof string_size != read (desc, &string_size, sizeof string_size))
|
||||
{
|
||||
error_with_file ("bad string table", entry);
|
||||
return -1;
|
||||
}
|
||||
|
||||
entry->ss_size = string_size + entry->header.a_syms;
|
||||
entry->symbols_and_strings = (struct nlist *) xmalloc (entry->ss_size);
|
||||
|
||||
lseek (desc, N_SYMOFF (entry->header), 0);
|
||||
if (entry->ss_size != read (desc, entry->symbols_and_strings, entry->ss_size))
|
||||
{
|
||||
error_with_file ("premature end of file in symbols/strings", entry);
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* Count the number of symbols of various categories in the file of ENTRY. */
|
||||
|
||||
void
|
||||
count_file_symbols (entry)
|
||||
struct file_entry *entry;
|
||||
{
|
||||
struct nlist *p, *end = entry->symbols_and_strings + entry->header.a_syms / sizeof (struct nlist);
|
||||
char *name_base = entry->header.a_syms + (char *) entry->symbols_and_strings;
|
||||
|
||||
for (p = entry->symbols_and_strings; p < end; p++)
|
||||
if (p->n_type & N_EXT)
|
||||
global_sym_count++;
|
||||
else if (p->n_un.n_strx && !(p->n_type & (N_STAB | N_EXT)))
|
||||
{
|
||||
if ((p->n_un.n_strx + name_base)[0] != 'L')
|
||||
non_L_local_sym_count++;
|
||||
local_sym_count++;
|
||||
}
|
||||
else debugger_sym_count++;
|
||||
}
|
||||
|
||||
void write_file_syms (), modify_relocation ();
|
||||
|
||||
/* Total size of string table strings allocated so far */
|
||||
int strtab_size;
|
||||
|
||||
/* Vector whose elements are the strings to go in the string table */
|
||||
char **strtab_vector;
|
||||
|
||||
/* Index in strtab_vector at which the next string will be stored */
|
||||
int strtab_index;
|
||||
|
||||
int sym_written_count;
|
||||
|
||||
int
|
||||
assign_string_table_index (name)
|
||||
char *name;
|
||||
{
|
||||
int index = strtab_size;
|
||||
|
||||
strtab_size += strlen (name) + 1;
|
||||
strtab_vector[strtab_index++] = name;
|
||||
|
||||
return index;
|
||||
}
|
||||
|
||||
void
|
||||
rewrite_file_symbols (entry)
|
||||
struct file_entry *entry;
|
||||
{
|
||||
int i;
|
||||
struct nlist *newsyms;
|
||||
|
||||
/* Calculate number of symbols to be preserved. */
|
||||
|
||||
if (strip_symbols == 1)
|
||||
nsyms = 0;
|
||||
else
|
||||
{
|
||||
nsyms = global_sym_count;
|
||||
if (discard_locals == 1)
|
||||
nsyms += non_L_local_sym_count;
|
||||
else if (discard_locals == 0)
|
||||
nsyms += local_sym_count;
|
||||
}
|
||||
|
||||
if (strip_symbols == 0)
|
||||
nsyms += debugger_sym_count;
|
||||
|
||||
strtab_vector = (char **) xmalloc (nsyms * sizeof (char *));
|
||||
strtab_index = 0;
|
||||
|
||||
strtab_size = 4;
|
||||
|
||||
/* Accumulate in 'newsyms' the symbol table to be written. */
|
||||
|
||||
newsyms = (struct nlist *) xmalloc (nsyms * sizeof (struct nlist));
|
||||
|
||||
sym_written_count = 0;
|
||||
|
||||
if (strip_symbols != 1)
|
||||
/* Write into newsyms the symbols we want to keep. */
|
||||
write_file_syms (entry, newsyms);
|
||||
|
||||
if (sym_written_count != nsyms)
|
||||
{
|
||||
fprintf (stderr, "written = %d, expected = %d\n",
|
||||
sym_written_count, nsyms);
|
||||
abort ();
|
||||
}
|
||||
|
||||
/* Modify the symbol-numbers in the relocation in the file,
|
||||
to preserve its meaning */
|
||||
modify_relocation (input_desc, entry);
|
||||
|
||||
#ifndef HAVE_FTRUNCATE
|
||||
{
|
||||
int size = N_SYMOFF (entry->header), mode;
|
||||
char *renamed = (char *)concat ("~", entry->filename, "~");
|
||||
char *copy_buffer = (char *)xmalloc (size);
|
||||
struct stat statbuf;
|
||||
|
||||
lseek (input_desc, 0, 0);
|
||||
if (read (input_desc, copy_buffer, size) != size)
|
||||
{
|
||||
error_with_file ("can't read up to symbol table", entry);
|
||||
return;
|
||||
}
|
||||
mode = fstat (input_desc, &statbuf) ? 0666 : statbuf.st_mode;
|
||||
if (rename (entry->filename, renamed))
|
||||
{
|
||||
perror_file (entry);
|
||||
return;
|
||||
}
|
||||
input_desc = creat (entry->filename, mode);
|
||||
if (input_desc < 0)
|
||||
{
|
||||
perror_file (entry);
|
||||
return;
|
||||
}
|
||||
if (write (input_desc, copy_buffer, size) != size)
|
||||
perror_file (entry);
|
||||
if (unlink (renamed))
|
||||
perror_name (renamed);
|
||||
free (copy_buffer);
|
||||
free (renamed);
|
||||
}
|
||||
#endif /* not HAVE_FTRUNCATE */
|
||||
|
||||
/* Now write contents of NEWSYMS into the file. */
|
||||
|
||||
lseek (input_desc, N_SYMOFF (entry->header), 0);
|
||||
write (input_desc, newsyms, nsyms * sizeof (struct nlist));
|
||||
free (newsyms);
|
||||
|
||||
/* Now write the string table. */
|
||||
|
||||
{
|
||||
char *strvec = (char *) xmalloc (strtab_size);
|
||||
char *p;
|
||||
|
||||
*((long *) strvec) = strtab_size;
|
||||
|
||||
p = strvec + sizeof (long);
|
||||
|
||||
for (i = 0; i < strtab_index; i++)
|
||||
{
|
||||
int len = strlen (strtab_vector[i]);
|
||||
strcpy (p, strtab_vector[i]);
|
||||
*(p+len) = 0;
|
||||
p += len + 1;
|
||||
}
|
||||
|
||||
write (input_desc, strvec, strtab_size);
|
||||
free (strvec);
|
||||
}
|
||||
|
||||
/* Adjust file to be smaller */
|
||||
|
||||
#ifdef HAVE_FTRUNCATE
|
||||
if (ftruncate (input_desc, tell (input_desc)) < 0)
|
||||
perror_file (entry);
|
||||
#endif
|
||||
|
||||
/* Write new symbol table size into file header. */
|
||||
|
||||
entry->header.a_syms = nsyms * sizeof (struct nlist);
|
||||
|
||||
lseek (input_desc, 0, 0);
|
||||
write (input_desc, &entry->header, sizeof (struct exec));
|
||||
|
||||
free (strtab_vector);
|
||||
}
|
||||
|
||||
/* Copy into NEWSYMS the symbol entries to be preserved.
|
||||
Count them in sym_written_count. */
|
||||
|
||||
/* We record, for each symbol written, its symbol number in the resulting file.
|
||||
This is so that the relocation can be updated later.
|
||||
Since the symbol names will not be needed again,
|
||||
this index goes in the `n_strx' field.
|
||||
If a symbol is not written, -1 is stored there. */
|
||||
|
||||
void
|
||||
write_file_syms (entry, newsyms)
|
||||
struct file_entry *entry;
|
||||
struct nlist *newsyms;
|
||||
{
|
||||
struct nlist *p = entry->symbols_and_strings;
|
||||
struct nlist *end = p + entry->header.a_syms / sizeof (struct nlist);
|
||||
char *string_base = (char *) end; /* address of start of file's string table */
|
||||
struct nlist *outp = newsyms;
|
||||
|
||||
for (; p < end; p++)
|
||||
{
|
||||
int type = p->n_type;
|
||||
int write;
|
||||
|
||||
if (p->n_type & N_EXT)
|
||||
write = 1;
|
||||
else if (p->n_un.n_strx && !(p->n_type & (N_STAB | N_EXT)))
|
||||
/* ordinary local symbol */
|
||||
write = (discard_locals != 2)
|
||||
&& !(discard_locals == 1 &&
|
||||
(p->n_un.n_strx + string_base)[0] == 'L');
|
||||
else
|
||||
/* debugger symbol */
|
||||
write = (strip_symbols == 0);
|
||||
|
||||
if (write)
|
||||
{
|
||||
if (p->n_un.n_strx)
|
||||
p->n_un.n_strx = assign_string_table_index (p->n_un.n_strx + string_base);
|
||||
|
||||
*outp++ = *p;
|
||||
|
||||
p->n_un.n_strx = sym_written_count++;
|
||||
}
|
||||
else p->n_un.n_strx = -1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Read in ENTRY's relocation, alter the symbolnums in it,
|
||||
and write it out again. */
|
||||
|
||||
void
|
||||
modify_relocation (desc, entry)
|
||||
int desc;
|
||||
struct file_entry *entry;
|
||||
{
|
||||
struct relocation_info *reloc, *p, *end;
|
||||
int size = entry->header.a_trsize + entry->header.a_drsize;
|
||||
struct nlist *sym_base = (struct nlist *) entry->symbols_and_strings;
|
||||
int losing = 0;
|
||||
|
||||
reloc = (struct relocation_info *) xmalloc (size);
|
||||
lseek (desc, N_TXTOFF (entry->header) + entry->header.a_text + entry->header.a_data, 0);
|
||||
read (desc, reloc, size);
|
||||
|
||||
p = reloc;
|
||||
end = (struct relocation_info *) (size + (char *) reloc);
|
||||
while (p < end)
|
||||
{
|
||||
if (p->r_extern)
|
||||
{
|
||||
int newnum = (sym_base == 0 ? -1
|
||||
:(sym_base + p->r_symbolnum) -> n_un.n_strx);
|
||||
if (newnum < 0)
|
||||
{
|
||||
if (losing == 0)
|
||||
error_with_file ("warning: file is now unlinkable", entry);
|
||||
losing = 1;
|
||||
}
|
||||
p->r_symbolnum = newnum;
|
||||
}
|
||||
p++;
|
||||
}
|
||||
|
||||
lseek (desc, N_TXTOFF (entry->header) + entry->header.a_text + entry->header.a_data, 0);
|
||||
write (desc, reloc, size);
|
||||
}
|
||||
|
||||
/* Report a fatal error.
|
||||
STRING is a printf format string and ARG is one arg for it. */
|
||||
|
||||
fatal (string, arg)
|
||||
char *string, *arg;
|
||||
{
|
||||
fprintf (stderr, "strip: ");
|
||||
fprintf (stderr, string, arg);
|
||||
fprintf (stderr, "\n");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
/* Report an error using the message for the last failed system call,
|
||||
followed by the string NAME. */
|
||||
|
||||
perror_name (name)
|
||||
char *name;
|
||||
{
|
||||
extern int errno, sys_nerr;
|
||||
extern char *sys_errlist[];
|
||||
char *s;
|
||||
|
||||
if (errno < sys_nerr)
|
||||
s = concat ("", sys_errlist[errno], " for %s");
|
||||
else
|
||||
s = "cannot open %s";
|
||||
error (s, name);
|
||||
}
|
||||
|
||||
/* Report an error using the message for the last failed system call,
|
||||
followed by the name of file ENTRY. */
|
||||
|
||||
perror_file (entry)
|
||||
struct file_entry *entry;
|
||||
{
|
||||
extern int errno, sys_nerr;
|
||||
extern char *sys_errlist[];
|
||||
char *s;
|
||||
|
||||
if (errno < sys_nerr)
|
||||
s = sys_errlist[errno];
|
||||
else
|
||||
s = "cannot open";
|
||||
error_with_file (s, entry);
|
||||
}
|
||||
|
||||
/* Report an error. STRING is printed, and the filename of ENTRY. */
|
||||
|
||||
error_with_file (string, entry, arg1, arg2)
|
||||
char *string;
|
||||
struct file_entry *entry;
|
||||
int arg1, arg2;
|
||||
{
|
||||
fprintf (stderr, "strip: ");
|
||||
print_file_name (entry, stderr);
|
||||
fprintf (stderr, ": ");
|
||||
fprintf (stderr, string, arg1, arg2);
|
||||
fprintf (stderr, "\n");
|
||||
}
|
||||
|
||||
/* Report a nonfatal error.
|
||||
STRING is a format for printf, and ARG1 ... ARG3 are args for it. */
|
||||
|
||||
error (string, arg1, arg2, arg3)
|
||||
char *string, *arg1, *arg2, *arg3;
|
||||
{
|
||||
fprintf (stderr, string, arg1, arg2, arg3);
|
||||
fprintf (stderr, "\n");
|
||||
}
|
||||
|
||||
/* Return a newly-allocated string whose contents
|
||||
concatenate those of S1, S2, S3. */
|
||||
|
||||
char *
|
||||
concat (s1, s2, s3)
|
||||
char *s1, *s2, *s3;
|
||||
{
|
||||
int len1 = strlen (s1), len2 = strlen (s2), len3 = strlen (s3);
|
||||
char *result = (char *) xmalloc (len1 + len2 + len3 + 1);
|
||||
|
||||
strcpy (result, s1);
|
||||
strcpy (result + len1, s2);
|
||||
strcpy (result + len1 + len2, s3);
|
||||
*(result + len1 + len2 + len3) = 0;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/* Like malloc but get fatal error if memory is exhausted. */
|
||||
|
||||
int
|
||||
xmalloc (size)
|
||||
int size;
|
||||
{
|
||||
int result = malloc (size);
|
||||
if (!result)
|
||||
fatal ("virtual memory exhausted", 0);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
#ifdef USG
|
||||
rename (from, to)
|
||||
char *from, *to;
|
||||
{
|
||||
if (unlink (to) < 0
|
||||
|| link (from, to) < 0
|
||||
|| unlink (from) < 0)
|
||||
return -1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
477
gnu/binutils/binutils.001/binutils/symseg.h
Normal file
477
gnu/binutils/binutils.001/binutils/symseg.h
Normal file
@@ -0,0 +1,477 @@
|
||||
/* GDB symbol table format definitions.
|
||||
Copyright (C) 1986 Free Software Foundation, Inc.
|
||||
Hacked by Michael Tiemann (tiemann@mcc.com)
|
||||
|
||||
GDB is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY. No author or distributor accepts responsibility to anyone
|
||||
for the consequences of using it or for whether it serves any
|
||||
particular purpose or works at all, unless he says so in writing.
|
||||
Refer to the GDB General Public License for full details.
|
||||
|
||||
Everyone is granted permission to copy, modify and redistribute GDB,
|
||||
but only under the conditions described in the GDB General Public
|
||||
License. A copy of this license is supposed to have been given to you
|
||||
along with GDB so you can know your rights and responsibilities. It
|
||||
should be in a file named COPYING. Among other things, the copyright
|
||||
notice and this notice must be preserved on all copies.
|
||||
|
||||
In other words, go ahead and share GDB, but don't try to stop
|
||||
anyone else from sharing it farther. Help stamp out software hoarding!
|
||||
*/
|
||||
|
||||
/* Format of GDB symbol table data.
|
||||
There is one symbol segment for each source file or
|
||||
independant compilation. These segments are simply concatenated
|
||||
to form the GDB symbol table. A zero word where the beginning
|
||||
of a segment is expected indicates there are no more segments.
|
||||
|
||||
Format of a symbol segment:
|
||||
|
||||
The symbol segment begins with a word containing 1
|
||||
if it is in the format described here. Other formats may
|
||||
be designed, with other code numbers.
|
||||
|
||||
The segment contains many objects which point at each other.
|
||||
The pointers are offsets in bytes from the beginning of the segment.
|
||||
Thus, each segment can be loaded into core and its pointers relocated
|
||||
to make valid in-core pointers.
|
||||
|
||||
All the data objects in the segment can be found indirectly from
|
||||
one of them, the root object, of type `struct symbol_root'.
|
||||
It appears at the beginning of the segment.
|
||||
|
||||
The total size of the segment, in bytes, appears as the `length'
|
||||
field of this object. This size includes the size of the
|
||||
root object.
|
||||
|
||||
All the object data types are defined here to contain pointer types
|
||||
appropriate for in-core use on a relocated symbol segment.
|
||||
Casts to and from type int are required for working with
|
||||
unrelocated symbol segments such as are found in the file.
|
||||
|
||||
The ldsymaddr word is filled in by the loader to contain
|
||||
the offset (in bytes) within the ld symbol table
|
||||
of the first nonglobal symbol from this compilation.
|
||||
This makes it possible to match those symbols
|
||||
(which contain line number information) reliably with
|
||||
the segment they go with.
|
||||
|
||||
Core addresses within the program that appear in the symbol segment
|
||||
are not relocated by the loader. They are inserted by the assembler
|
||||
and apply to addresses as output by the assembler, so GDB must
|
||||
relocate them when it loads the symbol segment. It gets the information
|
||||
on how to relocate from the textrel, datarel, bssrel, databeg and bssbeg
|
||||
words of the root object.
|
||||
|
||||
The words textrel, datarel and bssrel
|
||||
are filled in by ld with the amounts to relocate within-the-file
|
||||
text, data and bss addresses by; databeg and bssbeg can be
|
||||
used to tell which kind of relocation an address needs. */
|
||||
|
||||
enum language {language_c};
|
||||
|
||||
struct symbol_root
|
||||
{
|
||||
int format; /* Data format version */
|
||||
int length; /* # bytes in this symbol segment */
|
||||
int ldsymoff; /* Offset in ld symtab of this file's syms */
|
||||
int textrel; /* Relocation for text addresses */
|
||||
int datarel; /* Relocation for data addresses */
|
||||
int bssrel; /* Relocation for bss addresses */
|
||||
char *filename; /* Name of main source file compiled */
|
||||
char *filedir; /* Name of directory it was reached from */
|
||||
struct blockvector *blockvector; /* Vector of all symbol-naming blocks */
|
||||
struct typevector *typevector; /* Vector of all data types */
|
||||
enum language language; /* Code identifying the language used */
|
||||
char *version; /* Version info. Not fully specified */
|
||||
char *compilation; /* Compilation info. Not fully specified */
|
||||
int databeg; /* Address within the file of data start */
|
||||
int bssbeg; /* Address within the file of bss start */
|
||||
struct sourcevector *sourcevector; /* Vector of line-number info */
|
||||
};
|
||||
|
||||
/* All data types of symbols in the compiled program
|
||||
are represented by `struct type' objects.
|
||||
All of these objects are pointed to by the typevector.
|
||||
The type vector may have empty slots that contain zero. */
|
||||
|
||||
struct typevector
|
||||
{
|
||||
int length; /* Number of types described */
|
||||
struct type *type[1];
|
||||
};
|
||||
|
||||
/* Different kinds of data types are distinguished by the `code' field. */
|
||||
|
||||
enum type_code
|
||||
{
|
||||
TYPE_CODE_UNDEF, /* Not used; catches errors */
|
||||
TYPE_CODE_PTR, /* Pointer type */
|
||||
TYPE_CODE_ARRAY, /* Array type, lower bound zero */
|
||||
TYPE_CODE_STRUCT, /* C struct or Pascal record */
|
||||
TYPE_CODE_UNION, /* C union or Pascal variant part */
|
||||
TYPE_CODE_ENUM, /* Enumeration type */
|
||||
TYPE_CODE_FUNC, /* Function type */
|
||||
TYPE_CODE_INT, /* Integer type */
|
||||
TYPE_CODE_FLT, /* Floating type */
|
||||
TYPE_CODE_VOID, /* Void type (values zero length) */
|
||||
TYPE_CODE_SET, /* Pascal sets */
|
||||
TYPE_CODE_RANGE, /* Range (integers within spec'd bounds) */
|
||||
TYPE_CODE_PASCAL_ARRAY, /* Array with explicit type of index */
|
||||
|
||||
/* C++ */
|
||||
TYPE_CODE_MEMBER, /* Member type */
|
||||
TYPE_CODE_REF, /* C++ Reference types */
|
||||
};
|
||||
|
||||
/* This appears in a type's flags word for an unsigned integer type. */
|
||||
#define TYPE_FLAG_UNSIGNED 1
|
||||
|
||||
/* Other flag bits are used with GDB. */
|
||||
|
||||
#define TYPE_FLAG_HAS_CONSTRUCTOR 256
|
||||
#define TYPE_FLAG_HAS_DESTRUCTOR 512
|
||||
#define TYPE_FLAG_VIA_PUBLIC 1024
|
||||
#define TYPE_FLAG_VIA_VIRTUAL 2048
|
||||
|
||||
struct type
|
||||
{
|
||||
/* Code for kind of type */
|
||||
enum type_code code;
|
||||
/* Name of this type, or zero if none.
|
||||
This is used for printing only.
|
||||
Type names specified as input are defined by symbols. */
|
||||
char *name;
|
||||
/* Length in bytes of storage for a value of this type */
|
||||
int length;
|
||||
/* For a pointer type, describes the type of object pointed to.
|
||||
For an array type, describes the type of the elements.
|
||||
For a function type, describes the type of the value.
|
||||
Unused otherwise. */
|
||||
struct type *target_type;
|
||||
/* Type that is a pointer to this type.
|
||||
Zero if no such pointer-to type is known yet.
|
||||
The debugger may add the address of such a type
|
||||
if it has to construct one later. */
|
||||
struct type *pointer_type;
|
||||
/* C++: also need a reference type. */
|
||||
struct type *reference_type;
|
||||
/* Type that is a function returning this type.
|
||||
Zero if no such function type is known here.
|
||||
The debugger may add the address of such a type
|
||||
if it has to construct one later. */
|
||||
struct type *function_type;
|
||||
|
||||
/* Handling of pointers to members:
|
||||
TYPE_MAIN_VARIANT is used for pointer and pointer
|
||||
to member types. Normally it the value of the address of its
|
||||
containing type. However, for pointers to members, we must be
|
||||
able to allocate pointer to member types and look them up
|
||||
from some place of reference.
|
||||
NEXT_VARIANT is the next element in the chain. */
|
||||
struct type *main_variant, *next_variant;
|
||||
|
||||
/* Flags about this type. */
|
||||
short flags;
|
||||
/* Number of fields described for this type */
|
||||
short nfields;
|
||||
/* For structure and union types, a description of each field.
|
||||
For set and pascal array types, there is one "field",
|
||||
whose type is the domain type of the set or array.
|
||||
For range types, there are two "fields",
|
||||
the minimum and maximum values (both inclusive).
|
||||
For enum types, each possible value is described by one "field".
|
||||
For range types, there are two "fields", that record constant values
|
||||
(inclusive) for the minimum and maximum.
|
||||
|
||||
Using a pointer to a separate array of fields
|
||||
allows all types to have the same size, which is useful
|
||||
because we can allocate the space for a type before
|
||||
we know what to put in it. */
|
||||
struct field
|
||||
{
|
||||
/* Position of this field, counting in bits from start of
|
||||
containing structure. For a function type, this is the
|
||||
position in the argument list of this argument.
|
||||
For a range bound or enum value, this is the value itself. */
|
||||
int bitpos;
|
||||
/* Size of this field, in bits, or zero if not packed.
|
||||
For an unpacked field, the field's type's length
|
||||
says how many bytes the field occupies. */
|
||||
int bitsize;
|
||||
/* In a struct or enum type, type of this field.
|
||||
In a function type, type of this argument.
|
||||
In an array type, the domain-type of the array. */
|
||||
struct type *type;
|
||||
/* Name of field, value or argument.
|
||||
Zero for range bounds and array domains. */
|
||||
char *name;
|
||||
} *fields;
|
||||
|
||||
/* C++ */
|
||||
int *private_field_bits;
|
||||
int *protected_field_bits;
|
||||
|
||||
/* Number of methods described for this type */
|
||||
short nfn_fields;
|
||||
/* Number of base classes this type derives from. */
|
||||
short n_baseclasses;
|
||||
|
||||
/* Number of methods described for this type plus all the
|
||||
methods that it derives from. */
|
||||
int nfn_fields_total;
|
||||
|
||||
/* For classes, structures, and unions, a description of each field,
|
||||
which consists of an overloaded name, followed by the types of
|
||||
arguments that the method expects, and then the name after it
|
||||
has been renamed to make it distinct. */
|
||||
struct fn_fieldlist
|
||||
{
|
||||
/* The overloaded name. */
|
||||
char *name;
|
||||
/* The number of methods with this name. */
|
||||
int length;
|
||||
/* The list of methods. */
|
||||
struct fn_field
|
||||
{
|
||||
#if 0
|
||||
/* The overloaded name */
|
||||
char *name;
|
||||
#endif
|
||||
/* The type of the argument */
|
||||
struct type *type;
|
||||
/* The argument list */
|
||||
struct type **args;
|
||||
/* The name after it has been processed */
|
||||
char *physname;
|
||||
/* If this is a virtual function, the offset into the vtbl-1,
|
||||
else 0. */
|
||||
int voffset;
|
||||
} *fn_fields;
|
||||
|
||||
int *private_fn_field_bits;
|
||||
int *protected_fn_field_bits;
|
||||
|
||||
} *fn_fieldlists;
|
||||
|
||||
unsigned char via_protected;
|
||||
unsigned char via_public;
|
||||
|
||||
/* For types with virtual functions, VPTR_BASETYPE is the base class which
|
||||
defined the virtual function table pointer. VPTR_FIELDNO is
|
||||
the field number of that pointer in the structure.
|
||||
|
||||
For types that are pointer to member types, VPTR_BASETYPE
|
||||
ifs the type that this pointer is a member of.
|
||||
|
||||
Unused otherwise. */
|
||||
struct type *vptr_basetype;
|
||||
|
||||
int vptr_fieldno;
|
||||
|
||||
/* If this type has a base class, put it here.
|
||||
If this type is a pointer type, the chain of member pointer
|
||||
types goes here.
|
||||
Unused otherwise. */
|
||||
struct type **baseclasses;
|
||||
};
|
||||
|
||||
/* All of the name-scope contours of the program
|
||||
are represented by `struct block' objects.
|
||||
All of these objects are pointed to by the blockvector.
|
||||
|
||||
Each block represents one name scope.
|
||||
Each lexical context has its own block.
|
||||
|
||||
The first two blocks in the blockvector are special.
|
||||
The first one contains all the symbols defined in this compilation
|
||||
whose scope is the entire program linked together.
|
||||
The second one contains all the symbols whose scope is the
|
||||
entire compilation excluding other separate compilations.
|
||||
In C, these correspond to global symbols and static symbols.
|
||||
|
||||
Each block records a range of core addresses for the code that
|
||||
is in the scope of the block. The first two special blocks
|
||||
give, for the range of code, the entire range of code produced
|
||||
by the compilation that the symbol segment belongs to.
|
||||
|
||||
The blocks appear in the blockvector
|
||||
in order of increasing starting-address,
|
||||
and, within that, in order of decreasing ending-address.
|
||||
|
||||
This implies that within the body of one function
|
||||
the blocks appear in the order of a depth-first tree walk. */
|
||||
|
||||
struct blockvector
|
||||
{
|
||||
/* Number of blocks in the list. */
|
||||
int nblocks;
|
||||
/* The blocks themselves. */
|
||||
struct block *block[1];
|
||||
};
|
||||
|
||||
struct block
|
||||
{
|
||||
/* Addresses in the executable code that are in this block.
|
||||
Note: in an unrelocated symbol segment in a file,
|
||||
these are always zero. They can be filled in from the
|
||||
N_LBRAC and N_RBRAC symbols in the loader symbol table. */
|
||||
int startaddr, endaddr;
|
||||
/* The symbol that names this block,
|
||||
if the block is the body of a function;
|
||||
otherwise, zero.
|
||||
Note: In an unrelocated symbol segment in an object file,
|
||||
this field may be zero even when the block has a name.
|
||||
That is because the block is output before the name
|
||||
(since the name resides in a higher block).
|
||||
Since the symbol does point to the block (as its value),
|
||||
it is possible to find the block and set its name properly. */
|
||||
struct symbol *function;
|
||||
/* The `struct block' for the containing block, or 0 if none. */
|
||||
/* Note that in an unrelocated symbol segment in an object file
|
||||
this pointer may be zero when the correct value should be
|
||||
the second special block (for symbols whose scope is one compilation).
|
||||
This is because the compiler ouptuts the special blocks at the
|
||||
very end, after the other blocks. */
|
||||
struct block *superblock;
|
||||
/* A flag indicating whether or not the fucntion corresponding
|
||||
to this block was compiled with gcc or not. If there is no
|
||||
function corresponding to this block, this meaning of this flag
|
||||
is undefined. (In practice it will be 1 if the block was created
|
||||
while processing a file compiled with gcc and 0 when not). */
|
||||
unsigned char gcc_compile_flag;
|
||||
/* Number of local symbols. */
|
||||
int nsyms;
|
||||
/* The symbols. */
|
||||
struct symbol *sym[1];
|
||||
};
|
||||
|
||||
/* Represent one symbol name; a variable, constant, function or typedef. */
|
||||
|
||||
/* Different name spaces for symbols. Looking up a symbol specifies
|
||||
a namespace and ignores symbol definitions in other name spaces.
|
||||
|
||||
VAR_NAMESPACE is the usual namespace.
|
||||
In C, this contains variables, function names, typedef names
|
||||
and enum type values.
|
||||
|
||||
STRUCT_NAMESPACE is used in C to hold struct, union and enum type names.
|
||||
Thus, if `struct foo' is used in a C program,
|
||||
it produces a symbol named `foo' in the STRUCT_NAMESPACE.
|
||||
|
||||
LABEL_NAMESPACE may be used for names of labels (for gotos);
|
||||
currently it is not used and labels are not recorded at all. */
|
||||
|
||||
/* For a non-global symbol allocated statically,
|
||||
the correct core address cannot be determined by the compiler.
|
||||
The compiler puts an index number into the symbol's value field.
|
||||
This index number can be matched with the "desc" field of
|
||||
an entry in the loader symbol table. */
|
||||
|
||||
enum namespace
|
||||
{
|
||||
UNDEF_NAMESPACE, VAR_NAMESPACE, STRUCT_NAMESPACE, LABEL_NAMESPACE,
|
||||
};
|
||||
|
||||
/* An address-class says where to find the value of the symbol in core. */
|
||||
|
||||
enum address_class
|
||||
{
|
||||
LOC_UNDEF, /* Not used; catches errors */
|
||||
LOC_CONST, /* Value is constant int */
|
||||
LOC_STATIC, /* Value is at fixed address */
|
||||
LOC_REGISTER, /* Value is in register */
|
||||
LOC_ARG, /* Value is at spec'd position in arglist */
|
||||
LOC_REGPARM, /* Value is at spec'd position in register window */
|
||||
LOC_LOCAL, /* Value is at spec'd pos in stack frame */
|
||||
LOC_TYPEDEF, /* Value not used; definition in SYMBOL_TYPE
|
||||
Symbols in the namespace STRUCT_NAMESPACE
|
||||
all have this class. */
|
||||
LOC_LABEL, /* Value is address in the code */
|
||||
LOC_BLOCK, /* Value is address of a `struct block'.
|
||||
Function names have this class. */
|
||||
LOC_EXTERNAL, /* Value is at address not in this compilation.
|
||||
This is used for .comm symbols
|
||||
and for extern symbols within functions.
|
||||
Inside GDB, this is changed to LOC_STATIC once the
|
||||
real address is obtained from a loader symbol. */
|
||||
LOC_CONST_BYTES /* Value is a constant byte-sequence. */
|
||||
};
|
||||
|
||||
struct symbol
|
||||
{
|
||||
/* Symbol name */
|
||||
char *name;
|
||||
/* Name space code. */
|
||||
enum namespace namespace;
|
||||
/* Address class */
|
||||
enum address_class class;
|
||||
/* Data type of value */
|
||||
struct type *type;
|
||||
/* constant value, or address if static, or register number,
|
||||
or offset in arguments, or offset in stack frame. */
|
||||
union
|
||||
{
|
||||
long value;
|
||||
struct block *block; /* for LOC_BLOCK */
|
||||
char *bytes; /* for LOC_CONST_BYTES */
|
||||
}
|
||||
value;
|
||||
};
|
||||
|
||||
struct partial_symbol
|
||||
{
|
||||
/* Symbol name */
|
||||
char *name;
|
||||
/* Name space code. */
|
||||
enum namespace namespace;
|
||||
/* Address class (for info_symbols) */
|
||||
enum address_class class;
|
||||
};
|
||||
|
||||
/*
|
||||
* Vectors of all partial symbols read in from file; actually declared
|
||||
* and used in dbxread.c.
|
||||
*/
|
||||
extern struct partial_symbol *global_psymbols, *static_psymbols;
|
||||
|
||||
|
||||
/* Source-file information.
|
||||
This describes the relation between source files and line numbers
|
||||
and addresses in the program text. */
|
||||
|
||||
struct sourcevector
|
||||
{
|
||||
int length; /* Number of source files described */
|
||||
struct source *source[1]; /* Descriptions of the files */
|
||||
};
|
||||
|
||||
/* Each item represents a line-->pc (or the reverse) mapping. This is
|
||||
somewhat more wasteful of space than one might wish, but since only
|
||||
the files which are actually debugged are read in to core, we don't
|
||||
waste much space.
|
||||
|
||||
Each item used to be an int; either minus a line number, or a
|
||||
program counter. If it represents a line number, that is the line
|
||||
described by the next program counter value. If it is positive, it
|
||||
is the program counter at which the code for the next line starts. */
|
||||
|
||||
struct linetable_entry
|
||||
{
|
||||
int line;
|
||||
CORE_ADDR pc;
|
||||
};
|
||||
|
||||
struct linetable
|
||||
{
|
||||
int nitems;
|
||||
struct linetable_entry item[1];
|
||||
};
|
||||
|
||||
/* All the information on one source file. */
|
||||
|
||||
struct source
|
||||
{
|
||||
char *name; /* Name of file */
|
||||
struct linetable contents;
|
||||
};
|
||||
Reference in New Issue
Block a user