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,7 +84,10 @@ echo Done in `pwd`.
#
#
# $Log$
# Revision 1.3 1991/05/31 11:22:12 gnu
# 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.
#
# Revision 1.2 1991/05/29 02:40:08 gnu

View File

@ -1,4 +1,4 @@
#
#
# Copyright (C) 1990, 1991 Free Software Foundation, Inc.
#
# This file is part of BFD, the Binary File Diddler.
@ -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,31 +487,42 @@ 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
bfd_target VECNAME =
{
TARGETNAME,
bfd_target_aout_flavour_enum,
true, /* target byte order */
true, /* target headers byte order */
(HAS_RELOC | EXEC_P | /* object flags */
HAS_LINENO | HAS_DEBUG |
HAS_SYMS | HAS_LOCALS | DYNAMIC | WP_TEXT | D_PAGED),
(SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC), /* section flags */
' ', /* ar_pad_char */
16, /* ar_max_namelen */
_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, NAME(sunos,object_p),
bfd_generic_archive_p, sunos4_core_file_p},
{bfd_false, NAME(aout,mkobject),
_bfd_generic_mkarchive, bfd_false},
{bfd_false, NAME(aout,sunos4_write_object_contents), /* bfd_write_contents */
_bfd_write_archive_contents, bfd_false},
JUMP_TABLE(JNAME(aout))
};
TARGETNAME,
bfd_target_aout_flavour_enum,
true, /* target byte order */
true, /* target headers byte order */
(HAS_RELOC | EXEC_P | /* object flags */
HAS_LINENO | HAS_DEBUG |
HAS_SYMS | HAS_LOCALS | DYNAMIC | WP_TEXT | D_PAGED),
(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 */
{_bfd_dummy_target, NAME(sunos,object_p),
bfd_generic_archive_p, sunos4_core_file_p},
{bfd_false, NAME(aout,mkobject),
_bfd_generic_mkarchive, bfd_false},
{bfd_false, NAME(aout,sunos4_write_object_contents), /* bfd_write_contents */
_bfd_write_archive_contents, bfd_false},
JUMP_TABLE(JNAME(aout))
};

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
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. */
/*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.
*; 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
@ -1460,7 +1593,7 @@ DEFUN(NAME(aout,find_nearest_line),(abfd,
buffer[sizeof(buffer)-1] = 0;
/* Have to remove : stuff */
p = strchr(buffer,':');
if (p != NULL) {*p = NULL; }
if (p != NULL) { *p = NULL; }
*functionname_ptr = buffer;
return true;

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
@ -578,49 +622,52 @@ _bfd_slurp_extended_name_table (abfd)
we probably don't want to return true. */
if (bfd_read ((PTR)nextname, 1, 16, abfd) == 16) {
bfd_seek (abfd, -16L, SEEK_CUR);
bfd_seek (abfd, -16L, SEEK_CUR);
if (strncmp (nextname, "ARFILENAMES/ ", 16)) {
bfd_ardata (abfd)->extended_names = NULL;
return true;
}
if (strncmp (nextname, "ARFILENAMES/ ", 16) != 0 &&
strncmp (nextname, "// ", 16) != 0)
{
bfd_ardata (abfd)->extended_names = NULL;
return true;
}
namedata = snarf_ar_hdr (abfd);
if (namedata == NULL) return false;
namedata = snarf_ar_hdr (abfd);
if (namedata == NULL) return false;
bfd_ardata (abfd)->extended_names = bfd_zalloc(abfd,namedata->parsed_size);
if (bfd_ardata (abfd)->extended_names == NULL) {
bfd_error = no_memory;
byebye:
bfd_release (abfd, (PTR)namedata);
return false;
}
bfd_ardata (abfd)->extended_names = bfd_zalloc(abfd,namedata->parsed_size);
if (bfd_ardata (abfd)->extended_names == NULL) {
bfd_error = no_memory;
byebye:
bfd_release (abfd, (PTR)namedata);
return false;
}
if (bfd_read ((PTR)bfd_ardata (abfd)->extended_names, 1,
namedata->parsed_size, abfd) != namedata->parsed_size) {
bfd_error = malformed_archive;
bfd_release (abfd, (PTR)(bfd_ardata (abfd)->extended_names));
bfd_ardata (abfd)->extended_names = NULL;
goto byebye;
}
if (bfd_read ((PTR)bfd_ardata (abfd)->extended_names, 1,
namedata->parsed_size, abfd) != namedata->parsed_size) {
bfd_error = malformed_archive;
bfd_release (abfd, (PTR)(bfd_ardata (abfd)->extended_names));
bfd_ardata (abfd)->extended_names = NULL;
goto byebye;
}
/* It appears that the extended names are newline-padded, not null padded.
*/
{
char *temp = bfd_ardata (abfd)->extended_names;
for (; *temp != '\0'; ++temp)
if (*temp == '\n') *temp = '\0';
}
/* 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)
if (*temp == '\n') *temp = '\0';
}
/* Pad to an even boundary if you have to */
bfd_ardata (abfd)->first_file_filepos = bfd_tell (abfd);
bfd_ardata (abfd)->first_file_filepos +=
(bfd_ardata (abfd)->first_file_filepos) %2;
/* Pad to an even boundary if you have to */
bfd_ardata (abfd)->first_file_filepos = bfd_tell (abfd);
bfd_ardata (abfd)->first_file_filepos +=
(bfd_ardata (abfd)->first_file_filepos) %2;
/* FIXME, we can't release namedata here because it was allocated
below extended_names on the obstack... */
/* bfd_release (abfd, namedata); */
}
/* FIXME, we can't release namedata here because it was allocated
below extended_names on the obstack... */
/* bfd_release (abfd, namedata); */
}
return true;
}
@ -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);

