Now full of documentation. Yum Yum.

This commit is contained in:
Steve Chamberlain
1991-07-04 16:52:56 +00:00
parent 985fca1293
commit 6f715d66ad
15 changed files with 4214 additions and 2518 deletions

View File

@ -28,7 +28,9 @@ echo Sanitizing `pwd`...
Things-to-keep:
COPYING
bfd.texinfo
ChangeLog
Makefile
Makefile.in
TODO
VERSION
@ -40,19 +42,17 @@ archive.c
archures.c
archures.h
bfd.c
bfd.doc
bout.c
cache.c
coffcode.h
coffish.h
coffswap.c
config
configure
config.status
configure*
configure.in
cplus-dem.c
core.c
demo64.c
ecoff.c
filemode.c
format.c
host-aout.c
i386coff.c
icoff.c
@ -65,12 +65,14 @@ libieee.h
liboasys.h
m68kcoff.c
m88k-bcs.c
misc.h
newsos3.c
oasys.c
opncls.c
reloc.c
section.c
srec.c
sunos.c
syms.c
targets.c
trad-core.c
trad-core.h
@ -82,6 +84,9 @@ echo Done in `pwd`.
#
#
# $Log$
# Revision 1.4 1991/07/04 16:52:54 steve
# Now full of documentation. Yum Yum.
#
# Revision 1.3 1991/05/31 11:22:12 gnu
# Remove coff-code.h and liba.out.h, add libaout.h.
#

View File

@ -20,6 +20,8 @@
# $Id$
srcdir = .
destdir = /usr/local
libdir = $(destdir)/lib
RANLIB = ranlib
AR = ar
@ -35,18 +37,21 @@ CFLAGS = -g $(HDEFINES) $(TDEFINES) $(CSEARCH) $(CSWITCHES) # -DINTEL960VERSION
BFD_LIBS = libbfd.o opncls.o bfd.o archive.o targets.o cache.o \
archures.o
archures.o core.o section.o format.o syms.o reloc.o
BFD_BACKENDS = oasys.o ieee.o srec.o aout64.o aout32.o sunos.o icoff.o demo64.o \
m68kcoff.o i386coff.o m88k-bcs.o coffswap.o ecoff.o newsos3.o # trad-core.o bout.o
BFD_BACKENDS = oasys.o ieee.o srec.o aout64.o aout32.o sunos.o icoff.o \
demo64.o \
m68kcoff.o i386coff.o m88k-bcs.o ecoff.o newsos3.o # trad-core.o bout.o
BFD_H=$(INCDIR)/bfd.h
SYSDEP_H=$(INCDIR)/sysdep.h
# C source files that correspond to .o's.
CFILES = libbfd.c opncls.c bfd.c archive.c targets.c cache.c archures.c \
i386coff.c aout64.c aout32.c sunos.c demo64.c icoff.c srec.c oasys.c ieee.c m68kcoff.c \
m88k-bcs.c coffswap.c ecoff.c trad-core.c newsos3.c #bout.c
i386coff.c aout64.c aout32.c sunos.c demo64.c icoff.c srec.c \
oasys.c ieee.c m68kcoff.c \
format.c section.c core.c syms.c reloc.c \
m88k-bcs.c ecoff.c trad-core.c newsos3.c #bout.c
STAGESTUFF = $(TARGETLIB) $(OFILES)
@ -149,6 +154,8 @@ roll:
force:
install:
install -c libbfd.a $(libdir)
$(RANLIB) $(libdir)/libbfd.a
# Target to uncomment host-specific lines in this makefile. Such lines must
# have the following string beginning in column 1: #__<hostname>__#
@ -181,3 +188,81 @@ Makefile: $(srcdir)/Makefile.in $(srcdir)/configure
dep: $(CFILES)
mkdep $(CFLAGS) $?
# Stuff to make the documentation for bfd.
#
# make docs
# rebuilds the documentation. Has to be done when the source is
# modified until I work out how to do this properly
#
# make docs headers
# rebuilds the header files from the source
#
# make docs texdoc
# rebuilds the bfd.dvi manual
#
# make docs texinfo
# rebuilts the bfdinfo manual
.SUFFIXES: .doc .o .c .h .proto
.c.doc:
makedoc <$< doc/$*.doc doc/$*.proto doc/$*.protointernal doc/$*.drop
.h.doc:
makedoc <$< doc/$*.doc doc/$*.proto doc/$*.protointernal doc/$*.drop
.proto.doc:
makedoc <$< doc/$*.doc doc/$*.proto doc/$*.protointernal doc/$*.drop
DSRC=$(CFILES)
docs: syms.doc bfd.doc cache.doc format.doc section.doc archive.doc \
core.doc libbfd.doc archures.doc reloc.doc opncls.doc \
targets.doc aoutx.doc coffcode.doc
PROTOS = doc/opncls.proto doc/archures.proto doc/libbfd.proto doc/section.proto doc/syms.proto doc/bfd.proto doc/archive.proto \
doc/reloc.proto doc/targets.proto doc/format.proto
headers : $(PROTOS)
mkdir -f doc
# Rebuild prototypes in bfd.h
sed <$(BFD_H) >bfd.h.new -e '1,/THE FOLLOWING/!d'
cat doc/opncls.proto doc/archures.proto \
doc/libbfd.proto doc/section.proto doc/syms.proto doc/bfd.proto doc/archive.proto \
doc/reloc.proto doc/targets.proto doc/format.proto >>bfd.h.new
echo >> bfd.h.new
echo "#endif" >> bfd.h.new
echo >> bfd.h.new
mv bfd.h.new $(BFD_H)
# and libbfd.h
sed < libbfd.h >libbfd.h.new -e '1,/THE FOLLOWING/!d'
cat doc/libbfd.protointernal doc/cache.protointernal doc/reloc.protointernal >> libbfd.h.new
echo >> libbfd.h.new
mv libbfd.h.new libbfd.h
# and libcoff.h
sed < $(srcdir)/libcoff.h >libcoff.h.new -e '1,/THE FOLLOWING/!d'
cat doc/coffcode.proto >>libcoff.h.new
mv libcoff.h.new $(srcdir)/libcoff.h
texinfo:
makeinfo +no-validate bfd.texinfo
texdoc:
tex bfd.texinfo
texindex bfd.??
tex bfd.texinfo
quickdoc: $(DSRC) docs
tex bfd.texinfo

View File