947
bfd/bfd.c

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

1388
bfd/ieee.c

File diff suppressed because it is too large Load Diff

View File

@ -138,10 +138,10 @@ DEFUN(zalloc,(size),
static
int DEFUN(real_read,(where, a,b, file),
PTR where AND
int a AND
int b AND
FILE *file)
PTR where AND
int a AND
int b AND
FILE *file)
{
return fread(where, a,b,file);
}
@ -171,43 +171,44 @@ DEFUN(bfd_seek,(abfd, position, direction),
CONST file_ptr position AND
CONST int direction)
{
/* For the time being, a bfd may not seek to it's end. The
problem is that we don't easily have a way to recognize
the end of an element in an archive. */
/* For the time being, a bfd may not seek to it's end. The
problem is that we don't easily have a way to recognize
the end of an element in an archive. */
BFD_ASSERT(direction == SEEK_SET
|| direction == SEEK_CUR);
if (direction == SEEK_SET && abfd->my_archive != NULL)
{
/* This is a set within an archive, so we need to
add the base of the object within the archive */
return(fseek(bfd_cache_lookup(abfd),
position + abfd->origin,
direction));
}
else
{
return(fseek(bfd_cache_lookup(abfd), position, direction));
}
BFD_ASSERT(direction == SEEK_SET
|| direction == SEEK_CUR);
if (direction == SEEK_SET && abfd->my_archive != NULL)
{
/* This is a set within an archive, so we need to
add the base of the object within the archive */
return(fseek(bfd_cache_lookup(abfd),
position + abfd->origin,
direction));
}
else
{
return(fseek(bfd_cache_lookup(abfd), position, direction));
}
}
long
DEFUN(bfd_tell,(abfd),
bfd *abfd)
{
file_ptr ptr;
file_ptr ptr;
ptr = ftell (bfd_cache_lookup(abfd));
ptr = ftell (bfd_cache_lookup(abfd));
if (abfd->my_archive)
ptr -= abfd->origin;
return ptr;
if (abfd->my_archive)
ptr -= abfd->origin;
return ptr;
}
/** 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 */
@ -227,7 +228,7 @@ DEFUN(bfd_add_to_string_table,(table, new_string, table_length, free_ptr),
/* Avoid a useless regrow if we can (but of course we still
take it next time */
space_length = (string_length < DEFAULT_STRING_SPACE_SIZE ?
DEFAULT_STRING_SPACE_SIZE : string_length+1);
DEFAULT_STRING_SPACE_SIZE : string_length+1);
base = zalloc (space_length);
if (base == NULL) {
@ -265,21 +266,76 @@ DEFUN(bfd_add_to_string_table,(table, new_string, table_length, free_ptr),
/* FIXME: Should these take a count argument?
Answer (gnu@cygnus.com): No, but perhaps they should be inline
functions in swap.h #ifdef __GNUC__.
Gprof them later and find out. */
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)
{
return (addr[0] << 8) | addr[1];
return (addr[0] << 8) | addr[1];
}
unsigned int
DEFUN(_do_getl16,(addr),
register bfd_byte *addr)
{
return (addr[1] << 8) | addr[0];
return (addr[1] << 8) | addr[0];
}
void
@ -287,31 +343,31 @@ DEFUN(_do_putb16,(data, addr),
int data AND
register bfd_byte *addr)
{
addr[0] = (bfd_byte)(data >> 8);
addr[1] = (bfd_byte )data;
addr[0] = (bfd_byte)(data >> 8);
addr[1] = (bfd_byte )data;
}
void
DEFUN(_do_putl16,(data, addr),
int data AND
int data AND
register bfd_byte *addr)
{
addr[0] = (bfd_byte )data;
addr[1] = (bfd_byte)(data >> 8);
addr[0] = (bfd_byte )data;
addr[1] = (bfd_byte)(data >> 8);
}
unsigned int
DEFUN(_do_getb32,(addr),
register bfd_byte *addr)
{
return ((((addr[0] << 8) | addr[1]) << 8) | addr[2]) << 8 | addr[3];
return ((((addr[0] << 8) | addr[1]) << 8) | addr[2]) << 8 | addr[3];
}
unsigned int
_do_getl32 (addr)
register bfd_byte *addr;
register bfd_byte *addr;
{
return ((((addr[3] << 8) | addr[2]) << 8) | addr[1]) << 8 | addr[0];
return ((((addr[3] << 8) | addr[2]) << 8) | addr[1]) << 8 | addr[0];
}
bfd_64_type
@ -322,18 +378,20 @@ DEFUN(_do_getb64,(addr),
bfd_64_type low, high;
high= ((((((((addr[0]) << 8) |
addr[1]) << 8) |
addr[2]) << 8) |
addr[3]) );
addr[1]) << 8) |
addr[2]) << 8) |
addr[3]) );
low = ((((((((addr[4]) << 8) |
addr[5]) << 8) |
addr[6]) << 8) |
addr[7]));
addr[5]) << 8) |
addr[6]) << 8) |
addr[7]));
return high << 32 | low;
#else
bfd_64_type foo;
BFD_FAIL();
return foo;
#endif
}
@ -342,22 +400,26 @@ 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) |
addr[4]));
addr[6]) << 8) |
addr[5]) << 8) |
addr[4]));
low = (((((((addr[3] << 8) |
addr[2]) << 8) |
addr[1]) << 8) |
addr[0]) );
addr[2]) << 8) |
addr[1]) << 8) |
addr[0]) );
return high << 32 | low;
#else
bfd_64_type foo;
BFD_FAIL();
return foo;
#endif
}
void
@ -365,10 +427,10 @@ DEFUN(_do_putb32,(data, addr),
unsigned long data AND
register bfd_byte *addr)
{
addr[0] = (bfd_byte)(data >> 24);
addr[1] = (bfd_byte)(data >> 16);
addr[2] = (bfd_byte)(data >> 8);
addr[3] = (bfd_byte)data;
addr[0] = (bfd_byte)(data >> 24);
addr[1] = (bfd_byte)(data >> 16);
addr[2] = (bfd_byte)(data >> 8);
addr[3] = (bfd_byte)data;
}
void
@ -376,15 +438,15 @@ DEFUN(_do_putl32,(data, addr),
unsigned long data AND
register bfd_byte *addr)
{
addr[0] = (bfd_byte)data;
addr[1] = (bfd_byte)(data >> 8);
addr[2] = (bfd_byte)(data >> 16);
addr[3] = (bfd_byte)(data >> 24);
addr[0] = (bfd_byte)data;
addr[1] = (bfd_byte)(data >> 8);
addr[2] = (bfd_byte)(data >> 16);
addr[3] = (bfd_byte)(data >> 24);
}
void
DEFUN(_do_putb64,(data, addr),
bfd_64_type data AND
register bfd_byte *addr)
bfd_64_type data AND
register bfd_byte *addr)
{
#ifdef HOST_64_BIT
addr[0] = (bfd_byte)(data >> (7*8));
@ -433,10 +495,26 @@ DEFUN(bfd_generic_get_section_contents, (abfd, section, location, offset, count)
bfd_size_type count)
{
if (count == 0)
return true;
return true;
if ((bfd_size_type)offset >= section->size
|| bfd_seek(abfd,(file_ptr)( section->filepos + offset), SEEK_SET) == -1
|| bfd_read(location, (bfd_size_type)1, count, abfd) != count)
return (false); /* on error */
|| bfd_seek(abfd,(file_ptr)( section->filepos + offset), SEEK_SET) == -1
|| bfd_read(location, (bfd_size_type)1, count, abfd) != 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,25 +279,53 @@ DEFUN(oasys_archive_p,(abfd),
filepos = header.mod_tbl_offset;
for (i = 0; i < header.mod_count; i++) {
bfd_seek(abfd , filepos, SEEK_SET);
bfd_read((PTR)&record_ext, 1, sizeof(record_ext), abfd);
/* 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);
record.file_offset = bfd_h_get_32(abfd,
record_ext.file_offset);
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.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);
module[i].name = bfd_alloc(abfd,33);
module[i].name = bfd_alloc(abfd,33);
memcpy(module[i].name, record_ext.mod_name, 33);
filepos +=
sizeof(record_ext) +
record.dep_count * 4 +
record.depee_count * 4 +
record.sect_count * 8 + 187,
memcpy(module[i].name, record_ext.mod_name, 33);
filepos +=
sizeof(record_ext) +
record.dep_count * 4 +
record.depee_count * 4 +
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,169 +512,185 @@ 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) {
case oasys_record_is_header_enum:
break;
case oasys_record_is_data_enum:
switch (record.header.type)
{
case oasys_record_is_header_enum:
break;
case oasys_record_is_data_enum:
{
uint8e_type *src = record.data.data;
uint8e_type *end_src = ((uint8e_type *)&record) +
record.header.length;
unsigned int relbit;
bfd_byte *dst_ptr ;
bfd_byte *dst_base_ptr ;
unsigned int count;
asection * section =
data->sections[record.data.relb & RELOCATION_SECT_BITS];
bfd_vma dst_offset ;
per = oasys_per_section(section);
dst_offset = bfd_h_get_32(abfd, record.data.addr) ;
if (per->had_vma == false) {
/* Take the first vma we see as the base */
section->vma = dst_offset;
per->had_vma = true;
}
uint8e_type *src = record.data.data;
uint8e_type *end_src = ((uint8e_type *)&record) +
record.header.length;
unsigned int relbit;
bfd_byte *dst_ptr ;
bfd_byte *dst_base_ptr ;
unsigned int count;
asection * section =
data->sections[record.data.relb & RELOCATION_SECT_BITS];
bfd_vma dst_offset ;
per = oasys_per_section(section);
dst_offset -= section->vma;
dst_base_ptr = oasys_per_section(section)->data;
dst_ptr = oasys_per_section(section)->data +
dst_offset;
while (src < end_src) {
uint32_type gap = end_src - src -1;
uint8e_type mod_byte = *src++;
count = 8;
if (mod_byte == 0 && gap >= 8) {
dst_ptr[0] = src[0];
dst_ptr[1] = src[1];
dst_ptr[2] = src[2];
dst_ptr[3] = src[3];
dst_ptr[4] = src[4];
dst_ptr[5] = src[5];
dst_ptr[6] = src[6];
dst_ptr[7] = src[7];
dst_ptr+= 8;
src += 8;
}
else {
for (relbit = 1; count-- != 0 && gap != 0; gap --, relbit <<=1)
if (per->initialized == false)
{
if (relbit & mod_byte)
{
uint8e_type reloc = *src;
/* This item needs to be relocated */
switch (reloc & RELOCATION_TYPE_BITS) {
case RELOCATION_TYPE_ABS:
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;
}
break;
dst_offset = bfd_h_get_32(abfd, record.data.addr) ;
if (per->had_vma == false) {
/* Take the first vma we see as the base */
case RELOCATION_TYPE_REL:
{
/* Relocate the item relative to the section */
oasys_reloc_type *r =
(oasys_reloc_type *)
bfd_alloc(abfd,
sizeof(oasys_reloc_type));
*(per->reloc_tail_ptr) = r;
per->reloc_tail_ptr = &r->next;
r->next= (oasys_reloc_type *)NULL;
/* Reference to undefined symbol */
src++;
/* There is no symbol */
r->symbol = 0;
/* Work out the howto */
r->relent.section =
data->sections[reloc & RELOCATION_SECT_BITS];
r->relent.addend = - r->relent.section->vma;
r->relent.address = dst_ptr - dst_base_ptr;
r->relent.howto = &howto_table[reloc>>6];
r->relent.sym_ptr_ptr = (asymbol **)NULL;
section->reloc_count++;
/* Fake up the data to look like it's got the -ve pc in it, this makes
it much easier to convert into other formats. This is done by
hitting the addend.
*/
if (r->relent.howto->pc_relative == true) {
r->relent.addend -= dst_ptr - dst_base_ptr;
}
section->vma = dst_offset;
per->had_vma = true;
}
}
break;
dst_offset -= section->vma;
case RELOCATION_TYPE_UND:
{
oasys_reloc_type *r =
(oasys_reloc_type *)
bfd_alloc(abfd,
sizeof(oasys_reloc_type));
*(per->reloc_tail_ptr) = r;
per->reloc_tail_ptr = &r->next;
r->next= (oasys_reloc_type *)NULL;
/* Reference to undefined symbol */
src++;
/* Get symbol number */
r->symbol = (src[0]<<8) | src[1];
/* Work out the howto */
r->relent.section = (asection *)NULL;
r->relent.addend = 0;
r->relent.address = dst_ptr - dst_base_ptr;
r->relent.howto = &howto_table[reloc>>6];
r->relent.sym_ptr_ptr = (asymbol **)NULL;
section->reloc_count++;
dst_base_ptr = oasys_per_section(section)->data;
dst_ptr = oasys_per_section(section)->data +
dst_offset;
src+=2;
/* Fake up the data to look like it's got the -ve pc in it, this makes
it much easier to convert into other formats. This is done by
hitting the addend.
*/
if (r->relent.howto->pc_relative == true) {
r->relent.addend -= dst_ptr - dst_base_ptr;
}
if (src < end_src) {
section->flags |= SEC_LOAD | SEC_HAS_CONTENTS;
}
while (src < end_src) {
uint8e_type mod_byte = *src++;
uint32_type gap = end_src - src;
count = 8;
if (mod_byte == 0 && gap >= 8) {
dst_ptr[0] = src[0];
dst_ptr[1] = src[1];
dst_ptr[2] = src[2];
dst_ptr[3] = src[3];
dst_ptr[4] = src[4];
dst_ptr[5] = src[5];
dst_ptr[6] = src[6];
dst_ptr[7] = src[7];
dst_ptr+= 8;
src += 8;
}
else {
for (relbit = 1; count-- != 0 && src < end_src; relbit <<=1)
{
if (relbit & mod_byte)
{
uint8e_type reloc = *src;
/* This item needs to be relocated */
switch (reloc & RELOCATION_TYPE_BITS) {
case RELOCATION_TYPE_ABS:
break;
case RELOCATION_TYPE_REL:
{
/* Relocate the item relative to the section */
oasys_reloc_type *r =
(oasys_reloc_type *)
bfd_alloc(abfd,
sizeof(oasys_reloc_type));
*(per->reloc_tail_ptr) = r;
per->reloc_tail_ptr = &r->next;
r->next= (oasys_reloc_type *)NULL;
/* Reference to undefined symbol */
src++;
/* There is no symbol */
r->symbol = 0;
/* Work out the howto */
r->relent.section =
data->sections[reloc & RELOCATION_SECT_BITS];
r->relent.addend = - r->relent.section->vma;
r->relent.address = dst_ptr - dst_base_ptr;
r->relent.howto = &howto_table[reloc>>6];
r->relent.sym_ptr_ptr = (asymbol **)NULL;
section->reloc_count++;
/* Fake up the data to look like it's got the -ve pc in it, this makes
it much easier to convert into other formats. This is done by
hitting the addend.
*/
if (r->relent.howto->pc_relative == true) {
r->relent.addend -= dst_ptr - dst_base_ptr;
}
}
break;
case RELOCATION_TYPE_UND:
{
oasys_reloc_type *r =
(oasys_reloc_type *)
bfd_alloc(abfd,
sizeof(oasys_reloc_type));
*(per->reloc_tail_ptr) = r;
per->reloc_tail_ptr = &r->next;
r->next= (oasys_reloc_type *)NULL;
/* Reference to undefined symbol */
src++;
/* Get symbol number */
r->symbol = (src[0]<<8) | src[1];
/* Work out the howto */
r->relent.section = (asection *)NULL;
r->relent.addend = 0;
r->relent.address = dst_ptr - dst_base_ptr;
r->relent.howto = &howto_table[reloc>>6];
r->relent.sym_ptr_ptr = (asymbol **)NULL;
section->reloc_count++;
src+=2;
/* Fake up the data to look like it's got the -ve pc in it, this makes
it much easier to convert into other formats. This is done by
hitting the addend.
*/
if (r->relent.howto->pc_relative == true) {
r->relent.addend -= dst_ptr - dst_base_ptr;
}
}
break;
case RELOCATION_TYPE_COM:
BFD_FAIL();
}
break;
case RELOCATION_TYPE_COM:
BFD_FAIL();
}
}
*dst_ptr++ = *src++;
}
}
*dst_ptr++ = *src++;
}
}
}
}
}
break;
case oasys_record_is_local_enum:
case oasys_record_is_symbol_enum:
case oasys_record_is_section_enum:
break;
default:
loop = false;
}
break;
case oasys_record_is_local_enum:
case oasys_record_is_symbol_enum:
case oasys_record_is_section_enum:
break;
default:
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);
(void) memcpy(location, p->data + offset, (int)count);
if (p->initialized == false)
{
(void) memset(location, 0, (int)count);
}
else
{
(void) memcpy(location, p->data + offset, (int)count);
}
return true;
}
@ -781,7 +852,15 @@ DEFUN(oasys_write_syms, (abfd),
continue;
}
else {
symbol.relb = RELOCATION_TYPE_REL | g->section->output_section->target_index;
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,140 +979,142 @@ DEFUN(oasys_write_data, (abfd),
{
asection *s;
for (s = abfd->sections; s != (asection *)NULL; s = s->next) {
uint8e_type *raw_data = oasys_per_section(s)->data;
oasys_data_record_type processed_data;
bfd_size_type current_byte_index = 0;
unsigned int relocs_to_go = s->reloc_count;
arelent **p = s->orelocation;
if (s->reloc_count != 0) {
/* Sort the reloc records so it's easy to insert the relocs into the
data */
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;
unsigned int relocs_to_go = s->reloc_count;
arelent **p = s->orelocation;
if (s->reloc_count != 0) {
/* Sort the reloc records so it's easy to insert the relocs into the
data */
qsort(s->orelocation,
s->reloc_count,
sizeof(arelent **),
comp);
}
current_byte_index = 0;
processed_data.relb = s->target_index | RELOCATION_TYPE_REL;
qsort(s->orelocation,
s->reloc_count,
sizeof(arelent **),
comp);
}
current_byte_index = 0;
processed_data.relb = s->target_index | RELOCATION_TYPE_REL;
while (current_byte_index < s->size)
{
/* Scan forwards by eight bytes or however much is left and see if
there are any relocations going on */
uint8e_type *mod = &processed_data.data[0];
uint8e_type *dst = &processed_data.data[1];
while (current_byte_index < s->size)
{
/* Scan forwards by eight bytes or however much is left and see if
there are any relocations going on */
uint8e_type *mod = &processed_data.data[0];
uint8e_type *dst = &processed_data.data[1];
unsigned int i;
unsigned int long_length = 128;
unsigned int i;
unsigned int long_length = 128;
bfd_h_put_32(abfd, s->vma + current_byte_index, processed_data.addr);
if ((size_t)(long_length + current_byte_index) > (size_t)(s->size)) {
long_length = s->size - current_byte_index;
}
while (long_length > 0 && (dst - (uint8e_type*)&processed_data < 128)) {
bfd_h_put_32(abfd, s->vma + current_byte_index, processed_data.addr);
if ((size_t)(long_length + current_byte_index) > (size_t)(s->size)) {
long_length = s->size - current_byte_index;
}
while (long_length > 0 && (dst - (uint8e_type*)&processed_data < 128)) {
unsigned int length = long_length;
*mod =0;
if (length > 8)
length = 8;
unsigned int length = long_length;
*mod =0;
if (length > 8)
length = 8;
for (i = 0; i < length; i++) {
if (relocs_to_go != 0) {
arelent *r = *p;
reloc_howto_type *CONST how=r->howto;
/* There is a relocation, is it for this byte ? */
if (r->address == current_byte_index) {
uint8e_type rel_byte;
p++;
relocs_to_go--;
for (i = 0; i < length; i++) {
if (relocs_to_go != 0) {
arelent *r = *p;
reloc_howto_type *CONST how=r->howto;
/* There is a relocation, is it for this byte ? */
if (r->address == current_byte_index) {
uint8e_type rel_byte;
p++;
relocs_to_go--;
*mod |= (1<<i);
if(how->pc_relative) {
rel_byte = 0x80;
*mod |= (1<<i);
if(how->pc_relative) {
rel_byte = 0x80;
/* Also patch the raw data so that it doesn't have
the -ve stuff any more */
if (how->size != 2) {
bfd_put_16(abfd,
/* Also patch the raw data so that it doesn't have
the -ve stuff any more */
if (how->size != 2) {
bfd_put_16(abfd,
bfd_get_16(abfd,raw_data) +
current_byte_index, raw_data);
}
}
else {
bfd_put_32(abfd,
bfd_get_32(abfd,raw_data) +
current_byte_index, raw_data);
}
}
else {
bfd_put_32(abfd,
bfd_get_32(abfd,raw_data) +
current_byte_index, raw_data);
rel_byte = 0;
}
if (how->size ==2) {
rel_byte |= 0x40;
}
}
else {
rel_byte = 0;
}
if (how->size ==2) {
rel_byte |= 0x40;
}
/* Is this a section relative relocation, or a symbol
relative relocation ? */
if (r->section != (asection*)NULL)
{
/* The relent has a section attatched, so it must be section
relative */
rel_byte |= RELOCATION_TYPE_REL;
rel_byte |= r->section->output_section->target_index;
*dst++ = rel_byte;
}
else
{
asymbol *p = *(r->sym_ptr_ptr);
/* If this symbol has a section attatched, then it
has already been resolved. Change from a symbol
ref to a section ref */
if(p->section != (asection *)NULL) {
/* Is this a section relative relocation, or a symbol
relative relocation ? */
if (r->section != (asection*)NULL)
{
/* The relent has a section attatched, so it must be section
relative */
rel_byte |= RELOCATION_TYPE_REL;
rel_byte |=
p->section->output_section->target_index;
rel_byte |= r->section->output_section->target_index;
*dst++ = rel_byte;
}
else {
rel_byte |= RELOCATION_TYPE_UND;
else
{
asymbol *p = *(r->sym_ptr_ptr);
/* If this symbol has a section attatched, then it
has already been resolved. Change from a symbol
ref to a section ref */
if(p->section != (asection *)NULL) {
rel_byte |= RELOCATION_TYPE_REL;
rel_byte |=
p->section->output_section->target_index;
*dst++ = rel_byte;
}
else {
rel_byte |= RELOCATION_TYPE_UND;
*dst++ = rel_byte;
/* Next two bytes are a symbol index - we can get
this from the symbol value which has been zapped
into the symbol index in the table when the
symbol table was written
*/
*dst++ = p->value >> 8;
*dst++ = p->value;
*dst++ = rel_byte;
/* Next two bytes are a symbol index - we can get
this from the symbol value which has been zapped
into the symbol index in the table when the
symbol table was written
*/
*dst++ = p->value >> 8;
*dst++ = p->value;
}
}
}
}
}
/* If this is coming from an unloadable section then copy
zeros */
if (raw_data == (uint8e_type *)NULL) {
*dst++ = 0;
}
else {
*dst++ = *raw_data++;
}
current_byte_index++;
}
/* If this is coming from an unloadable section then copy
zeros */
if (raw_data == (uint8e_type *)NULL) {
*dst++ = 0;
}
else {
*dst++ = *raw_data++;
}
current_byte_index++;
mod = dst++;
long_length -= length;
}
mod = dst++;
long_length -= length;
}
oasys_write_record(abfd,
oasys_record_is_data_enum,
(oasys_record_union_type *)&processed_data,
dst - (uint8e_type*)&processed_data);
oasys_write_record(abfd,
oasys_record_is_data_enum,
(oasys_record_union_type *)&processed_data,
dst - (uint8e_type*)&processed_data);
}
}
}
}
}
static boolean
@ -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;
@ -46,93 +295,93 @@ extern bfd_target DEFAULT_VECTOR;
#endif
#ifdef GNU960
#define ICOFF_LITTLE_VEC icoff_little_vec
#define ICOFF_BIG_VEC icoff_big_vec
#define B_OUT_VEC_LITTLE_HOST b_out_vec_little_host
#define B_OUT_VEC_BIG_HOST b_out_vec_big_host
#define ICOFF_LITTLE_VEC icoff_little_vec
#define ICOFF_BIG_VEC icoff_big_vec
#define B_OUT_VEC_LITTLE_HOST b_out_vec_little_host
#define B_OUT_VEC_BIG_HOST b_out_vec_big_host
#endif /* GNU960 */
#ifndef RESTRICTED
#define ECOFF_LITTLE_VEC ecoff_little_vec
#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 SUNOS_VEC_BIG_HOST sunos_big_vec
#define DEMO_64_VEC demo_64_vec
#define OASYS_VEC oasys_vec
#define IEEE_VEC ieee_vec
#define M88K_BCS_VEC m88k_bcs_vec
#define SREC_VEC srec_vec
#define M68KCOFF_VEC m68kcoff_vec
#define I386COFF_VEC i386coff_vec
#define ECOFF_LITTLE_VEC ecoff_little_vec
#define ECOFF_BIG_VEC ecoff_big_vec
#define ICOFF_LITTLE_VEC icoff_little_vec
#define ICOFF_BIG_VEC icoff_big_vec
#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
#define IEEE_VEC ieee_vec
#define M88K_BCS_VEC m88k_bcs_vec
#define SREC_VEC srec_vec
#define M68KCOFF_VEC m68kcoff_vec
#define I386COFF_VEC i386coff_vec
#endif
bfd_target *target_vector[] = {
#ifdef DEFAULT_VECTOR
&DEFAULT_VECTOR,
&DEFAULT_VECTOR,
#endif /* DEFAULT_VECTOR */
#ifdef I386COFF_VEC
&I386COFF_VEC,
#endif /* I386COFF_VEC */
#ifdef I386COFF_VEC
&I386COFF_VEC,
#endif /* I386COFF_VEC */
#ifdef ECOFF_LITTLE_VEC
&ECOFF_LITTLE_VEC,
&ECOFF_LITTLE_VEC,
#endif
#ifdef ECOFF_BIG_VEC
&ECOFF_BIG_VEC,
&ECOFF_BIG_VEC,
#endif
#ifdef IEEE_VEC
&IEEE_VEC,
&IEEE_VEC,
#endif /* IEEE_VEC */
#ifdef OASYS_VEC
&OASYS_VEC,
&OASYS_VEC,
#endif /* OASYS_VEC */
#ifdef SUNOS_VEC_BIG_HOST
&SUNOS_VEC_BIG_HOST,
&SUNOS_VEC_BIG_HOST,
#endif /* SUNOS_BIG_VEC */
#ifdef HOST_64_BIT
#ifdef DEMO_64_VEC
&DEMO_64_VEC,
&DEMO_64_VEC,
#endif
#endif
#ifdef M88K_BCS_VEC
&M88K_BCS_VEC,
&M88K_BCS_VEC,
#endif /* M88K_BCS_VEC */
#ifdef SREC_VEC
&SREC_VEC,
&SREC_VEC,
#endif /* SREC_VEC */
#ifdef ICOFF_LITTLE_VEC
&ICOFF_LITTLE_VEC,
&ICOFF_LITTLE_VEC,
#endif /* ICOFF_LITTLE_VEC */
#ifdef ICOFF_BIG_VEC
&ICOFF_BIG_VEC,
&ICOFF_BIG_VEC,
#endif /* ICOFF_BIG_VEC */
#ifdef B_OUT_VEC_LITTLE_HOST
&B_OUT_VEC_LITTLE_HOST,
&B_OUT_VEC_LITTLE_HOST,
#endif /* B_OUT_VEC_LITTLE_HOST */
#ifdef B_OUT_VEC_BIG_HOST
&B_OUT_VEC_BIG_HOST,
&B_OUT_VEC_BIG_HOST,
#endif /* B_OUT_VEC_BIG_HOST */
#ifdef M68KCOFF_VEC
&M68KCOFF_VEC,
#endif /* M68KCOFF_VEC */
#ifdef M68KCOFF_VEC
&M68KCOFF_VEC,
#endif /* M68KCOFF_VEC */
NULL, /* end of list marker */
NULL, /* end of list marker */
};
@ -141,7 +390,85 @@ bfd_target *target_vector[] = {
bfd_target *default_vector[] = {
#ifdef DEFAULT_VECTOR
&DEFAULT_VECTOR,
&DEFAULT_VECTOR,
#endif
0,
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;
}