@ -1,5 +1,3 @@
/* BFD backend for generic a.out flavour 1 */
/* Copyright (C) 1990, 1991 Free Software Foundation, Inc.
This file is part of BFD, the Binary File Diddler.
@ -18,6 +16,7 @@ You should have received a copy of the GNU General Public License
along with BFD; see the file COPYING. If not, write to
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#include <ansidecl.h>
#include <sysdep.h>
struct external_exec;
@ -33,6 +32,33 @@ struct external_exec;
#include "ar.h"
/*
inheritd two core files and various implimentation files.
The file @code{aoutf1.h} contains the code for BFD's
a.out back end. Control over the generated back end is given by these
three preprocessor names:
@table @code
@item ARCH
This value should be either 32 or 64, depending upon the size of an
int in the target format. It changes the sizes of the structs which
perform the memory/disk mapping of structures.
The 64 bit backend may only be used if the host compiler supports 64
ints (eg with gcc), by defining the name @code{HOST_64_BIT}. With this
name defined, @emph{all} bfd operations are performed with 64bit
arithmetic, not just those to a 64bit target.
@item TARGETNAME
bit long longsIf bfd is being compiled with gcc, (or any other compiler which gives
64 bit long longs),
@item
It is structured in such a way that @code{#define}ing
the size of the architecture into a @code{#include}ing
it with different @code{#define}s present will alter the definitions
of various structures in include files and generate correct code for
th
*/
void (*bfd_error_trap)();
@ -177,7 +203,7 @@ DEFUN(NAME(aout,sunos4_write_object_contents),(abfd),
choose_reloc_size(abfd);
/* FIXME */
N_SET_FLAGS (*execp, 0x81);
N_SET_FLAGS (*execp, 0x1);
WRITE_HEADERS(abfd, execp);
@ -461,6 +487,16 @@ DEFUN(swapcore,(abfd, core),
#define aout_64_core_file_failing_signal sunos4_core_file_failing_signal
#define aout_64_core_file_matches_executable_p sunos4_core_file_matches_executable_p
#define aout_64_bfd_debug_info_start bfd_void
#define aout_64_bfd_debug_info_end bfd_void
#define aout_64_bfd_debug_info_accumulate bfd_void
#define aout_32_bfd_debug_info_start bfd_void
#define aout_32_bfd_debug_info_end bfd_void
#define aout_32_bfd_debug_info_accumulate bfd_void
/* We implement these routines ourselves, rather than using the generic
a.out versions. */
#define aout_write_object_contents sunos4_write_object_contents
@ -477,6 +513,7 @@ TARGETNAME,
(SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC), /* section flags */
' ', /* ar_pad_char */
16, /* ar_max_namelen */
3, /* minimum alignment power */
_do_getb64, _do_putb64, _do_getb32, _do_putb32, _do_getb16, _do_putb16, /* data */
_do_getb64, _do_putb64, _do_getb32, _do_putb32, _do_getb16, _do_putb16, /* hdrs */

View File

@ -20,13 +20,69 @@ along with BFD; see the file COPYING. If not, write to
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
/*doc*
@section a.out backends
BFD supports a number of different flavours of a.out format, though
the major differences are only the sizes of the structures on disk,
and the shape of the relocation information.
The support is split into a basic support file @code{aoutx.h} and
other files which derive functions from the base. One derivation file
is @code{aoutf1.h} (for a.out flavour 1), and adds to the basic a.out
functions support for sun3, sun4, 386 and 29k a.out files, to create a
target jump vector for a specific target.
This information is further split out into more specific files for each
machine, including @code{sunos.c} - for sun3 and sun4 and
@code{demo64} for a demonstration of a 64 bit a.out format.
The base file @code{aoutx.h} defines general mechanisms for reading
and writing records to and from disk, and various other methods which
bfd requires. It is included by @code{aout32.c} and @code{aout64.c} to
form the names aout_32_swap_exec_header_in,
aout_64_swap_exec_header_in, etc.
As an example, this is what goes on to make the back end for a sun4, from aout32.c
@example
#define ARCH_SIZE 32
#include "aoutx.h"
@end example
Which exports names:
@example
...
aout_32_canonicalize_reloc
aout_32_find_nearest_line
aout_32_get_lineno
aout_32_get_reloc_upper_bound
...
@end example
from sunos.c
@example
#define ARCH 32
#define TARGET_NAME "a.out-sunos-big"
#define VECNAME sunos_big_vec
#include "aoutf1.h"
@end example
requires all the names from aout32.c, and produces the jump vector
@example
sunos_big_vec
@end example
*/
#include <sysdep.h>
#include <ansidecl.h>
#include "bfd.h"
struct external_exec;
#include "liba.out.h"
#include "libaout.h"
#include "libbfd.h"
#include "aout64.h"
#include "stab.gnu.h"
@ -34,9 +90,15 @@ struct external_exec;
void (*bfd_error_trap)();
/*SUPPRESS558*/
/*SUPPRESS529*/
/*doc*
@subsection relocations
The file @code{aoutx.h} caters for both the @emph{standard} and
@emph{extended} forms of a.out relocation records.
The standard records are characterised by containing only an address,
a symbol index and a type field. The extended records (used on 29ks
and sparcs) also have a full integer for an addend.
*/
#define CTOR_TABLE_RELOC_IDX 2
static reloc_howto_type howto_table_ext[] =
{
@ -85,6 +147,24 @@ HOWTO( 7, 0, 3, 64, true, 0, false, true,0,"DISP64", true, 0xfeedfac
bfd_error_vector_type bfd_error_vector;
/*doc*
@subsection Internal Entry Points
@code{aoutx.h} exports several routines for accessing the contents of
an a.out file, which are gathered and exported in turn by various
format specific files (eg sunos.c).
*/
/*doc*
*i aout_<size>_swap_exec_header_in
Swaps the information in an executable header taken from a raw byte stream memory image,
into the internal exec_header structure.
*; PROTO(void, aout_<size>_swap_exec_header_in,
(bfd *abfd,
struct external_exec *raw_bytes,
struct internal_exec *execp));
*/
void
DEFUN(NAME(aout,swap_exec_header_in),(abfd, raw_bytes, execp),
bfd *abfd AND
@ -104,6 +184,15 @@ DEFUN(NAME(aout,swap_exec_header_in),(abfd, raw_bytes, execp),
execp->a_drsize = GET_WORD (abfd, bytes->e_drsize);
}
/*doc*
*i aout_<size>_swap_exec_header_out
Swaps the information in an internal exec header structure into the
supplied buffer ready for writing to disk.
*; PROTO(void, aout_<size>_swap_exec_header_out,
(bfd *abfd,
struct internal_exec *execp,
struct external_exec *raw_bytes));
*/
void
DEFUN(NAME(aout,swap_exec_header_out),(abfd, execp, raw_bytes),
bfd *abfd AND
@ -128,10 +217,19 @@ struct container {
struct internal_exec e;
};
/* Some A.OUT variant thinks that the file whose format we're checking
/*doc*
*i aout_<size>_some_aout_object_p
Some A.OUT variant thinks that the file whose format we're checking
is an a.out file. Do some more checking, and set up for access if
it really is. Call back to the calling environments "finish up"
function just before returning, to handle any last-minute setup. */
function just before returning, to handle any last-minute setup.
*; PROTO(bfd_target *, aout_<size>_some_aout_object_p,
(bfd *abfd,
bfd_target *(*callback_to_real_object_p)()));
*/
bfd_target *
DEFUN(NAME(aout,some_aout_object_p),(abfd, callback_to_real_object_p),
@ -282,6 +380,13 @@ DEFUN(NAME(aout,some_aout_object_p),(abfd, callback_to_real_object_p),
return (*callback_to_real_object_p)(abfd);
}
/*doc*
*i aout_<size>_mkobject
This routine initializes a bfd for use with a.out files.
*; PROTO(boolean, aout_<size>_mkobject, (bfd *));
*/
boolean
DEFUN(NAME(aout,mkobject),(abfd),
@ -314,12 +419,21 @@ DEFUN(NAME(aout,mkobject),(abfd),
return true;
}
/* Keep track of machine architecture and machine type for a.out's.
/*doc*
*i aout_<size>_machine_type
Keep track of machine architecture and machine type for a.out's.
Return the machine_type for a particular arch&machine, or M_UNKNOWN
if that exact arch&machine can't be represented in a.out format.
If the architecture is understood, machine type 0 (default) should
always be understood. */
always be understood.
*; PROTO(enum machine_type, aout_<size>_machine_type,
(enum bfd_architecture arch,
unsigned long machine));
*/
enum machine_type
DEFUN(NAME(aout,machine_type),(arch, machine),
@ -360,6 +474,19 @@ DEFUN(NAME(aout,machine_type),(arch, machine),
return arch_flags;
}
/*doc*
*i aout_<size>_set_arch_mach
Sets the architecture and the machine of the bfd to those values
supplied. Verifies that the format can support the architecture
required.
*; PROTO(boolean, aout_<size>_set_arch_mach,
(bfd *,
enum bfd_architecture,
unsigned long machine));
*/
boolean
DEFUN(NAME(aout,set_arch_mach),(abfd, arch, machine),
bfd *abfd AND
@ -373,9 +500,15 @@ DEFUN(NAME(aout,set_arch_mach),(abfd, arch, machine),
return false; /* We can't represent this type */
return true; /* We're easy ... */
}
/* exec and core file sections */
/*doc*
*i aout_<size>new_section_hook
Called by the bfd in response to a @code{bfd_make_section} request.
*; PROTO(boolean, aout_<size>_new_section_hook,
(bfd *abfd,
asection *newsect));
*/
boolean
DEFUN(NAME(aout,new_section_hook),(abfd, newsect),
bfd *abfd AND

View File

@ -1,6 +1,4 @@
/*** archive.c -- an attempt at combining the machine-independent parts of
archives */
/* Copyright (C) 1990, 1991 Free Software Foundation, Inc.
@ -21,6 +19,21 @@ along with BFD; see the file COPYING. If not, write to
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
/*doc*
@setfilename archive-info
@section Archives
Gumby, you promised to write this bit...
Archives are supported in bfd in @code{archive.c}.
An archive is represented internally just like another bfd, with a
pointer to a chain of contained bfds. Archives can be created by
opening bfds, linking them together and attatching them as children to
another bfd and then closing the parent bfd.
*-*/
/* Assumes:
o - all archive elements start on an even boundary, newline padded;
o - all arch headers are char *;
@ -72,6 +85,10 @@ _bfd_generic_mkarchive (abfd)
return true;
}
/*proto* bfd_get_next_mapent
What this does
*; PROTO(symindex, bfd_get_next_mapent, (bfd *, symindex, carsym **));
*/
symindex
bfd_get_next_mapent (abfd, prev, entry)
bfd *abfd;
@ -107,9 +124,16 @@ _bfd_create_empty_archive_element_shell (obfd)
return nbfd;
}
/*proto* bfd_set_archive_head
Used whilst processing archives. Sets the head of the chain of bfds
contained in an archive to @var{new_head}. (see chapter on archives)
*; PROTO(boolean, bfd_set_archive_head, (bfd *output, bfd *new_head));
*/
boolean
bfd_set_archive_head (output_archive, new_head)
bfd *output_archive, *new_head;
DEFUN(bfd_set_archive_head,(output_archive, new_head),
bfd *output_archive AND
bfd *new_head)
{
output_archive->archive_head = new_head;
@ -229,8 +253,10 @@ snarf_ar_hdr (abfd)
return NULL;
}
/* extract the filename from the archive */
if (hdr.ar_name[0] == ' ' && bfd_ardata (abfd)->extended_names != NULL) {
/* extract the filename from the archive - there are two ways to
specify an extendend name table, either the first char of the
name is a space, or it's a slash */
if ((hdr.ar_name[0] == '/' || hdr.ar_name[0] == ' ') && bfd_ardata (abfd)->extended_names != NULL) {
filename = get_extended_arelt_filename (abfd, hdr.ar_name);
if (filename == NULL) {
bfd_error = malformed_archive;
@ -325,10 +351,22 @@ bfd_get_elt_at_index (abfd, index)
return result;
}
/* If you've got an archive, call this to read each subfile. */
/*proto* bfd_openr_next_archived_file
Initially provided a bfd containing an archive and NULL, opens a bfd
on the first contained element and returns that. Subsequent calls to
bfd_openr_next_archived_file should pass the archive and the previous
return value to return a created bfd to the next contained element.
NULL is returned when there are no more.
*; PROTO(bfd*, bfd_openr_next_archived_file,
(bfd *archive, bfd *previous));
*/
bfd *
bfd_openr_next_archived_file (archive, last_file)
bfd *archive, *last_file;
DEFUN(bfd_openr_next_archived_file,(archive, last_file),
bfd *archive AND
bfd*last_file)
{
if ((bfd_get_format (archive) != bfd_archive) ||
@ -411,7 +449,7 @@ boolean
bfd_slurp_bsd_armap (abfd)
bfd *abfd;
{
int i;
struct areltdata *mapdata;
char nextname[17];
unsigned int counter = 0;
@ -451,7 +489,7 @@ bfd_slurp_bsd_armap (abfd)
goto byebye;
}
ardata->symdef_count = bfd_h_get_32(abfd, raw_armap) / sizeof (struct symdef);
ardata->symdef_count = bfd_h_get_32(abfd, (PTR)raw_armap) / sizeof (struct symdef);
ardata->cache = 0;
rbase = raw_armap+1;
ardata->symdefs = (carsym *) rbase;
@ -459,8 +497,8 @@ bfd_slurp_bsd_armap (abfd)
for (;counter < ardata->symdef_count; counter++) {
struct symdef *sym = ((struct symdef *) rbase) + counter;
sym->s.name = bfd_h_get_32(abfd, &(sym->s.string_offset)) + stringbase;
sym->file_offset = bfd_h_get_32(abfd, &(sym->file_offset));
sym->s.name = bfd_h_get_32(abfd, (PTR)(&(sym->s.string_offset))) + stringbase;
sym->file_offset = bfd_h_get_32(abfd, (PTR)( &(sym->file_offset)));
}
ardata->first_file_filepos = bfd_tell (abfd);
@ -501,13 +539,16 @@ bfd_slurp_coff_armap (abfd)
if (mapdata == NULL) return false;
raw_armap = (int *) bfd_alloc(abfd,mapdata->parsed_size);
if (raw_armap == NULL) {
if (raw_armap == NULL)
{
bfd_error = no_memory;
byebye:
bfd_release (abfd, (PTR)mapdata);
return false;
}
/* read in the raw map */
if (bfd_read ((PTR)raw_armap, 1, mapdata->parsed_size, abfd) !=
mapdata->parsed_size) {
bfd_error = malformed_archive;
@ -552,19 +593,22 @@ bfd_slurp_coff_armap (abfd)
ardata->first_file_filepos = bfd_tell (abfd);
/* Pad to an even boundary if you have to */
ardata->first_file_filepos += (ardata->first_file_filepos) %2;
bfd_release (abfd, (PTR)raw_armap);
bfd_release (abfd, (PTR)mapdata);
/* bfd_release (abfd, (PTR)raw_armap);
bfd_release (abfd, (PTR)mapdata);*/
bfd_has_map (abfd) = true;
return true;
}
/** Extended name table.
Normally archives support only 14-character filenames. Intel has extended
the format: longer names are stored in a special element (the first in the
archive, or second if there is an armap); the name in the ar_hdr is replaced
by <space><index into filename element>. Index is the P.R. of an int (radix:
8). */
Normally archives support only 14-character filenames.
Intel has extended the format: longer names are stored in a special
element (the first in the archive, or second if there is an armap);
the name in the ar_hdr is replaced by <space><index into filename
element>. Index is the P.R. of an int (radix: 8). Data General have
extended the format by using the prefix // for the special element */
/* Returns false on error, true otherwise */
boolean
@ -580,7 +624,9 @@ _bfd_slurp_extended_name_table (abfd)
bfd_seek (abfd, -16L, SEEK_CUR);
if (strncmp (nextname, "ARFILENAMES/ ", 16)) {
if (strncmp (nextname, "ARFILENAMES/ ", 16) != 0 &&
strncmp (nextname, "// ", 16) != 0)
{
bfd_ardata (abfd)->extended_names = NULL;
return true;
}
@ -604,8 +650,9 @@ _bfd_slurp_extended_name_table (abfd)
goto byebye;
}
/* It appears that the extended names are newline-padded, not null padded.
*/
/* Since the archive is supposed to be printable if it contains
text, the entries in the list are newline-padded, not null
padded. We'll fix that there.. */
{
char *temp = bfd_ardata (abfd)->extended_names;
for (; *temp != '\0'; ++temp)
@ -1127,7 +1174,7 @@ bsd_write_armap (arch, elength, map, orl_count, stridx)
for (i = 0; i < sizeof (struct ar_hdr); i++)
if (((char *)(&hdr))[i] == '\0') (((char *)(&hdr))[i]) = ' ';
bfd_write ((char *)&hdr, 1, sizeof (struct ar_hdr), arch);
bfd_h_put_32(arch, ranlibsize, &temp);
bfd_h_put_32(arch, ranlibsize, (PTR)&temp);
bfd_write (&temp, 1, sizeof (temp), arch);
for (count = 0; count < orl_count; count++) {
@ -1143,13 +1190,13 @@ bsd_write_armap (arch, elength, map, orl_count, stridx)
} /* if new archive element */
last_elt = current;
bfd_h_put_32(arch, ((map[count]).namidx), &outs.s.string_offset);
bfd_h_put_32(arch, firstreal, &outs.file_offset);
bfd_h_put_32(arch, ((map[count]).namidx),(PTR) &outs.s.string_offset);
bfd_h_put_32(arch, firstreal,(PTR) &outs.file_offset);
bfd_write ((char *)outp, 1, sizeof (outs), arch);
}
/* now write the strings themselves */
bfd_h_put_32(arch, stridx, &temp);
bfd_h_put_32(arch, stridx, (PTR)&temp);
bfd_write ((PTR)&temp, 1, sizeof (temp), arch);
for (count = 0; count < orl_count; count++)
bfd_write (*((map[count]).name), 1, strlen (*((map[count]).name))+1, arch);

885
bfd/bfd.c
View File

@ -1,11 +1,3 @@
/* -*- C -*- */
/*** bfd -- binary file diddling routines by Gumby Wallace of Cygnus Support.
Every definition in this file should be exported and declared
in bfd.h. If you don't want it to be user-visible, put it in
libbfd.c!
*/
/* Copyright (C) 1990, 1991 Free Software Foundation, Inc.
This file is part of BFD, the Binary File Diddler.
@ -24,11 +16,154 @@ You should have received a copy of the GNU General Public License
along with BFD; see the file COPYING. If not, write to
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
/* $Id$ */
/*proto*
@section typedef bfd
Pointers to bfd structs are the cornerstone of any application using
libbfd. References though the bfd and to data in the bfd give the
entire bfd functionality.
Finally! The BFD struct itself. This contains the major data about
the file, and contains pointers to the rest of the data.
*+++
$struct _bfd
${
The filename the application opened the bfd with.
$ CONST char *filename;
A pointer to the target jump table.
$ struct bfd_target *xvec;
To avoid dragging too many header files into every file that
includes bfd.h, IOSTREAM has been declared as a "char *", and MTIME
as a "long". Their correct types, to which they are cast when used,
are "FILE *" and "time_t".
The iostream is the result of an fopen on the filename.
$ char *iostream;
Is the file being cached @xref{File Caching}.
$ boolean cacheable;
Marks whether there was a default target specified when the bfd was
opened. This is used to select what matching algorithm to use to chose
the back end.
$ boolean target_defaulted;
The caching routines use these to maintain an LRU list of bfds.
$ struct _bfd *lru_prev, *lru_next;
When a file is closed by the caching routines, it retains the state
here:
$ file_ptr where;
and here:
$ boolean opened_once;
$ boolean mtime_set;
File modified time
$ long mtime;
For output files, channel we locked (is this used?).
$int ifd;
The format which belongs to the bfd.
$ bfd_format format;
The direction the bfd was opened with
$ enum bfd_direction {no_direction = 0,
$ read_direction = 1,
$ write_direction = 2,
$ both_direction = 3} direction;
Format_specific flags
$ flagword flags;
Currently my_archive is tested before adding origin to anything. I
believe that this can become always an add of origin, with origin set
to 0 for non archive files.
$ file_ptr origin;
Remember when output has begun, to stop strange things happening.
$ boolean output_has_begun;
Pointer to linked list of sections
$ struct sec *sections;
The number of sections
$ unsigned int section_count;
Stuff only usefull for object files:
The start address.
$ bfd_vma start_address;
Used for input and output
$ unsigned int symcount;
Symtab for output bfd
$ struct symbol_cache_entry **outsymbols;
Architecture of object machine, eg m68k
$ enum bfd_architecture obj_arch;
Particular machine within arch, e.g. 68010
$ unsigned long obj_machine;
Stuff only usefull for archives:
$ PTR arelt_data;
$ struct _bfd *my_archive;
$ struct _bfd *next;
$ struct _bfd *archive_head;
$ boolean has_armap;
Used by the back end to hold private data.
$ PTR tdata;
Used by the application to hold private data
$ PTR usrdata;
Where all the allocated stuff under this BFD goes
$ struct obstack memory;
$};
*---
*/
#include <sysdep.h>
#include "bfd.h"
#include "libbfd.h"
short _bfd_host_big_endian = 0x0100;
/* Accessing the above as (*(char*)&_bfd_host_big_endian), will
return 1 if the host is big-endian, 0 otherwise.
@ -136,415 +271,11 @@ DEFUN(bfd_perror,(message),
}
}
/* for error messages */
char *
bfd_format_string (format)
bfd_format format;
{
if (((int)format <(int) bfd_unknown) || ((int)format >=(int) bfd_type_end)) return "invalid";
switch (format) {
case bfd_object: return "object"; /* linker/assember/compiler output */
case bfd_archive: return "archive"; /* object archive file */
case bfd_core: return "core"; /* core dump */
default: return "unknown";
}
}
/** Target configurations */
extern bfd_target *target_vector[];
extern bfd_target *default_vector[];
/* Returns a pointer to the transfer vector for the object target
named target_name. If target_name is NULL, chooses the one in the
environment variable GNUTARGET; if that is null or not defined then
the first entry in the target list is chosen. Passing in the
string "default" or setting the environment variable to "default"
will cause the first entry in the target list to be returned,
and "target_defaulted" will be set in the bfd. This causes
bfd_check_format to loop over all the targets to find the one
that matches the file being read. */
bfd_target *
DEFUN(bfd_find_target,(target_name, abfd),
CONST char *target_name AND
bfd *abfd)
{
bfd_target **target;
extern char *getenv ();
CONST char *targname = (target_name ? target_name : getenv ("GNUTARGET"));
/* This is safe; the vector cannot be null */
if (targname == NULL || !strcmp (targname, "default")) {
abfd->target_defaulted = true;
return abfd->xvec = target_vector[0];
}
abfd->target_defaulted = false;
for (target = &target_vector[0]; *target != NULL; target++) {
if (!strcmp (targname, (*target)->name))
return abfd->xvec = *target;
}
bfd_error = invalid_target;
return NULL;
}
/* Returns a freshly-consed, NULL-terminated vector of the names of all the
valid bfd targets. Do not modify the names */
char **
bfd_target_list ()
{
int vec_length= 0;
bfd_target **target;
char **name_list, **name_ptr;
for (target = &target_vector[0]; *target != NULL; target++)
vec_length++;
name_ptr = name_list = (char **) zalloc ((vec_length + 1) * sizeof (char **));
if (name_list == NULL) {
bfd_error = no_memory;
return NULL;
}
for (target = &target_vector[0]; *target != NULL; target++)
*(name_ptr++) = (*target)->name;
return name_list;
}
/* Init a bfd for read of the proper format. If the target was unspecified,
search all the possible targets. */
boolean
DEFUN(bfd_check_format,(abfd, format),
bfd *abfd AND
bfd_format format)
{
bfd_target **target, *save_targ, *right_targ;
int match_count;
if (!bfd_read_p (abfd) ||
((int)(abfd->format) < (int)bfd_unknown) ||
((int)(abfd->format) >= (int)bfd_type_end)) {
bfd_error = invalid_operation;
return false;
}
if (abfd->format != bfd_unknown)
return (abfd->format == format)? true: false;
/* presume the answer is yes */
abfd->format = format;
/* If the target type was explicitly specified, just check that target. */
if (!abfd->target_defaulted) {
bfd_seek (abfd, (file_ptr)0, SEEK_SET); /* rewind! */
right_targ = BFD_SEND_FMT (abfd, _bfd_check_format, (abfd));
if (right_targ) {
abfd->xvec = right_targ; /* Set the target as returned */
return true; /* File position has moved, BTW */
}
return false; /* Specified target is not right */
}
/* Since the target type was defaulted, check them
all in the hope that one will be uniquely recognized. */
save_targ = abfd->xvec;
match_count = 0;
right_targ = 0;
for (target = target_vector; *target != NULL; target++) {
bfd_target *temp;
abfd->xvec = *target; /* Change BFD's target temporarily */
bfd_seek (abfd, (file_ptr)0, SEEK_SET);
temp = BFD_SEND_FMT (abfd, _bfd_check_format, (abfd));
if (temp) { /* This format checks out as ok! */
right_targ = temp;
match_count++;
/* If this is the default target, accept it, even if other targets
might match. People who want those other targets have to set
the GNUTARGET variable. */
if (temp == default_vector[0])
break;
#ifdef GNU960
/* Big- and little-endian b.out archives look the same, but it doesn't
* matter: there is no difference in their headers, and member file byte
* orders will (I hope) be handled appropriately by bfd. Ditto for big
* and little coff archives. And the 4 coff/b.out object formats are
* unambiguous. So accept the first match we find.
*/
break;
#endif
}
}
if (match_count == 1) {
abfd->xvec = right_targ; /* Change BFD's target permanently */
return true; /* File position has moved, BTW */
}
abfd->xvec = save_targ; /* Restore original target type */
abfd->format = bfd_unknown; /* Restore original format */
bfd_error = ((match_count == 0) ? file_not_recognized :
file_ambiguously_recognized);
return false;
}
boolean
DEFUN(bfd_set_format,(abfd, format),
bfd *abfd AND
bfd_format format)
{
if (bfd_read_p (abfd) ||
((int)abfd->format < (int)bfd_unknown) ||
((int)abfd->format >= (int)bfd_type_end)) {
bfd_error = invalid_operation;
return false;
}
if (abfd->format != bfd_unknown) return (abfd->format == format) ? true:false;
/* presume the answer is yes */
abfd->format = format;
if (!BFD_SEND_FMT (abfd, _bfd_set_format, (abfd))) {
abfd->format = bfd_unknown;
return false;
}
return true;
}
/* Hack object and core file sections */
sec_ptr
DEFUN(bfd_get_section_by_name,(abfd, name),
bfd *abfd AND
CONST char *name)
{
asection *sect;
for (sect = abfd->sections; sect != NULL; sect = sect->next)
if (!strcmp (sect->name, name)) return sect;
return NULL;
}
/* If you try to create a section with a name which is already in use,
returns the old section by that name instead. */
sec_ptr
DEFUN(bfd_make_section,(abfd, name),
bfd *abfd AND
CONST char *CONST name)
{
asection *newsect;
asection ** prev = &abfd->sections;
asection * sect = abfd->sections;
if (abfd->output_has_begun) {
bfd_error = invalid_operation;
return NULL;
}
while (sect) {
if (!strcmp(sect->name, name)) return sect;
prev = &sect->next;
sect = sect->next;
}
newsect = (asection *) bfd_zalloc(abfd, sizeof (asection));
if (newsect == NULL) {
bfd_error = no_memory;
return NULL;
}
newsect->name = name;
newsect->index = abfd->section_count++;
newsect->flags = SEC_NO_FLAGS;
newsect->userdata = 0;
newsect->next = (asection *)NULL;
newsect->relocation = (arelent *)NULL;
newsect->reloc_count = 0;
newsect->line_filepos =0;
if (BFD_SEND (abfd, _new_section_hook, (abfd, newsect)) != true) {
free (newsect);
return NULL;
}
*prev = newsect;
return newsect;
}
/* Call operation on each section. Operation gets three args: the bfd,
the section, and a void * pointer (whatever the user supplied). */
/* This is attractive except that without lexical closures its use is hard
to make reentrant. */
/*VARARGS2*/
void
bfd_map_over_sections (abfd, operation, user_storage)
bfd *abfd;
void (*operation)();
PTR user_storage;
{
asection *sect;
int i = 0;
for (sect = abfd->sections; sect != NULL; i++, sect = sect->next)
(*operation) (abfd, sect, user_storage);
if (i != abfd->section_count) /* Debugging */
abort();
}
boolean
bfd_set_section_flags (abfd, section, flags)
bfd *abfd;
sec_ptr section;
flagword flags;
{
if ((flags & bfd_applicable_section_flags (abfd)) != flags) {
bfd_error = invalid_operation;
return false;
}
section->flags = flags;
return true;
}
boolean
bfd_set_section_size (abfd, ptr, val)
bfd *abfd;
sec_ptr ptr;
unsigned long val;
{
/* Once you've started writing to any section you cannot create or change
the size of any others. */
if (abfd->output_has_begun) {
bfd_error = invalid_operation;
return false;
}
ptr->size = val;
return true;
}
boolean
DEFUN(bfd_set_section_contents,(abfd, section, location, offset, count),
bfd *abfd AND
sec_ptr section AND
PTR location AND
file_ptr offset AND
bfd_size_type count)
{
if (!(bfd_get_section_flags(abfd, section) &
SEC_HAS_CONTENTS)) {
bfd_error = no_contents;
return(false);
} /* if section has no contents */
if (BFD_SEND (abfd, _bfd_set_section_contents,
(abfd, section, location, offset, count))) {
abfd->output_has_begun = true;
return true;
}
return false;
}
boolean
DEFUN(bfd_get_section_contents,(abfd, section, location, offset, count),
bfd *abfd AND
sec_ptr section AND
PTR location AND
file_ptr offset AND
bfd_size_type count)
{
if (section->flags & SEC_CONSTRUCTOR) {
memset(location, 0, (unsigned)count);
return true;
}
else {
return (BFD_SEND (abfd, _bfd_get_section_contents,
(abfd, section, location, offset, count)));
}
}
/** Some core file info commands */
/* Returns a read-only string explaining what program was running when
it failed. */
char *
bfd_core_file_failing_command (abfd)
bfd *abfd;
{
if (abfd->format != bfd_core) {
bfd_error = invalid_operation;
return NULL;
}
return BFD_SEND (abfd, _core_file_failing_command, (abfd));
}
int
bfd_core_file_failing_signal (abfd)
bfd *abfd;
{
if (abfd->format != bfd_core) {
bfd_error = invalid_operation;
return 0;
}
return BFD_SEND (abfd, _core_file_failing_signal, (abfd));
}
boolean
core_file_matches_executable_p (core_bfd, exec_bfd)
bfd *core_bfd, *exec_bfd;
{
if ((core_bfd->format != bfd_core) || (exec_bfd->format != bfd_object)) {
bfd_error = wrong_format;
return false;
}
return BFD_SEND (core_bfd, _core_file_matches_executable_p, (core_bfd, exec_bfd));
}
/** Symbols */
boolean
bfd_set_symtab (abfd, location, symcount)
bfd *abfd;
asymbol **location;
unsigned int symcount;
{
if ((abfd->format != bfd_object) || (bfd_read_p (abfd))) {
bfd_error = invalid_operation;
return false;
}
bfd_get_outsymbols (abfd) = location;
bfd_get_symcount (abfd) = symcount;
return true;
}
/* returns the number of octets of storage required */
unsigned int
get_reloc_upper_bound (abfd, asect)
bfd *abfd;
@ -573,32 +304,6 @@ bfd_canonicalize_reloc (abfd, asect, location, symbols)
return BFD_SEND (abfd, _bfd_canonicalize_reloc, (abfd, asect, location, symbols));
}
void
bfd_print_symbol_vandf(file, symbol)
PTR file;
asymbol *symbol;
{
flagword type = symbol->flags;
if (symbol->section != (asection *)NULL)
{
fprintf_vma(file, symbol->value+symbol->section->vma);
}
else
{
fprintf_vma(file, symbol->value);
}
fprintf(file," %c%c%c%c%c%c%c",
(type & BSF_LOCAL) ? 'l':' ',
(type & BSF_GLOBAL) ? 'g' : ' ',
(type & BSF_IMPORT) ? 'i' : ' ',
(type & BSF_EXPORT) ? 'e' : ' ',
(type & BSF_UNDEFINED) ? 'u' : ' ',
(type & BSF_FORT_COMM) ? 'c' : ' ',
(type & BSF_DEBUGGING) ? 'd' :' ');
}
boolean
bfd_set_file_flags (abfd, flags)
@ -635,250 +340,6 @@ bfd_set_reloc (ignore_abfd, asect, location, count)
asect->orelocation = location;
asect->reloc_count = count;
}
/*
If an output_bfd is supplied to this function the generated image
will be relocatable, the relocations are copied to the output file
after they have been changed to reflect the new state of the world.
There are two ways of reflecting the results of partial linkage in an
output file; by modifying the output data in place, and by modifying
the relocation record. Some native formats (eg basic a.out and basic
coff) have no way of specifying an addend in the relocation type, so
the addend has to go in the output data. This is no big deal since in
these formats the output data slot will always be big enough for the
addend. Complex reloc types with addends were invented to solve just
this problem.
*/
bfd_reloc_status_enum_type
DEFUN(bfd_perform_relocation,(abfd,
reloc_entry,
data,
input_section,
output_bfd),
bfd *abfd AND
arelent *reloc_entry AND
PTR data AND
asection *input_section AND
bfd *output_bfd)
{
bfd_vma relocation;
bfd_reloc_status_enum_type flag = bfd_reloc_ok;
bfd_vma addr = reloc_entry->address ;
bfd_vma output_base = 0;
reloc_howto_type *howto = reloc_entry->howto;
asection *reloc_target_output_section;
asection *reloc_target_input_section;
asymbol *symbol;
if (reloc_entry->sym_ptr_ptr) {
symbol = *( reloc_entry->sym_ptr_ptr);
if ((symbol->flags & BSF_UNDEFINED) && output_bfd == (bfd *)NULL) {
flag = bfd_reloc_undefined;
}
}
else {
symbol = (asymbol*)NULL;
}
if (howto->special_function){
bfd_reloc_status_enum_type cont;
cont = howto->special_function(abfd,
reloc_entry,
symbol,
data,
input_section);
if (cont != bfd_reloc_continue) return cont;
}
/*
Work out which section the relocation is targetted at and the
initial relocation command value.
*/
if (symbol != (asymbol *)NULL){
if (symbol->flags & BSF_FORT_COMM) {
relocation = 0;
}
else {
relocation = symbol->value;
}
if (symbol->section != (asection *)NULL)
{
reloc_target_input_section = symbol->section;
}
else {
reloc_target_input_section = (asection *)NULL;
}
}
else if (reloc_entry->section != (asection *)NULL)
{
relocation = 0;
reloc_target_input_section = reloc_entry->section;
}
else {
relocation = 0;
reloc_target_input_section = (asection *)NULL;
}
if (reloc_target_input_section != (asection *)NULL) {
reloc_target_output_section =
reloc_target_input_section->output_section;
if (output_bfd && howto->partial_inplace==false) {
output_base = 0;
}
else {
output_base = reloc_target_output_section->vma;
}
relocation += output_base + reloc_target_input_section->output_offset;
}
relocation += reloc_entry->addend ;
if(reloc_entry->address > (bfd_vma)(input_section->size))
{
return bfd_reloc_outofrange;
}
if (howto->pc_relative == true)
{
/*
Anything which started out as pc relative should end up that
way too.
There are two ways we can see a pcrel instruction. Sometimes
the pcrel displacement has been partially calculated, it
includes the distance from the start of the section to the
instruction in it (eg sun3), and sometimes the field is
totally blank - eg m88kbcs.
*/
relocation -=
output_base + input_section->output_offset;
if (howto->pcrel_offset == true) {
relocation -= reloc_entry->address;
}
}
if (output_bfd!= (bfd *)NULL) {
if ( howto->partial_inplace == false) {
/*
This is a partial relocation, and we want to apply the relocation
to the reloc entry rather than the raw data. Modify the reloc
inplace to reflect what we now know.
*/
reloc_entry->addend = relocation ;
reloc_entry->section = reloc_target_input_section;
if (reloc_target_input_section != (asection *)NULL) {
/* If we know the output section we can forget the symbol */
reloc_entry->sym_ptr_ptr = (asymbol**)NULL;
}
reloc_entry->address +=
input_section->output_offset;
return flag;
}
else
{
/* This is a partial relocation, but inplace, so modify the
reloc record a bit
*/
}
}
reloc_entry->addend = 0;
/*
Either we are relocating all the way, or we don't want to apply
the relocation to the reloc entry (probably because there isn't
any room in the output format to describe addends to relocs)
*/
relocation >>= howto->rightshift;
/* Shift everything up to where it's going to be used */
relocation <<= howto->bitpos;
/* Wait for the day when all have the mask in them */
/* What we do:
i instruction to be left alone
o offset within instruction
r relocation offset to apply
S src mask
D dst mask
N ~dst mask
A part 1
B part 2
R result
Do this:
i i i i i o o o o o from bfd_get<size>
and S S S S S to get the size offset we want
+ r r r r r r r r r r to get the final value to place
and D D D D D to chop to right size
-----------------------
A A A A A
And this:
... i i i i i o o o o o from bfd_get<size>
and N N N N N get instruction
-----------------------
... B B B B B
And then:
B B B B B
or A A A A A
-----------------------
R R R R R R R R R R put into bfd_put<size>
*/
#define DOIT(x) \
x = ( (x & ~howto->dst_mask) | (((x & howto->src_mask) + relocation) & howto->dst_mask))
switch (howto->size)
{
case 0:
{
char x = bfd_get_8(abfd, (char *)data + addr);
DOIT(x);
bfd_put_8(abfd,x, (unsigned char *) data + addr);
}
break;
case 1:
{
short x = bfd_get_16(abfd, (bfd_byte *)data + addr);
DOIT(x);
bfd_put_16(abfd, x, (unsigned char *)data + addr);
}
break;
case 2:
{
long x = bfd_get_32(abfd, (bfd_byte *) data + addr);
DOIT(x);
bfd_put_32(abfd,x, (bfd_byte *)data + addr);
}
break;
case 3:
/* Do nothing */
break;
default:
return bfd_reloc_other;
}
return flag;
}
void
bfd_assert(file, line)
@ -889,6 +350,14 @@ int line;
}
/*proto* bfd_set_start_address
Marks the entry point of an output bfd. Returns @code{true} on
success, @code{false} otherwise.
*; PROTO(boolean, bfd_set_start_address,(bfd *, bfd_vma));
*/
boolean
bfd_set_start_address(abfd, vma)
bfd *abfd;
@ -899,19 +368,15 @@ bfd_vma vma;
}
bfd_vma bfd_log2(x)
bfd_vma x;
{
bfd_vma result = 0;
while ( (bfd_vma)(1<< result) < x)
result++;
return result;
}
/*proto* bfd_get_mtime
/* bfd_get_mtime: Return cached file modification time (e.g. as read
from archive header for archive members, or from file system if we have
been called before); else determine modify time, cache it, and
return it. */
Return cached file modification time (e.g. as read from archive header
for archive members, or from file system if we have been called
before); else determine modify time, cache it, and return it.
*;PROTO(long, bfd_get_mtime, (bfd *));
*/
long
bfd_get_mtime (abfd)
@ -931,3 +396,33 @@ bfd_get_mtime (abfd)
abfd->mtime = buf.st_mtime;
return abfd->mtime;
}
/*proto*
*i stuff
*+
#define bfd_sizeof_headers(abfd, reloc) \
BFD_SEND (abfd, _bfd_sizeof_headers, (abfd, reloc))
#define bfd_find_nearest_line(abfd, section, symbols, offset, filename_ptr, func, line_ptr) \
BFD_SEND (abfd, _bfd_find_nearest_line, (abfd, section, symbols, offset, filename_ptr, func, line_ptr))
#define bfd_debug_info_start(abfd) \
BFD_SEND (abfd, _bfd_debug_info_start, (abfd))
#define bfd_debug_info_end(abfd) \
BFD_SEND (abfd, _bfd_debug_info_end, (abfd))
#define bfd_debug_info_accumulate(abfd, section) \
BFD_SEND (abfd, _bfd_debug_info_accumulate, (abfd, section))
#define bfd_stat_arch_elt(abfd, stat) \
BFD_SEND (abfd, _bfd_stat_arch_elt,(abfd, stat))
*-
*/

File diff suppressed because it is too large Load Diff

1178
bfd/ieee.c

File diff suppressed because it is too large Load Diff

View File

@ -207,7 +207,8 @@ DEFUN(bfd_tell,(abfd),
/** Make a string table */
/* Add string to table pointed to by table, at location starting with free_ptr.
/*>bfd.h<
Add string to table pointed to by table, at location starting with free_ptr.
resizes the table if necessary (if it's NULL, creates it, ignoring
table_length). Updates free_ptr, table, table_length */
@ -268,6 +269,61 @@ DEFUN(bfd_add_to_string_table,(table, new_string, table_length, free_ptr),
functions in swap.h #ifdef __GNUC__.
Gprof them later and find out. */
/*proto*
*i bfd_put_size
*i bfd_get_size
These macros as used for reading and writing raw data in sections;
each access (except for bytes) is vectored through the target format
of the bfd and mangled accordingly. The mangling performs any
necessary endian translations and removes alignment restrictions.
*+
#define bfd_put_8(abfd, val, ptr) \
(*((char *)ptr) = (char)val)
#define bfd_get_8(abfd, ptr) \
(*((char *)ptr))
#define bfd_put_16(abfd, val, ptr) \
BFD_SEND(abfd, bfd_putx16, (val,ptr))
#define bfd_get_16(abfd, ptr) \
BFD_SEND(abfd, bfd_getx16, (ptr))
#define bfd_put_32(abfd, val, ptr) \
BFD_SEND(abfd, bfd_putx32, (val,ptr))
#define bfd_get_32(abfd, ptr) \
BFD_SEND(abfd, bfd_getx32, (ptr))
#define bfd_put_64(abfd, val, ptr) \
BFD_SEND(abfd, bfd_putx64, (val, ptr))
#define bfd_get_64(abfd, ptr) \
BFD_SEND(abfd, bfd_getx64, (ptr))
*-
*-*/
/*proto*
*i bfd_h_put_size
*i bfd_h_get_size
These macros have the same function as their @code{bfd_get_x}
bretherin, except that they are used for removing information for the
header records of object files. Believe it or not, some object files
keep their header records in big endian order, and their data in little
endan order.
*+
#define bfd_h_put_8(abfd, val, ptr) \
(*((char *)ptr) = (char)val)
#define bfd_h_get_8(abfd, ptr) \
(*((char *)ptr))
#define bfd_h_put_16(abfd, val, ptr) \
BFD_SEND(abfd, bfd_h_putx16,(val,ptr))
#define bfd_h_get_16(abfd, ptr) \
BFD_SEND(abfd, bfd_h_getx16,(ptr))
#define bfd_h_put_32(abfd, val, ptr) \
BFD_SEND(abfd, bfd_h_putx32,(val,ptr))
#define bfd_h_get_32(abfd, ptr) \
BFD_SEND(abfd, bfd_h_getx32,(ptr))
#define bfd_h_put_64(abfd, val, ptr) \
BFD_SEND(abfd, bfd_h_putx64,(val, ptr))
#define bfd_h_get_64(abfd, ptr) \
BFD_SEND(abfd, bfd_h_getx64,(ptr))
*-
*-*/
unsigned int
DEFUN(_do_getb16,(addr),
register bfd_byte *addr)
@ -333,7 +389,9 @@ DEFUN(_do_getb64,(addr),
return high << 32 | low;
#else
bfd_64_type foo;
BFD_FAIL();
return foo;
#endif
}
@ -342,8 +400,9 @@ bfd_64_type
DEFUN(_do_getl64,(addr),
register bfd_byte *addr)
{
bfd_64_type low, high;
#ifdef HOST_64_BIT
bfd_64_type low, high;
high= (((((((addr[7] << 8) |
addr[6]) << 8) |
addr[5]) << 8) |
@ -356,8 +415,11 @@ DEFUN(_do_getl64,(addr),
return high << 32 | low;
#else
bfd_64_type foo;
BFD_FAIL();
return foo;
#endif
}
void
@ -440,3 +502,19 @@ DEFUN(bfd_generic_get_section_contents, (abfd, section, location, offset, count)
return (false); /* on error */
return (true);
}
/*proto-internal*
*i bfd_log2
Return the log base 2 of the value supplied, rounded up. eg an arg
of 1025 would return 11.
*; PROTO(bfd_vma, bfd_log2,(bfd_vma x));
*-*/
bfd_vma bfd_log2(x)
bfd_vma x;
{
bfd_vma result = 0;
while ( (bfd_vma)(1<< result) < x)
result++;
return result;
}

View File

@ -65,14 +65,17 @@ PROTO (char *, zalloc, (bfd_size_type size));
PROTO(PTR, bfd_alloc, (bfd *abfd, bfd_size_type size));
PROTO(PTR, bfd_zalloc,(bfd *abfd, bfd_size_type size));
PROTO(PTR, bfd_realloc,(bfd *abfd, PTR orig, bfd_size_type new));
PROTO(void, bfd_alloc_grow,(bfd *abfd, PTR thing, bfd_size_type size));
PROTO(PTR, bfd_alloc_finish,(bfd *abfd));
#define bfd_release(x,y) (void) obstack_free(&(x->memory),y)
PROTO (bfd_target *, bfd_find_target, (CONST char *target_name, bfd *));
PROTO (bfd_size_type, bfd_read, (PTR ptr, bfd_size_type size, bfd_size_type nitems, bfd *abfd));
PROTO (bfd_size_type, bfd_write, (PTR ptr, bfd_size_type size, bfd_size_type nitems, bfd *abfd));
PROTO (FILE *, bfd_cache_lookup, (bfd *));
PROTO (void, bfd_cache_close, (bfd *));
PROTO (int, bfd_seek,(bfd* abfd, file_ptr fp , int direction));
PROTO (long, bfd_tell, (bfd *abfd));
PROTO (bfd *, _bfd_create_empty_archive_element_shell, (bfd *obfd));
@ -161,8 +164,6 @@ PROTO (void, bfd_assert,(char*,int));
PROTO (FILE *, bfd_cache_lookup_worker, (bfd *));
extern bfd *bfd_last_cache;
#define bfd_cache_lookup(x) \
(x==bfd_last_cache?(FILE*)(bfd_last_cache->iostream):bfd_cache_lookup_worker(x))
/* Now Steve, what's the story here? */
#ifdef lint
@ -175,3 +176,51 @@ extern bfd *bfd_last_cache;
/* Generic routine for close_and_cleanup is really just bfd_true. */
#define bfd_generic_close_and_cleanup bfd_true
/* THE FOLLOWING IS EXTRACTED FROM THE SOURCE*/
/* Return the log base 2 of the value supplied, rounded up. eg an arg
of 1025 would return 11.
*/
PROTO(bfd_vma, bfd_log2,(bfd_vma x));
/* The maxiumum number of files which the cache will keep open at one
time.
*/
#define BFD_CACHE_MAX_OPEN 10
/* Zero, or a pointer to the topmost bfd on the chain. This is used by the
bfd_cache_lookup() macro in libbfd.h to determine when it can avoid a function
call.
*/
extern bfd *bfd_last_cache;
/* Checks to see if the required bfd is the same as the last one looked
up. If so then it can use the iostream in the bfd with impunity, since
it can't have changed since the last lookup, otherwise it has to
perform the complicated lookup function
*/
#define bfd_cache_lookup(x) \
((x)==bfd_last_cache? \
(FILE*)(bfd_last_cache->iostream): \
bfd_cache_lookup_worker(x))
/* Initialize a BFD by putting it on the cache LRU.
*/
PROTO(void, bfd_cache_init, (bfd *));
/* Remove the bfd from the cache. If the attatched file is open, then close it too.
*/
PROTO(void, bfd_cache_close, (bfd *));
/* Call the OS to open a file for this BFD. Returns the FILE *
(possibly null) that results from this operation. Sets up the
BFD so that future accesses know the file is open. If the FILE *
returned is null, then there is won't have been put in the cache, so
it won't have to be removed from it.
*/
PROTO(FILE *, bfd_open_file, (bfd *));
/* Called when the macro @code{bfd_cache_lookup} fails to find a quick
answer. Finds a file descriptor for this BFD. If necessary, it open it.
If there are already more than BFD_CACHE_MAX_OPEN files open, it trys to close
one first, to avoid running out of file descriptors.
*/
PROTO(FILE *, bfd_cache_lookup_worker, (bfd *));

View File

@ -31,16 +31,22 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#include "bfd.h"
#include "libbfd.h"
#include "aout64.h"
/**From: bothner@cs.wisc.edu***********************************************/
#undef N_TXTOFF
#define N_TXTOFF(x) ( (N_MAGIC((x)) == ZMAGIC) ? PAGE_SIZE : EXEC_BYTES_SIZE)
/**************************************************************************/
#include "stab.gnu.h"
#include "ar.h"
#include "libaout.h" /* BFD a.out internal data structures */
#if 0
int vfprintf(file, format, args) /* Temporary crock! */
FILE *file; char *format; char *args;
{
return _doprnt (format, args, file);
}
#endif
bfd_target *newsos3_callback ();
@ -49,7 +55,7 @@ bfd_target *
DEFUN(newsos3_object_p,(abfd),
bfd *abfd)
{
unsigned char magicbuf[LONG_SIZE]; /* Raw bytes of magic number from file */
unsigned char magicbuf[4]; /* Raw bytes of magic number from file */
unsigned long magic; /* Swapped magic number */
bfd_error = system_call_error;
@ -99,19 +105,40 @@ DEFUN(newsos3_write_object_contents,(abfd),
/* Transfer vectors for NEWS-OS version 3 */
/* We use BFD generic archive files. */
#define aout_32_openr_next_archived_file bfd_generic_openr_next_archived_file
#define aout_32_generic_stat_arch_elt bfd_generic_stat_arch_elt
#define aout_32_slurp_armap bfd_slurp_bsd_armap
#define aout_32_slurp_extended_name_table bfd_true
#define aout_32_write_armap bsd_write_armap
#define aout_32_truncate_arname bfd_bsd_truncate_arname
#define newsos_openr_next_archived_file bfd_generic_openr_next_archived_file
#define newsos_generic_stat_arch_elt bfd_generic_stat_arch_elt
#define newsos_slurp_armap bfd_slurp_bsd_armap
#define newsos_slurp_extended_name_table bfd_true
#define newsos_write_armap bsd_write_armap
#define newsos_truncate_arname bfd_bsd_truncate_arname
/* We don't support core files yet. FIXME. */
#define aout_32_core_file_failing_command _bfd_dummy_core_file_failing_command
#define aout_32_core_file_failing_signal _bfd_dummy_core_file_failing_signal
#define aout_32_core_file_matches_executable_p \
#define newsos_core_file_failing_command _bfd_dummy_core_file_failing_command
#define newsos_core_file_failing_signal _bfd_dummy_core_file_failing_signal
#define newsos_core_file_matches_executable_p \
_bfd_dummy_core_file_matches_executable_p
#define aout_32_core_file_p _bfd_dummy_target
#define newsos_core_file_p _bfd_dummy_target
#define newsos_bfd_debug_info_start bfd_void
#define newsos_bfd_debug_info_end bfd_void
#define newsos_bfd_debug_info_accumulate bfd_void
#define newsos_mkobject aout_32_mkobject
#define newsos_close_and_cleanup aout_32_close_and_cleanup
#define newsos_set_section_contents aout_32_set_section_contents
#define newsos_get_section_contents aout_32_get_section_contents
#define newsos_new_section_hook aout_32_new_section_hook
#define newsos_get_symtab_upper_bound aout_32_get_symtab_upper_bound
#define newsos_get_symtab aout_32_get_symtab
#define newsos_get_reloc_upper_bound aout_32_get_reloc_upper_bound
#define newsos_canonicalize_reloc aout_32_canonicalize_reloc
#define newsos_make_empty_symbol aout_32_make_empty_symbol
#define newsos_print_symbol aout_32_print_symbol
#define newsos_get_lineno aout_32_get_lineno
#define newsos_set_arch_mach aout_32_set_arch_mach
#define newsos_find_nearest_line aout_32_find_nearest_line
#define newsos_sizeof_headers aout_32_sizeof_headers
/* We define our own versions of these routines. */
@ -128,16 +155,16 @@ bfd_target newsos3_vec = /* Sony 68k-based machines running newos3 */
(SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC), /* section flags */
' ', /* ar_pad_char */
16, /* ar_max_namelen */
1, /* minimum alignment */
_do_getb64, _do_putb64, _do_getb32, _do_putb32, _do_getb16, _do_putb16, /* data */
_do_getb64, _do_putb64, _do_getb32, _do_putb32, _do_getb16, _do_putb16, /* hdrs */
{_bfd_dummy_target, newsos3_object_p, /* bfd_check_format */
bfd_generic_archive_p, aout_32_core_file_p},
{bfd_false, aout_32_mkobject, /* bfd_set_format */
bfd_generic_archive_p, newsos_core_file_p},
{bfd_false, newsos_mkobject, /* bfd_set_format */
_bfd_generic_mkarchive, bfd_false},
{bfd_false, newsos3_write_object_contents, /* bfd_write_contents */
_bfd_write_archive_contents, bfd_false},
JUMP_TABLE(aout_32)
JUMP_TABLE(newsos)
};

View File

@ -30,6 +30,11 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#include "libbfd.h"
#include "oasys.h"
#include "liboasys.h"
/* Read in all the section data and relocation stuff too */
PROTO(static boolean,oasys_slurp_section_data,(bfd *CONST abfd));
static void
DEFUN(oasys_read_record,(abfd, record),
bfd *CONST abfd AND
@ -127,6 +132,12 @@ DEFUN(oasys_slurp_symbol_table,(abfd),
if (record.header.type == oasys_record_is_local_enum)
{
dest->flags = BSF_LOCAL;
if (dest->section ==(asection *)(~0)) {
/* It seems that sometimes internal symbols are tied up, but
still get output, even though there is no
section */
dest->section = 0;
}
}
else {
@ -258,7 +269,7 @@ DEFUN(oasys_archive_p,(abfd),
oasys_module_table_type record;
oasys_external_module_table_type record_ext;
set_tdata(abfd, ar);
ar->module = module;
@ -268,6 +279,11 @@ DEFUN(oasys_archive_p,(abfd),
filepos = header.mod_tbl_offset;
for (i = 0; i < header.mod_count; i++) {
bfd_seek(abfd , filepos, SEEK_SET);
/* There are two ways of specifying the archive header */
if (0) {
oasys_external_module_table_type_a_type record_ext;
bfd_read((PTR)&record_ext, 1, sizeof(record_ext), abfd);
record.mod_size = bfd_h_get_32(abfd, record_ext.mod_size);
@ -286,7 +302,30 @@ DEFUN(oasys_archive_p,(abfd),
sizeof(record_ext) +
record.dep_count * 4 +
record.depee_count * 4 +
record.sect_count * 8 + 187,
record.sect_count * 8 + 187;
}
else {
oasys_external_module_table_type_b_type record_ext;
bfd_read((PTR)&record_ext, 1, sizeof(record_ext), abfd);
record.mod_size = bfd_h_get_32(abfd, record_ext.mod_size);
record.file_offset = bfd_h_get_32(abfd,
record_ext.file_offset);
record.dep_count = bfd_h_get_32(abfd, record_ext.dep_count);
record.depee_count = bfd_h_get_32(abfd, record_ext.depee_count);
record.sect_count = bfd_h_get_32(abfd, record_ext.sect_count);
record.module_name_size = bfd_h_get_32(abfd, record_ext.mod_name_length);
module[i].name = bfd_alloc(abfd,record.module_name_size + 1);
bfd_read((PTR)module[i].name, 1, record.module_name_size, abfd);
module[i].name[record.module_name_size] = 0;
filepos +=
sizeof(record_ext) +
record.dep_count * 4 +
record.module_name_size + 1;
}
module[i].size = record.mod_size;
@ -375,7 +414,7 @@ DEFUN(oasys_object_p,(abfd),
s->size = bfd_h_get_32(abfd, & record.section.value[0]) ;
s->vma = bfd_h_get_32(abfd, &record.section.vma[0]);
s->flags |= SEC_LOAD | SEC_HAS_CONTENTS;
s->flags= 0;
had_usefull = true;
}
break;
@ -402,6 +441,14 @@ DEFUN(oasys_object_p,(abfd),
if (abfd->symcount != 0) {
abfd->flags |= HAS_SYMS;
}
/*
We don't know if a section has data until we've read it..
*/
oasys_slurp_section_data(abfd);
return abfd->xvec;
fail:
@ -465,21 +512,20 @@ DEFUN(oasys_slurp_section_data,(abfd),
asection *s;
/* Buy enough memory for all the section data and relocations */
/* See if the data has been slurped already .. */
for (s = abfd->sections; s != (asection *)NULL; s= s->next) {
per = oasys_per_section(s);
if (per->data != (bfd_byte*)NULL) return true;
per->data = (bfd_byte *) bfd_alloc(abfd, s->size);
per->reloc_tail_ptr = (oasys_reloc_type **)&(s->relocation);
per->had_vma = false;
s->reloc_count = 0;
if (per->initialized == true)
return true;
}
if (data->first_data_record == 0) return true;
bfd_seek(abfd, data->first_data_record, SEEK_SET);
while (loop) {
oasys_read_record(abfd, &record);
switch (record.header.type) {
switch (record.header.type)
{
case oasys_record_is_header_enum:
break;
case oasys_record_is_data_enum:
@ -496,6 +542,18 @@ DEFUN(oasys_slurp_section_data,(abfd),
data->sections[record.data.relb & RELOCATION_SECT_BITS];
bfd_vma dst_offset ;
per = oasys_per_section(section);
if (per->initialized == false)
{
per->data = (bfd_byte *) bfd_zalloc(abfd, section->size);
per->reloc_tail_ptr = (oasys_reloc_type **)&(section->relocation);
per->had_vma = false;
per->initialized = true;
section->reloc_count = 0;
section->flags = SEC_ALLOC;
}
dst_offset = bfd_h_get_32(abfd, record.data.addr) ;
if (per->had_vma == false) {
/* Take the first vma we see as the base */
@ -512,9 +570,13 @@ DEFUN(oasys_slurp_section_data,(abfd),
dst_ptr = oasys_per_section(section)->data +
dst_offset;
if (src < end_src) {
section->flags |= SEC_LOAD | SEC_HAS_CONTENTS;
}
while (src < end_src) {
uint32_type gap = end_src - src -1;
uint8e_type mod_byte = *src++;
uint32_type gap = end_src - src;
count = 8;
if (mod_byte == 0 && gap >= 8) {
dst_ptr[0] = src[0];
@ -529,7 +591,7 @@ DEFUN(oasys_slurp_section_data,(abfd),
src += 8;
}
else {
for (relbit = 1; count-- != 0 && gap != 0; gap --, relbit <<=1)
for (relbit = 1; count-- != 0 && src < end_src; relbit <<=1)
{
if (relbit & mod_byte)
{
@ -628,6 +690,7 @@ DEFUN(oasys_slurp_section_data,(abfd),
loop = false;
}
}
return true;
}
@ -646,7 +709,8 @@ DEFUN(oasys_new_section_hook,(abfd, newsect),
oasys_per_section( newsect)->data = (bfd_byte *)NULL;
oasys_per_section(newsect)->section = newsect;
oasys_per_section(newsect)->offset = 0;
newsect->alignment_power = 3;
oasys_per_section(newsect)->initialized = false;
newsect->alignment_power = 1;
/* Turn the section string into an index */
sscanf(newsect->name,"%u", &newsect->target_index);
@ -674,7 +738,14 @@ DEFUN(oasys_get_section_contents,(abfd, section, location, offset, count),
{
oasys_per_section_type *p = (oasys_per_section_type *) section->used_by_bfd;
oasys_slurp_section_data(abfd);
if (p->initialized == false)
{
(void) memset(location, 0, (int)count);
}
else
{
(void) memcpy(location, p->data + offset, (int)count);
}
return true;
}
@ -780,8 +851,16 @@ DEFUN(oasys_write_syms, (abfd),
/* throw it away */
continue;
}
else {
if (g->section == (asection *)NULL) {
/* Sometime, the oasys tools give out a symbol with illegal
bits in it, we'll output it in the same broken way */
symbol.relb = RELOCATION_TYPE_REL | 0;
}
else {
symbol.relb = RELOCATION_TYPE_REL |g->section->output_section->target_index;
}
bfd_h_put_16(abfd, 0, (uint8e_type *)(&symbol.refno[0]));
}
while (src[l]) {
@ -900,6 +979,7 @@ DEFUN(oasys_write_data, (abfd),
{
asection *s;
for (s = abfd->sections; s != (asection *)NULL; s = s->next) {
if (s->flags & SEC_LOAD) {
uint8e_type *raw_data = oasys_per_section(s)->data;
oasys_data_record_type processed_data;
bfd_size_type current_byte_index = 0;
@ -1036,6 +1116,7 @@ DEFUN(oasys_write_data, (abfd),
}
}
}
}
static boolean
DEFUN(oasys_write_object_contents, (abfd),
bfd * CONST abfd)
@ -1180,17 +1261,20 @@ DEFUN(oasys_sizeof_headers,(abfd, exec),
{
return 0;
}
#define FOO PROTO
#define oasys_core_file_failing_command (char *(*)())(bfd_nullvoidptr)
#define oasys_core_file_failing_signal (int (*)())bfd_0
#define oasys_core_file_matches_executable_p 0 /*(PROTO(boolean, (*),(bfd*, bfd*)))bfd_false*/
#define oasys_core_file_matches_executable_p 0
#define oasys_slurp_armap bfd_true
#define oasys_slurp_extended_name_table bfd_true
#define oasys_truncate_arname (void (*)())bfd_nullvoidptr
#define oasys_write_armap 0 /* (PROTO( boolean, (*),(bfd *, unsigned int, struct orl *, int, int))) bfd_nullvoidptr*/
#define oasys_write_armap 0
#define oasys_get_lineno (struct lineno_cache_entry *(*)())bfd_nullvoidptr
#define oasys_close_and_cleanup bfd_generic_close_and_cleanup
#define oasys_bfd_debug_info_start bfd_void
#define oasys_bfd_debug_info_end bfd_void
#define oasys_bfd_debug_info_accumulate (FOO(void, (*), (bfd *, asection *)))bfd_void
/*SUPPRESS 460 */
@ -1207,7 +1291,7 @@ bfd_target oasys_vec =
|SEC_ALLOC | SEC_LOAD | SEC_RELOC), /* section flags */
' ', /* ar_pad_char */
16, /* ar_max_namelen */
1, /* minimum alignment */
_do_getb64, _do_putb64, _do_getb32, _do_putb32, _do_getb16, _do_putb16, /* data */
_do_getb64, _do_putb64, _do_getb32, _do_putb32, _do_getb16, _do_putb16, /* hdrs */

View File

@ -96,8 +96,19 @@ bfd *obfd;
return nbfd;
}
/** bfd_openr, bfd_fdopenr -- open for reading.
Returns a pointer to a freshly-allocated bfd on success, or NULL. */
/*doc*
@section Opening and Closing BFDs
*/
/*proto*
*i bfd_openr
Opens the file supplied (using fopen) with the target supplied, it
returns a pointer to the created bfd.
If NULL is returned then an error has occured.
Possible errors are no_memory, invalid_target or system_call error.
*; PROTO(bfd*, bfd_openr, (CONST char *filename,CONST char*target));
*-*/
bfd *
DEFUN(bfd_openr, (filename, target),
@ -139,6 +150,15 @@ DEFUN(bfd_openr, (filename, target),
close it if anything goes wrong. Closing the stream means closing
the file descriptor too, even though we didn't open it.
*/
/*proto*
*i bfd_fdopenr
bfd_fdopenr is to bfd_fopenr much like fdopen is to fopen. It opens a bfd on
a file already described by the @var{fd} supplied.
Possible errors are no_memory, invalid_target and system_call error.
*; PROTO(bfd *, bfd_fdopenr,
(CONST char *filename, CONST char *target, int fd));
*-*/
bfd *
DEFUN(bfd_fdopenr,(filename, target, fd),
@ -155,7 +175,7 @@ DEFUN(bfd_fdopenr,(filename, target, fd),
bfd_error = system_call_error;
fdflags = fcntl (fd, F_GETFL);
fdflags = fcntl (fd, F_GETFL, NULL);
if (fdflags == -1) return NULL;
#ifdef BFD_LOCKS
@ -214,6 +234,14 @@ DEFUN(bfd_fdopenr,(filename, target, fd),
See comment by bfd_fdopenr before you try to modify this function. */
/*proto* bfd_openw
Creates a bfd, associated with file @var{filename}, using the file
format @var{target}, and returns a pointer to it.
Possible errors are system_call_error, no_memory, invalid_target.
*; PROTO(bfd *, bfd_openw, (CONST char *filename, CONST char *target));
*/
bfd *
DEFUN(bfd_openw,(filename, target),
CONST char *filename AND
@ -246,11 +274,22 @@ DEFUN(bfd_openw,(filename, target),
}
return nbfd;
}
/* Close up shop, get your deposit back. */
/*proto* bfd_close
This function closes a bfd. If the bfd was open for writing, then
pending operations are completed and the file written out and closed.
If the created file is executable, then @code{chmod} is called to mark
it as such.
All memory attatched to the bfd's obstacks is released.
@code{true} is returned if all is ok, otherwise @code{false}.
*; PROTO(boolean, bfd_close,(bfd *));
*/
boolean
bfd_close (abfd)
bfd *abfd;
DEFUN(bfd_close,(abfd),
bfd *abfd)
{
if (!bfd_read_p(abfd))
if (BFD_SEND_FMT (abfd, _bfd_write_contents, (abfd)) != true)
@ -283,12 +322,18 @@ bfd_close (abfd)
return true;
}
/* Create a bfd with no associated file or target. */
/*proto* bfd_create
This routine creates a new bfd in the manner of bfd_openw, but without
opening a file. The new bfd takes the target from the target used by
@var{template}. The format is always set to @code{bfd_object}.
*; PROTO(bfd *, bfd_create, (CONST char *filename, bfd *template));
*/
bfd *
DEFUN(bfd_create,(filename, template),
CONST char *filename AND
CONST bfd *template)
bfd *template)
{
bfd *nbfd = new_bfd();
if (nbfd == (bfd *)NULL) {
@ -313,6 +358,20 @@ DEFUN(PTR bfd_alloc_by_size_t,(abfd, size),
PTR res = obstack_alloc(&(abfd->memory), size);
return res;
}
DEFUN(void bfd_alloc_grow,(abfd, ptr, size),
bfd *abfd AND
PTR ptr AND
bfd_size_type size)
{
obstack_grow(&(abfd->memory), ptr, size);
}
DEFUN(PTR bfd_alloc_finish,(abfd),
bfd *abfd)
{
return obstack_finish(&(abfd->memory));
}
DEFUN(PTR bfd_alloc, (abfd, size),
bfd *abfd AND
bfd_size_type size)
@ -339,8 +398,14 @@ DEFUN(PTR bfd_realloc,(abfd, old, size),
return res;
}
/*proto* bfd_alloc_size
Return the number of bytes in the obstacks connected to the supplied
bfd.
*; PROTO(bfd_size_type,bfd_alloc_size,(bfd *abfd));
*/
DEFUN(bfd_size_type bfd_alloc_size,(abfd),
bfd_size_type
DEFUN( bfd_alloc_size,(abfd),
bfd *abfd)
{
struct _obstack_chunk *chunk = abfd->memory.chunk;

View File

@ -187,7 +187,7 @@ asection *section;
+ (HEX(buffer.u.type_3.address+1) << 16)
+ (HEX(buffer.u.type_3.address+2) << 8)
+ (HEX(buffer.u.type_3.address+3));
func(abfd,section, address, buffer.u.type_2.data, bytes_on_line -1);
func(abfd,section, address, buffer.u.type_3.data, bytes_on_line -1);
break;
@ -320,7 +320,7 @@ int bytes_to_do;
check_sum += TOHEX(buffer.u.type_3.address+3, address >> 0);
size = bytes_this_chunk + 5;
data = buffer.u.type_3.data;
break;
case 2:
check_sum = TOHEX(buffer.u.type_3.address, address >> 16);
check_sum += TOHEX(buffer.u.type_3.address+1, address >> 8);
@ -334,6 +334,7 @@ int bytes_to_do;
check_sum += TOHEX(buffer.u.type_3.address+1, address >> 0);
size = bytes_this_chunk + 3;
data = buffer.u.type_1.data;
break;
}
for (i = 0; i < bytes_this_chunk; i++) {
@ -380,31 +381,32 @@ DEFUN(srec_make_empty_symbol, (abfd),
new->the_bfd = abfd;
return new;
}
/*SUPPRESS 460 */
#define srec_new_section_hook (PROTO(boolean, (*), (bfd *, asection *)))bfd_true
#define FOO PROTO
#define srec_new_section_hook (FOO(boolean, (*), (bfd *, asection *)))bfd_true
#define srec_get_symtab_upper_bound bfd_false
#define srec_get_symtab (PROTO(unsigned int, (*), (bfd *, asymbol **)))bfd_0
#define srec_get_reloc_upper_bound (PROTO(unsigned int, (*),(bfd*, asection *)))bfd_false
#define srec_canonicalize_reloc (PROTO(unsigned int, (*),(bfd*,asection *, arelent **, asymbol **))) bfd_0
#define srec_get_symtab (FOO(unsigned int, (*), (bfd *, asymbol **)))bfd_0
#define srec_get_reloc_upper_bound (FOO(unsigned int, (*),(bfd*, asection *)))bfd_false
#define srec_canonicalize_reloc (FOO(unsigned int, (*),(bfd*,asection *, arelent **, asymbol **))) bfd_0
#define srec_print_symbol (PROTO(void,(*),(bfd *, PTR, asymbol *, bfd_print_symbol_enum_type))) bfd_void
#define srec_print_symbol (FOO(void,(*),(bfd *, PTR, asymbol *, bfd_print_symbol_enum_type))) bfd_void
#define srec_openr_next_archived_file (PROTO(bfd *, (*), (bfd*,bfd*))) bfd_nullvoidptr
#define srec_find_nearest_line (PROTO(boolean, (*),(bfd*,asection*,asymbol**,bfd_vma, CONST char**, CONST char**, unsigned int *))) bfd_false
#define srec_generic_stat_arch_elt (PROTO(int, (*), (bfd *,struct stat *))) bfd_0
#define srec_openr_next_archived_file (FOO(bfd *, (*), (bfd*,bfd*))) bfd_nullvoidptr
#define srec_find_nearest_line (FOO(boolean, (*),(bfd*,asection*,asymbol**,bfd_vma, CONST char**, CONST char**, unsigned int *))) bfd_false
#define srec_generic_stat_arch_elt (FOO(int, (*), (bfd *,struct stat *))) bfd_0
#define srec_core_file_failing_command (char *(*)())(bfd_nullvoidptr)
#define srec_core_file_failing_signal (int (*)())bfd_0
#define srec_core_file_matches_executable_p (PROTO(boolean, (*),(bfd*, bfd*)))bfd_false
#define srec_core_file_matches_executable_p (FOO(boolean, (*),(bfd*, bfd*)))bfd_false
#define srec_slurp_armap bfd_true
#define srec_slurp_extended_name_table bfd_true
#define srec_truncate_arname (void (*)())bfd_nullvoidptr
#define srec_write_armap (PROTO( boolean, (*),(bfd *, unsigned int, struct orl *, int, int))) bfd_nullvoidptr
#define srec_write_armap (FOO( boolean, (*),(bfd *, unsigned int, struct orl *, int, int))) bfd_nullvoidptr
#define srec_get_lineno (struct lineno_cache_entry *(*)())bfd_nullvoidptr
#define srec_close_and_cleanup bfd_generic_close_and_cleanup
#define srec_bfd_debug_info_start bfd_void
#define srec_bfd_debug_info_end bfd_void
#define srec_bfd_debug_info_accumulate (FOO(void, (*), (bfd *, asection *))) bfd_void
bfd_target srec_vec =
@ -420,6 +422,7 @@ bfd_target srec_vec =
|SEC_ALLOC | SEC_LOAD | SEC_RELOC), /* section flags */
' ', /* ar_pad_char */
16, /* ar_max_namelen */
1, /* minimum alignment */
_do_getb64, _do_putb64, _do_getb32, _do_putb32, _do_getb16, _do_putb16, /* data */
_do_getb64, _do_putb64, _do_getb32, _do_putb32, _do_getb16, _do_putb16, /* hdrs */

View File

@ -19,13 +19,262 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
/* $Id$ */
/* This -*- C -*- source file will someday be machine-generated */
/*** Defines the target vector through which operations dispatch */
#include <sysdep.h>
#include "bfd.h"
#include "libbfd.h"
/*doc*
@section Targets
Each port of BFD to a different machine requries the creation of a
target back end. All the back end provides to the root part of bfd is
a structure containing pointers to functions which perform certain low
level operations on files. BFD translates the applications's requests
through a pointer into calls to the back end routines.
When a file is opened with @code{bfd_openr}, its format and target are
unknown. BFD uses various mechanisms to determine how to interpret the
file. The operatios performed are:
@itemize @bullet
@item
First a bfd is created by calling the internal routine
@code{new_bfd}, then @code{bfd_find_target} is called with the target
string supplied to @code{bfd_openr} and the new bfd pointer.
@item
If a null target string was provided to
@code{bfd_find_target}, it looks up the environment variable
@code{GNUTARGET} and uses that as the target string.
@item
If the target string is still NULL, or the target string
is @code{default}, then the first item in the target vector is used as
the target type. @xref{targets}.
@item
Otherwise, the elements in the target vector are
inspected one by one, until a match on target name is found. When
found, that is used.
@item
Otherwise the error @code{invalid_target} is returned to
@code{bfd_openr}.
@item
@code{bfd_openr} attempts to open the file using
@code{bfd_open_file}, and returns the bfd.
@end itemize
Once the bfd has been opened and the target selected, the file format
may be determined. This is done by calling @code{bfd_check_format} on
the bfd with a suggested format. The routine returns @code{true} when
the application guesses right.
*/
/*proto* bfd_target
@node bfd_target
@subsection bfd_target
This structure contains everything that BFD knows about a target.
It includes things like its byte order, name, what routines to call
to do various operations, etc.
Every BFD points to a target structure with its "xvec" member.
Shortcut for declaring fields which are prototyped function pointers,
while avoiding anguish on compilers that don't support protos.
$#define SDEF(ret, name, arglist) \
$ PROTO(ret,(*name),arglist)
$#define SDEF_FMT(ret, name, arglist) \
$ PROTO(ret,(*name[bfd_type_end]),arglist)
These macros are used to dispatch to functions through the bfd_target
vector. They are used in a number of macros further down in bfd.h, and
are also used when calling various routines by hand inside the bfd
implementation. The "arglist" argument must be parenthesized; it
contains all the arguments to the called function.
$#define BFD_SEND(bfd, message, arglist) \
$ ((*((bfd)->xvec->message)) arglist)
For operations which index on the bfd format
$#define BFD_SEND_FMT(bfd, message, arglist) \
$ (((bfd)->xvec->message[(int)((bfd)->format)]) arglist)
This is the struct which defines the type of BFD this is. The
"xvec" member of the struct bfd itself points here. Each module
that implements access to a different target under BFD, defines
one of these.
FIXME, these names should be rationalised with the names of the
entry points which call them. Too bad we can't have one macro to
define them both!
*+++
$typedef struct bfd_target
${
identifies the kind of target, eg SunOS4, Ultrix, etc
$ char *name;
The "flavour" of a back end is a general indication about the contents
of a file.
$ enum target_flavour_enum {
$ bfd_target_aout_flavour_enum,
$ bfd_target_coff_flavour_enum,
$ bfd_target_ieee_flavour_enum,
$ bfd_target_oasys_flavour_enum,
$ bfd_target_srec_flavour_enum} flavour;
The order of bytes within the data area of a file.
$ boolean byteorder_big_p;
The order of bytes within the header parts of a file.
$ boolean header_byteorder_big_p;
This is a mask of all the flags which an executable may have set -
from the set @code{NO_FLAGS}, @code{HAS_RELOC}, ...@code{D_PAGED}.
$ flagword object_flags;
This is a mask of all the flags which a section may have set - from
the set @code{SEC_NO_FLAGS}, @code{SEC_ALLOC}, ...@code{SET_NEVER_LOAD}.
$ flagword section_flags;
The pad character for filenames within an archive header.
$ char ar_pad_char;
The maximum number of characters in an archive header.
$ unsigned short ar_max_namelen;
The minimum alignment restriction for any section.
$ unsigned int align_power_min;
Entries for byte swapping for data. These are different to the other
entry points, since they don't take bfd as first arg. Certain other handlers
could do the same.
$ SDEF (bfd_64_type, bfd_getx64, (bfd_byte *));
$ SDEF (void, bfd_putx64, (bfd_64_type, bfd_byte *));
$ SDEF (unsigned int, bfd_getx32, (bfd_byte *));
$ SDEF (void, bfd_putx32, (unsigned long, bfd_byte *));
$ SDEF (unsigned int, bfd_getx16, (bfd_byte *));
$ SDEF (void, bfd_putx16, (int, bfd_byte *));
Byte swapping for the headers
$ SDEF (bfd_64_type, bfd_h_getx64, (bfd_byte *));
$ SDEF (void, bfd_h_putx64, (bfd_64_type, bfd_byte *));
$ SDEF (unsigned int, bfd_h_getx32, (bfd_byte *));
$ SDEF (void, bfd_h_putx32, (unsigned long, bfd_byte *));
$ SDEF (unsigned int, bfd_h_getx16, (bfd_byte *));
$ SDEF (void, bfd_h_putx16, (int, bfd_byte *));
Format dependent routines, these turn into vectors of entry points
within the target vector structure; one for each format to check.
Check the format of a file being read. Return bfd_target * or zero.
$ SDEF_FMT (struct bfd_target *, _bfd_check_format, (bfd *));
Set the format of a file being written.
$ SDEF_FMT (boolean, _bfd_set_format, (bfd *));
Write cached information into a file being written, at bfd_close.
$ SDEF_FMT (boolean, _bfd_write_contents, (bfd *));
The following functions are defined in @code{JUMP_TABLE}. The idea is
that the back end writer of @code{foo} names all the routines
@code{foo_}@var{entry_point}, @code{JUMP_TABLE} will built the entries
in this structure in the right order.
Core file entry points
$ SDEF (char *, _core_file_failing_command, (bfd *));
$ SDEF (int, _core_file_failing_signal, (bfd *));
$ SDEF (boolean, _core_file_matches_executable_p, (bfd *, bfd *));
Archive entry points
$ SDEF (boolean, _bfd_slurp_armap, (bfd *));
$ SDEF (boolean, _bfd_slurp_extended_name_table, (bfd *));
$ SDEF (void, _bfd_truncate_arname, (bfd *, CONST char *, char *));
$ SDEF (boolean, write_armap, (bfd *arch,
$ unsigned int elength,
$ struct orl *map,
$ int orl_count,
$ int stridx));
Standard stuff.
$ SDEF (boolean, _close_and_cleanup, (bfd *));
$ SDEF (boolean, _bfd_set_section_contents, (bfd *, sec_ptr, PTR,
$ file_ptr, bfd_size_type));
$ SDEF (boolean, _bfd_get_section_contents, (bfd *, sec_ptr, PTR,
$ file_ptr, bfd_size_type));
$ SDEF (boolean, _new_section_hook, (bfd *, sec_ptr));
Symbols and reloctions
$ SDEF (unsigned int, _get_symtab_upper_bound, (bfd *));
$ SDEF (unsigned int, _bfd_canonicalize_symtab,
$ (bfd *, struct symbol_cache_entry **));
$ SDEF (unsigned int, _get_reloc_upper_bound, (bfd *, sec_ptr));
$ SDEF (unsigned int, _bfd_canonicalize_reloc, (bfd *, sec_ptr, arelent **,
$ struct symbol_cache_entry**));
$ SDEF (struct symbol_cache_entry *, _bfd_make_empty_symbol, (bfd *));
$ SDEF (void, _bfd_print_symbol, (bfd *, PTR, struct symbol_cache_entry *,
$ bfd_print_symbol_enum_type));
$#define bfd_print_symbol(b,p,s,e) BFD_SEND(b, _bfd_print_symbol, (b,p,s,e))
$ SDEF (alent *, _get_lineno, (bfd *, struct symbol_cache_entry *));
$
$ SDEF (boolean, _bfd_set_arch_mach, (bfd *, enum bfd_architecture,
$ unsigned long));
$
$ SDEF (bfd *, openr_next_archived_file, (bfd *arch, bfd *prev));
$ SDEF (boolean, _bfd_find_nearest_line,
$ (bfd *abfd, struct sec *section,
$ struct symbol_cache_entry **symbols,bfd_vma offset,
$ CONST char **file, CONST char **func, unsigned int *line));
$ SDEF (int, _bfd_stat_arch_elt, (bfd *, struct stat *));
$
$ SDEF (int, _bfd_sizeof_headers, (bfd *, boolean));
$
$ SDEF (void, _bfd_debug_info_start, (bfd *));
$ SDEF (void, _bfd_debug_info_end, (bfd *));
$ SDEF (void, _bfd_debug_info_accumulate, (bfd *, struct sec *));
Special entry points for gdb to swap in coff symbol table parts
$ SDEF(void, _bfd_coff_swap_aux_in,(
$ bfd *abfd ,
$ PTR ext,
$ int type,
$ int class ,
$ PTR in));
$
$ SDEF(void, _bfd_coff_swap_sym_in,(
$ bfd *abfd ,
$ PTR ext,
$ PTR in));
$
$ SDEF(void, _bfd_coff_swap_lineno_in, (
$ bfd *abfd,
$ PTR ext,
$ PTR in));
$
$} bfd_target;
*---
*/
extern bfd_target ecoff_little_vec;
extern bfd_target ecoff_big_vec;
extern bfd_target sunos_big_vec;
@ -57,8 +306,8 @@ extern bfd_target DEFAULT_VECTOR;
#define ECOFF_BIG_VEC ecoff_big_vec
#define ICOFF_LITTLE_VEC icoff_little_vec
#define ICOFF_BIG_VEC icoff_big_vec
#define XB_OUT_VEC_LITTLE_HOST b_out_vec_little_host
#define XB_OUT_VEC_BIG_HOST b_out_vec_big_host
#define ZB_OUT_VEC_LITTLE_HOST b_out_vec_little_host
#define ZB_OUT_VEC_BIG_HOST b_out_vec_big_host
#define SUNOS_VEC_BIG_HOST sunos_big_vec
#define DEMO_64_VEC demo_64_vec
#define OASYS_VEC oasys_vec
@ -145,3 +394,81 @@ bfd_target *default_vector[] = {
#endif
0,
};
/*proto*
*i bfd_find_target
Returns a pointer to the transfer vector for the object target
named target_name. If target_name is NULL, chooses the one in the
environment variable GNUTARGET; if that is null or not defined then
the first entry in the target list is chosen. Passing in the
string "default" or setting the environment variable to "default"
will cause the first entry in the target list to be returned,
and "target_defaulted" will be set in the bfd. This causes
bfd_check_format to loop over all the targets to find the one
that matches the file being read.
*; PROTO(bfd_target *, bfd_find_target,(CONST char *, bfd *));
*-*/
bfd_target *
DEFUN(bfd_find_target,(target_name, abfd),
CONST char *target_name AND
bfd *abfd)
{
bfd_target **target;
extern char *getenv ();
CONST char *targname = (target_name ? target_name : getenv ("GNUTARGET"));
/* This is safe; the vector cannot be null */
if (targname == NULL || !strcmp (targname, "default")) {
abfd->target_defaulted = true;
return abfd->xvec = target_vector[0];
}
abfd->target_defaulted = false;
for (target = &target_vector[0]; *target != NULL; target++) {
if (!strcmp (targname, (*target)->name))
return abfd->xvec = *target;
}
bfd_error = invalid_target;
return NULL;
}
/*proto*
*i bfd_target_list
This function returns a freshly malloced NULL-terminated vector of the
names of all the valid bfd targets. Do not modify the names
*; PROTO(CONST char **,bfd_target_list,());
*-*/
CONST char **
DEFUN_VOID(bfd_target_list)
{
int vec_length= 0;
bfd_target **target;
CONST char **name_list, **name_ptr;
for (target = &target_vector[0]; *target != NULL; target++)
vec_length++;
name_ptr =
name_list = (CONST char **) zalloc ((vec_length + 1) * sizeof (char **));
if (name_list == NULL) {
bfd_error = no_memory;
return NULL;
}
for (target = &target_vector[0]; *target != NULL; target++)
*(name_ptr++) = (*target)->name;
return name_list;
}