diff options
author | Jordan K. Hubbard <jkh@FreeBSD.org> | 1994-12-30 23:27:33 +0000 |
---|---|---|
committer | Jordan K. Hubbard <jkh@FreeBSD.org> | 1994-12-30 23:27:33 +0000 |
commit | 01db5e69c1b8ed8f657fa883a9416c69b2e5425a (patch) | |
tree | 9e4e1ee771b678aacbaa34624639c5b3ea159d34 /gnu/usr.bin/gdb/bfd | |
parent | 2558753d2e1a7823a7df6d1220d6ba120b54c58e (diff) |
Hurrah! Let the champagne flow, the olive oil barrel be opened and
the wild, slippery orgy commence!
Gary Jennejohn, too studly for his own good, has finally come through with
the new, improved gdb 4.13. This gdb features:
o kgdb support - if this works (and I urge folks to test it), we can
finally purge the old and hateful version of kgdb from our source
tree.
o attach/detach support. See comments in README.FreeBSD for more
details.
o Well, it's newer. Our previous version was 4.11.
Comments and flames to gj, of course! :-)
Thanks, Gary. Much appreciated. The previous state of gdb/kgdb has been a
thorn in all of our sides for some time..
Submitted by: gj
Notes
Notes:
svn path=/head/; revision=5300
Diffstat (limited to 'gnu/usr.bin/gdb/bfd')
35 files changed, 13501 insertions, 7305 deletions
diff --git a/gnu/usr.bin/gdb/bfd/Makefile b/gnu/usr.bin/gdb/bfd/Makefile index ea29afed0d86..24322afcabfb 100644 --- a/gnu/usr.bin/gdb/bfd/Makefile +++ b/gnu/usr.bin/gdb/bfd/Makefile @@ -1,8 +1,17 @@ LIB = bfd -SRCS = archive.c archures.c bfd.c cache.c coffgen.c core.c ctor.c \ - format.c init.c libbfd.c opncls.c reloc.c seclet.c section.c syms.c \ - targets.c ecoff.c elf.c srec.c freebsd386.c aout32.c stab-syms.c \ - cpu-i386.c trad-core.c + +SRCS = libbfd.c opncls.c bfd.c archive.c targets.c cache.c \ + archures.c coff-i386.c aout32.c \ + srec.c \ + ecoff.c ecofflink.c \ + coffgen.c format.c \ + section.c core.c syms.c stab-syms.c reloc.c init.c ctor.c \ + trad-core.c \ + i386aout.c \ + freebsd386.c \ + cpu-i386.c \ + elf.c elf32.c elf32-i386.c \ + hash.c linker.c CFLAGS+= -I$(.CURDIR)/. -I$(.CURDIR)/../gdb/. CFLAGS+= -DDEFAULT_VECTOR=freebsd386_vec -DSELECT_VECS='&freebsd386_vec' \ diff --git a/gnu/usr.bin/gdb/bfd/README.FreeBSD b/gnu/usr.bin/gdb/bfd/README.FreeBSD index 204119c1af74..033fa005db07 100644 --- a/gnu/usr.bin/gdb/bfd/README.FreeBSD +++ b/gnu/usr.bin/gdb/bfd/README.FreeBSD @@ -1,7 +1,4 @@ This is a greatly pared down libbfd directory. Only what's required to build -gdb-4.12 on FreeBSD was kept. +gdb-4.13 on FreeBSD 2.0 was kept. -This is temporary. In FreeBSD 2.0 a fully ported libbfd will likely appear -as a system library for use by all the build tools. - -paul@freefall.cdrom.com +gj@freebsd.org diff --git a/gnu/usr.bin/gdb/bfd/VERSION b/gnu/usr.bin/gdb/bfd/VERSION index 8bbe6cf74a1e..ae7202bf99b4 100644 --- a/gnu/usr.bin/gdb/bfd/VERSION +++ b/gnu/usr.bin/gdb/bfd/VERSION @@ -1 +1 @@ -2.2 +cygnus-2.3 diff --git a/gnu/usr.bin/gdb/bfd/aout-target.h b/gnu/usr.bin/gdb/bfd/aout-target.h index 65a22fff9b04..fc8d592e4e9c 100644 --- a/gnu/usr.bin/gdb/bfd/aout-target.h +++ b/gnu/usr.bin/gdb/bfd/aout-target.h @@ -1,5 +1,5 @@ /* Define a target vector and some small routines for a variant of a.out. - Copyright (C) 1990, 1991, 1992, 1993 Free Software Foundation, Inc. + Copyright (C) 1990, 1991, 1992, 1993, 1994 Free Software Foundation, Inc. This file is part of BFD, the Binary File Descriptor library. @@ -27,11 +27,13 @@ extern CONST struct reloc_howto_struct * NAME(aout,reloc_type_lookup) (); /* Set parameters about this a.out file that are machine-dependent. This routine is called from some_aout_object_p just before it returns. */ #ifndef MY_callback -static bfd_target * -DEFUN(MY(callback),(abfd), - bfd *abfd) +static const bfd_target * +MY(callback) (abfd) + bfd *abfd; { struct internal_exec *execp = exec_hdr (abfd); + unsigned int arch_align_power; + unsigned long arch_align; /* Calculate the file positions of the parts of a newly read aout header */ obj_textsec (abfd)->_raw_size = N_TXTSIZE(*execp); @@ -60,6 +62,26 @@ DEFUN(MY(callback),(abfd), bfd_default_set_arch_mach(abfd, DEFAULT_ARCH, 0); #endif + /* Now that we know the architecture, set the alignments of the + sections. This is normally done by NAME(aout,new_section_hook), + but when the initial sections were created the architecture had + not yet been set. However, for backward compatibility, we don't + set the alignment power any higher than as required by the size + of the section. */ + arch_align_power = bfd_get_arch_info (abfd)->section_align_power; + arch_align = 1 << arch_align_power; + if ((BFD_ALIGN (obj_textsec (abfd)->_raw_size, arch_align) + == obj_textsec (abfd)->_raw_size) + && (BFD_ALIGN (obj_datasec (abfd)->_raw_size, arch_align) + == obj_datasec (abfd)->_raw_size) + && (BFD_ALIGN (obj_bsssec (abfd)->_raw_size, arch_align) + == obj_bsssec (abfd)->_raw_size)) + { + obj_textsec (abfd)->alignment_power = arch_align_power; + obj_datasec (abfd)->alignment_power = arch_align_power; + obj_bsssec (abfd)->alignment_power = arch_align_power; + } + /* Don't set sizes now -- can't be sure until we know arch & mach. Sizes get set in set_sizes callback, later. */ #if 0 @@ -79,25 +101,26 @@ DEFUN(MY(callback),(abfd), #ifndef MY_object_p /* Finish up the reading of an a.out file header */ -static bfd_target * -DEFUN(MY(object_p),(abfd), - bfd *abfd) +static const bfd_target * +MY(object_p) (abfd) + bfd *abfd; { struct external_exec exec_bytes; /* Raw exec header from file */ struct internal_exec exec; /* Cleaned-up exec header */ - bfd_target *target; + const bfd_target *target; if (bfd_read ((PTR) &exec_bytes, 1, EXEC_BYTES_SIZE, abfd) != EXEC_BYTES_SIZE) { - bfd_error = wrong_format; + if (bfd_get_error () != bfd_error_system_call) + bfd_set_error (bfd_error_wrong_format); return 0; } -#ifdef NO_SWAP_MAGIC - memcpy (&exec.a_info, exec_bytes.e_info, sizeof(exec.a_info)); +#ifdef SWAP_MAGIC + exec.a_info = SWAP_MAGIC (exec_bytes.e_info); #else exec.a_info = bfd_h_get_32 (abfd, exec_bytes.e_info); -#endif /* NO_SWAP_MAGIC */ +#endif /* SWAP_MAGIC */ if (N_BADMAG (exec)) return 0; #ifdef MACHTYPE_OK @@ -105,6 +128,12 @@ DEFUN(MY(object_p),(abfd), #endif NAME(aout,swap_exec_header_in)(abfd, &exec_bytes, &exec); + +#ifdef SWAP_MAGIC + /* swap_exec_header_in read in a_info with the wrong byte order */ + exec.a_info = SWAP_MAGIC (exec_bytes.e_info); +#endif /* SWAP_MAGIC */ + target = NAME(aout,some_aout_object_p) (abfd, &exec, MY(callback)); #ifdef ENTRY_CAN_BE_ZERO @@ -134,8 +163,8 @@ DEFUN(MY(object_p),(abfd), #ifndef MY_mkobject static boolean -DEFUN(MY(mkobject),(abfd), - bfd *abfd) +MY(mkobject) (abfd) + bfd *abfd; { if (NAME(aout,mkobject)(abfd) == false) return false; @@ -154,14 +183,36 @@ DEFUN(MY(mkobject),(abfd), #define MY_mkobject MY(mkobject) #endif +#ifndef MY_bfd_copy_private_section_data + +/* Copy private section data. This actually does nothing with the + sections. It copies the subformat field. We copy it here, because + we need to know whether this is a QMAGIC file before we set the + section contents, and copy_private_bfd_data is not called until + after the section contents have been set. */ + +/*ARGSUSED*/ +static boolean +MY_bfd_copy_private_section_data (ibfd, isec, obfd, osec) + bfd *ibfd; + asection *isec; + bfd *obfd; + asection *osec; +{ + obj_aout_subformat (obfd) = obj_aout_subformat (ibfd); + return true; +} + +#endif + /* Write an object file. Section contents have already been written. We write the file header, symbols, and relocation. */ #ifndef MY_write_object_contents static boolean -DEFUN(MY(write_object_contents),(abfd), - bfd *abfd) +MY(write_object_contents) (abfd) + bfd *abfd; { struct external_exec exec_bytes; struct internal_exec *execp = exec_hdr (abfd); @@ -181,31 +232,112 @@ DEFUN(MY(write_object_contents),(abfd), #ifndef MY_set_sizes static boolean -DEFUN(MY(set_sizes),(abfd), bfd *abfd) +MY(set_sizes) (abfd) + bfd *abfd; { adata(abfd).page_size = PAGE_SIZE; + #ifdef SEGMENT_SIZE adata(abfd).segment_size = SEGMENT_SIZE; #else adata(abfd).segment_size = PAGE_SIZE; #endif + +#ifdef ZMAGIC_DISK_BLOCK_SIZE + adata(abfd).zmagic_disk_block_size = ZMAGIC_DISK_BLOCK_SIZE; +#else + adata(abfd).zmagic_disk_block_size = PAGE_SIZE; +#endif + adata(abfd).exec_bytes_size = EXEC_BYTES_SIZE; return true; } #define MY_set_sizes MY(set_sizes) #endif +#ifndef MY_exec_hdr_flags +#define MY_exec_hdr_flags 0 +#endif + #ifndef MY_backend_data + +#ifndef MY_text_includes_header +#define MY_text_includes_header 0 +#endif +#ifndef MY_add_dynamic_symbols +#define MY_add_dynamic_symbols 0 +#endif +#ifndef MY_add_one_symbol +#define MY_add_one_symbol 0 +#endif +#ifndef MY_link_dynamic_object +#define MY_link_dynamic_object 0 +#endif +#ifndef MY_write_dynamic_symbol +#define MY_write_dynamic_symbol 0 +#endif +#ifndef MY_check_dynamic_reloc +#define MY_check_dynamic_reloc 0 +#endif +#ifndef MY_finish_dynamic_link +#define MY_finish_dynamic_link 0 +#endif + static CONST struct aout_backend_data MY(backend_data) = { 0, /* zmagic contiguous */ - 0, /* text incl header */ + MY_text_includes_header, + MY_exec_hdr_flags, 0, /* text vma? */ MY_set_sizes, 0, /* exec header is counted */ + MY_add_dynamic_symbols, + MY_add_one_symbol, + MY_link_dynamic_object, + MY_write_dynamic_symbol, + MY_check_dynamic_reloc, + MY_finish_dynamic_link }; #define MY_backend_data &MY(backend_data) #endif +#ifndef MY_final_link_callback + +/* Callback for the final_link routine to set the section offsets. */ + +static void MY_final_link_callback + PARAMS ((bfd *, file_ptr *, file_ptr *, file_ptr *)); + +static void +MY_final_link_callback (abfd, ptreloff, pdreloff, psymoff) + bfd *abfd; + file_ptr *ptreloff; + file_ptr *pdreloff; + file_ptr *psymoff; +{ + struct internal_exec *execp = exec_hdr (abfd); + + *ptreloff = N_TRELOFF (*execp); + *pdreloff = N_DRELOFF (*execp); + *psymoff = N_SYMOFF (*execp); +} + +#endif + +#ifndef MY_bfd_final_link + +/* Final link routine. We need to use a call back to get the correct + offsets in the output file. */ + +static boolean +MY_bfd_final_link (abfd, info) + bfd *abfd; + struct bfd_link_info *info; +{ + return NAME(aout,final_link) (abfd, info, MY_final_link_callback); +} + +#endif + /* We assume BFD generic archive files. */ #ifndef MY_openr_next_archived_file #define MY_openr_next_archived_file bfd_generic_openr_next_archived_file @@ -228,14 +360,14 @@ static CONST struct aout_backend_data MY(backend_data) = { /* No core file defined here -- configure in trad-core.c separately. */ #ifndef MY_core_file_failing_command -#define MY_core_file_failing_command _bfd_dummy_core_file_failing_command +#define MY_core_file_failing_command _bfd_nocore_core_file_failing_command #endif #ifndef MY_core_file_failing_signal -#define MY_core_file_failing_signal _bfd_dummy_core_file_failing_signal +#define MY_core_file_failing_signal _bfd_nocore_core_file_failing_signal #endif #ifndef MY_core_file_matches_executable_p #define MY_core_file_matches_executable_p \ - _bfd_dummy_core_file_matches_executable_p + _bfd_nocore_core_file_matches_executable_p #endif #ifndef MY_core_file_p #define MY_core_file_p _bfd_dummy_target @@ -261,21 +393,6 @@ static CONST struct aout_backend_data MY(backend_data) = { #ifndef MY_core_file_matches_executable_p #define MY_core_file_matches_executable_p NAME(aout,core_file_matches_executable_p) #endif -#ifndef MY_slurp_armap -#define MY_slurp_armap NAME(aout,slurp_armap) -#endif -#ifndef MY_slurp_extended_name_table -#define MY_slurp_extended_name_table NAME(aout,slurp_extended_name_table) -#endif -#ifndef MY_truncate_arname -#define MY_truncate_arname NAME(aout,truncate_arname) -#endif -#ifndef MY_write_armap -#define MY_write_armap NAME(aout,write_armap) -#endif -#ifndef MY_close_and_cleanup -#define MY_close_and_cleanup NAME(aout,close_and_cleanup) -#endif #ifndef MY_set_section_contents #define MY_set_section_contents NAME(aout,set_section_contents) #endif @@ -312,32 +429,63 @@ static CONST struct aout_backend_data MY(backend_data) = { #ifndef MY_set_arch_mach #define MY_set_arch_mach NAME(aout,set_arch_mach) #endif -#ifndef MY_openr_next_archived_file -#define MY_openr_next_archived_file NAME(aout,openr_next_archived_file) -#endif #ifndef MY_find_nearest_line #define MY_find_nearest_line NAME(aout,find_nearest_line) #endif -#ifndef MY_generic_stat_arch_elt -#define MY_generic_stat_arch_elt NAME(aout,generic_stat_arch_elt) -#endif #ifndef MY_sizeof_headers #define MY_sizeof_headers NAME(aout,sizeof_headers) #endif -#ifndef MY_bfd_debug_info_start -#define MY_bfd_debug_info_start NAME(aout,bfd_debug_info_start) +#ifndef MY_bfd_get_relocated_section_contents +#define MY_bfd_get_relocated_section_contents \ + bfd_generic_get_relocated_section_contents #endif -#ifndef MY_bfd_debug_info_end -#define MY_bfd_debug_info_end NAME(aout,bfd_debug_info_end) +#ifndef MY_bfd_relax_section +#define MY_bfd_relax_section bfd_generic_relax_section +#endif +#ifndef MY_bfd_reloc_type_lookup +#define MY_bfd_reloc_type_lookup NAME(aout,reloc_type_lookup) +#endif +#ifndef MY_bfd_make_debug_symbol +#define MY_bfd_make_debug_symbol 0 +#endif +#ifndef MY_bfd_link_hash_table_create +#define MY_bfd_link_hash_table_create NAME(aout,link_hash_table_create) +#endif +#ifndef MY_bfd_link_add_symbols +#define MY_bfd_link_add_symbols NAME(aout,link_add_symbols) +#endif + +#ifndef MY_bfd_copy_private_bfd_data +#define MY_bfd_copy_private_bfd_data _bfd_generic_bfd_copy_private_bfd_data +#endif + +#ifndef MY_bfd_is_local_label +#define MY_bfd_is_local_label bfd_generic_is_local_label #endif -#ifndef MY_bfd_debug_info_accumulat -#define MY_bfd_debug_info_accumulat NAME(aout,bfd_debug_info_accumulat) + +#ifndef MY_bfd_free_cached_info +#define MY_bfd_free_cached_info NAME(aout,bfd_free_cached_info) #endif -#ifndef MY_reloc_howto_type_lookup -#define MY_reloc_howto_type_lookup NAME(aout,reloc_type_lookup) + +#ifndef MY_close_and_cleanup +#define MY_close_and_cleanup MY_bfd_free_cached_info #endif -#ifndef MY_make_debug_symbol -#define MY_make_debug_symbol 0 + +#ifndef MY_get_dynamic_symtab_upper_bound +#define MY_get_dynamic_symtab_upper_bound \ + _bfd_nodynamic_get_dynamic_symtab_upper_bound +#endif +#ifndef MY_canonicalize_dynamic_symtab +#define MY_canonicalize_dynamic_symtab \ + _bfd_nodynamic_canonicalize_dynamic_symtab +#endif +#ifndef MY_get_dynamic_reloc_upper_bound +#define MY_get_dynamic_reloc_upper_bound \ + _bfd_nodynamic_get_dynamic_reloc_upper_bound +#endif +#ifndef MY_canonicalize_dynamic_reloc +#define MY_canonicalize_dynamic_reloc \ + _bfd_nodynamic_canonicalize_dynamic_reloc #endif /* Aout symbols normally have leading underscores */ @@ -351,7 +499,7 @@ static CONST struct aout_backend_data MY(backend_data) = { #endif #ifndef MY_BFD_TARGET -bfd_target MY(vec) = +const bfd_target MY(vec) = { TARGETNAME, /* name */ bfd_target_aout_flavour, @@ -392,38 +540,16 @@ bfd_target MY(vec) = {bfd_false, MY_write_object_contents, /* bfd_write_contents */ _bfd_write_archive_contents, bfd_false}, - MY_core_file_failing_command, - MY_core_file_failing_signal, - MY_core_file_matches_executable_p, - MY_slurp_armap, - MY_slurp_extended_name_table, - MY_truncate_arname, - MY_write_armap, - MY_close_and_cleanup, - MY_set_section_contents, - MY_get_section_contents, - MY_new_section_hook, - MY_get_symtab_upper_bound, - MY_get_symtab, - MY_get_reloc_upper_bound, - MY_canonicalize_reloc, - MY_make_empty_symbol, - MY_print_symbol, - MY_get_symbol_info, - MY_get_lineno, - MY_set_arch_mach, - MY_openr_next_archived_file, - MY_find_nearest_line, - MY_generic_stat_arch_elt, - MY_sizeof_headers, - MY_bfd_debug_info_start, - MY_bfd_debug_info_end, - MY_bfd_debug_info_accumulate, - bfd_generic_get_relocated_section_contents, - bfd_generic_relax_section, - bfd_generic_seclet_link, - MY_reloc_howto_type_lookup, - MY_make_debug_symbol, + BFD_JUMP_TABLE_GENERIC (MY), + BFD_JUMP_TABLE_COPY (MY), + BFD_JUMP_TABLE_CORE (MY), + BFD_JUMP_TABLE_ARCHIVE (MY), + BFD_JUMP_TABLE_SYMBOLS (MY), + BFD_JUMP_TABLE_RELOCS (MY), + BFD_JUMP_TABLE_WRITE (MY), + BFD_JUMP_TABLE_LINK (MY), + BFD_JUMP_TABLE_DYNAMIC (MY), + (PTR) MY_backend_data, }; #endif /* MY_BFD_TARGET */ diff --git a/gnu/usr.bin/gdb/bfd/aout32.c b/gnu/usr.bin/gdb/bfd/aout32.c index 84d20872fc96..294dc1de6363 100644 --- a/gnu/usr.bin/gdb/bfd/aout32.c +++ b/gnu/usr.bin/gdb/bfd/aout32.c @@ -1,5 +1,5 @@ /* BFD back-end for 32-bit a.out files. - Copyright (C) 1990-1991 Free Software Foundation, Inc. + Copyright (C) 1990, 91, 92, 93, 94 Free Software Foundation, Inc. Written by Cygnus Support. This file is part of BFD, the Binary File Descriptor library. diff --git a/gnu/usr.bin/gdb/bfd/aoutx.h b/gnu/usr.bin/gdb/bfd/aoutx.h index 1ab442926ff2..0bcc860a6acb 100644 --- a/gnu/usr.bin/gdb/bfd/aoutx.h +++ b/gnu/usr.bin/gdb/bfd/aoutx.h @@ -1,5 +1,5 @@ /* BFD semi-generic back-end for a.out binaries. - Copyright 1990, 1991, 1992, 1993 Free Software Foundation, Inc. + Copyright 1990, 1991, 1992, 1993, 1994 Free Software Foundation, Inc. Written by Cygnus Support. This file is part of BFD, the Binary File Descriptor library. @@ -30,26 +30,26 @@ DESCRIPTION structures on disk, and the shape of the relocation information. - The support is split into a basic support file @code{aoutx.h} + The support is split into a basic support file @file{aoutx.h} and other files which derive functions from the base. One - derivation file is @code{aoutf1.h} (for a.out flavour 1), and + derivation file is @file{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, - @code{newsos3.c} for the Sony NEWS, and @code{demo64.c} for a + for each machine, including @file{sunos.c} for sun3 and sun4, + @file{newsos3.c} for the Sony NEWS, and @file{demo64.c} 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 + The base file @file{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. + @file{aout32.c} and @file{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 + sun4, from @file{aout32.c}: | #define ARCH_SIZE 32 | #include "aoutx.h" @@ -63,18 +63,17 @@ DESCRIPTION | aout_32_get_reloc_upper_bound | ... - from sunos.c + from @file{sunos.c}: -| #define ARCH 32 | #define TARGET_NAME "a.out-sunos-big" | #define VECNAME sunos_big_vec | #include "aoutf1.h" - requires all the names from aout32.c, and produces the jump vector + requires all the names from @file{aout32.c}, and produces the jump vector | sunos_big_vec - The file host-aout.c is a special case. It is for a large set + The file @file{host-aout.c} is a special case. It is for a large set of hosts that use ``more or less standard'' a.out files, and for which cross-debugging is not interesting. It uses the standard 32-bit a.out support routines, but determines the @@ -93,17 +92,18 @@ DESCRIPTION | HOST_TEXT_START_ADDR | HOST_STACK_END_ADDR - in the file <<../include/sys/h-XXX.h>> (for your host). These - values, plus the structures and macros defined in <<a.out.h>> on + in the file @file{../include/sys/h-@var{XXX}.h} (for your host). These + values, plus the structures and macros defined in @file{a.out.h} on your host system, will produce a BFD target that will access ordinary a.out files on your host. To configure a new machine - to use <<host-aout.c>., specify: + to use @file{host-aout.c}, specify: | TDEFAULTS = -DDEFAULT_VECTOR=host_aout_big_vec | TDEPFILES= host-aout.o trad-core.o - in the <<config/mt-XXX>> file, and modify configure.in to use the - <<mt-XXX>> file (by setting "<<bfd_target=XXX>>") when your + in the @file{config/@var{XXX}.mt} file, and modify @file{configure.in} + to use the + @file{@var{XXX}.mt} file (by setting "<<bfd_target=XXX>>") when your configuration is selected. */ @@ -120,43 +120,58 @@ DESCRIPTION #define KEEPIT flags #define KEEPITTYPE int -#include <assert.h> #include <string.h> /* For strchr and friends */ #include "bfd.h" #include <sysdep.h> -#include <ansidecl.h> +#include "bfdlink.h" -struct external_exec; #include "libaout.h" #include "libbfd.h" #include "aout/aout64.h" #include "aout/stab_gnu.h" #include "aout/ar.h" -extern void (*bfd_error_trap)(); +static boolean aout_get_external_symbols PARAMS ((bfd *)); +static boolean translate_from_native_sym_flags + PARAMS ((bfd *, aout_symbol_type *)); +static boolean translate_to_native_sym_flags + PARAMS ((bfd *, asymbol *, struct external_nlist *)); /* SUBSECTION - relocations + Relocations DESCRIPTION - The file @code{aoutx.h} caters for both the @emph{standard} + The file @file{aoutx.h} provides 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 + The standard records contain 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. */ +#ifndef CTOR_TABLE_RELOC_HOWTO #define CTOR_TABLE_RELOC_IDX 2 +#define CTOR_TABLE_RELOC_HOWTO(BFD) ((obj_reloc_entry_size(BFD) == RELOC_EXT_SIZE \ + ? howto_table_ext : howto_table_std) \ + + CTOR_TABLE_RELOC_IDX) +#endif + +#ifndef MY_swap_std_reloc_in +#define MY_swap_std_reloc_in NAME(aout,swap_std_reloc_in) +#endif + +#ifndef MY_swap_std_reloc_out +#define MY_swap_std_reloc_out NAME(aout,swap_std_reloc_out) +#endif #define howto_table_ext NAME(aout,ext_howto_table) #define howto_table_std NAME(aout,std_howto_table) reloc_howto_type howto_table_ext[] = { - /* type rs size bsz pcrel bitpos ovrf sf name part_inpl readmask setmask pcdone */ + /* type rs size bsz pcrel bitpos ovrf sf name part_inpl readmask setmask pcdone */ HOWTO(RELOC_8, 0, 0, 8, false, 0, complain_overflow_bitfield,0,"8", false, 0,0x000000ff, false), HOWTO(RELOC_16, 0, 1, 16, false, 0, complain_overflow_bitfield,0,"16", false, 0,0x0000ffff, false), HOWTO(RELOC_32, 0, 2, 32, false, 0, complain_overflow_bitfield,0,"32", false, 0,0xffffffff, false), @@ -186,7 +201,7 @@ reloc_howto_type howto_table_ext[] = /* Convert standard reloc records to "arelent" format (incl byte swap). */ reloc_howto_type howto_table_std[] = { - /* type rs size bsz pcrel bitpos ovrf sf name part_inpl readmask setmask pcdone */ + /* type rs size bsz pcrel bitpos ovrf sf name part_inpl readmask setmask pcdone */ HOWTO( 0, 0, 0, 8, false, 0, complain_overflow_bitfield,0,"8", true, 0x000000ff,0x000000ff, false), HOWTO( 1, 0, 1, 16, false, 0, complain_overflow_bitfield,0,"16", true, 0x0000ffff,0x0000ffff, false), HOWTO( 2, 0, 2, 32, false, 0, complain_overflow_bitfield,0,"32", true, 0xffffffff,0xffffffff, false), @@ -195,17 +210,40 @@ HOWTO( 4, 0, 0, 8, true, 0, complain_overflow_signed, 0,"DISP8", tru HOWTO( 5, 0, 1, 16, true, 0, complain_overflow_signed, 0,"DISP16", true, 0x0000ffff,0x0000ffff, false), HOWTO( 6, 0, 2, 32, true, 0, complain_overflow_signed, 0,"DISP32", true, 0xffffffff,0xffffffff, false), HOWTO( 7, 0, 4, 64, true, 0, complain_overflow_signed, 0,"DISP64", true, 0xfeedface,0xfeedface, false), -{ -1 }, +HOWTO( 8, 0, 2, 0, false, 0, complain_overflow_bitfield,0,"GOT_REL", false, 0,0x00000000, false), HOWTO( 9, 0, 1, 16, false, 0, complain_overflow_bitfield,0,"BASE16", false,0xffffffff,0xffffffff, false), HOWTO(10, 0, 2, 32, false, 0, complain_overflow_bitfield,0,"BASE32", false,0xffffffff,0xffffffff, false), +{ -1 }, +{ -1 }, +{ -1 }, +{ -1 }, +{ -1 }, + HOWTO(16, 0, 2, 0, false, 0, complain_overflow_bitfield,0,"JMP_TABLE", false, 0,0x00000000, false), +{ -1 }, +{ -1 }, +{ -1 }, +{ -1 }, +{ -1 }, +{ -1 }, +{ -1 }, +{ -1 }, { -1 }, { -1 }, { -1 }, { -1 }, { -1 }, { -1 }, { -1 }, + HOWTO(32, 0, 2, 0, false, 0, complain_overflow_bitfield,0,"RELATIVE", false, 0,0x00000000, false), +{ -1 }, +{ -1 }, +{ -1 }, +{ -1 }, +{ -1 }, +{ -1 }, +{ -1 }, + HOWTO(40, 0, 2, 0, false, 0, complain_overflow_bitfield,0,"BASEREL", false, 0,0x00000000, false), }; #define TABLE_SIZE(TABLE) (sizeof(TABLE)/sizeof(TABLE[0])) CONST struct reloc_howto_struct * -DEFUN(NAME(aout,reloc_type_lookup),(abfd,code), - bfd *abfd AND - bfd_reloc_code_real_type code) +NAME(aout,reloc_type_lookup) (abfd,code) + bfd *abfd; + bfd_reloc_code_real_type code; { #define EXT(i,j) case i: return &howto_table_ext[j] #define STD(i,j) case i: return &howto_table_std[j] @@ -216,6 +254,9 @@ DEFUN(NAME(aout,reloc_type_lookup),(abfd,code), case 32: code = BFD_RELOC_32; break; + case 64: + code = BFD_RELOC_64; + break; } if (ext) switch (code) @@ -224,6 +265,9 @@ DEFUN(NAME(aout,reloc_type_lookup),(abfd,code), EXT (BFD_RELOC_HI22, 8); EXT (BFD_RELOC_LO10, 11); EXT (BFD_RELOC_32_PCREL_S2, 6); + EXT (BFD_RELOC_SPARC_WDISP22, 7); + EXT (BFD_RELOC_SPARC13, 10); + EXT (BFD_RELOC_SPARC_BASE13, 15); default: return (CONST struct reloc_howto_struct *) 0; } else @@ -241,14 +285,12 @@ DEFUN(NAME(aout,reloc_type_lookup),(abfd,code), } } -extern bfd_error_vector_type bfd_error_vector; - /* SUBSECTION - Internal Entry Points + Internal entry points DESCRIPTION - @code{aoutx.h} exports several routines for accessing the + @file{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). @@ -256,26 +298,26 @@ DESCRIPTION /* FUNCTION - aout_<size>_swap_exec_header_in - -DESCRIPTION - Swaps the information in an executable header taken from a raw - byte stream memory image, into the internal exec_header - structure. + aout_@var{size}_swap_exec_header_in SYNOPSIS - void aout_<size>_swap_exec_header_in, + void aout_@var{size}_swap_exec_header_in, (bfd *abfd, struct external_exec *raw_bytes, struct internal_exec *execp); + +DESCRIPTION + Swap the information in an executable header @var{raw_bytes} taken + from a raw byte stream memory image into the internal exec header + structure @var{execp}. */ #ifndef NAME_swap_exec_header_in void -DEFUN(NAME(aout,swap_exec_header_in),(abfd, raw_bytes, execp), - bfd *abfd AND - struct external_exec *raw_bytes AND - struct internal_exec *execp) +NAME(aout,swap_exec_header_in) (abfd, raw_bytes, execp) + bfd *abfd; + struct external_exec *raw_bytes; + struct internal_exec *execp; { struct external_exec *bytes = (struct external_exec *)raw_bytes; @@ -283,7 +325,7 @@ DEFUN(NAME(aout,swap_exec_header_in),(abfd, raw_bytes, execp), configuration (IE for i960), so ensure that all such uninitialized fields are zero'd out. There are places where two of these structs are memcmp'd, and thus the contents do matter. */ - memset (execp, 0, sizeof (struct internal_exec)); + memset ((PTR) execp, 0, sizeof (struct internal_exec)); /* Now fill in fields in the execp, from the bytes in the raw data. */ execp->a_info = bfd_h_get_32 (abfd, bytes->e_info); execp->a_text = GET_WORD (abfd, bytes->e_text); @@ -299,23 +341,23 @@ DEFUN(NAME(aout,swap_exec_header_in),(abfd, raw_bytes, execp), /* FUNCTION - aout_<size>_swap_exec_header_out - -DESCRIPTION - Swaps the information in an internal exec header structure - into the supplied buffer ready for writing to disk. + aout_@var{size}_swap_exec_header_out SYNOPSIS - void aout_<size>_swap_exec_header_out + void aout_@var{size}_swap_exec_header_out (bfd *abfd, struct internal_exec *execp, struct external_exec *raw_bytes); + +DESCRIPTION + Swap the information in an internal exec header structure + @var{execp} into the buffer @var{raw_bytes} ready for writing to disk. */ void -DEFUN(NAME(aout,swap_exec_header_out),(abfd, execp, raw_bytes), - bfd *abfd AND - struct internal_exec *execp AND - struct external_exec *raw_bytes) +NAME(aout,swap_exec_header_out) (abfd, execp, raw_bytes) + bfd *abfd; + struct internal_exec *execp; + struct external_exec *raw_bytes; { struct external_exec *bytes = (struct external_exec *)raw_bytes; @@ -330,37 +372,53 @@ DEFUN(NAME(aout,swap_exec_header_out),(abfd, execp, raw_bytes), PUT_WORD (abfd, execp->a_drsize, bytes->e_drsize); } +/* Make all the section for an a.out file. */ +boolean +NAME(aout,make_sections) (abfd) + bfd *abfd; +{ + if (obj_textsec (abfd) == (asection *) NULL + && bfd_make_section (abfd, ".text") == (asection *) NULL) + return false; + if (obj_datasec (abfd) == (asection *) NULL + && bfd_make_section (abfd, ".data") == (asection *) NULL) + return false; + if (obj_bsssec (abfd) == (asection *) NULL + && bfd_make_section (abfd, ".bss") == (asection *) NULL) + return false; + return true; +} /* FUNCTION - aout_<size>_some_aout_object_p + aout_@var{size}_some_aout_object_p + +SYNOPSIS + const bfd_target *aout_@var{size}_some_aout_object_p + (bfd *abfd, + const bfd_target *(*callback_to_real_object_p)()); DESCRIPTION - Some A.OUT variant thinks that the file whose format we're + Some a.out variant thinks that the file open in @var{abfd} 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 + environment's "finish up" function just before returning, to handle any last-minute setup. - -SYNOPSIS - 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, execp, callback_to_real_object_p), - bfd *abfd AND - struct internal_exec *execp AND - bfd_target *(*callback_to_real_object_p) PARAMS ((bfd *))) +const bfd_target * +NAME(aout,some_aout_object_p) (abfd, execp, callback_to_real_object_p) + bfd *abfd; + struct internal_exec *execp; + const bfd_target *(*callback_to_real_object_p) PARAMS ((bfd *)); { struct aout_data_struct *rawptr, *oldrawptr; - bfd_target *result; + const bfd_target *result; rawptr = (struct aout_data_struct *) bfd_zalloc (abfd, sizeof (struct aout_data_struct )); if (rawptr == NULL) { - bfd_error = no_memory; + bfd_set_error (bfd_error_no_memory); return 0; } @@ -385,19 +443,34 @@ DEFUN(NAME(aout,some_aout_object_p),(abfd, execp, callback_to_real_object_p), /* Setting of EXEC_P has been deferred to the bottom of this function */ if (execp->a_syms) abfd->flags |= HAS_LINENO | HAS_DEBUG | HAS_SYMS | HAS_LOCALS; + if (N_DYNAMIC(*execp)) + abfd->flags |= DYNAMIC; if (N_MAGIC (*execp) == ZMAGIC) { - abfd->flags |= D_PAGED|WP_TEXT; - adata(abfd).magic = z_magic; + abfd->flags |= D_PAGED | WP_TEXT; + adata (abfd).magic = z_magic; + } + else if (N_MAGIC (*execp) == QMAGIC) + { + abfd->flags |= D_PAGED | WP_TEXT; + adata (abfd).magic = z_magic; + adata (abfd).subformat = q_magic_format; } else if (N_MAGIC (*execp) == NMAGIC) { abfd->flags |= WP_TEXT; - adata(abfd).magic = n_magic; + adata (abfd).magic = n_magic; } + else if (N_MAGIC (*execp) == OMAGIC + || N_MAGIC (*execp) == BMAGIC) + adata (abfd).magic = o_magic; else - adata(abfd).magic = o_magic; + { + /* Should have been checked with N_BADMAG before this routine + was called. */ + abort (); + } bfd_get_start_address (abfd) = execp->a_entry; @@ -410,34 +483,30 @@ DEFUN(NAME(aout,some_aout_object_p),(abfd, execp, callback_to_real_object_p), /* The default symbol entry size is that of traditional Unix. */ obj_symbol_entry_size (abfd) = EXTERNAL_NLIST_SIZE; - /* Create the sections. This is raunchy, but bfd_close wants to reclaim - them. */ - - obj_textsec (abfd) = bfd_make_section_old_way (abfd, ".text"); - obj_datasec (abfd) = bfd_make_section_old_way (abfd, ".data"); - obj_bsssec (abfd) = bfd_make_section_old_way (abfd, ".bss"); + obj_aout_external_syms (abfd) = NULL; + obj_aout_external_strings (abfd) = NULL; + obj_aout_sym_hashes (abfd) = NULL; -#if 0 - (void)bfd_make_section (abfd, ".text"); - (void)bfd_make_section (abfd, ".data"); - (void)bfd_make_section (abfd, ".bss"); -#endif + if (! NAME(aout,make_sections) (abfd)) + return NULL; obj_datasec (abfd)->_raw_size = execp->a_data; obj_bsssec (abfd)->_raw_size = execp->a_bss; - obj_textsec (abfd)->flags = (execp->a_trsize != 0 ? - (SEC_ALLOC | SEC_LOAD | SEC_CODE | SEC_HAS_CONTENTS | SEC_RELOC) : - (SEC_ALLOC | SEC_LOAD | SEC_CODE | SEC_HAS_CONTENTS)); - obj_datasec (abfd)->flags = (execp->a_drsize != 0 ? - (SEC_ALLOC | SEC_LOAD | SEC_DATA | SEC_HAS_CONTENTS | SEC_RELOC) : - (SEC_ALLOC | SEC_LOAD | SEC_DATA | SEC_HAS_CONTENTS)); + obj_textsec (abfd)->flags = + (execp->a_trsize != 0 + ? (SEC_ALLOC | SEC_LOAD | SEC_CODE | SEC_HAS_CONTENTS | SEC_RELOC) + : (SEC_ALLOC | SEC_LOAD | SEC_CODE | SEC_HAS_CONTENTS)); + obj_datasec (abfd)->flags = + (execp->a_drsize != 0 + ? (SEC_ALLOC | SEC_LOAD | SEC_DATA | SEC_HAS_CONTENTS | SEC_RELOC) + : (SEC_ALLOC | SEC_LOAD | SEC_DATA | SEC_HAS_CONTENTS)); obj_bsssec (abfd)->flags = SEC_ALLOC; #ifdef THIS_IS_ONLY_DOCUMENTATION /* The common code can't fill in these things because they depend on either the start address of the text segment, the rounding - up of virtual addersses between segments, or the starting file + up of virtual addresses between segments, or the starting file position of the text segment -- all of which varies among different versions of a.out. */ @@ -493,6 +562,23 @@ DEFUN(NAME(aout,some_aout_object_p),(abfd, execp, callback_to_real_object_p), result = (*callback_to_real_object_p)(abfd); +#if defined(MACH) || defined(STAT_FOR_EXEC) + /* The original heuristic doesn't work in some important cases. The + * a.out file has no information about the text start address. For + * files (like kernels) linked to non-standard addresses (ld -Ttext + * nnn) the entry point may not be between the default text start + * (obj_textsec(abfd)->vma) and (obj_textsec(abfd)->vma) + text size + * This is not just a mach issue. Many kernels are loaded at non + * standard addresses. + */ + { + struct stat stat_buf; + if (abfd->iostream + && (fstat(fileno((FILE *) (abfd->iostream)), &stat_buf) == 0) + && ((stat_buf.st_mode & 0111) != 0)) + abfd->flags |= EXEC_P; + } +#else /* ! MACH */ /* Now that the segment addresses have been worked out, take a better guess at whether the file is executable. If the entry point is within the text segment, assume it is. (This makes files @@ -504,6 +590,7 @@ DEFUN(NAME(aout,some_aout_object_p),(abfd, execp, callback_to_real_object_p), if ((execp->a_entry >= obj_textsec(abfd)->vma) && (execp->a_entry < obj_textsec(abfd)->vma + obj_textsec(abfd)->_raw_size)) abfd->flags |= EXEC_P; +#endif /* MACH */ if (result) { #if 0 /* These should be set correctly anyways. */ @@ -522,45 +609,37 @@ DEFUN(NAME(aout,some_aout_object_p),(abfd, execp, callback_to_real_object_p), /* FUNCTION - aout_<size>_mkobject - -DESCRIPTION - This routine initializes a BFD for use with a.out files. + aout_@var{size}_mkobject SYNOPSIS - boolean aout_<size>_mkobject, (bfd *); + boolean aout_@var{size}_mkobject, (bfd *abfd); + +DESCRIPTION + Initialize BFD @var{abfd} for use with a.out files. */ boolean -DEFUN(NAME(aout,mkobject),(abfd), - bfd *abfd) +NAME(aout,mkobject) (abfd) + bfd *abfd; { struct aout_data_struct *rawptr; - bfd_error = system_call_error; + bfd_set_error (bfd_error_system_call); /* Use an intermediate variable for clarity */ rawptr = (struct aout_data_struct *)bfd_zalloc (abfd, sizeof (struct aout_data_struct )); if (rawptr == NULL) { - bfd_error = no_memory; + bfd_set_error (bfd_error_no_memory); return false; } abfd->tdata.aout_data = rawptr; exec_hdr (abfd) = &(rawptr->e); - /* For simplicity's sake we just make all the sections right here. */ - obj_textsec (abfd) = (asection *)NULL; obj_datasec (abfd) = (asection *)NULL; obj_bsssec (abfd) = (asection *)NULL; - bfd_make_section (abfd, ".text"); - bfd_make_section (abfd, ".data"); - bfd_make_section (abfd, ".bss"); - bfd_make_section (abfd, BFD_ABS_SECTION_NAME); - bfd_make_section (abfd, BFD_UND_SECTION_NAME); - bfd_make_section (abfd, BFD_COM_SECTION_NAME); return true; } @@ -568,31 +647,33 @@ DEFUN(NAME(aout,mkobject),(abfd), /* FUNCTION - aout_<size>_machine_type + aout_@var{size}_machine_type + +SYNOPSIS + enum machine_type aout_@var{size}_machine_type + (enum bfd_architecture arch, + unsigned long machine)); DESCRIPTION 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. + a.out's. Return the <<machine_type>> for a particular + architecture and machine, or <<M_UNKNOWN>> if that exact architecture + and machine can't be represented in a.out format. If the architecture is understood, machine type 0 (default) - should always be understood. - -SYNOPSIS - enum machine_type aout_<size>_machine_type - (enum bfd_architecture arch, - unsigned long machine)); + is always understood. */ enum machine_type -DEFUN(NAME(aout,machine_type),(arch, machine), - enum bfd_architecture arch AND - unsigned long machine) +NAME(aout,machine_type) (arch, machine, unknown) + enum bfd_architecture arch; + unsigned long machine; + boolean *unknown; { enum machine_type arch_flags; arch_flags = M_UNKNOWN; + *unknown = true; switch (arch) { case bfd_arch_sparc: @@ -602,7 +683,7 @@ DEFUN(NAME(aout,machine_type),(arch, machine), case bfd_arch_m68k: switch (machine) { case 0: arch_flags = M_68010; break; - case 68000: arch_flags = M_UNKNOWN; break; + case 68000: arch_flags = M_UNKNOWN; *unknown = false; break; case 68010: arch_flags = M_68010; break; case 68020: arch_flags = M_68020; break; default: arch_flags = M_UNKNOWN; break; @@ -629,41 +710,59 @@ DEFUN(NAME(aout,machine_type),(arch, machine), } break; + case bfd_arch_ns32k: + switch (machine) { + case 0: arch_flags = M_NS32532; break; + case 32032: arch_flags = M_NS32032; break; + case 32532: arch_flags = M_NS32532; break; + default: arch_flags = M_UNKNOWN; break; + } + break; + default: arch_flags = M_UNKNOWN; } + + if (arch_flags != M_UNKNOWN) + *unknown = false; + return arch_flags; } /* FUNCTION - aout_<size>_set_arch_mach - -DESCRIPTION - Sets the architecture and the machine of the BFD to those - values supplied. Verifies that the format can support the - architecture required. + aout_@var{size}_set_arch_mach SYNOPSIS - boolean aout_<size>_set_arch_mach, + boolean aout_@var{size}_set_arch_mach, (bfd *, - enum bfd_architecture, + enum bfd_architecture arch, unsigned long machine)); + +DESCRIPTION + Set the architecture and the machine of the BFD @var{abfd} to the + values @var{arch} and @var{machine}. Verify that @var{abfd}'s format + can support the architecture required. */ boolean -DEFUN(NAME(aout,set_arch_mach),(abfd, arch, machine), - bfd *abfd AND - enum bfd_architecture arch AND - unsigned long machine) +NAME(aout,set_arch_mach) (abfd, arch, machine) + bfd *abfd; + enum bfd_architecture arch; + unsigned long machine; { if (! bfd_default_set_arch_mach (abfd, arch, machine)) return false; - if (arch != bfd_arch_unknown && - NAME(aout,machine_type) (arch, machine) == M_UNKNOWN) - return false; /* We can't represent this type */ + if (arch != bfd_arch_unknown) + { + boolean unknown; + + NAME(aout,machine_type) (arch, machine, &unknown); + if (unknown) + return false; + } /* Determine the size of a relocation entry */ switch (arch) { @@ -680,29 +779,224 @@ DEFUN(NAME(aout,set_arch_mach),(abfd, arch, machine), return (*aout_backend_info(abfd)->set_sizes) (abfd); } -boolean -DEFUN (NAME (aout,adjust_sizes_and_vmas), (abfd, text_size, text_end), - bfd *abfd AND bfd_size_type *text_size AND file_ptr *text_end) +static void +adjust_o_magic (abfd, execp) + bfd *abfd; + struct internal_exec *execp; { - struct internal_exec *execp = exec_hdr (abfd); - if ((obj_textsec (abfd) == NULL) || (obj_datasec (abfd) == NULL)) + file_ptr pos = adata (abfd).exec_bytes_size; + bfd_vma vma = 0; + int pad = 0; + + /* Text. */ + obj_textsec(abfd)->filepos = pos; + pos += obj_textsec(abfd)->_raw_size; + vma += obj_textsec(abfd)->_raw_size; + + /* Data. */ + if (!obj_datasec(abfd)->user_set_vma) { - bfd_error = invalid_operation; - return false; +#if 0 /* ?? Does alignment in the file image really matter? */ + pad = align_power (vma, obj_datasec(abfd)->alignment_power) - vma; +#endif + obj_textsec(abfd)->_raw_size += pad; + pos += pad; + vma += pad; + obj_datasec(abfd)->vma = vma; + } + obj_datasec(abfd)->filepos = pos; + pos += obj_datasec(abfd)->_raw_size; + vma += obj_datasec(abfd)->_raw_size; + + /* BSS. */ + if (!obj_bsssec(abfd)->user_set_vma) + { +#if 0 + pad = align_power (vma, obj_bsssec(abfd)->alignment_power) - vma; +#endif + obj_datasec(abfd)->_raw_size += pad; + pos += pad; + vma += pad; + obj_bsssec(abfd)->vma = vma; + } + obj_bsssec(abfd)->filepos = pos; + + /* Fix up the exec header. */ + execp->a_text = obj_textsec(abfd)->_raw_size; + execp->a_data = obj_datasec(abfd)->_raw_size; + execp->a_bss = obj_bsssec(abfd)->_raw_size; + N_SET_MAGIC (*execp, OMAGIC); +} + +static void +adjust_z_magic (abfd, execp) + bfd *abfd; + struct internal_exec *execp; +{ + bfd_size_type data_pad, text_pad; + file_ptr text_end; + CONST struct aout_backend_data *abdp; + int ztih; /* Nonzero if text includes exec header. */ + + abdp = aout_backend_info (abfd); + + /* Text. */ + ztih = (abdp != NULL + && (abdp->text_includes_header + || obj_aout_subformat (abfd) == q_magic_format)); + obj_textsec(abfd)->filepos = (ztih + ? adata(abfd).exec_bytes_size + : adata(abfd).zmagic_disk_block_size); + if (! obj_textsec(abfd)->user_set_vma) + /* ?? Do we really need to check for relocs here? */ + obj_textsec(abfd)->vma = ((abfd->flags & HAS_RELOC) + ? 0 + : (ztih + ? (abdp->default_text_vma + + adata(abfd).exec_bytes_size) + : abdp->default_text_vma)); + /* Could take strange alignment of text section into account here? */ + + /* Find start of data. */ + if (ztih) + { + text_end = obj_textsec (abfd)->filepos + obj_textsec (abfd)->_raw_size; + text_pad = BFD_ALIGN (text_end, adata (abfd).page_size) - text_end; } - if (adata(abfd).magic != undecided_magic) return true; + else + { + /* Note that if page_size == zmagic_disk_block_size, then + filepos == page_size, and this case is the same as the ztih + case. */ + text_end = obj_textsec (abfd)->_raw_size; + text_pad = BFD_ALIGN (text_end, adata (abfd).page_size) - text_end; + text_end += obj_textsec (abfd)->filepos; + } + obj_textsec(abfd)->_raw_size += text_pad; + text_end += text_pad; + + /* Data. */ + if (!obj_datasec(abfd)->user_set_vma) + { + bfd_vma vma; + vma = obj_textsec(abfd)->vma + obj_textsec(abfd)->_raw_size; + obj_datasec(abfd)->vma = BFD_ALIGN (vma, adata(abfd).segment_size); + } + if (abdp && abdp->zmagic_mapped_contiguous) + { + text_pad = (obj_datasec(abfd)->vma + - obj_textsec(abfd)->vma + - obj_textsec(abfd)->_raw_size); + obj_textsec(abfd)->_raw_size += text_pad; + } + obj_datasec(abfd)->filepos = (obj_textsec(abfd)->filepos + + obj_textsec(abfd)->_raw_size); + + /* Fix up exec header while we're at it. */ + execp->a_text = obj_textsec(abfd)->_raw_size; + if (ztih && (!abdp || (abdp && !abdp->exec_header_not_counted))) + execp->a_text += adata(abfd).exec_bytes_size; + if (obj_aout_subformat (abfd) == q_magic_format) + N_SET_MAGIC (*execp, QMAGIC); + else + N_SET_MAGIC (*execp, ZMAGIC); + + /* Spec says data section should be rounded up to page boundary. */ + obj_datasec(abfd)->_raw_size + = align_power (obj_datasec(abfd)->_raw_size, + obj_bsssec(abfd)->alignment_power); + execp->a_data = BFD_ALIGN (obj_datasec(abfd)->_raw_size, + adata(abfd).page_size); + data_pad = execp->a_data - obj_datasec(abfd)->_raw_size; + + /* BSS. */ + if (!obj_bsssec(abfd)->user_set_vma) + obj_bsssec(abfd)->vma = (obj_datasec(abfd)->vma + + obj_datasec(abfd)->_raw_size); + /* If the BSS immediately follows the data section and extra space + in the page is left after the data section, fudge data + in the header so that the bss section looks smaller by that + amount. We'll start the bss section there, and lie to the OS. + (Note that a linker script, as well as the above assignment, + could have explicitly set the BSS vma to immediately follow + the data section.) */ + if (align_power (obj_bsssec(abfd)->vma, obj_bsssec(abfd)->alignment_power) + == obj_datasec(abfd)->vma + obj_datasec(abfd)->_raw_size) + execp->a_bss = (data_pad > obj_bsssec(abfd)->_raw_size) ? 0 : + obj_bsssec(abfd)->_raw_size - data_pad; + else + execp->a_bss = obj_bsssec(abfd)->_raw_size; +} + +static void +adjust_n_magic (abfd, execp) + bfd *abfd; + struct internal_exec *execp; +{ + file_ptr pos = adata(abfd).exec_bytes_size; + bfd_vma vma = 0; + int pad; + + /* Text. */ + obj_textsec(abfd)->filepos = pos; + if (!obj_textsec(abfd)->user_set_vma) + obj_textsec(abfd)->vma = vma; + else + vma = obj_textsec(abfd)->vma; + pos += obj_textsec(abfd)->_raw_size; + vma += obj_textsec(abfd)->_raw_size; + + /* Data. */ + obj_datasec(abfd)->filepos = pos; + if (!obj_datasec(abfd)->user_set_vma) + obj_datasec(abfd)->vma = BFD_ALIGN (vma, adata(abfd).segment_size); + vma = obj_datasec(abfd)->vma; + + /* Since BSS follows data immediately, see if it needs alignment. */ + vma += obj_datasec(abfd)->_raw_size; + pad = align_power (vma, obj_bsssec(abfd)->alignment_power) - vma; + obj_datasec(abfd)->_raw_size += pad; + pos += obj_datasec(abfd)->_raw_size; + + /* BSS. */ + if (!obj_bsssec(abfd)->user_set_vma) + obj_bsssec(abfd)->vma = vma; + else + vma = obj_bsssec(abfd)->vma; + + /* Fix up exec header. */ + execp->a_text = obj_textsec(abfd)->_raw_size; + execp->a_data = obj_datasec(abfd)->_raw_size; + execp->a_bss = obj_bsssec(abfd)->_raw_size; + N_SET_MAGIC (*execp, NMAGIC); +} + +boolean +NAME(aout,adjust_sizes_and_vmas) (abfd, text_size, text_end) + bfd *abfd; + bfd_size_type *text_size; + file_ptr *text_end; +{ + struct internal_exec *execp = exec_hdr (abfd); + + if (! NAME(aout,make_sections) (abfd)) + return false; + + if (adata(abfd).magic != undecided_magic) + return true; + obj_textsec(abfd)->_raw_size = align_power(obj_textsec(abfd)->_raw_size, obj_textsec(abfd)->alignment_power); *text_size = obj_textsec (abfd)->_raw_size; /* Rule (heuristic) for when to pad to a new page. Note that there - * are (at least) two ways demand-paged (ZMAGIC) files have been - * handled. Most Berkeley-based systems start the text segment at - * (PAGE_SIZE). However, newer versions of SUNOS start the text - * segment right after the exec header; the latter is counted in the - * text segment size, and is paged in by the kernel with the rest of - * the text. */ + are (at least) two ways demand-paged (ZMAGIC) files have been + handled. Most Berkeley-based systems start the text segment at + (PAGE_SIZE). However, newer versions of SUNOS start the text + segment right after the exec header; the latter is counted in the + text segment size, and is paged in by the kernel with the rest of + the text. */ /* This perhaps isn't the right way to do this, but made it simpler for me to understand enough to implement it. Better would probably be to go @@ -711,17 +1005,14 @@ DEFUN (NAME (aout,adjust_sizes_and_vmas), (abfd, text_size, text_end), other magic, that it was a little hard for me to understand. I think I understand it better now, but I haven't time to do the cleanup this minute. */ - if (adata(abfd).magic == undecided_magic) - { - if (abfd->flags & D_PAGED) - /* Whether or not WP_TEXT is set -- let D_PAGED override. */ - /* @@ What about QMAGIC? */ - adata(abfd).magic = z_magic; - else if (abfd->flags & WP_TEXT) - adata(abfd).magic = n_magic; - else - adata(abfd).magic = o_magic; - } + + if (abfd->flags & D_PAGED) + /* Whether or not WP_TEXT is set -- let D_PAGED override. */ + adata(abfd).magic = z_magic; + else if (abfd->flags & WP_TEXT) + adata(abfd).magic = n_magic; + else + adata(abfd).magic = o_magic; #ifdef BFD_AOUT_DEBUG /* requires gcc2 */ #if __GNUC__ >= 2 @@ -735,187 +1026,59 @@ DEFUN (NAME (aout,adjust_sizes_and_vmas), (abfd, text_size, text_end), } str; }), - obj_textsec(abfd)->vma, obj_textsec(abfd)->_raw_size, obj_textsec(abfd)->alignment_power, - obj_datasec(abfd)->vma, obj_datasec(abfd)->_raw_size, obj_datasec(abfd)->alignment_power, - obj_bsssec(abfd)->vma, obj_bsssec(abfd)->_raw_size, obj_bsssec(abfd)->alignment_power); + obj_textsec(abfd)->vma, obj_textsec(abfd)->_raw_size, + obj_textsec(abfd)->alignment_power, + obj_datasec(abfd)->vma, obj_datasec(abfd)->_raw_size, + obj_datasec(abfd)->alignment_power, + obj_bsssec(abfd)->vma, obj_bsssec(abfd)->_raw_size, + obj_bsssec(abfd)->alignment_power); #endif #endif switch (adata(abfd).magic) { case o_magic: - { - file_ptr pos = adata (abfd).exec_bytes_size; - bfd_vma vma = 0; - int pad = 0; - - obj_textsec(abfd)->filepos = pos; - pos += obj_textsec(abfd)->_raw_size; - vma += obj_textsec(abfd)->_raw_size; - if (!obj_datasec(abfd)->user_set_vma) - { -#if 0 /* ?? Does alignment in the file image really matter? */ - pad = align_power (vma, obj_datasec(abfd)->alignment_power) - vma; -#endif - obj_textsec(abfd)->_raw_size += pad; - pos += pad; - vma += pad; - obj_datasec(abfd)->vma = vma; - } - obj_datasec(abfd)->filepos = pos; - pos += obj_datasec(abfd)->_raw_size; - vma += obj_datasec(abfd)->_raw_size; - if (!obj_bsssec(abfd)->user_set_vma) - { -#if 0 - pad = align_power (vma, obj_bsssec(abfd)->alignment_power) - vma; -#endif - obj_datasec(abfd)->_raw_size += pad; - pos += pad; - vma += pad; - obj_bsssec(abfd)->vma = vma; - } - obj_bsssec(abfd)->filepos = pos; - execp->a_text = obj_textsec(abfd)->_raw_size; - execp->a_data = obj_datasec(abfd)->_raw_size; - execp->a_bss = obj_bsssec(abfd)->_raw_size; - N_SET_MAGIC (*execp, OMAGIC); - } + adjust_o_magic (abfd, execp); break; case z_magic: - { - bfd_size_type data_pad, text_pad; - file_ptr text_end; - CONST struct aout_backend_data *abdp; - int ztih; - bfd_vma data_vma; - - abdp = aout_backend_info (abfd); - ztih = abdp && abdp->text_includes_header; - obj_textsec(abfd)->filepos = (ztih - ? adata(abfd).exec_bytes_size - : adata(abfd).page_size); - if (! obj_textsec(abfd)->user_set_vma) - /* ?? Do we really need to check for relocs here? */ - obj_textsec(abfd)->vma = ((abfd->flags & HAS_RELOC) - ? 0 - : (ztih - ? (abdp->default_text_vma - + adata(abfd).exec_bytes_size) - : abdp->default_text_vma)); - /* Could take strange alignment of text section into account here? */ - - /* Find start of data. */ - text_end = obj_textsec(abfd)->filepos + obj_textsec(abfd)->_raw_size; - text_pad = BFD_ALIGN (text_end, adata(abfd).page_size) - text_end; - obj_textsec(abfd)->_raw_size += text_pad; - text_end += text_pad; - - if (!obj_datasec(abfd)->user_set_vma) - { - bfd_vma vma; - vma = obj_textsec(abfd)->vma + obj_textsec(abfd)->_raw_size; - obj_datasec(abfd)->vma = BFD_ALIGN (vma, adata(abfd).segment_size); - } - data_vma = obj_datasec(abfd)->vma; - if (abdp && abdp->zmagic_mapped_contiguous) - { - text_pad = (obj_datasec(abfd)->vma - - obj_textsec(abfd)->vma - - obj_textsec(abfd)->_raw_size); - obj_textsec(abfd)->_raw_size += text_pad; - } - obj_datasec(abfd)->filepos = (obj_textsec(abfd)->filepos - + obj_textsec(abfd)->_raw_size); - - /* Fix up exec header while we're at it. */ - execp->a_text = obj_textsec(abfd)->_raw_size; - if (ztih && (!abdp || (abdp && !abdp->exec_header_not_counted))) - execp->a_text += adata(abfd).exec_bytes_size; - N_SET_MAGIC (*execp, ZMAGIC); - /* Spec says data section should be rounded up to page boundary. */ - /* If extra space in page is left after data section, fudge data - in the header so that the bss section looks smaller by that - amount. We'll start the bss section there, and lie to the OS. */ - obj_datasec(abfd)->_raw_size - = align_power (obj_datasec(abfd)->_raw_size, - obj_bsssec(abfd)->alignment_power); - execp->a_data = BFD_ALIGN (obj_datasec(abfd)->_raw_size, - adata(abfd).page_size); - data_pad = execp->a_data - obj_datasec(abfd)->_raw_size; - - if (!obj_bsssec(abfd)->user_set_vma) - obj_bsssec(abfd)->vma = (obj_datasec(abfd)->vma - + obj_datasec(abfd)->_raw_size); - if (data_pad > obj_bsssec(abfd)->_raw_size) - execp->a_bss = 0; - else - execp->a_bss = obj_bsssec(abfd)->_raw_size - data_pad; - } + adjust_z_magic (abfd, execp); break; case n_magic: - { - file_ptr pos = adata(abfd).exec_bytes_size; - bfd_vma vma = 0; - int pad; - - obj_textsec(abfd)->filepos = pos; - if (!obj_textsec(abfd)->user_set_vma) - obj_textsec(abfd)->vma = vma; - else - vma = obj_textsec(abfd)->vma; - pos += obj_textsec(abfd)->_raw_size; - vma += obj_textsec(abfd)->_raw_size; - obj_datasec(abfd)->filepos = pos; - if (!obj_datasec(abfd)->user_set_vma) - obj_datasec(abfd)->vma = BFD_ALIGN (vma, adata(abfd).segment_size); - vma = obj_datasec(abfd)->vma; - - /* Since BSS follows data immediately, see if it needs alignment. */ - vma += obj_datasec(abfd)->_raw_size; - pad = align_power (vma, obj_bsssec(abfd)->alignment_power) - vma; - obj_datasec(abfd)->_raw_size += pad; - pos += obj_datasec(abfd)->_raw_size; - - if (!obj_bsssec(abfd)->user_set_vma) - obj_bsssec(abfd)->vma = vma; - else - vma = obj_bsssec(abfd)->vma; - } - execp->a_text = obj_textsec(abfd)->_raw_size; - execp->a_data = obj_datasec(abfd)->_raw_size; - execp->a_bss = obj_bsssec(abfd)->_raw_size; - N_SET_MAGIC (*execp, NMAGIC); + adjust_n_magic (abfd, execp); break; default: abort (); } + #ifdef BFD_AOUT_DEBUG fprintf (stderr, " text=<%x,%x,%x> data=<%x,%x,%x> bss=<%x,%x>\n", - obj_textsec(abfd)->vma, obj_textsec(abfd)->_raw_size, obj_textsec(abfd)->filepos, - obj_datasec(abfd)->vma, obj_datasec(abfd)->_raw_size, obj_datasec(abfd)->filepos, + obj_textsec(abfd)->vma, obj_textsec(abfd)->_raw_size, + obj_textsec(abfd)->filepos, + obj_datasec(abfd)->vma, obj_datasec(abfd)->_raw_size, + obj_datasec(abfd)->filepos, obj_bsssec(abfd)->vma, obj_bsssec(abfd)->_raw_size); #endif + return true; } /* FUNCTION - aout_<size>_new_section_hook - -DESCRIPTION - Called by the BFD in response to a @code{bfd_make_section} - request. + aout_@var{size}_new_section_hook SYNOPSIS - boolean aout_<size>_new_section_hook, + boolean aout_@var{size}_new_section_hook, (bfd *abfd, asection *newsect)); + +DESCRIPTION + Called by the BFD in response to a @code{bfd_make_section} + request. */ boolean -DEFUN(NAME(aout,new_section_hook),(abfd, newsect), - bfd *abfd AND - asection *newsect) +NAME(aout,new_section_hook) (abfd, newsect) + bfd *abfd; + asection *newsect; { /* align to double at least */ newsect->alignment_power = bfd_get_arch_info(abfd)->section_align_power; @@ -925,19 +1088,19 @@ DEFUN(NAME(aout,new_section_hook),(abfd, newsect), { if (obj_textsec(abfd) == NULL && !strcmp(newsect->name, ".text")) { obj_textsec(abfd)= newsect; - newsect->target_index = N_TEXT | N_EXT; + newsect->target_index = N_TEXT; return true; } if (obj_datasec(abfd) == NULL && !strcmp(newsect->name, ".data")) { obj_datasec(abfd) = newsect; - newsect->target_index = N_DATA | N_EXT; + newsect->target_index = N_DATA; return true; } if (obj_bsssec(abfd) == NULL && !strcmp(newsect->name, ".bss")) { obj_bsssec(abfd) = newsect; - newsect->target_index = N_BSS | N_EXT; + newsect->target_index = N_BSS; return true; } @@ -948,12 +1111,12 @@ DEFUN(NAME(aout,new_section_hook),(abfd, newsect), } boolean -DEFUN(NAME(aout,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) +NAME(aout,set_section_contents) (abfd, section, location, offset, count) + bfd *abfd; + sec_ptr section; + PTR location; + file_ptr offset; + bfd_size_type count; { file_ptr text_end; bfd_size_type text_size; @@ -969,7 +1132,8 @@ DEFUN(NAME(aout,set_section_contents),(abfd, section, location, offset, count), /* regardless, once we know what we're doing, we might as well get going */ if (section != obj_bsssec(abfd)) { - bfd_seek (abfd, section->filepos + offset, SEEK_SET); + if (bfd_seek (abfd, section->filepos + offset, SEEK_SET) != 0) + return false; if (count) { return (bfd_write ((PTR)location, 1, count, abfd) == count) ? @@ -980,113 +1144,259 @@ DEFUN(NAME(aout,set_section_contents),(abfd, section, location, offset, count), return true; } -/* Classify stabs symbols */ +/* Read the external symbols from an a.out file. */ -#define sym_in_text_section(sym) \ - (((sym)->type & (N_ABS | N_TEXT | N_DATA | N_BSS))== N_TEXT) - -#define sym_in_data_section(sym) \ - (((sym)->type & (N_ABS | N_TEXT | N_DATA | N_BSS))== N_DATA) +static boolean +aout_get_external_symbols (abfd) + bfd *abfd; +{ + if (obj_aout_external_syms (abfd) == (struct external_nlist *) NULL) + { + bfd_size_type count; + struct external_nlist *syms; -#define sym_in_bss_section(sym) \ - (((sym)->type & (N_ABS | N_TEXT | N_DATA | N_BSS))== N_BSS) + count = exec_hdr (abfd)->a_syms / EXTERNAL_NLIST_SIZE; -/* Symbol is undefined if type is N_UNDF|N_EXT and if it has - zero in the "value" field. Nonzeroes there are fortrancommon - symbols. */ -#define sym_is_undefined(sym) \ - ((sym)->type == (N_UNDF | N_EXT) && (sym)->symbol.value == 0) + /* We allocate using malloc to make the values easy to free + later on. If we put them on the obstack it might not be + possible to free them. */ + syms = ((struct external_nlist *) + malloc ((size_t) count * EXTERNAL_NLIST_SIZE)); + if (syms == (struct external_nlist *) NULL && count != 0) + { + bfd_set_error (bfd_error_no_memory); + return false; + } -/* Symbol is a global definition if N_EXT is on and if it has - a nonzero type field. */ -#define sym_is_global_defn(sym) \ - (((sym)->type & N_EXT) && (sym)->type & N_TYPE) + if (bfd_seek (abfd, obj_sym_filepos (abfd), SEEK_SET) != 0 + || (bfd_read (syms, 1, exec_hdr (abfd)->a_syms, abfd) + != exec_hdr (abfd)->a_syms)) + { + free (syms); + return false; + } -/* Symbol is debugger info if any bits outside N_TYPE or N_EXT - are on. */ -#define sym_is_debugger_info(sym) \ - (((sym)->type & ~(N_EXT | N_TYPE)) || (sym)->type == N_FN) + obj_aout_external_syms (abfd) = syms; + obj_aout_external_sym_count (abfd) = count; + } + + if (obj_aout_external_strings (abfd) == NULL + && exec_hdr (abfd)->a_syms != 0) + { + unsigned char string_chars[BYTES_IN_WORD]; + bfd_size_type stringsize; + char *strings; + + /* Get the size of the strings. */ + if (bfd_seek (abfd, obj_str_filepos (abfd), SEEK_SET) != 0 + || (bfd_read ((PTR) string_chars, BYTES_IN_WORD, 1, abfd) + != BYTES_IN_WORD)) + return false; + stringsize = GET_WORD (abfd, string_chars); + + strings = (char *) malloc ((size_t) stringsize + 1); + if (strings == NULL) + { + bfd_set_error (bfd_error_no_memory); + return false; + } -#define sym_is_fortrancommon(sym) \ - (((sym)->type == (N_EXT)) && (sym)->symbol.value != 0) + /* Skip space for the string count in the buffer for convenience + when using indexes. */ + if (bfd_read (strings + BYTES_IN_WORD, 1, stringsize - BYTES_IN_WORD, + abfd) + != stringsize - BYTES_IN_WORD) + { + free (strings); + return false; + } -/* Symbol is absolute if it has N_ABS set */ -#define sym_is_absolute(sym) \ - (((sym)->type & N_TYPE)== N_ABS) + /* Sanity preservation. */ + strings[stringsize] = '\0'; + obj_aout_external_strings (abfd) = strings; + obj_aout_external_string_size (abfd) = stringsize; + } -#define sym_is_indirect(sym) \ - (((sym)->type & N_ABS)== N_ABS) + return true; +} -/* Only in their own functions for ease of debugging; when sym flags have - stabilised these should be inlined into their (single) caller */ +/* Translate an a.out symbol into a BFD symbol. The desc, other, type + and symbol->value fields of CACHE_PTR will be set from the a.out + nlist structure. This function is responsible for setting + symbol->flags and symbol->section, and adjusting symbol->value. */ -static void -DEFUN (translate_from_native_sym_flags, (sym_pointer, cache_ptr, abfd), - struct external_nlist *sym_pointer AND - aout_symbol_type * cache_ptr AND - bfd * abfd) +static boolean +translate_from_native_sym_flags (abfd, cache_ptr) + bfd *abfd; + aout_symbol_type *cache_ptr; { - cache_ptr->symbol.section = 0; - switch (cache_ptr->type & N_TYPE) + flagword visible; + + if ((cache_ptr->type & N_STAB) != 0 + || cache_ptr->type == N_FN) { - case N_SETA: - case N_SETT: - case N_SETD: - case N_SETB: + asection *sec; + + /* This is a debugging symbol. */ + + cache_ptr->symbol.flags = BSF_DEBUGGING; + + /* Work out the symbol section. */ + switch (cache_ptr->type & N_TYPE) + { + case N_TEXT: + case N_FN: + sec = obj_textsec (abfd); + break; + case N_DATA: + sec = obj_datasec (abfd); + break; + case N_BSS: + sec = obj_bsssec (abfd); + break; + default: + case N_ABS: + sec = bfd_abs_section_ptr; + break; + } + + cache_ptr->symbol.section = sec; + cache_ptr->symbol.value -= sec->vma; + + return true; + } + + /* Get the default visibility. This does not apply to all types, so + we just hold it in a local variable to use if wanted. */ + if ((cache_ptr->type & N_EXT) == 0) + visible = BSF_LOCAL; + else + visible = BSF_GLOBAL; + + switch (cache_ptr->type) + { + default: + case N_ABS: case N_ABS | N_EXT: + cache_ptr->symbol.section = bfd_abs_section_ptr; + cache_ptr->symbol.flags = visible; + break; + + case N_UNDF | N_EXT: + if (cache_ptr->symbol.value != 0) + { + /* This is a common symbol. */ + cache_ptr->symbol.flags = BSF_GLOBAL; + cache_ptr->symbol.section = bfd_com_section_ptr; + } + else + { + cache_ptr->symbol.flags = 0; + cache_ptr->symbol.section = bfd_und_section_ptr; + } + break; + + case N_TEXT: case N_TEXT | N_EXT: + cache_ptr->symbol.section = obj_textsec (abfd); + cache_ptr->symbol.value -= cache_ptr->symbol.section->vma; + cache_ptr->symbol.flags = visible; + break; + + /* N_SETV symbols used to represent set vectors placed in the + data section. They are no longer generated. Theoretically, + it was possible to extract the entries and combine them with + new ones, although I don't know if that was ever actually + done. Unless that feature is restored, treat them as data + symbols. */ + case N_SETV: case N_SETV | N_EXT: + case N_DATA: case N_DATA | N_EXT: + cache_ptr->symbol.section = obj_datasec (abfd); + cache_ptr->symbol.value -= cache_ptr->symbol.section->vma; + cache_ptr->symbol.flags = visible; + break; + + case N_BSS: case N_BSS | N_EXT: + cache_ptr->symbol.section = obj_bsssec (abfd); + cache_ptr->symbol.value -= cache_ptr->symbol.section->vma; + cache_ptr->symbol.flags = visible; + break; + + case N_SETA: case N_SETA | N_EXT: + case N_SETT: case N_SETT | N_EXT: + case N_SETD: case N_SETD | N_EXT: + case N_SETB: case N_SETB | N_EXT: { - char *copy = bfd_alloc (abfd, strlen (cache_ptr->symbol.name) + 1); asection *section; + arelent_chain *reloc; asection *into_section; - arelent_chain *reloc = (arelent_chain *) bfd_alloc (abfd, sizeof (arelent_chain)); - strcpy (copy, cache_ptr->symbol.name); + /* This is a set symbol. The name of the symbol is the name + of the set (e.g., __CTOR_LIST__). The value of the symbol + is the value to add to the set. We create a section with + the same name as the symbol, and add a reloc to insert the + appropriate value into the section. + + This action is actually obsolete; it used to make the + linker do the right thing, but the linker no longer uses + this function. */ + + section = bfd_get_section_by_name (abfd, cache_ptr->symbol.name); + if (section == NULL) + { + char *copy; + + copy = bfd_alloc (abfd, strlen (cache_ptr->symbol.name) + 1); + if (copy == NULL) + { + bfd_set_error (bfd_error_no_memory); + return false; + } + + strcpy (copy, cache_ptr->symbol.name); + section = bfd_make_section (abfd, copy); + if (section == NULL) + return false; + } - /* Make sure that this bfd has a section with the right contructor - name */ - section = bfd_get_section_by_name (abfd, copy); - if (!section) - section = bfd_make_section (abfd, copy); + reloc = (arelent_chain *) bfd_alloc (abfd, sizeof (arelent_chain)); + if (reloc == NULL) + { + bfd_set_error (bfd_error_no_memory); + return false; + } - /* Build a relocation entry for the constructor */ - switch ((cache_ptr->type & N_TYPE)) + /* Build a relocation entry for the constructor. */ + switch (cache_ptr->type & N_TYPE) { case N_SETA: - into_section = &bfd_abs_section; + into_section = bfd_abs_section_ptr; cache_ptr->type = N_ABS; break; case N_SETT: - into_section = (asection *) obj_textsec (abfd); + into_section = obj_textsec (abfd); cache_ptr->type = N_TEXT; break; case N_SETD: - into_section = (asection *) obj_datasec (abfd); + into_section = obj_datasec (abfd); cache_ptr->type = N_DATA; break; case N_SETB: - into_section = (asection *) obj_bsssec (abfd); + into_section = obj_bsssec (abfd); cache_ptr->type = N_BSS; break; - default: - abort (); } - /* Build a relocation pointing into the constuctor section - pointing at the symbol in the set vector specified */ - + /* Build a relocation pointing into the constructor section + pointing at the symbol in the set vector specified. */ reloc->relent.addend = cache_ptr->symbol.value; - cache_ptr->symbol.section = into_section->symbol->section; + cache_ptr->symbol.section = into_section; reloc->relent.sym_ptr_ptr = into_section->symbol_ptr_ptr; - - /* We modify the symbol to belong to a section depending upon the - name of the symbol - probably __CTOR__ or __DTOR__ but we don't - really care, and add to the size of the section to contain a - pointer to the symbol. Build a reloc entry to relocate to this - symbol attached to this section. */ - - section->flags = SEC_CONSTRUCTOR; - + /* We modify the symbol to belong to a section depending upon + the name of the symbol, and add to the size of the section + to contain a pointer to the symbol. Build a reloc entry to + relocate to this symbol attached to this section. */ + section->flags = SEC_CONSTRUCTOR | SEC_RELOC; section->reloc_count++; section->alignment_power = 2; @@ -1094,735 +1404,529 @@ DEFUN (translate_from_native_sym_flags, (sym_pointer, cache_ptr, abfd), reloc->next = section->constructor_chain; section->constructor_chain = reloc; reloc->relent.address = section->_raw_size; - section->_raw_size += sizeof (int *); + section->_raw_size += BYTES_IN_WORD; + + reloc->relent.howto = CTOR_TABLE_RELOC_HOWTO(abfd); - reloc->relent.howto - = (obj_reloc_entry_size(abfd) == RELOC_EXT_SIZE - ? howto_table_ext : howto_table_std) - + CTOR_TABLE_RELOC_IDX; cache_ptr->symbol.flags |= BSF_CONSTRUCTOR; } break; - default: - if (cache_ptr->type == N_WARNING) - { - /* This symbol is the text of a warning message, the next symbol - is the symbol to associate the warning with */ - cache_ptr->symbol.flags = BSF_DEBUGGING | BSF_WARNING; - - /* @@ Stuffing pointers into integers is a no-no. - We can usually get away with it if the integer is - large enough though. */ - if (sizeof (cache_ptr + 1) > sizeof (bfd_vma)) - abort (); - cache_ptr->symbol.value = (bfd_vma) ((cache_ptr + 1)); - - /* We furgle with the next symbol in place. - We don't want it to be undefined, we'll trample the type */ - (sym_pointer + 1)->e_type[0] = 0xff; - break; - } - if ((cache_ptr->type | N_EXT) == (N_INDR | N_EXT)) - { - /* Two symbols in a row for an INDR message. The first symbol - contains the name we will match, the second symbol contains - the name the first name is translated into. It is supplied to - us undefined. This is good, since we want to pull in any files - which define it */ - cache_ptr->symbol.flags = BSF_DEBUGGING | BSF_INDIRECT; - - /* @@ Stuffing pointers into integers is a no-no. - We can usually get away with it if the integer is - large enough though. */ - if (sizeof (cache_ptr + 1) > sizeof (bfd_vma)) - abort (); - - cache_ptr->symbol.value = (bfd_vma) ((cache_ptr + 1)); - cache_ptr->symbol.section = &bfd_ind_section; - } - else if (sym_is_debugger_info (cache_ptr)) - { - cache_ptr->symbol.flags = BSF_DEBUGGING; - /* Work out the section correct for this symbol */ - switch (cache_ptr->type & N_TYPE) - { - case N_TEXT: - case N_FN: - cache_ptr->symbol.section = obj_textsec (abfd); - cache_ptr->symbol.value -= obj_textsec (abfd)->vma; - break; - case N_DATA: - cache_ptr->symbol.value -= obj_datasec (abfd)->vma; - cache_ptr->symbol.section = obj_datasec (abfd); - break; - case N_BSS: - cache_ptr->symbol.section = obj_bsssec (abfd); - cache_ptr->symbol.value -= obj_bsssec (abfd)->vma; - break; - default: - case N_ABS: + case N_WARNING: + /* This symbol is the text of a warning message. The next + symbol is the symbol to associate the warning with. If a + reference is made to that symbol, a warning is issued. */ + cache_ptr->symbol.flags = BSF_DEBUGGING | BSF_WARNING; - cache_ptr->symbol.section = &bfd_abs_section; - break; - } - } - else - { + /* @@ Stuffing pointers into integers is a no-no. We can + usually get away with it if the integer is large enough + though. */ + if (sizeof (cache_ptr + 1) > sizeof (bfd_vma)) + abort (); + cache_ptr->symbol.value = (bfd_vma) (cache_ptr + 1); - if (sym_is_fortrancommon (cache_ptr)) - { - cache_ptr->symbol.flags = 0; - cache_ptr->symbol.section = &bfd_com_section; - } - else - { + cache_ptr->symbol.section = bfd_abs_section_ptr; + break; - } + case N_INDR: case N_INDR | N_EXT: + /* An indirect symbol. This consists of two symbols in a row. + The first symbol is the name of the indirection. The second + symbol is the name of the target. A reference to the first + symbol becomes a reference to the second. */ + cache_ptr->symbol.flags = BSF_DEBUGGING | BSF_INDIRECT | visible; - /* In a.out, the value of a symbol is always relative to the - * start of the file, if this is a data symbol we'll subtract - * the size of the text section to get the section relative - * value. If this is a bss symbol (which would be strange) - * we'll subtract the size of the previous two sections - * to find the section relative address. - */ + /* @@ Stuffing pointers into integers is a no-no. We can + usually get away with it if the integer is large enough + though. */ + if (sizeof (cache_ptr + 1) > sizeof (bfd_vma)) + abort (); + cache_ptr->symbol.value = (bfd_vma) (cache_ptr + 1); - if (sym_in_text_section (cache_ptr)) - { - cache_ptr->symbol.value -= obj_textsec (abfd)->vma; - cache_ptr->symbol.section = obj_textsec (abfd); - } - else if (sym_in_data_section (cache_ptr)) - { - cache_ptr->symbol.value -= obj_datasec (abfd)->vma; - cache_ptr->symbol.section = obj_datasec (abfd); - } - else if (sym_in_bss_section (cache_ptr)) - { - cache_ptr->symbol.section = obj_bsssec (abfd); - cache_ptr->symbol.value -= obj_bsssec (abfd)->vma; - } - else if (sym_is_undefined (cache_ptr)) - { - cache_ptr->symbol.flags = 0; - cache_ptr->symbol.section = &bfd_und_section; - } - else if (sym_is_absolute (cache_ptr)) - { - cache_ptr->symbol.section = &bfd_abs_section; - } + cache_ptr->symbol.section = bfd_ind_section_ptr; - if (sym_is_global_defn (cache_ptr)) - { - cache_ptr->symbol.flags = BSF_GLOBAL | BSF_EXPORT; - } - else - { - cache_ptr->symbol.flags = BSF_LOCAL; - } - } + break; + + case N_WEAKU: + cache_ptr->symbol.section = bfd_und_section_ptr; + cache_ptr->symbol.flags = BSF_WEAK; + break; + + case N_WEAKA: + cache_ptr->symbol.section = bfd_abs_section_ptr; + cache_ptr->symbol.flags = BSF_WEAK; + break; + + case N_WEAKT: + cache_ptr->symbol.section = obj_textsec (abfd); + cache_ptr->symbol.value -= cache_ptr->symbol.section->vma; + cache_ptr->symbol.flags = BSF_WEAK; + break; + + case N_WEAKD: + cache_ptr->symbol.section = obj_datasec (abfd); + cache_ptr->symbol.value -= cache_ptr->symbol.section->vma; + cache_ptr->symbol.flags = BSF_WEAK; + break; + + case N_WEAKB: + cache_ptr->symbol.section = obj_bsssec (abfd); + cache_ptr->symbol.value -= cache_ptr->symbol.section->vma; + cache_ptr->symbol.flags = BSF_WEAK; + break; } - if (cache_ptr->symbol.section == 0) - abort (); -} + return true; +} +/* Set the fields of SYM_POINTER according to CACHE_PTR. */ -static void -DEFUN(translate_to_native_sym_flags,(sym_pointer, cache_ptr, abfd), - struct external_nlist *sym_pointer AND - asymbol *cache_ptr AND - bfd *abfd) +static boolean +translate_to_native_sym_flags (abfd, cache_ptr, sym_pointer) + bfd *abfd; + asymbol *cache_ptr; + struct external_nlist *sym_pointer; { bfd_vma value = cache_ptr->value; - /* mask out any existing type bits in case copying from one section - to another */ + /* Mask out any existing type bits in case copying from one section + to another. */ sym_pointer->e_type[0] &= ~N_TYPE; - - /* We attempt to order these tests by decreasing frequency of success, - according to tcov when linking the linker. */ - if (bfd_get_output_section(cache_ptr) == &bfd_abs_section) { + if (bfd_is_abs_section (bfd_get_section (cache_ptr))) sym_pointer->e_type[0] |= N_ABS; - } - else if (bfd_get_output_section(cache_ptr) == obj_textsec (abfd)) { + else if (bfd_get_section (cache_ptr) == obj_textsec (abfd) + || (bfd_get_section (cache_ptr)->output_section + == obj_textsec (abfd))) sym_pointer->e_type[0] |= N_TEXT; - } - else if (bfd_get_output_section(cache_ptr) == obj_datasec (abfd)) { + else if (bfd_get_section (cache_ptr) == obj_datasec (abfd) + || (bfd_get_section (cache_ptr)->output_section + == obj_datasec (abfd))) sym_pointer->e_type[0] |= N_DATA; - } - else if (bfd_get_output_section(cache_ptr) == obj_bsssec (abfd)) { + else if (bfd_get_section (cache_ptr) == obj_bsssec (abfd) + || (bfd_get_section (cache_ptr)->output_section + == obj_bsssec (abfd))) sym_pointer->e_type[0] |= N_BSS; - } - else if (bfd_get_output_section(cache_ptr) == &bfd_und_section) + else if (bfd_get_section (cache_ptr) == NULL) { - sym_pointer->e_type[0] = (N_UNDF | N_EXT); + /* Protect the bfd_is_com_section call. This case occurs, e.g., + for the *DEBUG* section of a COFF file. */ + bfd_set_error (bfd_error_nonrepresentable_section); + return false; } - else if (bfd_get_output_section(cache_ptr) == &bfd_ind_section) + else if (bfd_is_und_section (bfd_get_section (cache_ptr))) + sym_pointer->e_type[0] = N_UNDF | N_EXT; + else if (bfd_is_ind_section (bfd_get_section (cache_ptr))) + sym_pointer->e_type[0] = N_INDR; + else if (bfd_is_com_section (bfd_get_section (cache_ptr))) + sym_pointer->e_type[0] = N_UNDF | N_EXT; + else { - sym_pointer->e_type[0] = N_INDR; + bfd_set_error (bfd_error_nonrepresentable_section); + return false; } - else if (bfd_is_com_section (bfd_get_output_section (cache_ptr))) { - sym_pointer->e_type[0] = (N_UNDF | N_EXT); - } - else { - if (cache_ptr->section->output_section) - { - bfd_error_vector.nonrepresentable_section(abfd, - bfd_get_output_section(cache_ptr)->name); - } - else - { - bfd_error_vector.nonrepresentable_section(abfd, - cache_ptr->section->name); - - } - - } /* Turn the symbol from section relative to absolute again */ + value += cache_ptr->section->vma; + + if ((cache_ptr->flags & BSF_WARNING) != 0) + sym_pointer->e_type[0] = N_WARNING; - value += cache_ptr->section->output_section->vma + cache_ptr->section->output_offset ; + if ((cache_ptr->flags & BSF_DEBUGGING) != 0) + sym_pointer->e_type[0] = ((aout_symbol_type *) cache_ptr)->type; + else if ((cache_ptr->flags & BSF_GLOBAL) != 0) + sym_pointer->e_type[0] |= N_EXT; + if ((cache_ptr->flags & BSF_CONSTRUCTOR) != 0) + { + int type = ((aout_symbol_type *) cache_ptr)->type; + switch (type) + { + case N_ABS: type = N_SETA; break; + case N_TEXT: type = N_SETT; break; + case N_DATA: type = N_SETD; break; + case N_BSS: type = N_SETB; break; + } + sym_pointer->e_type[0] = type; + } - if (cache_ptr->flags & (BSF_WARNING)) { - (sym_pointer+1)->e_type[0] = 1; - } + if ((cache_ptr->flags & BSF_WEAK) != 0) + { + int type; - if (cache_ptr->flags & BSF_DEBUGGING) { - sym_pointer->e_type[0] = ((aout_symbol_type *)cache_ptr)->type; - } - else if (cache_ptr->flags & (BSF_GLOBAL | BSF_EXPORT)) { - sym_pointer->e_type[0] |= N_EXT; - } - if (cache_ptr->flags & BSF_CONSTRUCTOR) { - int type = ((aout_symbol_type *)cache_ptr)->type; - switch (type) - { - case N_ABS: type = N_SETA; break; - case N_TEXT: type = N_SETT; break; - case N_DATA: type = N_SETD; break; - case N_BSS: type = N_SETB; break; - } - sym_pointer->e_type[0] = type; - } + switch (sym_pointer->e_type[0] & N_TYPE) + { + default: + case N_ABS: type = N_WEAKA; break; + case N_TEXT: type = N_WEAKT; break; + case N_DATA: type = N_WEAKD; break; + case N_BSS: type = N_WEAKB; break; + case N_UNDF: type = N_WEAKU; break; + } + sym_pointer->e_type[0] = type; + } PUT_WORD(abfd, value, sym_pointer->e_value); + + return true; } /* Native-level interface to symbols. */ -/* We read the symbols into a buffer, which is discarded when this -function exits. We read the strings into a buffer large enough to -hold them all plus all the cached symbol entries. */ - asymbol * -DEFUN(NAME(aout,make_empty_symbol),(abfd), - bfd *abfd) +NAME(aout,make_empty_symbol) (abfd) + bfd *abfd; { aout_symbol_type *new = (aout_symbol_type *)bfd_zalloc (abfd, sizeof (aout_symbol_type)); + if (!new) + { + bfd_set_error (bfd_error_no_memory); + return NULL; + } new->symbol.the_bfd = abfd; return &new->symbol; } +/* Translate a set of internal symbols into external symbols. */ + boolean -DEFUN(NAME(aout,slurp_symbol_table),(abfd), - bfd *abfd) +NAME(aout,translate_symbol_table) (abfd, in, ext, count, str, strsize, dynamic) + bfd *abfd; + aout_symbol_type *in; + struct external_nlist *ext; + bfd_size_type count; + char *str; + bfd_size_type strsize; + boolean dynamic; { - bfd_size_type symbol_size; - bfd_size_type string_size; - unsigned char string_chars[BYTES_IN_WORD]; - struct external_nlist *syms; - char *strings; + struct external_nlist *ext_end; + + ext_end = ext + count; + for (; ext < ext_end; ext++, in++) + { + bfd_vma x; + + x = GET_WORD (abfd, ext->e_strx); + in->symbol.the_bfd = abfd; + + /* For the normal symbols, the zero index points at the number + of bytes in the string table but is to be interpreted as the + null string. For the dynamic symbols, the number of bytes in + the string table is stored in the __DYNAMIC structure and the + zero index points at an actual string. */ + if (x == 0 && ! dynamic) + in->symbol.name = ""; + else if (x < strsize) + in->symbol.name = str + x; + else + return false; + + in->symbol.value = GET_SWORD (abfd, ext->e_value); + in->desc = bfd_h_get_16 (abfd, ext->e_desc); + in->other = bfd_h_get_8 (abfd, ext->e_other); + in->type = bfd_h_get_8 (abfd, ext->e_type); + in->symbol.udata = 0; + + if (! translate_from_native_sym_flags (abfd, in)) + return false; + + if (dynamic) + in->symbol.flags |= BSF_DYNAMIC; + } + + return true; +} + +/* We read the symbols into a buffer, which is discarded when this + function exits. We read the strings into a buffer large enough to + hold them all plus all the cached symbol entries. */ + +boolean +NAME(aout,slurp_symbol_table) (abfd) + bfd *abfd; +{ + struct external_nlist *old_external_syms; aout_symbol_type *cached; + size_t cached_size; /* If there's no work to be done, don't do any */ - if (obj_aout_symbols (abfd) != (aout_symbol_type *)NULL) return true; - symbol_size = exec_hdr(abfd)->a_syms; - if (symbol_size == 0) + if (obj_aout_symbols (abfd) != (aout_symbol_type *) NULL) + return true; + + old_external_syms = obj_aout_external_syms (abfd); + + if (! aout_get_external_symbols (abfd)) + return false; + + if (obj_aout_external_sym_count (abfd) == 0) { - bfd_error = no_symbols; + bfd_set_error (bfd_error_no_symbols); return false; } - bfd_seek (abfd, obj_str_filepos (abfd), SEEK_SET); - if (bfd_read ((PTR)string_chars, BYTES_IN_WORD, 1, abfd) != BYTES_IN_WORD) - return false; - string_size = GET_WORD (abfd, string_chars); - - strings =(char *) bfd_alloc(abfd, string_size + 1); - cached = (aout_symbol_type *) - bfd_zalloc(abfd, (bfd_size_type)(bfd_get_symcount (abfd) * sizeof(aout_symbol_type))); - - /* malloc this, so we can free it if simply. The symbol caching - might want to allocate onto the bfd's obstack */ - syms = (struct external_nlist *) bfd_xmalloc(symbol_size); - bfd_seek (abfd, obj_sym_filepos (abfd), SEEK_SET); - if (bfd_read ((PTR)syms, 1, symbol_size, abfd) != symbol_size) - { - bailout: - if (syms) - free (syms); - if (cached) - bfd_release (abfd, cached); - if (strings) - bfd_release (abfd, strings); + cached_size = (obj_aout_external_sym_count (abfd) + * sizeof (aout_symbol_type)); + cached = (aout_symbol_type *) malloc (cached_size); + if (cached == NULL) + { + bfd_set_error (bfd_error_no_memory); return false; } - - bfd_seek (abfd, obj_str_filepos (abfd), SEEK_SET); - if (bfd_read ((PTR)strings, 1, string_size, abfd) != string_size) + memset (cached, 0, cached_size); + + /* Convert from external symbol information to internal. */ + if (! (NAME(aout,translate_symbol_table) + (abfd, cached, + obj_aout_external_syms (abfd), + obj_aout_external_sym_count (abfd), + obj_aout_external_strings (abfd), + obj_aout_external_string_size (abfd), + false))) { - goto bailout; + free (cached); + return false; } - strings[string_size] = 0; /* Just in case. */ - /* OK, now walk the new symtable, cacheing symbol properties */ - { - register struct external_nlist *sym_pointer; - register struct external_nlist *sym_end = syms + bfd_get_symcount (abfd); - register aout_symbol_type *cache_ptr = cached; + bfd_get_symcount (abfd) = obj_aout_external_sym_count (abfd); - /* Run through table and copy values */ - for (sym_pointer = syms, cache_ptr = cached; - sym_pointer < sym_end; sym_pointer ++, cache_ptr++) - { - long x = GET_WORD(abfd, sym_pointer->e_strx); - cache_ptr->symbol.the_bfd = abfd; - if (x == 0) - cache_ptr->symbol.name = ""; - else if (x >= 0 && x < string_size) - cache_ptr->symbol.name = x + strings; - else - goto bailout; - - cache_ptr->symbol.value = GET_SWORD(abfd, sym_pointer->e_value); - cache_ptr->desc = bfd_h_get_16(abfd, sym_pointer->e_desc); - cache_ptr->other = bfd_h_get_8(abfd, sym_pointer->e_other); - cache_ptr->type = bfd_h_get_8(abfd, sym_pointer->e_type); - cache_ptr->symbol.udata = 0; - translate_from_native_sym_flags (sym_pointer, cache_ptr, abfd); - } - } + obj_aout_symbols (abfd) = cached; - obj_aout_symbols (abfd) = cached; - free((PTR)syms); + /* It is very likely that anybody who calls this function will not + want the external symbol information, so if it was allocated + because of our call to aout_get_external_symbols, we free it up + right away to save space. */ + if (old_external_syms == (struct external_nlist *) NULL + && obj_aout_external_syms (abfd) != (struct external_nlist *) NULL) + { + free (obj_aout_external_syms (abfd)); + obj_aout_external_syms (abfd) = NULL; + } return true; } - -/* Possible improvements: +/* We use a hash table when writing out symbols so that we only write + out a particular string once. This helps particularly when the + linker writes out stabs debugging entries, because each different + contributing object file tends to have many duplicate stabs + strings. + + Possible improvements: + look for strings matching trailing substrings of other strings + better data structures? balanced trees? - + smaller per-string or per-symbol data? re-use some of the symbol's - data fields? - + also look at reducing memory use elsewhere -- maybe if we didn't have to - construct the entire symbol table at once, we could get by with smaller - amounts of VM? (What effect does that have on the string table - reductions?) - + rip this out of here, put it into its own file in bfd or libiberty, so - coff and elf can use it too. I'll work on this soon, but have more - pressing tasks right now. - - A hash table might(?) be more efficient for handling exactly the cases that - are handled now, but for trailing substring matches, I think we want to - examine the `nearest' values (reverse-)lexically, not merely impose a strict - order, nor look only for exact-match or not-match. I don't think a hash - table would be very useful for that, and I don't feel like fleshing out two - completely different implementations. [raeburn:930419.0331EDT] */ - -struct stringtab_entry { - /* Hash value for this string. Only useful so long as we aren't doing - substring matches. */ - unsigned int hash; - - /* Next node to look at, depending on whether the hash value of the string - being searched for is less than or greater than the hash value of the - current node. For now, `equal to' is lumped in with `greater than', for - space efficiency. It's not a common enough case to warrant another field - to be used for all nodes. */ - struct stringtab_entry *less; - struct stringtab_entry *greater; - - /* The string itself. */ - CONST char *string; - - /* The index allocated for this string. */ - bfd_size_type index; - -#ifdef GATHER_STATISTICS - /* How many references have there been to this string? (Not currently used; - could be dumped out for anaylsis, if anyone's interested.) */ - unsigned long count; -#endif - - /* Next node in linked list, in suggested output order. */ - struct stringtab_entry *next_to_output; -}; + + look at reducing memory use elsewhere -- maybe if we didn't have + to construct the entire symbol table at once, we could get by + with smaller amounts of VM? (What effect does that have on the + string table reductions?) -struct stringtab_data { - /* Tree of string table entries. */ - struct stringtab_entry *strings; + This hash table code breaks dbx on SunOS 4.1.3, so we don't do it + if BFD_TRADITIONAL_FORMAT is set. */ - /* Fudge factor used to center top node of tree. */ - int hash_zero; +/* An entry in the strtab hash table. */ - /* Next index value to issue. */ +struct strtab_hash_entry +{ + struct bfd_hash_entry root; + /* Index in string table. */ bfd_size_type index; - - /* Index used for empty strings. Cached here because checking for them - is really easy, and we can avoid searching the tree. */ - bfd_size_type empty_string_index; - - /* These fields indicate the two ends of a singly-linked list that indicates - the order strings should be written out in. Use this order, and no - seeking will need to be done, so output efficiency should be maximized. */ - struct stringtab_entry **end; - struct stringtab_entry *output_order; - -#ifdef GATHER_STATISTICS - /* Number of strings which duplicate strings already in the table. */ - unsigned long duplicates; - - /* Number of bytes saved by not having to write all the duplicate strings. */ - unsigned long bytes_saved; - - /* Number of zero-length strings. Currently, these all turn into - references to the null byte at the end of the first string. In some - cases (possibly not all? explore this...), it should be possible to - simply write out a zero index value. */ - unsigned long empty_strings; - - /* Number of times the hash values matched but the strings were different. - Note that this includes the number of times the other string(s) occurs, so - there may only be two strings hashing to the same value, even if this - number is very large. */ - unsigned long bad_hash_matches; - - /* Null strings aren't counted in this one. - This will probably only be nonzero if we've got an input file - which was produced by `ld -r' (i.e., it's already been processed - through this code). Under some operating systems, native tools - may make all empty strings have the same index; but the pointer - check won't catch those, because to get to that stage we'd already - have to compute the checksum, which requires reading the string, - so we short-circuit that case with empty_string_index above. */ - unsigned long pointer_matches; - - /* Number of comparisons done. I figure with the algorithms in use below, - the average number of comparisons done (per symbol) should be roughly - log-base-2 of the number of unique strings. */ - unsigned long n_compares; -#endif + /* Next string in strtab. */ + struct strtab_hash_entry *next; }; -/* Some utility functions for the string table code. */ +/* The strtab hash table. */ -/* For speed, only hash on the first this many bytes of strings. - This number was chosen by profiling ld linking itself, with -g. */ -#define HASHMAXLEN 25 +struct strtab_hash +{ + struct bfd_hash_table table; + /* Size of strtab--also next available index. */ + bfd_size_type size; + /* First string in strtab. */ + struct strtab_hash_entry *first; + /* Last string in strtab. */ + struct strtab_hash_entry *last; +}; -#define HASH_CHAR(c) (sum ^= sum >> 20, sum ^= sum << 7, sum += (c)) +static struct bfd_hash_entry *strtab_hash_newfunc + PARAMS ((struct bfd_hash_entry *, struct bfd_hash_table *, const char *)); +static boolean stringtab_init PARAMS ((struct strtab_hash *)); +static bfd_size_type add_to_stringtab + PARAMS ((bfd *, struct strtab_hash *, const char *, boolean)); +static boolean emit_stringtab PARAMS ((bfd *, struct strtab_hash *)); -static INLINE unsigned int -hash (string, len) - unsigned char *string; - register unsigned int len; -{ - register unsigned int sum = 0; +/* Routine to create an entry in a strtab. */ - if (len > HASHMAXLEN) +static struct bfd_hash_entry * +strtab_hash_newfunc (entry, table, string) + struct bfd_hash_entry *entry; + struct bfd_hash_table *table; + const char *string; +{ + struct strtab_hash_entry *ret = (struct strtab_hash_entry *) entry; + + /* Allocate the structure if it has not already been allocated by a + subclass. */ + if (ret == (struct strtab_hash_entry *) NULL) + ret = ((struct strtab_hash_entry *) + bfd_hash_allocate (table, sizeof (struct strtab_hash_entry))); + if (ret == (struct strtab_hash_entry *) NULL) { - HASH_CHAR (len); - len = HASHMAXLEN; + bfd_set_error (bfd_error_no_memory); + return NULL; } - while (len--) + /* Call the allocation method of the superclass. */ + ret = ((struct strtab_hash_entry *) + bfd_hash_newfunc ((struct bfd_hash_entry *) ret, table, string)); + + if (ret) { - HASH_CHAR (*string++); + /* Initialize the local fields. */ + ret->index = (bfd_size_type) -1; + ret->next = NULL; } - return sum; -} -static INLINE void -stringtab_init (tab) - struct stringtab_data *tab; -{ - tab->strings = 0; - tab->output_order = 0; - tab->end = &tab->output_order; - - /* Initial string table length includes size of length field. */ - tab->index = BYTES_IN_WORD; - tab->empty_string_index = -1; -#ifdef GATHER_STATISTICS - tab->duplicates = 0; - tab->empty_strings = 0; - tab->bad_hash_matches = 0; - tab->pointer_matches = 0; - tab->bytes_saved = 0; - tab->n_compares = 0; -#endif + return (struct bfd_hash_entry *) ret; } -static INLINE int -compare (entry, str, hash) - struct stringtab_entry *entry; - CONST char *str; - unsigned int hash; -{ - return hash - entry->hash; -} +/* Look up an entry in an strtab. */ + +#define strtab_hash_lookup(t, string, create, copy) \ + ((struct strtab_hash_entry *) \ + bfd_hash_lookup (&(t)->table, (string), (create), (copy))) -#ifdef GATHER_STATISTICS -/* Don't want to have to link in math library with all bfd applications... */ -static INLINE double -log2 (num) - int num; +/* Create a new strtab. */ + +static boolean +stringtab_init (table) + struct strtab_hash *table; { - double d = num; - int n = 0; - while (d >= 2.0) - n++, d /= 2.0; - return ((d > 1.41) ? 0.5 : 0) + n; + if (! bfd_hash_table_init (&table->table, strtab_hash_newfunc)) + return false; + + /* Leave space for the size of the string table. */ + table->size = BYTES_IN_WORD; + + table->first = NULL; + table->last = NULL; + + return true; } -#endif -/* Main string table routines. */ -/* Returns index in string table. Whether or not this actually adds an - entry into the string table should be irrelevant -- it just has to - return a valid index. */ -static bfd_size_type -add_to_stringtab (abfd, str, tab, check) - bfd *abfd; - CONST char *str; - struct stringtab_data *tab; - int check; -{ - struct stringtab_entry **ep; - register struct stringtab_entry *entry; - unsigned int hashval, len; +/* Free a strtab. */ - if (str[0] == 0) - { - bfd_size_type index; - CONST bfd_size_type minus_one = -1; +#define stringtab_free(tab) bfd_hash_table_free (&(tab)->table) -#ifdef GATHER_STATISTICS - tab->empty_strings++; -#endif - index = tab->empty_string_index; - if (index != minus_one) - { - got_empty: -#ifdef GATHER_STATISTICS - tab->bytes_saved++; - tab->duplicates++; -#endif - return index; - } +/* Get the index of a string in a strtab, adding it if it is not + already present. If HASH is false, we don't really use the hash + table, and we don't eliminate duplicate strings. */ - /* Need to find it. */ - entry = tab->strings; - if (entry) - { - index = entry->index + strlen (entry->string); - tab->empty_string_index = index; - goto got_empty; - } - len = 0; - } - else - len = strlen (str); +static INLINE bfd_size_type +add_to_stringtab (abfd, tab, str, copy) + bfd *abfd; + struct strtab_hash *tab; + const char *str; + boolean copy; +{ + register struct strtab_hash_entry *entry; - /* The hash_zero value is chosen such that the first symbol gets a value of - zero. With a balanced tree, this wouldn't be very useful, but without it, - we might get a more even split at the top level, instead of skewing it - badly should hash("/usr/lib/crt0.o") (or whatever) be far from zero. */ - hashval = hash (str, len) ^ tab->hash_zero; - ep = &tab->strings; - if (!*ep) + /* An index of 0 always means the empty string. */ + if (*str == '\0') + return 0; + + if ((abfd->flags & BFD_TRADITIONAL_FORMAT) == 0) { - tab->hash_zero = hashval; - hashval = 0; - goto add_it; + entry = strtab_hash_lookup (tab, str, true, copy); + if (entry == NULL) + return (bfd_size_type) -1; } - - while (*ep) + else { - register int cmp; - - entry = *ep; -#ifdef GATHER_STATISTICS - tab->n_compares++; -#endif - cmp = compare (entry, str, hashval); - /* The not-equal cases are more frequent, so check them first. */ - if (cmp > 0) - ep = &entry->greater; - else if (cmp < 0) - ep = &entry->less; + entry = ((struct strtab_hash_entry *) + bfd_hash_allocate (&tab->table, + sizeof (struct strtab_hash_entry))); + if (entry == NULL) + return (bfd_size_type) -1; + if (! copy) + entry->root.string = str; else { - if (entry->string == str) - { -#ifdef GATHER_STATISTICS - tab->pointer_matches++; -#endif - goto match; - } - /* Compare the first bytes to save a function call if they - don't match. */ - if (entry->string[0] == str[0] && !strcmp (entry->string, str)) - { - match: -#ifdef GATHER_STATISTICS - entry->count++; - tab->bytes_saved += len + 1; - tab->duplicates++; -#endif - /* If we're in the linker, and the new string is from a new - input file which might have already had these reductions - run over it, we want to keep the new string pointer. I - don't think we're likely to see any (or nearly as many, - at least) cases where a later string is in the same location - as an earlier one rather than this one. */ - entry->string = str; - return entry->index; - } -#ifdef GATHER_STATISTICS - tab->bad_hash_matches++; -#endif - ep = &entry->greater; + char *n; + + n = (char *) bfd_hash_allocate (&tab->table, strlen (str) + 1); + if (n == NULL) + return (bfd_size_type) -1; + entry->root.string = n; } + entry->index = (bfd_size_type) -1; + entry->next = NULL; } - /* If we get here, nothing that's in the table already matched. - EP points to the `next' field at the end of the chain; stick a - new entry on here. */ - add_it: - entry = (struct stringtab_entry *) - bfd_alloc_by_size_t (abfd, sizeof (struct stringtab_entry)); - - entry->less = entry->greater = 0; - entry->hash = hashval; - entry->index = tab->index; - entry->string = str; - entry->next_to_output = 0; -#ifdef GATHER_STATISTICS - entry->count = 1; -#endif - - assert (*tab->end == 0); - *(tab->end) = entry; - tab->end = &entry->next_to_output; - assert (*tab->end == 0); + if (entry->index == (bfd_size_type) -1) + { + entry->index = tab->size; + tab->size += strlen (str) + 1; + if (tab->first == NULL) + tab->first = entry; + else + tab->last->next = entry; + tab->last = entry; + } - { - tab->index += len + 1; - if (len == 0) - tab->empty_string_index = entry->index; - } - assert (*ep == 0); - *ep = entry; return entry->index; } -static void -emit_strtab (abfd, tab) - bfd *abfd; - struct stringtab_data *tab; -{ - struct stringtab_entry *entry; -#ifdef GATHER_STATISTICS - int count = 0; -#endif +/* Write out a strtab. ABFD is already at the right location in the + file. */ - /* Be sure to put string length into correct byte ordering before writing - it out. */ - char buffer[BYTES_IN_WORD]; +static boolean +emit_stringtab (abfd, tab) + register bfd *abfd; + struct strtab_hash *tab; +{ + bfd_byte buffer[BYTES_IN_WORD]; + register struct strtab_hash_entry *entry; - PUT_WORD (abfd, tab->index, (unsigned char *) buffer); - bfd_write ((PTR) buffer, 1, BYTES_IN_WORD, abfd); + PUT_WORD (abfd, tab->size, buffer); + if (bfd_write ((PTR) buffer, 1, BYTES_IN_WORD, abfd) != BYTES_IN_WORD) + return false; - for (entry = tab->output_order; entry; entry = entry->next_to_output) + for (entry = tab->first; entry != NULL; entry = entry->next) { - bfd_write ((PTR) entry->string, 1, strlen (entry->string) + 1, abfd); -#ifdef GATHER_STATISTICS - count++; -#endif - } + register const char *str; + register size_t len; -#ifdef GATHER_STATISTICS - /* Short form only, for now. - To do: Specify output file. Conditionalize on environment? Detailed - analysis if desired. */ - { - int n_syms = bfd_get_symcount (abfd); - - fprintf (stderr, "String table data for output file:\n"); - fprintf (stderr, " %8d symbols output\n", n_syms); - fprintf (stderr, " %8d duplicate strings\n", tab->duplicates); - fprintf (stderr, " %8d empty strings\n", tab->empty_strings); - fprintf (stderr, " %8d unique strings output\n", count); - fprintf (stderr, " %8d pointer matches\n", tab->pointer_matches); - fprintf (stderr, " %8d bytes saved\n", tab->bytes_saved); - fprintf (stderr, " %8d bad hash matches\n", tab->bad_hash_matches); - fprintf (stderr, " %8d hash-val comparisons\n", tab->n_compares); - if (n_syms) - { - double n_compares = tab->n_compares; - double avg_compares = n_compares / n_syms; - /* The second value here should usually be near one. */ - fprintf (stderr, - "\t average %f comparisons per symbol (%f * log2 nstrings)\n", - avg_compares, avg_compares / log2 (count)); - } - } -#endif - -/* Old code: - unsigned int count; - generic = bfd_get_outsymbols(abfd); - for (count = 0; count < bfd_get_symcount(abfd); count++) - { - asymbol *g = *(generic++); + str = entry->root.string; + len = strlen (str) + 1; + if (bfd_write ((PTR) str, 1, len, abfd) != len) + return false; + } - if (g->name) - { - size_t length = strlen(g->name)+1; - bfd_write((PTR)g->name, 1, length, abfd); - } - g->KEEPIT = (KEEPITTYPE) count; - } */ + return true; } - -void -DEFUN(NAME(aout,write_syms),(abfd), - bfd *abfd) + +boolean +NAME(aout,write_syms) (abfd) + bfd *abfd; { unsigned int count ; asymbol **generic = bfd_get_outsymbols (abfd); - struct stringtab_data strtab; + struct strtab_hash strtab; - stringtab_init (&strtab); + if (! stringtab_init (&strtab)) + return false; for (count = 0; count < bfd_get_symcount (abfd); count++) { asymbol *g = generic[count]; + bfd_size_type indx; struct external_nlist nsp; - if (g->name) - PUT_WORD (abfd, add_to_stringtab (abfd, g->name, &strtab), - (unsigned char *) nsp.e_strx); - else - PUT_WORD (abfd, 0, (unsigned char *)nsp.e_strx); + indx = add_to_stringtab (abfd, &strtab, g->name, false); + if (indx == (bfd_size_type) -1) + goto error_return; + PUT_WORD (abfd, indx, (bfd_byte *) nsp.e_strx); if (bfd_asymbol_flavour(g) == abfd->xvec->flavour) { @@ -1837,28 +1941,41 @@ DEFUN(NAME(aout,write_syms),(abfd), bfd_h_put_8(abfd, 0, nsp.e_type); } - translate_to_native_sym_flags (&nsp, g, abfd); + if (! translate_to_native_sym_flags (abfd, g, &nsp)) + goto error_return; - bfd_write((PTR)&nsp,1,EXTERNAL_NLIST_SIZE, abfd); + if (bfd_write((PTR)&nsp,1,EXTERNAL_NLIST_SIZE, abfd) + != EXTERNAL_NLIST_SIZE) + goto error_return; /* NB: `KEEPIT' currently overlays `flags', so set this only here, at the end. */ g->KEEPIT = count; } - emit_strtab (abfd, &strtab); + if (! emit_stringtab (abfd, &strtab)) + goto error_return; + + stringtab_free (&strtab); + + return true; + +error_return: + stringtab_free (&strtab); + return false; } -unsigned int -DEFUN(NAME(aout,get_symtab),(abfd, location), - bfd *abfd AND - asymbol **location) +long +NAME(aout,get_symtab) (abfd, location) + bfd *abfd; + asymbol **location; { unsigned int counter = 0; aout_symbol_type *symbase; - if (!NAME(aout,slurp_symbol_table)(abfd)) return 0; + if (!NAME(aout,slurp_symbol_table)(abfd)) + return -1; for (symbase = obj_aout_symbols(abfd); counter++ < bfd_get_symcount (abfd);) *(location++) = (asymbol *)( symbase++); @@ -1871,10 +1988,10 @@ DEFUN(NAME(aout,get_symtab),(abfd, location), /* Output standard relocation information to a file in target byte order. */ void -DEFUN(NAME(aout,swap_std_reloc_out),(abfd, g, natptr), - bfd *abfd AND - arelent *g AND - struct reloc_std_external *natptr) +NAME(aout,swap_std_reloc_out) (abfd, g, natptr) + bfd *abfd; + arelent *g; + struct reloc_std_external *natptr; { int r_index; asymbol *sym = *(g->sym_ptr_ptr); @@ -1882,7 +1999,6 @@ DEFUN(NAME(aout,swap_std_reloc_out),(abfd, g, natptr), unsigned int r_length; int r_pcrel; int r_baserel, r_jmptable, r_relative; - unsigned int r_addend; asection *output_section = sym->section->output_section; PUT_WORD(abfd, g->address, natptr->r_address); @@ -1891,11 +2007,13 @@ DEFUN(NAME(aout,swap_std_reloc_out),(abfd, g, natptr), r_pcrel = (int) g->howto->pc_relative; /* Relative to PC? */ /* XXX This relies on relocs coming from a.out files. */ r_baserel = (g->howto->type & 8) != 0; - /* r_jmptable, r_relative??? FIXME-soon */ - r_jmptable = 0; - r_relative = 0; + r_jmptable = (g->howto->type & 16) != 0; + r_relative = (g->howto->type & 32) != 0; +#if 0 + /* For a standard reloc, the addend is in the object file. */ r_addend = g->addend + (*(g->sym_ptr_ptr))->section->output_section->vma; +#endif /* name was clobbered by aout_write_syms to be symbol index */ @@ -1909,10 +2027,10 @@ DEFUN(NAME(aout,swap_std_reloc_out),(abfd, g, natptr), if (bfd_is_com_section (output_section) - || output_section == &bfd_abs_section - || output_section == &bfd_und_section) + || bfd_is_abs_section (output_section) + || bfd_is_und_section (output_section)) { - if (bfd_abs_section.symbol == sym) + if (bfd_abs_section_ptr->symbol == sym) { /* Whoops, looked like an abs symbol, but is really an offset from the abs section */ @@ -1965,10 +2083,10 @@ DEFUN(NAME(aout,swap_std_reloc_out),(abfd, g, natptr), /* Output extended relocation information to a file in target byte order. */ void -DEFUN(NAME(aout,swap_ext_reloc_out),(abfd, g, natptr), - bfd *abfd AND - arelent *g AND - register struct reloc_ext_external *natptr) +NAME(aout,swap_ext_reloc_out) (abfd, g, natptr) + bfd *abfd; + arelent *g; + register struct reloc_ext_external *natptr; { int r_index; int r_extern; @@ -1991,10 +2109,10 @@ DEFUN(NAME(aout,swap_ext_reloc_out),(abfd, g, natptr), check for that here. */ if (bfd_is_com_section (output_section) - || output_section == &bfd_abs_section - || output_section == &bfd_und_section) + || bfd_is_abs_section (output_section) + || bfd_is_und_section (output_section)) { - if (bfd_abs_section.symbol == sym) + if (bfd_abs_section_ptr->symbol == sym) { /* Whoops, looked like an abs symbol, but is really an offset from the abs section */ @@ -2070,18 +2188,18 @@ DEFUN(NAME(aout,swap_ext_reloc_out),(abfd, g, natptr), default: \ case N_ABS: \ case N_ABS | N_EXT: \ - cache_ptr->sym_ptr_ptr = bfd_abs_section.symbol_ptr_ptr; \ + cache_ptr->sym_ptr_ptr = bfd_abs_section_ptr->symbol_ptr_ptr; \ cache_ptr->addend = ad; \ break; \ } \ } \ void -DEFUN(NAME(aout,swap_ext_reloc_in), (abfd, bytes, cache_ptr, symbols), - bfd *abfd AND - struct reloc_ext_external *bytes AND - arelent *cache_ptr AND - asymbol **symbols) +NAME(aout,swap_ext_reloc_in) (abfd, bytes, cache_ptr, symbols) + bfd *abfd; + struct reloc_ext_external *bytes; + arelent *cache_ptr; + asymbol **symbols; { int r_index; int r_extern; @@ -2112,11 +2230,11 @@ DEFUN(NAME(aout,swap_ext_reloc_in), (abfd, bytes, cache_ptr, symbols), } void -DEFUN(NAME(aout,swap_std_reloc_in), (abfd, bytes, cache_ptr, symbols), - bfd *abfd AND - struct reloc_std_external *bytes AND - arelent *cache_ptr AND - asymbol **symbols) +NAME(aout,swap_std_reloc_in) (abfd, bytes, cache_ptr, symbols) + bfd *abfd; + struct reloc_std_external *bytes; + arelent *cache_ptr; + asymbol **symbols; { int r_index; int r_extern; @@ -2153,109 +2271,111 @@ DEFUN(NAME(aout,swap_std_reloc_in), (abfd, bytes, cache_ptr, symbols), >> RELOC_STD_BITS_LENGTH_SH_LITTLE; } - howto_idx = r_length + 4 * r_pcrel + 8 * r_baserel; + howto_idx = r_length + 4 * r_pcrel + 8 * r_baserel + + 16 * r_jmptable + 32 * r_relative; BFD_ASSERT (howto_idx < TABLE_SIZE (howto_table_std)); cache_ptr->howto = howto_table_std + howto_idx; BFD_ASSERT (cache_ptr->howto->type != -1); - BFD_ASSERT (r_jmptable == 0); - BFD_ASSERT (r_relative == 0); - /* FIXME-soon: Roll jmptable, relative bits into howto setting */ MOVE_ADDRESS(0); } -/* Reloc hackery */ +/* Read and swap the relocs for a section. */ boolean -DEFUN(NAME(aout,slurp_reloc_table),(abfd, asect, symbols), - bfd *abfd AND - sec_ptr asect AND - asymbol **symbols) +NAME(aout,slurp_reloc_table) (abfd, asect, symbols) + bfd *abfd; + sec_ptr asect; + asymbol **symbols; { unsigned int count; bfd_size_type reloc_size; PTR relocs; arelent *reloc_cache; size_t each_size; + unsigned int counter = 0; + arelent *cache_ptr; - if (asect->relocation) return true; + if (asect->relocation) + return true; - if (asect->flags & SEC_CONSTRUCTOR) return true; + if (asect->flags & SEC_CONSTRUCTOR) + return true; - if (asect == obj_datasec (abfd)) { + if (asect == obj_datasec (abfd)) reloc_size = exec_hdr(abfd)->a_drsize; - goto doit; - } - - if (asect == obj_textsec (abfd)) { + else if (asect == obj_textsec (abfd)) reloc_size = exec_hdr(abfd)->a_trsize; - goto doit; - } + else if (asect == obj_bsssec (abfd)) + reloc_size = 0; + else + { + bfd_set_error (bfd_error_invalid_operation); + return false; + } - bfd_error = invalid_operation; - return false; + if (bfd_seek (abfd, asect->rel_filepos, SEEK_SET) != 0) + return false; - doit: - bfd_seek (abfd, asect->rel_filepos, SEEK_SET); each_size = obj_reloc_entry_size (abfd); count = reloc_size / each_size; + reloc_cache = (arelent *) malloc ((size_t) (count * sizeof (arelent))); + if (reloc_cache == NULL && count != 0) + { + bfd_set_error (bfd_error_no_memory); + return false; + } + memset (reloc_cache, 0, count * sizeof (arelent)); - reloc_cache = (arelent *) bfd_zalloc (abfd, (size_t)(count * sizeof - (arelent))); - if (!reloc_cache) { -nomem: - bfd_error = no_memory; - return false; - } - - relocs = (PTR) bfd_alloc (abfd, reloc_size); - if (!relocs) { - bfd_release (abfd, reloc_cache); - goto nomem; - } + relocs = malloc (reloc_size); + if (relocs == NULL && reloc_size != 0) + { + free (reloc_cache); + bfd_set_error (bfd_error_no_memory); + return false; + } - if (bfd_read (relocs, 1, reloc_size, abfd) != reloc_size) { - bfd_release (abfd, relocs); - bfd_release (abfd, reloc_cache); - bfd_error = system_call_error; - return false; - } + if (bfd_read (relocs, 1, reloc_size, abfd) != reloc_size) + { + free (relocs); + free (reloc_cache); + return false; + } - if (each_size == RELOC_EXT_SIZE) { - register struct reloc_ext_external *rptr = (struct reloc_ext_external *) relocs; - unsigned int counter = 0; - arelent *cache_ptr = reloc_cache; + cache_ptr = reloc_cache; + if (each_size == RELOC_EXT_SIZE) + { + register struct reloc_ext_external *rptr = + (struct reloc_ext_external *) relocs; - for (; counter < count; counter++, rptr++, cache_ptr++) { - NAME(aout,swap_ext_reloc_in)(abfd, rptr, cache_ptr, symbols); + for (; counter < count; counter++, rptr++, cache_ptr++) + NAME(aout,swap_ext_reloc_in) (abfd, rptr, cache_ptr, symbols); } - } else { - register struct reloc_std_external *rptr = (struct reloc_std_external*) relocs; - unsigned int counter = 0; - arelent *cache_ptr = reloc_cache; + else + { + register struct reloc_std_external *rptr = + (struct reloc_std_external *) relocs; - for (; counter < count; counter++, rptr++, cache_ptr++) { - NAME(aout,swap_std_reloc_in)(abfd, rptr, cache_ptr, symbols); + for (; counter < count; counter++, rptr++, cache_ptr++) + MY_swap_std_reloc_in(abfd, rptr, cache_ptr, symbols); } - } + free (relocs); - bfd_release (abfd,relocs); asect->relocation = reloc_cache; - asect->reloc_count = count; + asect->reloc_count = cache_ptr - reloc_cache; + return true; } - - /* Write out a relocation section into an object file. */ boolean -DEFUN(NAME(aout,squirt_out_relocs),(abfd, section), - bfd *abfd AND - asection *section) +NAME(aout,squirt_out_relocs) (abfd, section) + bfd *abfd; + asection *section; { arelent **generic; unsigned char *native, *natptr; @@ -2270,7 +2390,7 @@ DEFUN(NAME(aout,squirt_out_relocs),(abfd, section), natsize = each_size * count; native = (unsigned char *) bfd_zalloc (abfd, natsize); if (!native) { - bfd_error = no_memory; + bfd_set_error (bfd_error_no_memory); return false; } @@ -2288,7 +2408,7 @@ DEFUN(NAME(aout,squirt_out_relocs),(abfd, section), for (natptr = native; count != 0; --count, natptr += each_size, ++generic) - NAME(aout,swap_std_reloc_out)(abfd, *generic, (struct reloc_std_external *)natptr); + MY_swap_std_reloc_out(abfd, *generic, (struct reloc_std_external *)natptr); } if ( bfd_write ((PTR) native, 1, natsize, abfd) != natsize) { @@ -2301,18 +2421,24 @@ DEFUN(NAME(aout,squirt_out_relocs),(abfd, section), } /* This is stupid. This function should be a boolean predicate */ -unsigned int -DEFUN(NAME(aout,canonicalize_reloc),(abfd, section, relptr, symbols), - bfd *abfd AND - sec_ptr section AND - arelent **relptr AND - asymbol **symbols) +long +NAME(aout,canonicalize_reloc) (abfd, section, relptr, symbols) + bfd *abfd; + sec_ptr section; + arelent **relptr; + asymbol **symbols; { arelent *tblptr = section->relocation; unsigned int count; + if (section == obj_bsssec (abfd)) + { + *relptr = NULL; + return 0; + } + if (!(tblptr || NAME(aout,slurp_reloc_table)(abfd, section, symbols))) - return 0; + return -1; if (section->flags & SEC_CONSTRUCTOR) { arelent_chain *chain = section->constructor_chain; @@ -2323,7 +2449,6 @@ DEFUN(NAME(aout,canonicalize_reloc),(abfd, section, relptr, symbols), } else { tblptr = section->relocation; - if (!tblptr) return 0; for (count = 0; count++ < section->reloc_count;) { @@ -2335,56 +2460,65 @@ DEFUN(NAME(aout,canonicalize_reloc),(abfd, section, relptr, symbols), return section->reloc_count; } -unsigned int -DEFUN(NAME(aout,get_reloc_upper_bound),(abfd, asect), - bfd *abfd AND - sec_ptr asect) +long +NAME(aout,get_reloc_upper_bound) (abfd, asect) + bfd *abfd; + sec_ptr asect; { if (bfd_get_format (abfd) != bfd_object) { - bfd_error = invalid_operation; - return 0; + bfd_set_error (bfd_error_invalid_operation); + return -1; } if (asect->flags & SEC_CONSTRUCTOR) { return (sizeof (arelent *) * (asect->reloc_count+1)); } - if (asect == obj_datasec (abfd)) - return (sizeof (arelent *) * - ((exec_hdr(abfd)->a_drsize / obj_reloc_entry_size (abfd)) - +1)); + return (sizeof (arelent *) + * ((exec_hdr(abfd)->a_drsize / obj_reloc_entry_size (abfd)) + + 1)); if (asect == obj_textsec (abfd)) - return (sizeof (arelent *) * - ((exec_hdr(abfd)->a_trsize / obj_reloc_entry_size (abfd)) - +1)); + return (sizeof (arelent *) + * ((exec_hdr(abfd)->a_trsize / obj_reloc_entry_size (abfd)) + + 1)); - bfd_error = invalid_operation; - return 0; + if (asect == obj_bsssec (abfd)) + return sizeof (arelent *); + + if (asect == obj_bsssec (abfd)) + return 0; + + bfd_set_error (bfd_error_invalid_operation); + return -1; } - unsigned int -DEFUN(NAME(aout,get_symtab_upper_bound),(abfd), - bfd *abfd) +long +NAME(aout,get_symtab_upper_bound) (abfd) + bfd *abfd; { - if (!NAME(aout,slurp_symbol_table)(abfd)) return 0; + if (!NAME(aout,slurp_symbol_table)(abfd)) + return -1; return (bfd_get_symcount (abfd)+1) * (sizeof (aout_symbol_type *)); } + +/*ARGSUSED*/ alent * -DEFUN(NAME(aout,get_lineno),(ignore_abfd, ignore_symbol), - bfd *ignore_abfd AND - asymbol *ignore_symbol) +NAME(aout,get_lineno) (ignore_abfd, ignore_symbol) + bfd *ignore_abfd; + asymbol *ignore_symbol; { return (alent *)NULL; } +/*ARGSUSED*/ void -DEFUN(NAME(aout,get_symbol_info),(ignore_abfd, symbol, ret), - bfd *ignore_abfd AND - asymbol *symbol AND - symbol_info *ret) +NAME(aout,get_symbol_info) (ignore_abfd, symbol, ret) + bfd *ignore_abfd; + asymbol *symbol; + symbol_info *ret; { bfd_symbol_info (symbol, ret); @@ -2406,12 +2540,13 @@ DEFUN(NAME(aout,get_symbol_info),(ignore_abfd, symbol, ret), } } +/*ARGSUSED*/ void -DEFUN(NAME(aout,print_symbol),(ignore_abfd, afile, symbol, how), - bfd *ignore_abfd AND - PTR afile AND - asymbol *symbol AND - bfd_print_symbol_type how) +NAME(aout,print_symbol) (ignore_abfd, afile, symbol, how) + bfd *ignore_abfd; + PTR afile; + asymbol *symbol; + bfd_print_symbol_type how; { FILE *file = (FILE *)afile; @@ -2451,20 +2586,15 @@ DEFUN(NAME(aout,print_symbol),(ignore_abfd, afile, symbol, how), */ boolean -DEFUN(NAME(aout,find_nearest_line),(abfd, - section, - symbols, - offset, - filename_ptr, - functionname_ptr, - line_ptr), - bfd *abfd AND - asection *section AND - asymbol **symbols AND - bfd_vma offset AND - CONST char **filename_ptr AND - CONST char **functionname_ptr AND - unsigned int *line_ptr) +NAME(aout,find_nearest_line) + (abfd, section, symbols, offset, filename_ptr, functionname_ptr, line_ptr) + bfd *abfd; + asection *section; + asymbol **symbols; + bfd_vma offset; + CONST char **filename_ptr; + CONST char **functionname_ptr; + unsigned int *line_ptr; { /* Run down the file looking for the filename, function and linenumber */ asymbol **p; @@ -2528,7 +2658,18 @@ DEFUN(NAME(aout,find_nearest_line),(abfd, if (*line_ptr && func) { CONST char *function = func->name; char *p; - strncpy(buffer, function, sizeof(buffer)-1); + + /* The caller expects a symbol name. We actually have a + function name, without the leading underscore. Put the + underscore back in, so that the caller gets a symbol + name. */ + if (bfd_get_symbol_leading_char (abfd) == '\0') + strncpy (buffer, function, sizeof (buffer) - 1); + else + { + buffer[0] = bfd_get_symbol_leading_char (abfd); + strncpy (buffer + 1, function, sizeof (buffer) - 2); + } buffer[sizeof(buffer)-1] = 0; /* Have to remove : stuff */ p = strchr(buffer,':'); @@ -2559,10 +2700,2295 @@ DEFUN(NAME(aout,find_nearest_line),(abfd, } +/*ARGSUSED*/ int -DEFUN(NAME(aout,sizeof_headers),(abfd, execable), - bfd *abfd AND - boolean execable) +NAME(aout,sizeof_headers) (abfd, execable) + bfd *abfd; + boolean execable; { return adata(abfd).exec_bytes_size; } + +/* Free all information we have cached for this BFD. We can always + read it again later if we need it. */ + +boolean +NAME(aout,bfd_free_cached_info) (abfd) + bfd *abfd; +{ + asection *o; + + if (bfd_get_format (abfd) != bfd_object) + return true; + +#define BFCI_FREE(x) if (x != NULL) { free (x); x = NULL; } + BFCI_FREE (obj_aout_symbols (abfd)); + BFCI_FREE (obj_aout_external_syms (abfd)); + BFCI_FREE (obj_aout_external_strings (abfd)); + for (o = abfd->sections; o != (asection *) NULL; o = o->next) + BFCI_FREE (o->relocation); +#undef BFCI_FREE + + return true; +} + +/* a.out link code. */ + +static boolean aout_link_add_object_symbols + PARAMS ((bfd *, struct bfd_link_info *)); +static boolean aout_link_check_archive_element + PARAMS ((bfd *, struct bfd_link_info *, boolean *)); +static boolean aout_link_free_symbols PARAMS ((bfd *)); +static boolean aout_link_check_ar_symbols + PARAMS ((bfd *, struct bfd_link_info *, boolean *pneeded)); +static boolean aout_link_add_symbols + PARAMS ((bfd *, struct bfd_link_info *)); + +/* Routine to create an entry in an a.out link hash table. */ + +struct bfd_hash_entry * +NAME(aout,link_hash_newfunc) (entry, table, string) + struct bfd_hash_entry *entry; + struct bfd_hash_table *table; + const char *string; +{ + struct aout_link_hash_entry *ret = (struct aout_link_hash_entry *) entry; + + /* Allocate the structure if it has not already been allocated by a + subclass. */ + if (ret == (struct aout_link_hash_entry *) NULL) + ret = ((struct aout_link_hash_entry *) + bfd_hash_allocate (table, sizeof (struct aout_link_hash_entry))); + if (ret == (struct aout_link_hash_entry *) NULL) + { + bfd_set_error (bfd_error_no_memory); + return (struct bfd_hash_entry *) ret; + } + + /* Call the allocation method of the superclass. */ + ret = ((struct aout_link_hash_entry *) + _bfd_link_hash_newfunc ((struct bfd_hash_entry *) ret, + table, string)); + if (ret) + { + /* Set local fields. */ + ret->written = false; + ret->indx = -1; + } + + return (struct bfd_hash_entry *) ret; +} + +/* Initialize an a.out link hash table. */ + +boolean +NAME(aout,link_hash_table_init) (table, abfd, newfunc) + struct aout_link_hash_table *table; + bfd *abfd; + struct bfd_hash_entry *(*newfunc) PARAMS ((struct bfd_hash_entry *, + struct bfd_hash_table *, + const char *)); +{ + return _bfd_link_hash_table_init (&table->root, abfd, newfunc); +} + +/* Create an a.out link hash table. */ + +struct bfd_link_hash_table * +NAME(aout,link_hash_table_create) (abfd) + bfd *abfd; +{ + struct aout_link_hash_table *ret; + + ret = ((struct aout_link_hash_table *) + malloc (sizeof (struct aout_link_hash_table))); + if (ret == (struct aout_link_hash_table *) NULL) + { + bfd_set_error (bfd_error_no_memory); + return (struct bfd_link_hash_table *) NULL; + } + if (! NAME(aout,link_hash_table_init) (ret, abfd, + NAME(aout,link_hash_newfunc))) + { + free (ret); + return (struct bfd_link_hash_table *) NULL; + } + return &ret->root; +} + +/* Given an a.out BFD, add symbols to the global hash table as + appropriate. */ + +boolean +NAME(aout,link_add_symbols) (abfd, info) + bfd *abfd; + struct bfd_link_info *info; +{ + switch (bfd_get_format (abfd)) + { + case bfd_object: + return aout_link_add_object_symbols (abfd, info); + case bfd_archive: + return _bfd_generic_link_add_archive_symbols + (abfd, info, aout_link_check_archive_element); + default: + bfd_set_error (bfd_error_wrong_format); + return false; + } +} + +/* Add symbols from an a.out object file. */ + +static boolean +aout_link_add_object_symbols (abfd, info) + bfd *abfd; + struct bfd_link_info *info; +{ + if (! aout_get_external_symbols (abfd)) + return false; + if (! aout_link_add_symbols (abfd, info)) + return false; + if (! info->keep_memory) + { + if (! aout_link_free_symbols (abfd)) + return false; + } + return true; +} + +/* Check a single archive element to see if we need to include it in + the link. *PNEEDED is set according to whether this element is + needed in the link or not. This is called from + _bfd_generic_link_add_archive_symbols. */ + +static boolean +aout_link_check_archive_element (abfd, info, pneeded) + bfd *abfd; + struct bfd_link_info *info; + boolean *pneeded; +{ + if (! aout_get_external_symbols (abfd)) + return false; + + if (! aout_link_check_ar_symbols (abfd, info, pneeded)) + return false; + + if (*pneeded) + { + if (! aout_link_add_symbols (abfd, info)) + return false; + } + + /* We keep around the symbols even if we aren't going to use this + object file, because we may want to reread it. This doesn't + waste too much memory, because it isn't all that common to read + an archive element but not need it. */ + if (! info->keep_memory) + { + if (! aout_link_free_symbols (abfd)) + return false; + } + + return true; +} + +/* Free up the internal symbols read from an a.out file. */ + +static boolean +aout_link_free_symbols (abfd) + bfd *abfd; +{ + if (obj_aout_external_syms (abfd) != (struct external_nlist *) NULL) + { + free ((PTR) obj_aout_external_syms (abfd)); + obj_aout_external_syms (abfd) = (struct external_nlist *) NULL; + } + if (obj_aout_external_strings (abfd) != (char *) NULL) + { + free ((PTR) obj_aout_external_strings (abfd)); + obj_aout_external_strings (abfd) = (char *) NULL; + } + return true; +} + +/* Look through the internal symbols to see if this object file should + be included in the link. We should include this object file if it + defines any symbols which are currently undefined. If this object + file defines a common symbol, then we may adjust the size of the + known symbol but we do not include the object file in the link + (unless there is some other reason to include it). */ + +static boolean +aout_link_check_ar_symbols (abfd, info, pneeded) + bfd *abfd; + struct bfd_link_info *info; + boolean *pneeded; +{ + register struct external_nlist *p; + struct external_nlist *pend; + char *strings; + + *pneeded = false; + + /* Look through all the symbols. */ + p = obj_aout_external_syms (abfd); + pend = p + obj_aout_external_sym_count (abfd); + strings = obj_aout_external_strings (abfd); + for (; p < pend; p++) + { + int type = bfd_h_get_8 (abfd, p->e_type); + const char *name; + struct bfd_link_hash_entry *h; + + /* Ignore symbols that are not externally visible. This is an + optimization only, as we check the type more thoroughly + below. */ + if (((type & N_EXT) == 0 + || (type & N_STAB) != 0 + || type == N_FN) + && type != N_WEAKA + && type != N_WEAKT + && type != N_WEAKD + && type != N_WEAKB) + { + if (type == N_WARNING + || type == N_INDR) + ++p; + continue; + } + + name = strings + GET_WORD (abfd, p->e_strx); + h = bfd_link_hash_lookup (info->hash, name, false, false, true); + + /* We are only interested in symbols that are currently + undefined or common. */ + if (h == (struct bfd_link_hash_entry *) NULL + || (h->type != bfd_link_hash_undefined + && h->type != bfd_link_hash_common)) + { + if (type == (N_INDR | N_EXT)) + ++p; + continue; + } + + if (type == (N_TEXT | N_EXT) + || type == (N_DATA | N_EXT) + || type == (N_BSS | N_EXT) + || type == (N_ABS | N_EXT) + || type == (N_INDR | N_EXT)) + { + /* This object file defines this symbol. We must link it + in. This is true regardless of whether the current + definition of the symbol is undefined or common. If the + current definition is common, we have a case in which we + have already seen an object file including + int a; + and this object file from the archive includes + int a = 5; + In such a case we must include this object file. + + FIXME: The SunOS 4.1.3 linker will pull in the archive + element if the symbol is defined in the .data section, + but not if it is defined in the .text section. That + seems a bit crazy to me, and I haven't implemented it. + However, it might be correct. */ + if (! (*info->callbacks->add_archive_element) (info, abfd, name)) + return false; + *pneeded = true; + return true; + } + + if (type == (N_UNDF | N_EXT)) + { + bfd_vma value; + + value = GET_WORD (abfd, p->e_value); + if (value != 0) + { + /* This symbol is common in the object from the archive + file. */ + if (h->type == bfd_link_hash_undefined) + { + bfd *symbfd; + + symbfd = h->u.undef.abfd; + if (symbfd == (bfd *) NULL) + { + /* This symbol was created as undefined from + outside BFD. We assume that we should link + in the object file. This is done for the -u + option in the linker. */ + if (! (*info->callbacks->add_archive_element) (info, + abfd, + name)) + return false; + *pneeded = true; + return true; + } + /* Turn the current link symbol into a common + symbol. It is already on the undefs list. */ + h->type = bfd_link_hash_common; + h->u.c.size = value; + h->u.c.section = bfd_make_section_old_way (symbfd, + "COMMON"); + } + else + { + /* Adjust the size of the common symbol if + necessary. */ + if (value > h->u.c.size) + h->u.c.size = value; + } + } + } + + if (type == N_WEAKA + || type == N_WEAKT + || type == N_WEAKD + || type == N_WEAKB) + { + /* This symbol is weak but defined. We must pull it in if + the current link symbol is undefined, but we don't want + it if the current link symbol is common. */ + if (h->type == bfd_link_hash_undefined) + { + if (! (*info->callbacks->add_archive_element) (info, abfd, name)) + return false; + *pneeded = true; + return true; + } + } + } + + /* We do not need this object file. */ + return true; +} + +/* Add all symbols from an object file to the hash table. */ + +static boolean +aout_link_add_symbols (abfd, info) + bfd *abfd; + struct bfd_link_info *info; +{ + boolean (*add_one_symbol) PARAMS ((struct bfd_link_info *, bfd *, + const char *, flagword, asection *, + bfd_vma, const char *, boolean, + boolean, + struct bfd_link_hash_entry **)); + bfd_size_type sym_count; + char *strings; + boolean copy; + struct aout_link_hash_entry **sym_hash; + register struct external_nlist *p; + struct external_nlist *pend; + + sym_count = obj_aout_external_sym_count (abfd); + strings = obj_aout_external_strings (abfd); + if (info->keep_memory) + copy = false; + else + copy = true; + + /* We keep a list of the linker hash table entries that correspond + to particular symbols. We could just look them up in the hash + table, but keeping the list is more efficient. Perhaps this + should be conditional on info->keep_memory. */ + sym_hash = ((struct aout_link_hash_entry **) + bfd_alloc (abfd, + ((size_t) sym_count + * sizeof (struct aout_link_hash_entry *)))); + if (sym_hash == NULL && sym_count != 0) + { + bfd_set_error (bfd_error_no_memory); + return false; + } + obj_aout_sym_hashes (abfd) = sym_hash; + + if ((abfd->flags & DYNAMIC) != 0 + && aout_backend_info (abfd)->add_dynamic_symbols != NULL) + { + if (! (*aout_backend_info (abfd)->add_dynamic_symbols) (abfd, info)) + return false; + } + + add_one_symbol = aout_backend_info (abfd)->add_one_symbol; + if (add_one_symbol == NULL) + add_one_symbol = _bfd_generic_link_add_one_symbol; + + p = obj_aout_external_syms (abfd); + pend = p + sym_count; + for (; p < pend; p++, sym_hash++) + { + int type; + const char *name; + bfd_vma value; + asection *section; + flagword flags; + const char *string; + + *sym_hash = NULL; + + type = bfd_h_get_8 (abfd, p->e_type); + + /* Ignore debugging symbols. */ + if ((type & N_STAB) != 0) + continue; + + name = strings + GET_WORD (abfd, p->e_strx); + value = GET_WORD (abfd, p->e_value); + flags = BSF_GLOBAL; + string = NULL; + switch (type) + { + default: + abort (); + + case N_UNDF: + case N_ABS: + case N_TEXT: + case N_DATA: + case N_BSS: + case N_FN_SEQ: + case N_COMM: + case N_SETV: + case N_FN: + /* Ignore symbols that are not externally visible. */ + continue; + case N_INDR: + /* Ignore local indirect symbol. */ + ++p; + ++sym_hash; + continue; + + case N_UNDF | N_EXT: + if (value == 0) + { + section = bfd_und_section_ptr; + flags = 0; + } + else + section = bfd_com_section_ptr; + break; + case N_ABS | N_EXT: + section = bfd_abs_section_ptr; + break; + case N_TEXT | N_EXT: + section = obj_textsec (abfd); + value -= bfd_get_section_vma (abfd, section); + break; + case N_DATA | N_EXT: + case N_SETV | N_EXT: + /* Treat N_SETV symbols as N_DATA symbol; see comment in + translate_from_native_sym_flags. */ + section = obj_datasec (abfd); + value -= bfd_get_section_vma (abfd, section); + break; + case N_BSS | N_EXT: + section = obj_bsssec (abfd); + value -= bfd_get_section_vma (abfd, section); + break; + case N_INDR | N_EXT: + /* An indirect symbol. The next symbol is the symbol + which this one really is. */ + BFD_ASSERT (p + 1 < pend); + ++p; + string = strings + GET_WORD (abfd, p->e_strx); + section = bfd_ind_section_ptr; + flags |= BSF_INDIRECT; + break; + case N_COMM | N_EXT: + section = bfd_com_section_ptr; + break; + case N_SETA: case N_SETA | N_EXT: + section = bfd_abs_section_ptr; + flags |= BSF_CONSTRUCTOR; + break; + case N_SETT: case N_SETT | N_EXT: + section = obj_textsec (abfd); + flags |= BSF_CONSTRUCTOR; + value -= bfd_get_section_vma (abfd, section); + break; + case N_SETD: case N_SETD | N_EXT: + section = obj_datasec (abfd); + flags |= BSF_CONSTRUCTOR; + value -= bfd_get_section_vma (abfd, section); + break; + case N_SETB: case N_SETB | N_EXT: + section = obj_bsssec (abfd); + flags |= BSF_CONSTRUCTOR; + value -= bfd_get_section_vma (abfd, section); + break; + case N_WARNING: + /* A warning symbol. The next symbol is the one to warn + about. */ + BFD_ASSERT (p + 1 < pend); + ++p; + string = name; + name = strings + GET_WORD (abfd, p->e_strx); + section = bfd_und_section_ptr; + flags |= BSF_WARNING; + break; + case N_WEAKU: + section = bfd_und_section_ptr; + flags = BSF_WEAK; + break; + case N_WEAKA: + section = bfd_abs_section_ptr; + flags = BSF_WEAK; + break; + case N_WEAKT: + section = obj_textsec (abfd); + value -= bfd_get_section_vma (abfd, section); + flags = BSF_WEAK; + break; + case N_WEAKD: + section = obj_datasec (abfd); + value -= bfd_get_section_vma (abfd, section); + flags = BSF_WEAK; + break; + case N_WEAKB: + section = obj_bsssec (abfd); + value -= bfd_get_section_vma (abfd, section); + flags = BSF_WEAK; + break; + } + + if (! ((*add_one_symbol) + (info, abfd, name, flags, section, value, string, copy, false, + (struct bfd_link_hash_entry **) sym_hash))) + return false; + + if (type == (N_INDR | N_EXT) || type == N_WARNING) + ++sym_hash; + } + + return true; +} + +/* During the final link step we need to pass around a bunch of + information, so we do it in an instance of this structure. */ + +struct aout_final_link_info +{ + /* General link information. */ + struct bfd_link_info *info; + /* Output bfd. */ + bfd *output_bfd; + /* Reloc file positions. */ + file_ptr treloff, dreloff; + /* File position of symbols. */ + file_ptr symoff; + /* String table. */ + struct strtab_hash strtab; +}; + +static boolean aout_link_input_bfd + PARAMS ((struct aout_final_link_info *, bfd *input_bfd)); +static boolean aout_link_write_symbols + PARAMS ((struct aout_final_link_info *, bfd *input_bfd, int *symbol_map)); +static boolean aout_link_write_other_symbol + PARAMS ((struct aout_link_hash_entry *, PTR)); +static boolean aout_link_input_section + PARAMS ((struct aout_final_link_info *, bfd *input_bfd, + asection *input_section, file_ptr *reloff_ptr, + bfd_size_type rel_size, int *symbol_map)); +static boolean aout_link_input_section_std + PARAMS ((struct aout_final_link_info *, bfd *input_bfd, + asection *input_section, struct reloc_std_external *, + bfd_size_type rel_size, bfd_byte *contents, int *symbol_map)); +static boolean aout_link_input_section_ext + PARAMS ((struct aout_final_link_info *, bfd *input_bfd, + asection *input_section, struct reloc_ext_external *, + bfd_size_type rel_size, bfd_byte *contents, int *symbol_map)); +static INLINE asection *aout_reloc_index_to_section + PARAMS ((bfd *, int)); +static boolean aout_link_reloc_link_order + PARAMS ((struct aout_final_link_info *, asection *, + struct bfd_link_order *)); + +/* Do the final link step. This is called on the output BFD. The + INFO structure should point to a list of BFDs linked through the + link_next field which can be used to find each BFD which takes part + in the output. Also, each section in ABFD should point to a list + of bfd_link_order structures which list all the input sections for + the output section. */ + +boolean +NAME(aout,final_link) (abfd, info, callback) + bfd *abfd; + struct bfd_link_info *info; + void (*callback) PARAMS ((bfd *, file_ptr *, file_ptr *, file_ptr *)); +{ + struct aout_final_link_info aout_info; + register bfd *sub; + bfd_size_type text_size; + file_ptr text_end; + register struct bfd_link_order *p; + asection *o; + boolean have_link_order_relocs; + + aout_info.info = info; + aout_info.output_bfd = abfd; + + if (! info->relocateable) + { + exec_hdr (abfd)->a_trsize = 0; + exec_hdr (abfd)->a_drsize = 0; + } + else + { + bfd_size_type trsize, drsize; + + /* Count up the relocation sizes. */ + trsize = 0; + drsize = 0; + for (sub = info->input_bfds; sub != (bfd *) NULL; sub = sub->link_next) + { + if (bfd_get_flavour (sub) == bfd_target_aout_flavour) + { + trsize += exec_hdr (sub)->a_trsize; + drsize += exec_hdr (sub)->a_drsize; + } + else + { + /* FIXME: We need to identify the .text and .data sections + and call get_reloc_upper_bound and canonicalize_reloc to + work out the number of relocs needed, and then multiply + by the reloc size. */ + abort (); + } + } + if (obj_textsec (abfd) != (asection *) NULL) + trsize += (_bfd_count_link_order_relocs (obj_textsec (abfd) + ->link_order_head) + * obj_reloc_entry_size (abfd)); + exec_hdr (abfd)->a_trsize = trsize; + if (obj_datasec (abfd) != (asection *) NULL) + drsize += (_bfd_count_link_order_relocs (obj_datasec (abfd) + ->link_order_head) + * obj_reloc_entry_size (abfd)); + exec_hdr (abfd)->a_drsize = drsize; + } + + exec_hdr (abfd)->a_entry = bfd_get_start_address (abfd); + + /* Adjust the section sizes and vmas according to the magic number. + This sets a_text, a_data and a_bss in the exec_hdr and sets the + filepos for each section. */ + if (! NAME(aout,adjust_sizes_and_vmas) (abfd, &text_size, &text_end)) + return false; + + /* The relocation and symbol file positions differ among a.out + targets. We are passed a callback routine from the backend + specific code to handle this. + FIXME: At this point we do not know how much space the symbol + table will require. This will not work for any (nonstandard) + a.out target that needs to know the symbol table size before it + can compute the relocation file positions. This may or may not + be the case for the hp300hpux target, for example. */ + (*callback) (abfd, &aout_info.treloff, &aout_info.dreloff, + &aout_info.symoff); + obj_textsec (abfd)->rel_filepos = aout_info.treloff; + obj_datasec (abfd)->rel_filepos = aout_info.dreloff; + obj_sym_filepos (abfd) = aout_info.symoff; + + /* We keep a count of the symbols as we output them. */ + obj_aout_external_sym_count (abfd) = 0; + + /* We accumulate the string table as we write out the symbols. */ + if (! stringtab_init (&aout_info.strtab)) + return false; + + /* The most time efficient way to do the link would be to read all + the input object files into memory and then sort out the + information into the output file. Unfortunately, that will + probably use too much memory. Another method would be to step + through everything that composes the text section and write it + out, and then everything that composes the data section and write + it out, and then write out the relocs, and then write out the + symbols. Unfortunately, that requires reading stuff from each + input file several times, and we will not be able to keep all the + input files open simultaneously, and reopening them will be slow. + + What we do is basically process one input file at a time. We do + everything we need to do with an input file once--copy over the + section contents, handle the relocation information, and write + out the symbols--and then we throw away the information we read + from it. This approach requires a lot of lseeks of the output + file, which is unfortunate but still faster than reopening a lot + of files. + + We use the output_has_begun field of the input BFDs to see + whether we have already handled it. */ + for (sub = info->input_bfds; sub != (bfd *) NULL; sub = sub->link_next) + sub->output_has_begun = false; + + have_link_order_relocs = false; + for (o = abfd->sections; o != (asection *) NULL; o = o->next) + { + for (p = o->link_order_head; + p != (struct bfd_link_order *) NULL; + p = p->next) + { + if (p->type == bfd_indirect_link_order + && (bfd_get_flavour (p->u.indirect.section->owner) + == bfd_target_aout_flavour)) + { + bfd *input_bfd; + + input_bfd = p->u.indirect.section->owner; + if (! input_bfd->output_has_begun) + { + if (! aout_link_input_bfd (&aout_info, input_bfd)) + return false; + input_bfd->output_has_begun = true; + } + } + else if (p->type == bfd_section_reloc_link_order + || p->type == bfd_symbol_reloc_link_order) + { + /* These are handled below. */ + have_link_order_relocs = true; + } + else + { + if (! _bfd_default_link_order (abfd, info, o, p)) + return false; + } + } + } + + /* Write out any symbols that we have not already written out. */ + aout_link_hash_traverse (aout_hash_table (info), + aout_link_write_other_symbol, + (PTR) &aout_info); + + /* Now handle any relocs we were asked to create by the linker. + These did not come from any input file. We must do these after + we have written out all the symbols, so that we know the symbol + indices to use. */ + if (have_link_order_relocs) + { + for (o = abfd->sections; o != (asection *) NULL; o = o->next) + { + for (p = o->link_order_head; + p != (struct bfd_link_order *) NULL; + p = p->next) + { + if (p->type == bfd_section_reloc_link_order + || p->type == bfd_symbol_reloc_link_order) + { + if (! aout_link_reloc_link_order (&aout_info, o, p)) + return false; + } + } + } + } + + /* Finish up any dynamic linking we may be doing. */ + if (aout_backend_info (abfd)->finish_dynamic_link != NULL) + { + if (! (*aout_backend_info (abfd)->finish_dynamic_link) (abfd, info)) + return false; + } + + /* Update the header information. */ + abfd->symcount = obj_aout_external_sym_count (abfd); + exec_hdr (abfd)->a_syms = abfd->symcount * EXTERNAL_NLIST_SIZE; + obj_str_filepos (abfd) = obj_sym_filepos (abfd) + exec_hdr (abfd)->a_syms; + obj_textsec (abfd)->reloc_count = + exec_hdr (abfd)->a_trsize / obj_reloc_entry_size (abfd); + obj_datasec (abfd)->reloc_count = + exec_hdr (abfd)->a_drsize / obj_reloc_entry_size (abfd); + + /* Write out the string table. */ + if (bfd_seek (abfd, obj_str_filepos (abfd), SEEK_SET) != 0) + return false; + return emit_stringtab (abfd, &aout_info.strtab); +} + +/* Link an a.out input BFD into the output file. */ + +static boolean +aout_link_input_bfd (finfo, input_bfd) + struct aout_final_link_info *finfo; + bfd *input_bfd; +{ + bfd_size_type sym_count; + int *symbol_map = NULL; + + BFD_ASSERT (bfd_get_format (input_bfd) == bfd_object); + + /* If this is a dynamic object, it may need special handling. */ + if ((input_bfd->flags & DYNAMIC) != 0 + && aout_backend_info (input_bfd)->link_dynamic_object != NULL) + { + return ((*aout_backend_info (input_bfd)->link_dynamic_object) + (finfo->info, input_bfd)); + } + + /* Get the symbols. We probably have them already, unless + finfo->info->keep_memory is false. */ + if (! aout_get_external_symbols (input_bfd)) + return false; + + sym_count = obj_aout_external_sym_count (input_bfd); + symbol_map = (int *) malloc ((size_t) sym_count * sizeof (int)); + if (symbol_map == NULL && sym_count != 0) + { + bfd_set_error (bfd_error_no_memory); + return false; + } + + /* Write out the symbols and get a map of the new indices. */ + if (! aout_link_write_symbols (finfo, input_bfd, symbol_map)) + goto error_return; + + /* Relocate and write out the sections. */ + if (! aout_link_input_section (finfo, input_bfd, + obj_textsec (input_bfd), + &finfo->treloff, + exec_hdr (input_bfd)->a_trsize, + symbol_map) + || ! aout_link_input_section (finfo, input_bfd, + obj_datasec (input_bfd), + &finfo->dreloff, + exec_hdr (input_bfd)->a_drsize, + symbol_map)) + goto error_return; + + /* If we are not keeping memory, we don't need the symbols any + longer. We still need them if we are keeping memory, because the + strings in the hash table point into them. */ + if (! finfo->info->keep_memory) + { + if (! aout_link_free_symbols (input_bfd)) + goto error_return; + } + + if (symbol_map != NULL) + free (symbol_map); + return true; + error_return: + if (symbol_map != NULL) + free (symbol_map); + return false; +} + +/* Adjust and write out the symbols for an a.out file. Set the new + symbol indices into a symbol_map. */ + +static boolean +aout_link_write_symbols (finfo, input_bfd, symbol_map) + struct aout_final_link_info *finfo; + bfd *input_bfd; + int *symbol_map; +{ + bfd *output_bfd; + bfd_size_type sym_count; + char *strings; + enum bfd_link_strip strip; + enum bfd_link_discard discard; + struct external_nlist *output_syms = NULL; + struct external_nlist *outsym; + bfd_size_type strtab_index; + register struct external_nlist *sym; + struct external_nlist *sym_end; + struct aout_link_hash_entry **sym_hash; + boolean pass; + boolean skip_indirect; + + output_bfd = finfo->output_bfd; + sym_count = obj_aout_external_sym_count (input_bfd); + strings = obj_aout_external_strings (input_bfd); + strip = finfo->info->strip; + discard = finfo->info->discard; + output_syms = ((struct external_nlist *) + malloc ((size_t) (sym_count + 1) * EXTERNAL_NLIST_SIZE)); + if (output_syms == NULL) + { + bfd_set_error (bfd_error_no_memory); + goto error_return; + } + outsym = output_syms; + + /* First write out a symbol for this object file, unless we are + discarding such symbols. */ + if (strip != strip_all + && (strip != strip_some + || bfd_hash_lookup (finfo->info->keep_hash, input_bfd->filename, + false, false) != NULL) + && discard != discard_all) + { + bfd_h_put_8 (output_bfd, N_TEXT, outsym->e_type); + bfd_h_put_8 (output_bfd, 0, outsym->e_other); + bfd_h_put_16 (output_bfd, (bfd_vma) 0, outsym->e_desc); + strtab_index = add_to_stringtab (output_bfd, &finfo->strtab, + input_bfd->filename, false); + if (strtab_index == (bfd_size_type) -1) + goto error_return; + PUT_WORD (output_bfd, strtab_index, outsym->e_strx); + PUT_WORD (output_bfd, + (bfd_get_section_vma (output_bfd, + obj_textsec (input_bfd)->output_section) + + obj_textsec (input_bfd)->output_offset), + outsym->e_value); + ++obj_aout_external_sym_count (output_bfd); + ++outsym; + } + + pass = false; + skip_indirect = false; + sym = obj_aout_external_syms (input_bfd); + sym_end = sym + sym_count; + sym_hash = obj_aout_sym_hashes (input_bfd); + for (; sym < sym_end; sym++, sym_hash++, symbol_map++) + { + const char *name; + int type; + struct aout_link_hash_entry *h; + boolean skip; + asection *symsec; + bfd_vma val = 0; + boolean copy; + + *symbol_map = -1; + + type = bfd_h_get_8 (input_bfd, sym->e_type); + name = strings + GET_WORD (input_bfd, sym->e_strx); + + h = NULL; + + if (pass) + { + /* Pass this symbol through. It is the target of an + indirect or warning symbol. */ + val = GET_WORD (input_bfd, sym->e_value); + pass = false; + } + else if (skip_indirect) + { + /* Skip this symbol, which is the target of an indirect + symbol that we have changed to no longer be an indirect + symbol. */ + skip_indirect = false; + continue; + } + else + { + struct aout_link_hash_entry *hresolve; + + /* We have saved the hash table entry for this symbol, if + there is one. Note that we could just look it up again + in the hash table, provided we first check that it is an + external symbol. */ + h = *sym_hash; + + /* If this is an indirect or warning symbol, then change + hresolve to the base symbol. We also change *sym_hash so + that the relocation routines relocate against the real + symbol. */ + hresolve = h; + if (h != (struct aout_link_hash_entry *) NULL + && (h->root.type == bfd_link_hash_indirect + || h->root.type == bfd_link_hash_warning)) + { + hresolve = (struct aout_link_hash_entry *) h->root.u.i.link; + while (hresolve->root.type == bfd_link_hash_indirect + || hresolve->root.type == bfd_link_hash_warning) + hresolve = ((struct aout_link_hash_entry *) + hresolve->root.u.i.link); + *sym_hash = hresolve; + } + + /* If the symbol has already been written out, skip it. */ + if (h != (struct aout_link_hash_entry *) NULL + && h->root.type != bfd_link_hash_warning + && h->written) + { + if ((type & N_TYPE) == N_INDR) + skip_indirect = true; + *symbol_map = h->indx; + continue; + } + + /* See if we are stripping this symbol. */ + skip = false; + switch (strip) + { + case strip_none: + break; + case strip_debugger: + if ((type & N_STAB) != 0) + skip = true; + break; + case strip_some: + if (bfd_hash_lookup (finfo->info->keep_hash, name, false, false) + == NULL) + skip = true; + break; + case strip_all: + skip = true; + break; + } + if (skip) + { + if (h != (struct aout_link_hash_entry *) NULL) + h->written = true; + continue; + } + + /* Get the value of the symbol. */ + if ((type & N_TYPE) == N_TEXT + || type == N_WEAKT) + symsec = obj_textsec (input_bfd); + else if ((type & N_TYPE) == N_DATA + || type == N_WEAKD) + symsec = obj_datasec (input_bfd); + else if ((type & N_TYPE) == N_BSS + || type == N_WEAKB) + symsec = obj_bsssec (input_bfd); + else if ((type & N_TYPE) == N_ABS + || type == N_WEAKA) + symsec = bfd_abs_section_ptr; + else if (((type & N_TYPE) == N_INDR + && (hresolve == (struct aout_link_hash_entry *) NULL + || (hresolve->root.type != bfd_link_hash_defined + && hresolve->root.type != bfd_link_hash_common))) + || type == N_WARNING) + { + /* Pass the next symbol through unchanged. The + condition above for indirect symbols is so that if + the indirect symbol was defined, we output it with + the correct definition so the debugger will + understand it. */ + pass = true; + val = GET_WORD (input_bfd, sym->e_value); + symsec = NULL; + } + else if ((type & N_STAB) != 0) + { + val = GET_WORD (input_bfd, sym->e_value); + symsec = NULL; + } + else + { + /* If we get here with an indirect symbol, it means that + we are outputting it with a real definition. In such + a case we do not want to output the next symbol, + which is the target of the indirection. */ + if ((type & N_TYPE) == N_INDR) + skip_indirect = true; + + /* We need to get the value from the hash table. We use + hresolve so that if we have defined an indirect + symbol we output the final definition. */ + if (h == (struct aout_link_hash_entry *) NULL) + val = 0; + else if (hresolve->root.type == bfd_link_hash_defined) + { + asection *input_section; + asection *output_section; + + /* This case means a common symbol which was turned + into a defined symbol. */ + input_section = hresolve->root.u.def.section; + output_section = input_section->output_section; + BFD_ASSERT (bfd_is_abs_section (output_section) + || output_section->owner == output_bfd); + val = (hresolve->root.u.def.value + + bfd_get_section_vma (output_bfd, output_section) + + input_section->output_offset); + + /* Get the correct type based on the section. If + this is a constructed set, force it to be + globally visible. */ + if (type == N_SETT + || type == N_SETD + || type == N_SETB + || type == N_SETA) + type |= N_EXT; + + type &=~ N_TYPE; + + if (output_section == obj_textsec (output_bfd)) + type |= N_TEXT; + else if (output_section == obj_datasec (output_bfd)) + type |= N_DATA; + else if (output_section == obj_bsssec (output_bfd)) + type |= N_BSS; + else + type |= N_ABS; + } + else if (hresolve->root.type == bfd_link_hash_common) + val = hresolve->root.u.c.size; + else if (hresolve->root.type == bfd_link_hash_weak) + { + val = 0; + type = N_WEAKU; + } + else + val = 0; + + symsec = NULL; + } + if (symsec != (asection *) NULL) + val = (symsec->output_section->vma + + symsec->output_offset + + (GET_WORD (input_bfd, sym->e_value) + - symsec->vma)); + + /* If this is a global symbol set the written flag, and if + it is a local symbol see if we should discard it. */ + if (h != (struct aout_link_hash_entry *) NULL) + { + h->written = true; + h->indx = obj_aout_external_sym_count (output_bfd); + } + else + { + switch (discard) + { + case discard_none: + break; + case discard_l: + if (*name == *finfo->info->lprefix + && (finfo->info->lprefix_len == 1 + || strncmp (name, finfo->info->lprefix, + finfo->info->lprefix_len) == 0)) + skip = true; + break; + case discard_all: + skip = true; + break; + } + if (skip) + { + pass = false; + continue; + } + } + } + + /* Copy this symbol into the list of symbols we are going to + write out. */ + bfd_h_put_8 (output_bfd, type, outsym->e_type); + bfd_h_put_8 (output_bfd, bfd_h_get_8 (input_bfd, sym->e_other), + outsym->e_other); + bfd_h_put_16 (output_bfd, bfd_h_get_16 (input_bfd, sym->e_desc), + outsym->e_desc); + copy = false; + if (! finfo->info->keep_memory) + { + /* name points into a string table which we are going to + free. If there is a hash table entry, use that string. + Otherwise, copy name into memory. */ + if (h != (struct aout_link_hash_entry *) NULL) + name = (*sym_hash)->root.root.string; + else + copy = true; + } + strtab_index = add_to_stringtab (output_bfd, &finfo->strtab, + name, copy); + if (strtab_index == (bfd_size_type) -1) + goto error_return; + PUT_WORD (output_bfd, strtab_index, outsym->e_strx); + PUT_WORD (output_bfd, val, outsym->e_value); + *symbol_map = obj_aout_external_sym_count (output_bfd); + ++obj_aout_external_sym_count (output_bfd); + ++outsym; + } + + /* Write out the output symbols we have just constructed. */ + if (outsym > output_syms) + { + bfd_size_type outsym_count; + + if (bfd_seek (output_bfd, finfo->symoff, SEEK_SET) != 0) + goto error_return; + outsym_count = outsym - output_syms; + if (bfd_write ((PTR) output_syms, (bfd_size_type) EXTERNAL_NLIST_SIZE, + (bfd_size_type) outsym_count, output_bfd) + != outsym_count * EXTERNAL_NLIST_SIZE) + goto error_return; + finfo->symoff += outsym_count * EXTERNAL_NLIST_SIZE; + } + + if (output_syms != NULL) + free (output_syms); + return true; + error_return: + if (output_syms != NULL) + free (output_syms); + return false; +} + +/* Write out a symbol that was not associated with an a.out input + object. */ + +static boolean +aout_link_write_other_symbol (h, data) + struct aout_link_hash_entry *h; + PTR data; +{ + struct aout_final_link_info *finfo = (struct aout_final_link_info *) data; + bfd *output_bfd; + int type; + bfd_vma val; + struct external_nlist outsym; + bfd_size_type indx; + + output_bfd = finfo->output_bfd; + + if (aout_backend_info (output_bfd)->write_dynamic_symbol != NULL) + { + if (! ((*aout_backend_info (output_bfd)->write_dynamic_symbol) + (output_bfd, finfo->info, h))) + { + /* FIXME: No way to handle errors. */ + abort (); + } + } + + if (h->written) + return true; + + h->written = true; + + if (finfo->info->strip == strip_all + || (finfo->info->strip == strip_some + && bfd_hash_lookup (finfo->info->keep_hash, h->root.root.string, + false, false) == NULL)) + return true; + + switch (h->root.type) + { + default: + case bfd_link_hash_new: + abort (); + /* Avoid variable not initialized warnings. */ + return true; + case bfd_link_hash_undefined: + type = N_UNDF | N_EXT; + val = 0; + break; + case bfd_link_hash_defined: + { + asection *sec; + + sec = h->root.u.def.section->output_section; + BFD_ASSERT (bfd_is_abs_section (sec) + || sec->owner == output_bfd); + if (sec == obj_textsec (output_bfd)) + type = N_TEXT | N_EXT; + else if (sec == obj_datasec (output_bfd)) + type = N_DATA | N_EXT; + else if (sec == obj_bsssec (output_bfd)) + type = N_BSS | N_EXT; + else + type = N_ABS | N_EXT; + val = (h->root.u.def.value + + sec->vma + + h->root.u.def.section->output_offset); + } + break; + case bfd_link_hash_common: + type = N_UNDF | N_EXT; + val = h->root.u.c.size; + break; + case bfd_link_hash_weak: + type = N_WEAKU; + val = 0; + case bfd_link_hash_indirect: + case bfd_link_hash_warning: + /* FIXME: Ignore these for now. The circumstances under which + they should be written out are not clear to me. */ + return true; + } + + bfd_h_put_8 (output_bfd, type, outsym.e_type); + bfd_h_put_8 (output_bfd, 0, outsym.e_other); + bfd_h_put_16 (output_bfd, 0, outsym.e_desc); + indx = add_to_stringtab (output_bfd, &finfo->strtab, h->root.root.string, + false); + if (indx == (bfd_size_type) -1) + { + /* FIXME: No way to handle errors. */ + abort (); + } + PUT_WORD (output_bfd, indx, outsym.e_strx); + PUT_WORD (output_bfd, val, outsym.e_value); + + if (bfd_seek (output_bfd, finfo->symoff, SEEK_SET) != 0 + || bfd_write ((PTR) &outsym, (bfd_size_type) EXTERNAL_NLIST_SIZE, + (bfd_size_type) 1, output_bfd) != EXTERNAL_NLIST_SIZE) + { + /* FIXME: No way to handle errors. */ + abort (); + } + + finfo->symoff += EXTERNAL_NLIST_SIZE; + h->indx = obj_aout_external_sym_count (output_bfd); + ++obj_aout_external_sym_count (output_bfd); + + return true; +} + +/* Link an a.out section into the output file. */ + +static boolean +aout_link_input_section (finfo, input_bfd, input_section, reloff_ptr, + rel_size, symbol_map) + struct aout_final_link_info *finfo; + bfd *input_bfd; + asection *input_section; + file_ptr *reloff_ptr; + bfd_size_type rel_size; + int *symbol_map; +{ + bfd_size_type input_size; + bfd_byte *contents = NULL; + PTR relocs; + PTR free_relocs = NULL; + + /* Get the section contents. */ + input_size = bfd_section_size (input_bfd, input_section); + contents = (bfd_byte *) malloc (input_size); + if (contents == NULL && input_size != 0) + { + bfd_set_error (bfd_error_no_memory); + goto error_return; + } + if (! bfd_get_section_contents (input_bfd, input_section, (PTR) contents, + (file_ptr) 0, input_size)) + goto error_return; + + /* Read in the relocs if we haven't already done it. */ + if (aout_section_data (input_section) != NULL + && aout_section_data (input_section)->relocs != NULL) + relocs = aout_section_data (input_section)->relocs; + else + { + relocs = free_relocs = (PTR) malloc (rel_size); + if (relocs == NULL && rel_size != 0) + { + bfd_set_error (bfd_error_no_memory); + goto error_return; + } + if (bfd_seek (input_bfd, input_section->rel_filepos, SEEK_SET) != 0 + || bfd_read (relocs, 1, rel_size, input_bfd) != rel_size) + goto error_return; + } + + /* Relocate the section contents. */ + if (obj_reloc_entry_size (input_bfd) == RELOC_STD_SIZE) + { + if (! aout_link_input_section_std (finfo, input_bfd, input_section, + (struct reloc_std_external *) relocs, + rel_size, contents, symbol_map)) + goto error_return; + } + else + { + if (! aout_link_input_section_ext (finfo, input_bfd, input_section, + (struct reloc_ext_external *) relocs, + rel_size, contents, symbol_map)) + goto error_return; + } + + /* Write out the section contents. */ + if (! bfd_set_section_contents (finfo->output_bfd, + input_section->output_section, + (PTR) contents, + input_section->output_offset, + input_size)) + goto error_return; + + /* If we are producing relocateable output, the relocs were + modified, and we now write them out. */ + if (finfo->info->relocateable) + { + if (bfd_seek (finfo->output_bfd, *reloff_ptr, SEEK_SET) != 0) + goto error_return; + if (bfd_write (relocs, (bfd_size_type) 1, rel_size, finfo->output_bfd) + != rel_size) + goto error_return; + *reloff_ptr += rel_size; + + /* Assert that the relocs have not run into the symbols, and + that if these are the text relocs they have not run into the + data relocs. */ + BFD_ASSERT (*reloff_ptr <= obj_sym_filepos (finfo->output_bfd) + && (reloff_ptr != &finfo->treloff + || (*reloff_ptr + <= obj_datasec (finfo->output_bfd)->rel_filepos))); + } + + if (free_relocs != NULL) + free (free_relocs); + if (contents != NULL) + free (contents); + return true; + error_return: + if (free_relocs != NULL) + free (free_relocs); + if (contents != NULL) + free (contents); + return false; +} + +/* Get the section corresponding to a reloc index. */ + +static INLINE asection * +aout_reloc_index_to_section (abfd, indx) + bfd *abfd; + int indx; +{ + switch (indx & N_TYPE) + { + case N_TEXT: + return obj_textsec (abfd); + case N_DATA: + return obj_datasec (abfd); + case N_BSS: + return obj_bsssec (abfd); + case N_ABS: + case N_UNDF: + return bfd_abs_section_ptr; + default: + abort (); + } +} + +/* Relocate an a.out section using standard a.out relocs. */ + +static boolean +aout_link_input_section_std (finfo, input_bfd, input_section, relocs, + rel_size, contents, symbol_map) + struct aout_final_link_info *finfo; + bfd *input_bfd; + asection *input_section; + struct reloc_std_external *relocs; + bfd_size_type rel_size; + bfd_byte *contents; + int *symbol_map; +{ + boolean (*check_dynamic_reloc) PARAMS ((struct bfd_link_info *, + bfd *, asection *, + struct aout_link_hash_entry *, + PTR, boolean *)); + bfd *output_bfd; + boolean relocateable; + struct external_nlist *syms; + char *strings; + struct aout_link_hash_entry **sym_hashes; + bfd_size_type reloc_count; + register struct reloc_std_external *rel; + struct reloc_std_external *rel_end; + + output_bfd = finfo->output_bfd; + check_dynamic_reloc = aout_backend_info (output_bfd)->check_dynamic_reloc; + + BFD_ASSERT (obj_reloc_entry_size (input_bfd) == RELOC_STD_SIZE); + BFD_ASSERT (input_bfd->xvec->header_byteorder_big_p + == output_bfd->xvec->header_byteorder_big_p); + + relocateable = finfo->info->relocateable; + syms = obj_aout_external_syms (input_bfd); + strings = obj_aout_external_strings (input_bfd); + sym_hashes = obj_aout_sym_hashes (input_bfd); + + reloc_count = rel_size / RELOC_STD_SIZE; + rel = relocs; + rel_end = rel + reloc_count; + for (; rel < rel_end; rel++) + { + bfd_vma r_addr; + int r_index; + int r_extern; + int r_pcrel; + int r_baserel; + int r_jmptable; + int r_relative; + int r_length; + int howto_idx; + reloc_howto_type *howto; + bfd_vma relocation; + bfd_reloc_status_type r; + + r_addr = GET_SWORD (input_bfd, rel->r_address); + +#ifdef MY_reloc_howto + howto = MY_reloc_howto(input_bfd, rel, r_index, r_extern, r_pcrel); +#else + if (input_bfd->xvec->header_byteorder_big_p) + { + r_index = ((rel->r_index[0] << 16) + | (rel->r_index[1] << 8) + | rel->r_index[2]); + r_extern = (0 != (rel->r_type[0] & RELOC_STD_BITS_EXTERN_BIG)); + r_pcrel = (0 != (rel->r_type[0] & RELOC_STD_BITS_PCREL_BIG)); + r_baserel = (0 != (rel->r_type[0] & RELOC_STD_BITS_BASEREL_BIG)); + r_jmptable= (0 != (rel->r_type[0] & RELOC_STD_BITS_JMPTABLE_BIG)); + r_relative= (0 != (rel->r_type[0] & RELOC_STD_BITS_RELATIVE_BIG)); + r_length = ((rel->r_type[0] & RELOC_STD_BITS_LENGTH_BIG) + >> RELOC_STD_BITS_LENGTH_SH_BIG); + } + else + { + r_index = ((rel->r_index[2] << 16) + | (rel->r_index[1] << 8) + | rel->r_index[0]); + r_extern = (0 != (rel->r_type[0] & RELOC_STD_BITS_EXTERN_LITTLE)); + r_pcrel = (0 != (rel->r_type[0] & RELOC_STD_BITS_PCREL_LITTLE)); + r_baserel = (0 != (rel->r_type[0] & RELOC_STD_BITS_BASEREL_LITTLE)); + r_jmptable= (0 != (rel->r_type[0] & RELOC_STD_BITS_JMPTABLE_LITTLE)); + r_relative= (0 != (rel->r_type[0] & RELOC_STD_BITS_RELATIVE_LITTLE)); + r_length = ((rel->r_type[0] & RELOC_STD_BITS_LENGTH_LITTLE) + >> RELOC_STD_BITS_LENGTH_SH_LITTLE); + } + + howto_idx = r_length + 4 * r_pcrel + 8 * r_baserel + + 16 * r_jmptable + 32 * r_relative; + BFD_ASSERT (howto_idx < TABLE_SIZE (howto_table_std)); + howto = howto_table_std + howto_idx; +#endif + + if (relocateable) + { + /* We are generating a relocateable output file, and must + modify the reloc accordingly. */ + if (r_extern) + { + struct aout_link_hash_entry *h; + + /* If we know the symbol this relocation is against, + convert it into a relocation against a section. This + is what the native linker does. */ + h = sym_hashes[r_index]; + if (h != (struct aout_link_hash_entry *) NULL + && h->root.type == bfd_link_hash_defined) + { + asection *output_section; + + /* Change the r_extern value. */ + if (output_bfd->xvec->header_byteorder_big_p) + rel->r_type[0] &=~ RELOC_STD_BITS_EXTERN_BIG; + else + rel->r_type[0] &=~ RELOC_STD_BITS_EXTERN_LITTLE; + + /* Compute a new r_index. */ + output_section = h->root.u.def.section->output_section; + if (output_section == obj_textsec (output_bfd)) + r_index = N_TEXT; + else if (output_section == obj_datasec (output_bfd)) + r_index = N_DATA; + else if (output_section == obj_bsssec (output_bfd)) + r_index = N_BSS; + else + r_index = N_ABS; + + /* Add the symbol value and the section VMA to the + addend stored in the contents. */ + relocation = (h->root.u.def.value + + output_section->vma + + h->root.u.def.section->output_offset); + } + else + { + /* We must change r_index according to the symbol + map. */ + r_index = symbol_map[r_index]; + + if (r_index == -1) + { + const char *name; + + name = strings + GET_WORD (input_bfd, + syms[r_index].e_strx); + if (! ((*finfo->info->callbacks->unattached_reloc) + (finfo->info, name, input_bfd, input_section, + r_addr))) + return false; + r_index = 0; + } + + relocation = 0; + } + + /* Write out the new r_index value. */ + if (output_bfd->xvec->header_byteorder_big_p) + { + rel->r_index[0] = r_index >> 16; + rel->r_index[1] = r_index >> 8; + rel->r_index[2] = r_index; + } + else + { + rel->r_index[2] = r_index >> 16; + rel->r_index[1] = r_index >> 8; + rel->r_index[0] = r_index; + } + } + else + { + asection *section; + + /* This is a relocation against a section. We must + adjust by the amount that the section moved. */ + section = aout_reloc_index_to_section (input_bfd, r_index); + relocation = (section->output_section->vma + + section->output_offset + - section->vma); + } + + /* Change the address of the relocation. */ + PUT_WORD (output_bfd, + r_addr + input_section->output_offset, + rel->r_address); + + /* Adjust a PC relative relocation by removing the reference + to the original address in the section and including the + reference to the new address. */ + if (r_pcrel) + relocation -= (input_section->output_section->vma + + input_section->output_offset + - input_section->vma); + + if (relocation == 0) + r = bfd_reloc_ok; + else + r = _bfd_relocate_contents (howto, + input_bfd, relocation, + contents + r_addr); + } + else + { + /* We are generating an executable, and must do a full + relocation. */ + if (r_extern) + { + struct aout_link_hash_entry *h; + + h = sym_hashes[r_index]; + + if (check_dynamic_reloc != NULL) + { + boolean skip; + + if (! ((*check_dynamic_reloc) + (finfo->info, input_bfd, input_section, h, + (PTR) rel, &skip))) + return false; + if (skip) + continue; + } + + if (h != (struct aout_link_hash_entry *) NULL + && h->root.type == bfd_link_hash_defined) + { + relocation = (h->root.u.def.value + + h->root.u.def.section->output_section->vma + + h->root.u.def.section->output_offset); + } + else if (h != (struct aout_link_hash_entry *) NULL + && h->root.type == bfd_link_hash_weak) + relocation = 0; + else + { + const char *name; + + name = strings + GET_WORD (input_bfd, syms[r_index].e_strx); + if (! ((*finfo->info->callbacks->undefined_symbol) + (finfo->info, name, input_bfd, input_section, + r_addr))) + return false; + relocation = 0; + } + } + else + { + asection *section; + + section = aout_reloc_index_to_section (input_bfd, r_index); + relocation = (section->output_section->vma + + section->output_offset + - section->vma); + if (r_pcrel) + relocation += input_section->vma; + } + + r = _bfd_final_link_relocate (howto, + input_bfd, input_section, + contents, r_addr, relocation, + (bfd_vma) 0); + } + + if (r != bfd_reloc_ok) + { + switch (r) + { + default: + case bfd_reloc_outofrange: + abort (); + case bfd_reloc_overflow: + { + const char *name; + + if (r_extern) + name = strings + GET_WORD (input_bfd, + syms[r_index].e_strx); + else + { + asection *s; + + s = aout_reloc_index_to_section (input_bfd, r_index); + name = bfd_section_name (input_bfd, s); + } + if (! ((*finfo->info->callbacks->reloc_overflow) + (finfo->info, name, howto->name, + (bfd_vma) 0, input_bfd, input_section, r_addr))) + return false; + } + break; + } + } + } + + return true; +} + +/* Relocate an a.out section using extended a.out relocs. */ + +static boolean +aout_link_input_section_ext (finfo, input_bfd, input_section, relocs, + rel_size, contents, symbol_map) + struct aout_final_link_info *finfo; + bfd *input_bfd; + asection *input_section; + struct reloc_ext_external *relocs; + bfd_size_type rel_size; + bfd_byte *contents; + int *symbol_map; +{ + boolean (*check_dynamic_reloc) PARAMS ((struct bfd_link_info *, + bfd *, asection *, + struct aout_link_hash_entry *, + PTR, boolean *)); + bfd *output_bfd; + boolean relocateable; + struct external_nlist *syms; + char *strings; + struct aout_link_hash_entry **sym_hashes; + bfd_size_type reloc_count; + register struct reloc_ext_external *rel; + struct reloc_ext_external *rel_end; + + output_bfd = finfo->output_bfd; + check_dynamic_reloc = aout_backend_info (output_bfd)->check_dynamic_reloc; + + BFD_ASSERT (obj_reloc_entry_size (input_bfd) == RELOC_EXT_SIZE); + BFD_ASSERT (input_bfd->xvec->header_byteorder_big_p + == output_bfd->xvec->header_byteorder_big_p); + + relocateable = finfo->info->relocateable; + syms = obj_aout_external_syms (input_bfd); + strings = obj_aout_external_strings (input_bfd); + sym_hashes = obj_aout_sym_hashes (input_bfd); + + reloc_count = rel_size / RELOC_EXT_SIZE; + rel = relocs; + rel_end = rel + reloc_count; + for (; rel < rel_end; rel++) + { + bfd_vma r_addr; + int r_index; + int r_extern; + int r_type; + bfd_vma r_addend; + bfd_vma relocation; + + r_addr = GET_SWORD (input_bfd, rel->r_address); + + if (input_bfd->xvec->header_byteorder_big_p) + { + r_index = ((rel->r_index[0] << 16) + | (rel->r_index[1] << 8) + | rel->r_index[2]); + r_extern = (0 != (rel->r_type[0] & RELOC_EXT_BITS_EXTERN_BIG)); + r_type = ((rel->r_type[0] & RELOC_EXT_BITS_TYPE_BIG) + >> RELOC_EXT_BITS_TYPE_SH_BIG); + } + else + { + r_index = ((rel->r_index[2] << 16) + | (rel->r_index[1] << 8) + | rel->r_index[0]); + r_extern = (0 != (rel->r_type[0] & RELOC_EXT_BITS_EXTERN_LITTLE)); + r_type = ((rel->r_type[0] & RELOC_EXT_BITS_TYPE_LITTLE) + >> RELOC_EXT_BITS_TYPE_SH_LITTLE); + } + + r_addend = GET_SWORD (input_bfd, rel->r_addend); + + BFD_ASSERT (r_type >= 0 + && r_type < TABLE_SIZE (howto_table_ext)); + + if (relocateable) + { + /* We are generating a relocateable output file, and must + modify the reloc accordingly. */ + if (r_extern) + { + struct aout_link_hash_entry *h; + + /* If we know the symbol this relocation is against, + convert it into a relocation against a section. This + is what the native linker does. */ + h = sym_hashes[r_index]; + if (h != (struct aout_link_hash_entry *) NULL + && h->root.type == bfd_link_hash_defined) + { + asection *output_section; + + /* Change the r_extern value. */ + if (output_bfd->xvec->header_byteorder_big_p) + rel->r_type[0] &=~ RELOC_EXT_BITS_EXTERN_BIG; + else + rel->r_type[0] &=~ RELOC_EXT_BITS_EXTERN_LITTLE; + + /* Compute a new r_index. */ + output_section = h->root.u.def.section->output_section; + if (output_section == obj_textsec (output_bfd)) + r_index = N_TEXT; + else if (output_section == obj_datasec (output_bfd)) + r_index = N_DATA; + else if (output_section == obj_bsssec (output_bfd)) + r_index = N_BSS; + else + r_index = N_ABS; + + /* Add the symbol value and the section VMA to the + addend. */ + relocation = (h->root.u.def.value + + output_section->vma + + h->root.u.def.section->output_offset); + + /* Now RELOCATION is the VMA of the final + destination. If this is a PC relative reloc, + then ADDEND is the negative of the source VMA. + We want to set ADDEND to the difference between + the destination VMA and the source VMA, which + means we must adjust RELOCATION by the change in + the source VMA. This is done below. */ + } + else + { + /* We must change r_index according to the symbol + map. */ + r_index = symbol_map[r_index]; + + if (r_index == -1) + { + const char *name; + + name = (strings + + GET_WORD (input_bfd, syms[r_index].e_strx)); + if (! ((*finfo->info->callbacks->unattached_reloc) + (finfo->info, name, input_bfd, input_section, + r_addr))) + return false; + r_index = 0; + } + + relocation = 0; + + /* If this is a PC relative reloc, then the addend + is the negative of the source VMA. We must + adjust it by the change in the source VMA. This + is done below. */ + } + + /* Write out the new r_index value. */ + if (output_bfd->xvec->header_byteorder_big_p) + { + rel->r_index[0] = r_index >> 16; + rel->r_index[1] = r_index >> 8; + rel->r_index[2] = r_index; + } + else + { + rel->r_index[2] = r_index >> 16; + rel->r_index[1] = r_index >> 8; + rel->r_index[0] = r_index; + } + } + else + { + asection *section; + + /* This is a relocation against a section. We must + adjust by the amount that the section moved. */ + section = aout_reloc_index_to_section (input_bfd, r_index); + relocation = (section->output_section->vma + + section->output_offset + - section->vma); + + /* If this is a PC relative reloc, then the addend is + the difference in VMA between the destination and the + source. We have just adjusted for the change in VMA + of the destination, so we must also adjust by the + change in VMA of the source. This is done below. */ + } + + /* As described above, we must always adjust a PC relative + reloc by the change in VMA of the source. */ + if (howto_table_ext[r_type].pc_relative) + relocation -= (input_section->output_section->vma + + input_section->output_offset + - input_section->vma); + + /* Change the addend if necessary. */ + if (relocation != 0) + PUT_WORD (output_bfd, r_addend + relocation, rel->r_addend); + + /* Change the address of the relocation. */ + PUT_WORD (output_bfd, + r_addr + input_section->output_offset, + rel->r_address); + } + else + { + bfd_reloc_status_type r; + + /* We are generating an executable, and must do a full + relocation. */ + if (r_extern) + { + struct aout_link_hash_entry *h; + + h = sym_hashes[r_index]; + + if (check_dynamic_reloc != NULL) + { + boolean skip; + + if (! ((*check_dynamic_reloc) + (finfo->info, input_bfd, input_section, h, + (PTR) rel, &skip))) + return false; + if (skip) + continue; + } + + if (h != (struct aout_link_hash_entry *) NULL + && h->root.type == bfd_link_hash_defined) + { + relocation = (h->root.u.def.value + + h->root.u.def.section->output_section->vma + + h->root.u.def.section->output_offset); + } + else if (h != (struct aout_link_hash_entry *) NULL + && h->root.type == bfd_link_hash_weak) + relocation = 0; + else + { + const char *name; + + name = strings + GET_WORD (input_bfd, syms[r_index].e_strx); + if (! ((*finfo->info->callbacks->undefined_symbol) + (finfo->info, name, input_bfd, input_section, + r_addr))) + return false; + relocation = 0; + } + } + else + { + asection *section; + + section = aout_reloc_index_to_section (input_bfd, r_index); + + /* If this is a PC relative reloc, then R_ADDEND is the + difference between the two vmas, or + old_dest_sec + old_dest_off - (old_src_sec + old_src_off) + where + old_dest_sec == section->vma + and + old_src_sec == input_section->vma + and + old_src_off == r_addr + + _bfd_final_link_relocate expects RELOCATION + + R_ADDEND to be the VMA of the destination minus + r_addr (the minus r_addr is because this relocation + is not pcrel_offset, which is a bit confusing and + should, perhaps, be changed), or + new_dest_sec + where + new_dest_sec == output_section->vma + output_offset + We arrange for this to happen by setting RELOCATION to + new_dest_sec + old_src_sec - old_dest_sec + + If this is not a PC relative reloc, then R_ADDEND is + simply the VMA of the destination, so we set + RELOCATION to the change in the destination VMA, or + new_dest_sec - old_dest_sec + */ + relocation = (section->output_section->vma + + section->output_offset + - section->vma); + if (howto_table_ext[r_type].pc_relative) + relocation += input_section->vma; + } + + r = _bfd_final_link_relocate (howto_table_ext + r_type, + input_bfd, input_section, + contents, r_addr, relocation, + r_addend); + if (r != bfd_reloc_ok) + { + switch (r) + { + default: + case bfd_reloc_outofrange: + abort (); + case bfd_reloc_overflow: + { + const char *name; + + if (r_extern) + name = strings + GET_WORD (input_bfd, + syms[r_index].e_strx); + else + { + asection *s; + + s = aout_reloc_index_to_section (input_bfd, r_index); + name = bfd_section_name (input_bfd, s); + } + if (! ((*finfo->info->callbacks->reloc_overflow) + (finfo->info, name, howto_table_ext[r_type].name, + r_addend, input_bfd, input_section, r_addr))) + return false; + } + break; + } + } + } + } + + return true; +} + +/* Handle a link order which is supposed to generate a reloc. */ + +static boolean +aout_link_reloc_link_order (finfo, o, p) + struct aout_final_link_info *finfo; + asection *o; + struct bfd_link_order *p; +{ + struct bfd_link_order_reloc *pr; + int r_index; + int r_extern; + const reloc_howto_type *howto; + file_ptr *reloff_ptr; + struct reloc_std_external srel; + struct reloc_ext_external erel; + PTR rel_ptr; + + pr = p->u.reloc.p; + + if (p->type == bfd_section_reloc_link_order) + { + r_extern = 0; + if (bfd_is_abs_section (pr->u.section)) + r_index = N_ABS | N_EXT; + else + { + BFD_ASSERT (pr->u.section->owner == finfo->output_bfd); + r_index = pr->u.section->target_index; + } + } + else + { + struct aout_link_hash_entry *h; + + BFD_ASSERT (p->type == bfd_symbol_reloc_link_order); + r_extern = 1; + h = aout_link_hash_lookup (aout_hash_table (finfo->info), + pr->u.name, false, false, true); + if (h != (struct aout_link_hash_entry *) NULL + && h->indx == -1) + r_index = h->indx; + else + { + if (! ((*finfo->info->callbacks->unattached_reloc) + (finfo->info, pr->u.name, (bfd *) NULL, + (asection *) NULL, (bfd_vma) 0))) + return false; + r_index = 0; + } + } + + howto = bfd_reloc_type_lookup (finfo->output_bfd, pr->reloc); + if (howto == (const reloc_howto_type *) NULL) + { + bfd_set_error (bfd_error_bad_value); + return false; + } + + if (o == obj_textsec (finfo->output_bfd)) + reloff_ptr = &finfo->treloff; + else if (o == obj_datasec (finfo->output_bfd)) + reloff_ptr = &finfo->dreloff; + else + abort (); + + if (obj_reloc_entry_size (finfo->output_bfd) == RELOC_STD_SIZE) + { + int r_pcrel; + int r_baserel; + int r_jmptable; + int r_relative; + int r_length; + +#ifdef MY_put_reloc + MY_put_reloc(finfo->output_bfd, r_extern, r_index, p->offset, howto, &srel); +#else + r_pcrel = howto->pc_relative; + r_baserel = (howto->type & 8) != 0; + r_jmptable = (howto->type & 16) != 0; + r_relative = (howto->type & 32) != 0; + r_length = howto->size; + + PUT_WORD (finfo->output_bfd, p->offset, srel.r_address); + if (finfo->output_bfd->xvec->header_byteorder_big_p) + { + srel.r_index[0] = r_index >> 16; + srel.r_index[1] = r_index >> 8; + srel.r_index[2] = r_index; + srel.r_type[0] = + ((r_extern ? RELOC_STD_BITS_EXTERN_BIG : 0) + | (r_pcrel ? RELOC_STD_BITS_PCREL_BIG : 0) + | (r_baserel ? RELOC_STD_BITS_BASEREL_BIG : 0) + | (r_jmptable ? RELOC_STD_BITS_JMPTABLE_BIG : 0) + | (r_relative ? RELOC_STD_BITS_RELATIVE_BIG : 0) + | (r_length << RELOC_STD_BITS_LENGTH_SH_BIG)); + } + else + { + srel.r_index[2] = r_index >> 16; + srel.r_index[1] = r_index >> 8; + srel.r_index[0] = r_index; + srel.r_type[0] = + ((r_extern ? RELOC_STD_BITS_EXTERN_LITTLE : 0) + | (r_pcrel ? RELOC_STD_BITS_PCREL_LITTLE : 0) + | (r_baserel ? RELOC_STD_BITS_BASEREL_LITTLE : 0) + | (r_jmptable ? RELOC_STD_BITS_JMPTABLE_LITTLE : 0) + | (r_relative ? RELOC_STD_BITS_RELATIVE_LITTLE : 0) + | (r_length << RELOC_STD_BITS_LENGTH_SH_LITTLE)); + } +#endif + rel_ptr = (PTR) &srel; + + /* We have to write the addend into the object file, since + standard a.out relocs are in place. It would be more + reliable if we had the current contents of the file here, + rather than assuming zeroes, but we can't read the file since + it was opened using bfd_openw. */ + if (pr->addend != 0) + { + bfd_size_type size; + bfd_reloc_status_type r; + bfd_byte *buf; + boolean ok; + + size = bfd_get_reloc_size (howto); + buf = (bfd_byte *) bfd_zmalloc (size); + if (buf == (bfd_byte *) NULL) + { + bfd_set_error (bfd_error_no_memory); + return false; + } + r = _bfd_relocate_contents (howto, finfo->output_bfd, + pr->addend, buf); + switch (r) + { + case bfd_reloc_ok: + break; + default: + case bfd_reloc_outofrange: + abort (); + case bfd_reloc_overflow: + if (! ((*finfo->info->callbacks->reloc_overflow) + (finfo->info, + (p->type == bfd_section_reloc_link_order + ? bfd_section_name (finfo->output_bfd, + pr->u.section) + : pr->u.name), + howto->name, pr->addend, (bfd *) NULL, + (asection *) NULL, (bfd_vma) 0))) + { + free (buf); + return false; + } + break; + } + ok = bfd_set_section_contents (finfo->output_bfd, o, + (PTR) buf, + (file_ptr) p->offset, + size); + free (buf); + if (! ok) + return false; + } + } + else + { + PUT_WORD (finfo->output_bfd, p->offset, erel.r_address); + + if (finfo->output_bfd->xvec->header_byteorder_big_p) + { + erel.r_index[0] = r_index >> 16; + erel.r_index[1] = r_index >> 8; + erel.r_index[2] = r_index; + erel.r_type[0] = + ((r_extern ? RELOC_EXT_BITS_EXTERN_BIG : 0) + | (howto->type << RELOC_EXT_BITS_TYPE_SH_BIG)); + } + else + { + erel.r_index[2] = r_index >> 16; + erel.r_index[1] = r_index >> 8; + erel.r_index[0] = r_index; + erel.r_type[0] = + (r_extern ? RELOC_EXT_BITS_EXTERN_LITTLE : 0) + | (howto->type << RELOC_EXT_BITS_TYPE_SH_LITTLE); + } + + PUT_WORD (finfo->output_bfd, pr->addend, erel.r_addend); + + rel_ptr = (PTR) &erel; + } + + if (bfd_seek (finfo->output_bfd, *reloff_ptr, SEEK_SET) != 0 + || (bfd_write (rel_ptr, (bfd_size_type) 1, + obj_reloc_entry_size (finfo->output_bfd), + finfo->output_bfd) + != obj_reloc_entry_size (finfo->output_bfd))) + return false; + + *reloff_ptr += obj_reloc_entry_size (finfo->output_bfd); + + /* Assert that the relocs have not run into the symbols, and that n + the text relocs have not run into the data relocs. */ + BFD_ASSERT (*reloff_ptr <= obj_sym_filepos (finfo->output_bfd) + && (reloff_ptr != &finfo->treloff + || (*reloff_ptr + <= obj_datasec (finfo->output_bfd)->rel_filepos))); + + return true; +} diff --git a/gnu/usr.bin/gdb/bfd/archive.c b/gnu/usr.bin/gdb/bfd/archive.c index 5edae9d3db0a..a91b49677f89 100644 --- a/gnu/usr.bin/gdb/bfd/archive.c +++ b/gnu/usr.bin/gdb/bfd/archive.c @@ -1,5 +1,5 @@ /* BFD back-end for archive files (libraries). - Copyright 1990, 1991, 1992, 1993 Free Software Foundation, Inc. + Copyright 1990, 91, 92, 93, 94 Free Software Foundation, Inc. Written by Cygnus Support. Mostly Gumby Henkel-Wallace's fault. This file is part of BFD, the Binary File Descriptor library. @@ -24,28 +24,26 @@ SECTION Archives DESCRIPTION - Archives are supported in BFD in <<archive.c>>. - An archive (or library) is just another BFD. It has a symbol table, although there's not much a user program will do with it. The big difference between an archive BFD and an ordinary BFD is that the archive doesn't have sections. Instead it has a - chain of BFDs considered its contents. These BFDs can be - manipulated just like any other. The BFDs contained in an - archive opened for reading will all be opened for reading; you + chain of BFDs that are considered its contents. These BFDs can + be manipulated like any other. The BFDs contained in an + archive opened for reading will all be opened for reading. You may put either input or output BFDs into an archive opened for - output; it will be handled correctly when the archive is closed. + output; they will be handled correctly when the archive is closed. - Use <<bfd_openr_next_archived_file>> to step through all - the contents of an archive opened for input. It's not - required that you read the entire archive if you don't want + Use <<bfd_openr_next_archived_file>> to step through + the contents of an archive opened for input. You don't + have to read the entire archive if you don't want to! Read it until you find what you want. Archive contents of output BFDs are chained through the <<next>> pointer in a BFD. The first one is findable through the <<archive_head>> slot of the archive. Set it with - <<set_archive_head>> (q.v.). A given BFD may be in only one + <<bfd_set_archive_head>> (q.v.). A given BFD may be in only one open output archive at a time. As expected, the BFD archive code is more general than the @@ -56,7 +54,7 @@ DESCRIPTION This can cause unexpected confusion, since some archive formats are more expressive than others. For instance, Intel - COFF archives can preserve long filenames; Sun a.out archives + COFF archives can preserve long filenames; SunOS a.out archives cannot. If you move a file from the first to the second format and back again, the filename may be truncated. Likewise, different a.out environments have different @@ -67,10 +65,13 @@ DESCRIPTION Beware: most of these formats do not react well to the presence of spaces in filenames. We do the best we can, but - can't always handle this due to restrctions in the format of - archives. Many unix utilities are braindead in regards to + can't always handle this case due to restrictions in the format of + archives. Many Unix utilities are braindead in regards to spaces and such in filenames anyway, so this shouldn't be much of a restriction. + + Archives are supported in BFD in <<archive.c>>. + */ /* Assumes: @@ -80,12 +81,12 @@ DESCRIPTION */ /* Some formats provide a way to cram a long filename into the short - (16 chars) space provided by a bsd archive. The trick is: make a + (16 chars) space provided by a BSD archive. The trick is: make a special "file" in the front of the archive, sort of like the SYMDEF entry. If the filename is too long to fit, put it in the extended name table, and use its index as the filename. To prevent confusion prepend the index with a space. This means you can't - have filenames that start with a space, but then again, many unix + have filenames that start with a space, but then again, many Unix utilities can't handle that anyway. This scheme unfortunately requires that you stand on your head in @@ -99,7 +100,7 @@ DESCRIPTION BSD 4.4 uses a third scheme: It writes a long filename directly after the header. This allows 'ar q' to work. - We current can read BSD 4.4 archives, but not write them. + We currently can read BSD 4.4 archives, but not write them. */ /* Summary of archive member names: @@ -141,7 +142,7 @@ extern int errno; #define BFD_GNU960_ARMAG(abfd) (BFD_COFF_FILE_P((abfd)) ? ARMAG : ARMAGB) #endif -/* Can't define this in hosts/*.h, because (e.g. in gprof) the hosts file +/* Can't define this in hosts/foo.h, because (e.g. in gprof) the hosts file is included, then obstack.h, which thinks if offsetof is defined, it doesn't need to include stddef.h. */ /* Define offsetof for those systems which lack it */ @@ -157,9 +158,10 @@ extern int errno; Note that the pointers here point to the front of the ar_hdr, not to the front of the contents! */ -struct ar_cache { +struct ar_cache +{ file_ptr ptr; - bfd* arelt; + bfd *arelt; struct ar_cache *next; }; @@ -169,28 +171,39 @@ struct ar_cache { #define arch_eltdata(bfd) ((struct areltdata *)((bfd)->arelt_data)) #define arch_hdr(bfd) ((struct ar_hdr *)arch_eltdata(bfd)->arch_header) -/* Forward declarations of functions */ - -boolean -compute_and_write_armap PARAMS ((bfd *arch, unsigned int elength)); - -static boolean -bsd_update_armap_timestamp PARAMS ((bfd *arch)); - - +static char *get_extended_arelt_filename PARAMS ((bfd *arch, + const char *name)); +static boolean do_slurp_bsd_armap PARAMS ((bfd *abfd)); +static boolean do_slurp_coff_armap PARAMS ((bfd *abfd)); +static const char *normalize PARAMS ((const char *file)); +static boolean bfd_construct_extended_name_table PARAMS ((bfd *abfd, + char **tabloc, + unsigned int *)); +static struct areltdata *bfd_ar_hdr_from_filesystem PARAMS ((bfd *abfd, + const char *)); +static boolean compute_and_write_armap PARAMS ((bfd *arch, + unsigned int elength)); +static boolean bsd_update_armap_timestamp PARAMS ((bfd *arch)); boolean _bfd_generic_mkarchive (abfd) bfd *abfd; { - abfd->tdata.aout_ar_data = (struct artdata *)bfd_zalloc(abfd, - sizeof (struct artdata)); + abfd->tdata.aout_ar_data = ((struct artdata *) + bfd_zalloc (abfd, sizeof (struct artdata))); - if (bfd_ardata (abfd) == NULL) { - bfd_error = no_memory; + if (bfd_ardata (abfd) == NULL) + { + bfd_set_error (bfd_error_no_memory); return false; } - bfd_ardata(abfd)->cache = 0; + + bfd_ardata (abfd)->cache = NULL; + bfd_ardata (abfd)->archive_head = NULL; + bfd_ardata (abfd)->symdefs = NULL; + bfd_ardata (abfd)->extended_names = NULL; + bfd_ardata (abfd)->tdata = NULL; + return true; } @@ -199,16 +212,16 @@ FUNCTION bfd_get_next_mapent SYNOPSIS - symindex bfd_get_next_mapent(bfd *, symindex previous, carsym ** sym); + symindex bfd_get_next_mapent(bfd *abfd, symindex previous, carsym **sym); DESCRIPTION - This function steps through an archive's symbol table (if it - has one). Successively updates <<sym>> with the next symbol's + Step through archive @var{abfd}'s symbol table (if it + has one). Successively update @var{sym} with the next symbol's information, returning that symbol's (internal) index into the symbol table. - Supply BFD_NO_MORE_SYMBOLS as the <<previous>> entry to get - the first one; returns BFD_NO_MORE_SYMBOLS when you're already + Supply <<BFD_NO_MORE_SYMBOLS>> as the @var{previous} entry to get + the first one; returns <<BFD_NO_MORE_SYMBOLS>> when you've already got the last one. A <<carsym>> is a canonical archive symbol. The only @@ -216,17 +229,19 @@ DESCRIPTION */ symindex -DEFUN(bfd_get_next_mapent,(abfd, prev, entry), - bfd *abfd AND - symindex prev AND - carsym **entry) +bfd_get_next_mapent (abfd, prev, entry) + bfd *abfd; + symindex prev; + carsym **entry; { - if (!bfd_has_map (abfd)) { - bfd_error = invalid_operation; - return BFD_NO_MORE_SYMBOLS; - } - - if (prev == BFD_NO_MORE_SYMBOLS) prev = 0; + if (!bfd_has_map (abfd)) + { + bfd_set_error (bfd_error_invalid_operation); + return BFD_NO_MORE_SYMBOLS; + } + + if (prev == BFD_NO_MORE_SYMBOLS) + prev = 0; else if (++prev >= bfd_ardata (abfd)->symdef_count) return BFD_NO_MORE_SYMBOLS; @@ -242,10 +257,10 @@ _bfd_create_empty_archive_element_shell (obfd) { bfd *nbfd; - nbfd = new_bfd_contained_in(obfd); + nbfd = _bfd_new_bfd_contained_in (obfd); if (nbfd == NULL) { - bfd_error = no_memory; + bfd_set_error (bfd_error_no_memory); return NULL; } return nbfd; @@ -259,14 +274,14 @@ SYNOPSIS boolean bfd_set_archive_head(bfd *output, bfd *new_head); DESCRIPTION - Used whilst processing archives. Sets the head of the chain of - BFDs contained in an archive to @var{new_head}. + Set the head of the chain of + BFDs contained in the archive @var{output} to @var{new_head}. */ boolean -DEFUN(bfd_set_archive_head,(output_archive, new_head), - bfd *output_archive AND - bfd *new_head) +bfd_set_archive_head (output_archive, new_head) + bfd *output_archive; + bfd *new_head; { output_archive->archive_head = new_head; @@ -274,7 +289,7 @@ DEFUN(bfd_set_archive_head,(output_archive, new_head), } bfd * -look_for_bfd_in_cache (arch_bfd, filepos) +_bfd_look_for_bfd_in_cache (arch_bfd, filepos) bfd *arch_bfd; file_ptr filepos; { @@ -282,48 +297,52 @@ look_for_bfd_in_cache (arch_bfd, filepos) for (current = bfd_ardata (arch_bfd)->cache; current != NULL; current = current->next) - if (current->ptr == filepos) return current->arelt; + if (current->ptr == filepos) + return current->arelt; return NULL; } /* Kind of stupid to call cons for each one, but we don't do too many */ boolean -add_bfd_to_cache (arch_bfd, filepos, new_elt) +_bfd_add_bfd_to_archive_cache (arch_bfd, filepos, new_elt) bfd *arch_bfd, *new_elt; file_ptr filepos; { - struct ar_cache *new_cache = (struct ar_cache *) - bfd_zalloc(arch_bfd, sizeof (struct ar_cache)); + struct ar_cache *new_cache = ((struct ar_cache *) + bfd_zalloc (arch_bfd, + sizeof (struct ar_cache))); - if (new_cache == NULL) { - bfd_error = no_memory; - return false; - } + if (new_cache == NULL) + { + bfd_set_error (bfd_error_no_memory); + return false; + } new_cache->ptr = filepos; new_cache->arelt = new_elt; - new_cache->next = (struct ar_cache *)NULL; + new_cache->next = (struct ar_cache *) NULL; if (bfd_ardata (arch_bfd)->cache == NULL) bfd_ardata (arch_bfd)->cache = new_cache; - else { - struct ar_cache *current = bfd_ardata (arch_bfd)->cache; + else + { + struct ar_cache *current = bfd_ardata (arch_bfd)->cache; + + while (current->next != NULL) + current = current->next; + current->next = new_cache; + } - for (; current->next != NULL; current = current->next); - current->next = new_cache; - } - return true; } - - /* The name begins with space. Hence the rest of the name is an index into the string table. */ -char * + +static char * get_extended_arelt_filename (arch, name) bfd *arch; - char *name; + const char *name; { unsigned long index = 0; @@ -331,14 +350,15 @@ get_extended_arelt_filename (arch, name) the next region, but I'm too lazy. */ errno = 0; /* Skip first char, which is '/' in SVR4 or ' ' in some other variants. */ - index = strtol (name+1, NULL, 10); - if (errno != 0) { - bfd_error = malformed_archive; + index = strtol (name + 1, NULL, 10); + if (errno != 0) + { + bfd_set_error (bfd_error_malformed_archive); return NULL; } return bfd_ardata (arch)->extended_names + index; -} +} /* This functions reads an arch header and returns an areltdata pointer, or NULL on error. @@ -350,154 +370,165 @@ get_extended_arelt_filename (arch, name) */ struct areltdata * -snarf_ar_hdr (abfd) +_bfd_snarf_ar_hdr (abfd) bfd *abfd; { #ifndef errno extern int errno; #endif - struct ar_hdr hdr; - char *hdrp = (char *) &hdr; - unsigned int parsed_size; - struct areltdata *ared; - char *filename = NULL; - unsigned int namelen = 0; - unsigned int allocsize = sizeof (struct areltdata) + sizeof (struct ar_hdr); - char *allocptr = 0; - - if (bfd_read ((PTR)hdrp, 1, sizeof (struct ar_hdr), abfd) - != sizeof (struct ar_hdr)) { - bfd_error = no_more_archived_files; - return NULL; + struct ar_hdr hdr; + char *hdrp = (char *) &hdr; + unsigned int parsed_size; + struct areltdata *ared; + char *filename = NULL; + unsigned int namelen = 0; + unsigned int allocsize = sizeof (struct areltdata) + sizeof (struct ar_hdr); + char *allocptr = 0; + + if (bfd_read ((PTR) hdrp, 1, sizeof (struct ar_hdr), abfd) + != sizeof (struct ar_hdr)) + { + if (bfd_get_error () != bfd_error_system_call) + bfd_set_error (bfd_error_no_more_archived_files); + return NULL; } - if (strncmp ((hdr.ar_fmag), ARFMAG, 2)) { - bfd_error = malformed_archive; - return NULL; + if (strncmp (hdr.ar_fmag, ARFMAG, 2)) + { + bfd_set_error (bfd_error_malformed_archive); + return NULL; } - errno = 0; - parsed_size = strtol (hdr.ar_size, NULL, 10); - if (errno != 0) { - bfd_error = malformed_archive; - return NULL; + errno = 0; + parsed_size = strtol (hdr.ar_size, NULL, 10); + if (errno != 0) + { + bfd_set_error (bfd_error_malformed_archive); + return 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] == ' ' - && memchr (hdr.ar_name, '/', ar_maxnamelen(abfd)) == NULL)) - && bfd_ardata (abfd)->extended_names != NULL) { - filename = get_extended_arelt_filename (abfd, hdr.ar_name); - if (filename == NULL) { - bfd_error = malformed_archive; - return 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] == ' ' + && memchr (hdr.ar_name, '/', ar_maxnamelen (abfd)) == NULL)) + && bfd_ardata (abfd)->extended_names != NULL) + { + filename = get_extended_arelt_filename (abfd, hdr.ar_name); + if (filename == NULL) + { + bfd_set_error (bfd_error_malformed_archive); + return NULL; } } - /* BSD4.4-style long filename. - Only implemented for reading, so far! */ - else if (hdr.ar_name[0] == '#' && hdr.ar_name[1] == '1' - && hdr.ar_name[2] == '/' && isdigit(hdr.ar_name[3])) - { - /* BSD-4.4 extended name */ - namelen = atoi (&hdr.ar_name[3]); - allocsize += namelen + 1; - parsed_size -= namelen; - - allocptr = bfd_zalloc(abfd, allocsize); - if (allocptr == NULL) { - bfd_error = no_memory; + /* BSD4.4-style long filename. + Only implemented for reading, so far! */ + else if (hdr.ar_name[0] == '#' && hdr.ar_name[1] == '1' + && hdr.ar_name[2] == '/' && isdigit (hdr.ar_name[3])) + { + /* BSD-4.4 extended name */ + namelen = atoi (&hdr.ar_name[3]); + allocsize += namelen + 1; + parsed_size -= namelen; + + allocptr = bfd_zalloc (abfd, allocsize); + if (allocptr == NULL) + { + bfd_set_error (bfd_error_no_memory); return NULL; } - filename = allocptr - + (sizeof (struct areltdata) + sizeof (struct ar_hdr)); - if (bfd_read (filename, 1, namelen, abfd) != namelen) { - bfd_error = no_more_archived_files; + filename = (allocptr + + sizeof (struct areltdata) + + sizeof (struct ar_hdr)); + if (bfd_read (filename, 1, namelen, abfd) != namelen) + { + if (bfd_get_error () != bfd_error_system_call) + bfd_set_error (bfd_error_no_more_archived_files); return NULL; } - filename[namelen] = '\0'; - } - else - { - /* We judge the end of the name by looking for '/' or ' '. - Note: The SYSV format (terminated by '/') allows embedded - spaces, so only look for ' ' if we don't find '/'. */ + filename[namelen] = '\0'; + } + else + { + /* We judge the end of the name by looking for '/' or ' '. + Note: The SYSV format (terminated by '/') allows embedded + spaces, so only look for ' ' if we don't find '/'. */ - namelen = 0; - while (hdr.ar_name[namelen] != '\0' && - hdr.ar_name[namelen] != '/') { + namelen = 0; + while (hdr.ar_name[namelen] != '\0' && + hdr.ar_name[namelen] != '/') + { + namelen++; + if (namelen == (unsigned) ar_maxnamelen (abfd)) + { + namelen = 0; + while (hdr.ar_name[namelen] != ' ' + && namelen < (unsigned) ar_maxnamelen (abfd)) namelen++; - if (namelen == (unsigned)ar_maxnamelen(abfd)) { - namelen = 0; - while (hdr.ar_name[namelen] != ' ' - && namelen < (unsigned)ar_maxnamelen(abfd)) { - namelen++; - } - break; - } + break; } - - allocsize += namelen + 1; } - if (!allocptr) { - allocptr = bfd_zalloc(abfd, allocsize); - if (allocptr == NULL) { - bfd_error = no_memory; - return NULL; - } + allocsize += namelen + 1; + } + + if (!allocptr) + { + allocptr = bfd_zalloc (abfd, allocsize); + if (allocptr == NULL) + { + bfd_set_error (bfd_error_no_memory); + return NULL; + } } - ared = (struct areltdata *) allocptr; + ared = (struct areltdata *) allocptr; - ared->arch_header = allocptr + sizeof (struct areltdata); - memcpy ((char *) ared->arch_header, (char *) &hdr, sizeof (struct ar_hdr)); - ared->parsed_size = parsed_size; + ared->arch_header = allocptr + sizeof (struct areltdata); + memcpy ((char *) ared->arch_header, (char *) &hdr, sizeof (struct ar_hdr)); + ared->parsed_size = parsed_size; - if (filename != NULL) ared->filename = filename; - else { - ared->filename = allocptr + (sizeof (struct areltdata) + - sizeof (struct ar_hdr)); - if (namelen) - memcpy (ared->filename, hdr.ar_name, namelen); - ared->filename[namelen] = '\0'; + if (filename != NULL) + ared->filename = filename; + else + { + ared->filename = allocptr + (sizeof (struct areltdata) + + sizeof (struct ar_hdr)); + if (namelen) + memcpy (ared->filename, hdr.ar_name, namelen); + ared->filename[namelen] = '\0'; } - - return ared; + + return ared; } /* This is an internal function; it's mainly used when indexing through the archive symbol table, but also used to get the next - element, since it handles the bookkeeping so nicely for us. -*/ + element, since it handles the bookkeeping so nicely for us. */ bfd * -get_elt_at_filepos (archive, filepos) +_bfd_get_elt_at_filepos (archive, filepos) bfd *archive; file_ptr filepos; { struct areltdata *new_areldata; bfd *n_nfd; - n_nfd = look_for_bfd_in_cache (archive, filepos); + n_nfd = _bfd_look_for_bfd_in_cache (archive, filepos); if (n_nfd) return n_nfd; if (0 > bfd_seek (archive, filepos, SEEK_SET)) - { - bfd_error = system_call_error; - return NULL; - } + return NULL; - if ((new_areldata = snarf_ar_hdr (archive)) == NULL) + if ((new_areldata = _bfd_snarf_ar_hdr (archive)) == NULL) return NULL; - + n_nfd = _bfd_create_empty_archive_element_shell (archive); if (n_nfd == NULL) { - bfd_release (archive, (PTR)new_areldata); + bfd_release (archive, (PTR) new_areldata); return NULL; } @@ -505,12 +536,12 @@ get_elt_at_filepos (archive, filepos) n_nfd->arelt_data = (PTR) new_areldata; n_nfd->filename = new_areldata->filename; - if (add_bfd_to_cache (archive, filepos, n_nfd)) + if (_bfd_add_bfd_to_archive_cache (archive, filepos, n_nfd)) return n_nfd; /* huh? */ - bfd_release (archive, (PTR)n_nfd); - bfd_release (archive, (PTR)new_areldata); + bfd_release (archive, (PTR) n_nfd); + bfd_release (archive, (PTR) new_areldata); return NULL; } @@ -519,22 +550,23 @@ FUNCTION bfd_get_elt_at_index SYNOPSIS - bfd *bfd_get_elt_at_index(bfd * archive, int index); + bfd *bfd_get_elt_at_index(bfd *archive, int index); DESCRIPTION - Return the bfd which is referenced by the symbol indexed by <<index>>. - <<index>> should have been returned by <<bfd_get_next_mapent>> (q.v.). + Return the BFD which is referenced by the symbol in @var{archive} + indexed by @var{index}. @var{index} should have been returned by + <<bfd_get_next_mapent>> (q.v.). */ bfd * -DEFUN(bfd_get_elt_at_index,(abfd, index), - bfd *abfd AND - int index) +bfd_get_elt_at_index (abfd, index) + bfd *abfd; + int index; { - bfd *result = - get_elt_at_filepos - (abfd, (bfd_ardata (abfd)->symdefs + index)->file_offset); - return result; + carsym *entry; + + entry = bfd_ardata (abfd)->symdefs + index; + return _bfd_get_elt_at_filepos (abfd, entry->file_offset); } /* @@ -542,12 +574,12 @@ FUNCTION bfd_openr_next_archived_file SYNOPSIS - bfd* bfd_openr_next_archived_file(bfd *archive, bfd *previous); + bfd *bfd_openr_next_archived_file(bfd *archive, bfd *previous); DESCRIPTION - Initially provided a BFD containing an archive and NULL, opens - an inpout BFD on the first contained element and returns that. - Subsequent calls to bfd_openr_next_archived_file should pass + Provided a BFD, @var{archive}, containing an archive and NULL, open + an input BFD on the first contained element and returns that. + Subsequent calls 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. @@ -562,7 +594,7 @@ bfd_openr_next_archived_file (archive, last_file) if ((bfd_get_format (archive) != bfd_archive) || (archive->direction == write_direction)) { - bfd_error = invalid_operation; + bfd_set_error (bfd_error_invalid_operation); return NULL; } @@ -581,119 +613,165 @@ bfd_generic_openr_next_archived_file (archive, last_file) if (!last_file) filestart = bfd_ardata (archive)->first_file_filepos; - else { - unsigned int size = arelt_size(last_file); - /* Pad to an even boundary... - Note that last_file->origin can be odd in the case of - BSD-4.4-style element with a long odd size. */ - filestart = last_file->origin + size; - filestart += filestart % 2; - } - - return get_elt_at_filepos (archive, filestart); + else + { + unsigned int size = arelt_size (last_file); + /* Pad to an even boundary... + Note that last_file->origin can be odd in the case of + BSD-4.4-style element with a long odd size. */ + filestart = last_file->origin + size; + filestart += filestart % 2; + } + + return _bfd_get_elt_at_filepos (archive, filestart); } -bfd_target * +const bfd_target * bfd_generic_archive_p (abfd) bfd *abfd; { - char armag[SARMAG+1]; + char armag[SARMAG + 1]; - if (bfd_read ((PTR)armag, 1, SARMAG, abfd) != SARMAG) { - bfd_error = wrong_format; - return 0; - } + if (bfd_read ((PTR) armag, 1, SARMAG, abfd) != SARMAG) + { + if (bfd_get_error () != bfd_error_system_call) + bfd_set_error (bfd_error_wrong_format); + return NULL; + } #ifdef GNU960 - if (strncmp (armag, BFD_GNU960_ARMAG(abfd), SARMAG)) return 0; + if (strncmp (armag, BFD_GNU960_ARMAG (abfd), SARMAG) != 0) + return 0; #else - if (strncmp (armag, ARMAG, SARMAG) && - strncmp (armag, ARMAGB, SARMAG)) return 0; + if (strncmp (armag, ARMAG, SARMAG) != 0 && + strncmp (armag, ARMAGB, SARMAG) != 0) + return 0; #endif - - /* We are setting bfd_ardata(abfd) here, but since bfd_ardata involves a cast, we can't do it as the left operand of assignment. */ - abfd->tdata.aout_ar_data = (struct artdata *) bfd_zalloc(abfd,sizeof (struct artdata)); + abfd->tdata.aout_ar_data = ((struct artdata *) + bfd_zalloc (abfd, sizeof (struct artdata))); - if (bfd_ardata (abfd) == NULL) { - bfd_error = no_memory; - return 0; - } + if (bfd_ardata (abfd) == NULL) + { + bfd_set_error (bfd_error_no_memory); + return NULL; + } bfd_ardata (abfd)->first_file_filepos = SARMAG; - - if (!BFD_SEND (abfd, _bfd_slurp_armap, (abfd))) { - bfd_release(abfd, bfd_ardata (abfd)); - abfd->tdata.aout_ar_data = NULL; - return 0; - } + bfd_ardata (abfd)->cache = NULL; + bfd_ardata (abfd)->archive_head = NULL; + bfd_ardata (abfd)->symdefs = NULL; + bfd_ardata (abfd)->extended_names = NULL; + bfd_ardata (abfd)->tdata = NULL; + + if (!BFD_SEND (abfd, _bfd_slurp_armap, (abfd))) + { + bfd_release (abfd, bfd_ardata (abfd)); + abfd->tdata.aout_ar_data = NULL; + return NULL; + } + + if (!BFD_SEND (abfd, _bfd_slurp_extended_name_table, (abfd))) + { + bfd_release (abfd, bfd_ardata (abfd)); + abfd->tdata.aout_ar_data = NULL; + return NULL; + } - if (!BFD_SEND (abfd, _bfd_slurp_extended_name_table, (abfd))) { - bfd_release(abfd, bfd_ardata (abfd)); - abfd->tdata.aout_ar_data = NULL; - return 0; - } - return abfd->xvec; } +/* Some constants for a 32 bit BSD archive structure. We do not + support 64 bit archives presently; so far as I know, none actually + exist. Supporting them would require changing these constants, and + changing some bfd_h_get_32 to bfd_h_get_64. */ + +/* The size of an external symdef structure. */ +#define BSD_SYMDEF_SIZE 8 + +/* The offset from the start of a symdef structure to the file offset. */ +#define BSD_SYMDEF_OFFSET_SIZE 4 + +/* The size of the symdef count. */ +#define BSD_SYMDEF_COUNT_SIZE 4 + +/* The size of the string count. */ +#define BSD_STRING_COUNT_SIZE 4 + /* Returns false on error, true otherwise */ + static boolean -DEFUN (do_slurp_bsd_armap, (abfd), - bfd *abfd) +do_slurp_bsd_armap (abfd) + bfd *abfd; { struct areltdata *mapdata; - unsigned int counter = 0; - int *raw_armap, *rbase; + unsigned int counter; + bfd_byte *raw_armap, *rbase; struct artdata *ardata = bfd_ardata (abfd); char *stringbase; unsigned int parsed_size; + carsym *set; - mapdata = snarf_ar_hdr (abfd); - if (mapdata == NULL) return false; + mapdata = _bfd_snarf_ar_hdr (abfd); + if (mapdata == NULL) + return false; parsed_size = mapdata->parsed_size; - bfd_release (abfd, (PTR)mapdata); /* Don't need it any more. */ - - raw_armap = (int *) bfd_zalloc(abfd, parsed_size); - if (raw_armap == NULL) { - bfd_error = no_memory; + bfd_release (abfd, (PTR) mapdata); /* Don't need it any more. */ + + raw_armap = (bfd_byte *) bfd_zalloc (abfd, parsed_size); + if (raw_armap == (bfd_byte *) NULL) + { + bfd_set_error (bfd_error_no_memory); return false; - } - - if (bfd_read ((PTR)raw_armap, 1, parsed_size, abfd) != parsed_size) { - bfd_error = malformed_archive; + } + + if (bfd_read ((PTR) raw_armap, 1, parsed_size, abfd) != parsed_size) + { + if (bfd_get_error () != bfd_error_system_call) + bfd_set_error (bfd_error_malformed_archive); byebye: - bfd_release (abfd, (PTR)raw_armap); + bfd_release (abfd, (PTR) raw_armap); return false; - } - - ardata->symdef_count = - bfd_h_get_32(abfd, (PTR)raw_armap) / sizeof (struct symdef); - - if (ardata->symdef_count * sizeof (struct symdef) - > parsed_size - sizeof (*raw_armap)) { + } + + ardata->symdef_count = bfd_h_get_32 (abfd, raw_armap) / BSD_SYMDEF_SIZE; + + if (ardata->symdef_count * BSD_SYMDEF_SIZE > + parsed_size - BSD_SYMDEF_COUNT_SIZE) + { /* Probably we're using the wrong byte ordering. */ - bfd_error = wrong_format; + bfd_set_error (bfd_error_wrong_format); goto byebye; - } - + } + ardata->cache = 0; - rbase = raw_armap+1; - ardata->symdefs = (carsym *) rbase; - stringbase = ((char *) (ardata->symdefs + ardata->symdef_count)) + 4; - - for (;counter < ardata->symdef_count; counter++) { - struct symdef *sym = ((struct symdef *) rbase) + counter; - 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))); - } - + rbase = raw_armap + BSD_SYMDEF_COUNT_SIZE; + stringbase = ((char *) rbase + + ardata->symdef_count * BSD_SYMDEF_SIZE + + BSD_STRING_COUNT_SIZE); + ardata->symdefs = (carsym *) bfd_alloc (abfd, + (ardata->symdef_count + * sizeof (carsym))); + if (!ardata->symdefs) + { + bfd_set_error (bfd_error_no_memory); + return false; + } + + for (counter = 0, set = ardata->symdefs; + counter < ardata->symdef_count; + counter++, set++, rbase += BSD_SYMDEF_SIZE) + { + set->name = bfd_h_get_32 (abfd, rbase) + stringbase; + set->file_offset = bfd_h_get_32 (abfd, rbase + BSD_SYMDEF_OFFSET_SIZE); + } + 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; + ardata->first_file_filepos += (ardata->first_file_filepos) % 2; /* FIXME, we should provide some way to free raw_ardata when we are done using the strings from it. For now, it seems to be allocated on an obstack anyway... */ @@ -703,8 +781,8 @@ DEFUN (do_slurp_bsd_armap, (abfd), /* Returns false on error, true otherwise */ static boolean -DEFUN (do_slurp_coff_armap, (abfd), - bfd *abfd) +do_slurp_coff_armap (abfd) + bfd *abfd; { struct areltdata *mapdata; int *raw_armap, *rawptr; @@ -713,25 +791,27 @@ DEFUN (do_slurp_coff_armap, (abfd), unsigned int stringsize; unsigned int parsed_size; carsym *carsyms; - unsigned int nsymz; /* Number of symbols in armap. */ - - bfd_vma (*swap) PARAMS ((bfd_byte*)); - char int_buf[sizeof(long)]; + unsigned int nsymz; /* Number of symbols in armap. */ + bfd_vma (*swap) PARAMS ((const bfd_byte *)); + char int_buf[sizeof (long)]; unsigned int carsym_size, ptrsize, i; - - mapdata = snarf_ar_hdr (abfd); - if (mapdata == NULL) return false; - parsed_size = mapdata->parsed_size; - bfd_release (abfd, (PTR)mapdata); /* Don't need it any more. */ - if (bfd_read ((PTR)int_buf, 1, 4, abfd) != 4) { - bfd_error = malformed_archive; + mapdata = _bfd_snarf_ar_hdr (abfd); + if (mapdata == NULL) return false; - } + parsed_size = mapdata->parsed_size; + bfd_release (abfd, (PTR) mapdata); /* Don't need it any more. */ + + if (bfd_read ((PTR) int_buf, 1, 4, abfd) != 4) + { + if (bfd_get_error () != bfd_error_system_call) + bfd_set_error (bfd_error_malformed_archive); + return false; + } /* It seems that all numeric information in a coff archive is always in big endian format, nomatter the host or target. */ swap = bfd_getb32; - nsymz = bfd_getb32((PTR)int_buf); + nsymz = bfd_getb32 ((PTR) int_buf); stringsize = parsed_size - (4 * nsymz) - 4; #if 1 @@ -739,64 +819,70 @@ DEFUN (do_slurp_coff_armap, (abfd), fault - the i960 little endian coff sometimes has big and sometimes little, because our tools changed. Here's a horrible hack to clean up the crap. */ - - if (stringsize > 0xfffff) { + + if (stringsize > 0xfffff) + { /* This looks dangerous, let's do it the other way around */ - nsymz = bfd_getl32((PTR)int_buf); + nsymz = bfd_getl32 ((PTR) int_buf); stringsize = parsed_size - (4 * nsymz) - 4; swap = bfd_getl32; - } + } #endif - /* The coff armap must be read sequentially. So we construct a bsd-style - one in core all at once, for simplicity. */ - + /* The coff armap must be read sequentially. So we construct a + bsd-style one in core all at once, for simplicity. */ + carsym_size = (nsymz * sizeof (carsym)); ptrsize = (4 * nsymz); - ardata->symdefs = (carsym *) bfd_zalloc(abfd, carsym_size + stringsize + 1); - if (ardata->symdefs == NULL) { - bfd_error = no_memory; + ardata->symdefs = (carsym *) bfd_zalloc (abfd, carsym_size + stringsize + 1); + if (ardata->symdefs == NULL) + { + bfd_set_error (bfd_error_no_memory); return false; - } + } carsyms = ardata->symdefs; stringbase = ((char *) ardata->symdefs) + carsym_size; /* Allocate and read in the raw offsets. */ - raw_armap = (int *) bfd_alloc(abfd, ptrsize); - if (raw_armap == NULL) { - bfd_error = no_memory; + raw_armap = (int *) bfd_alloc (abfd, ptrsize); + if (raw_armap == NULL) + { + bfd_set_error (bfd_error_no_memory); goto release_symdefs; - } - if (bfd_read ((PTR)raw_armap, 1, ptrsize, abfd) != ptrsize - || bfd_read ((PTR)stringbase, 1, stringsize, abfd) != stringsize) { - bfd_error = malformed_archive; - goto release_raw_armap; - } + } + if (bfd_read ((PTR) raw_armap, 1, ptrsize, abfd) != ptrsize + || bfd_read ((PTR) stringbase, 1, stringsize, abfd) != stringsize) + { + if (bfd_get_error () != bfd_error_system_call) + bfd_set_error (bfd_error_malformed_archive); + goto release_raw_armap; + } /* OK, build the carsyms */ - for (i = 0; i < nsymz; i++) { + for (i = 0; i < nsymz; i++) + { rawptr = raw_armap + i; - carsyms->file_offset = swap((PTR)rawptr); + carsyms->file_offset = swap ((PTR) rawptr); carsyms->name = stringbase; - while (*stringbase++) ; + stringbase += strlen (stringbase) + 1; carsyms++; - } + } *stringbase = 0; ardata->symdef_count = nsymz; 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; + ardata->first_file_filepos += (ardata->first_file_filepos) % 2; bfd_has_map (abfd) = true; - bfd_release (abfd, (PTR)raw_armap); + bfd_release (abfd, (PTR) raw_armap); return true; - release_raw_armap: - bfd_release (abfd, (PTR)raw_armap); - release_symdefs: - bfd_release (abfd, (PTR)(ardata)->symdefs); +release_raw_armap: + bfd_release (abfd, (PTR) raw_armap); +release_symdefs: + bfd_release (abfd, (PTR) (ardata)->symdefs); return false; } @@ -808,16 +894,18 @@ bfd_slurp_armap (abfd) bfd *abfd; { char nextname[17]; - int i = bfd_read ((PTR)nextname, 1, 16, abfd); - + int i = bfd_read ((PTR) nextname, 1, 16, abfd); + if (i == 0) - return true; + return true; if (i != 16) - return false; + return false; - bfd_seek (abfd, (file_ptr) -16, SEEK_CUR); + if (bfd_seek (abfd, (file_ptr) - 16, SEEK_CUR) != 0) + return false; - if (!strncmp (nextname, "__.SYMDEF ", 16)) + if (!strncmp (nextname, "__.SYMDEF ", 16) + || !strncmp (nextname, "__.SYMDEF/ ", 16)) /* old Linux archives */ return do_slurp_bsd_armap (abfd); else if (!strncmp (nextname, "/ ", 16)) return do_slurp_coff_armap (abfd); @@ -828,20 +916,24 @@ bfd_slurp_armap (abfd) /* Returns false on error, true otherwise */ /* flavor 2 of a bsd armap, similar to bfd_slurp_bsd_armap except the - header is in a slightly different order and the map name is '/'. + header is in a slightly different order and the map name is '/'. This flavour is used by hp300hpux. */ + +#define HPUX_SYMDEF_COUNT_SIZE 2 + boolean -bfd_slurp_bsd_armap_f2 (abfd) +bfd_slurp_bsd_armap_f2 (abfd) bfd *abfd; { struct areltdata *mapdata; char nextname[17]; - unsigned int counter = 0; - int *raw_armap, *rbase; + unsigned int counter; + bfd_byte *raw_armap, *rbase; struct artdata *ardata = bfd_ardata (abfd); char *stringbase; unsigned int stringsize; - int i = bfd_read ((PTR)nextname, 1, 16, abfd); + carsym *set; + int i = bfd_read ((PTR) nextname, 1, 16, abfd); if (i == 0) return true; @@ -849,9 +941,11 @@ bfd_slurp_bsd_armap_f2 (abfd) return false; /* The archive has at least 16 bytes in it */ - bfd_seek (abfd, -16L, SEEK_CUR); + if (bfd_seek (abfd, -16L, SEEK_CUR) != 0) + return false; - if (!strncmp (nextname, "__.SYMDEF ", 16)) + if (!strncmp (nextname, "__.SYMDEF ", 16) + || !strncmp (nextname, "__.SYMDEF/ ", 16)) /* old Linux archives */ return do_slurp_bsd_armap (abfd); if (strncmp (nextname, "/ ", 16)) @@ -860,55 +954,67 @@ bfd_slurp_bsd_armap_f2 (abfd) return true; } - mapdata = snarf_ar_hdr (abfd); - if (mapdata == NULL) return false; + mapdata = _bfd_snarf_ar_hdr (abfd); + if (mapdata == NULL) + return false; - raw_armap = (int *) bfd_zalloc(abfd,mapdata->parsed_size); + raw_armap = (bfd_byte *) bfd_zalloc (abfd, mapdata->parsed_size); if (raw_armap == NULL) { - bfd_error = no_memory; + bfd_set_error (bfd_error_no_memory); byebye: - bfd_release (abfd, (PTR)mapdata); + bfd_release (abfd, (PTR) mapdata); return false; } - if (bfd_read ((PTR)raw_armap, 1, mapdata->parsed_size, abfd) != + if (bfd_read ((PTR) raw_armap, 1, mapdata->parsed_size, abfd) != mapdata->parsed_size) { - bfd_error = malformed_archive; + if (bfd_get_error () != bfd_error_system_call) + bfd_set_error (bfd_error_malformed_archive); byebyebye: - bfd_release (abfd, (PTR)raw_armap); + bfd_release (abfd, (PTR) raw_armap); goto byebye; } - ardata->symdef_count = bfd_h_get_16(abfd, (PTR)raw_armap); + ardata->symdef_count = bfd_h_get_16 (abfd, (PTR) raw_armap); - if (ardata->symdef_count * sizeof (struct symdef) - > mapdata->parsed_size - sizeof (*raw_armap)) + if (ardata->symdef_count * BSD_SYMDEF_SIZE + > mapdata->parsed_size - HPUX_SYMDEF_COUNT_SIZE) { /* Probably we're using the wrong byte ordering. */ - bfd_error = wrong_format; + bfd_set_error (bfd_error_wrong_format); goto byebyebye; } ardata->cache = 0; - stringsize = bfd_h_get_32(abfd, (PTR)(((char*)raw_armap)+2)); + stringsize = bfd_h_get_32 (abfd, raw_armap + HPUX_SYMDEF_COUNT_SIZE); /* skip sym count and string sz */ - rbase = (int*)(((char*)raw_armap) + 6); - stringbase = (char *) rbase; - ardata->symdefs = (carsym *)(((char*) rbase) + stringsize); + stringbase = ((char *) raw_armap + + HPUX_SYMDEF_COUNT_SIZE + + BSD_STRING_COUNT_SIZE); + rbase = (bfd_byte *) stringbase + stringsize; + ardata->symdefs = (carsym *) bfd_alloc (abfd, + (ardata->symdef_count + * BSD_SYMDEF_SIZE)); + if (!ardata->symdefs) + { + bfd_set_error (bfd_error_no_memory); + return false; + } - for (;counter < ardata->symdef_count; counter++) + for (counter = 0, set = ardata->symdefs; + counter < ardata->symdef_count; + counter++, set++, rbase += BSD_SYMDEF_SIZE) { - struct symdef *sym = ((struct symdef *) ardata->symdefs) + counter; - 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))); + set->name = bfd_h_get_32 (abfd, rbase) + stringbase; + set->file_offset = bfd_h_get_32 (abfd, rbase + BSD_SYMDEF_OFFSET_SIZE); } 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; + ardata->first_file_filepos += (ardata->first_file_filepos) % 2; /* FIXME, we should provide some way to free raw_ardata when we are done using the strings from it. For now, it seems to be allocated on an obstack anyway... */ @@ -936,57 +1042,64 @@ _bfd_slurp_extended_name_table (abfd) /* FIXME: Formatting sucks here, and in case of failure of BFD_READ, we probably don't want to return true. */ - if (bfd_read ((PTR)nextname, 1, 16, abfd) == 16) { + if (bfd_read ((PTR) nextname, 1, 16, abfd) == 16) + { - bfd_seek (abfd, (file_ptr) -16, SEEK_CUR); + if (bfd_seek (abfd, (file_ptr) - 16, SEEK_CUR) != 0) + return false; - if (strncmp (nextname, "ARFILENAMES/ ", 16) != 0 && - strncmp (nextname, "// ", 16) != 0) + if (strncmp (nextname, "ARFILENAMES/ ", 16) != 0 && + strncmp (nextname, "// ", 16) != 0) { - bfd_ardata (abfd)->extended_names = NULL; - return true; - } + bfd_ardata (abfd)->extended_names = NULL; + return true; + } - 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; - } + namedata = _bfd_snarf_ar_hdr (abfd); + if (namedata == NULL) + 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; - } + bfd_ardata (abfd)->extended_names = + bfd_zalloc (abfd, namedata->parsed_size); + if (bfd_ardata (abfd)->extended_names == NULL) + { + bfd_set_error (bfd_error_no_memory); + byebye: + bfd_release (abfd, (PTR) namedata); + return false; + } - /* Since the archive is supposed to be printable if it contains - text, the entries in the list are newline-padded, not null - padded. In SVR4-style archives, the names also have a - trailing '/'. We'll fix both problems here.. */ + if (bfd_read ((PTR) bfd_ardata (abfd)->extended_names, 1, + namedata->parsed_size, abfd) != namedata->parsed_size) + { + if (bfd_get_error () != bfd_error_system_call) + bfd_set_error (bfd_error_malformed_archive); + bfd_release (abfd, (PTR) (bfd_ardata (abfd)->extended_names)); + bfd_ardata (abfd)->extended_names = NULL; + goto byebye; + } + + /* Since the archive is supposed to be printable if it contains + text, the entries in the list are newline-padded, not null + padded. In SVR4-style archives, the names also have a + trailing '/'. We'll fix both problems here.. */ { char *temp = bfd_ardata (abfd)->extended_names; char *limit = temp + namedata->parsed_size; for (; temp < limit; ++temp) - if (*temp == '\n') + if (*temp == '\012') temp[temp[-1] == '/' ? -1 : 0] = '\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; - - /* FIXME, we can't release namedata here because it was allocated - below extended_names on the obstack... */ - /* bfd_release (abfd, namedata); */ - } + + /* 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); */ + } return true; } @@ -994,65 +1107,68 @@ _bfd_slurp_extended_name_table (abfd) /* Return a copy of the stuff in the filename between any :]> and a semicolon */ -static CONST char * -DEFUN(normalize,(file), - CONST char *file) +static const char * +normalize (file) + const char *file; { CONST char *first; CONST char *last; char *copy; - first = file + strlen(file)-1; - last = first+1; - - while (first != file) - { - if (*first == ';') - last = first; - if (*first == ':' || *first == ']' ||*first == '>') - { - first++; - break; + first = file + strlen (file) - 1; + last = first + 1; + + while (first != file) + { + if (*first == ';') + last = first; + if (*first == ':' || *first == ']' || *first == '>') + { + first++; + break; + } + first--; } - first --; - } - - copy = bfd_xmalloc(last - first + 1); - memcpy(copy, first, last-first); - copy[last-first] = 0; + + copy = malloc (last - first + 1); + if (!copy) + return copy; + + memcpy (copy, first, last - first); + copy[last - first] = 0; return copy; } #else -static CONST char * -DEFUN (normalize, (file), - CONST char *file) +static const char * +normalize (file) + const char *file; { - CONST char * filename = strrchr(file, '/'); + CONST char *filename = strrchr (file, '/'); - if (filename != (char *)NULL) { - filename ++; - } - else { - filename = file; - } + if (filename != (char *) NULL) + filename++; + else + filename = file; return filename; } #endif -/* Follows archive_head and produces an extended name table if necessary. - Returns (in tabloc) a pointer to an extended name table, and in tablen - the length of the table. If it makes an entry it clobbers the filename - so that the element may be written without further massage. - Returns true if it ran successfully, false if something went wrong. - A successful return may still involve a zero-length tablen! - */ -boolean -DEFUN (bfd_construct_extended_name_table, (abfd, tabloc, tablen), - bfd *abfd AND - char **tabloc AND - unsigned int *tablen) + +/* Follows archive_head and produces an extended name table if + necessary. Returns (in tabloc) a pointer to an extended name + table, and in tablen the length of the table. If it makes an entry + it clobbers the filename so that the element may be written without + further massage. Returns true if it ran successfully, false if + something went wrong. A successful return may still involve a + zero-length tablen! */ + +static boolean +bfd_construct_extended_name_table (abfd, tabloc, tablen) + bfd *abfd; + char **tabloc; + unsigned int *tablen; { unsigned int maxname = abfd->xvec->ar_max_namelen; unsigned int total_namelen = 0; @@ -1060,103 +1176,127 @@ DEFUN (bfd_construct_extended_name_table, (abfd, tabloc, tablen), char *strptr; *tablen = 0; - + /* Figure out how long the table should be */ - for (current = abfd->archive_head; current != NULL; current = current->next){ - unsigned int thislen = strlen (normalize(current->filename)); - if (thislen > maxname) total_namelen += thislen + 1; /* leave room for \n */ - } + for (current = abfd->archive_head; current != NULL; current = current->next) + { + CONST char *normal = normalize (current->filename); + unsigned int thislen; + + if (!normal) + { + bfd_set_error (bfd_error_no_memory); + return false; + } + thislen = strlen (normal); + if (thislen > maxname) + total_namelen += thislen + 1; /* leave room for \n */ + } - if (total_namelen == 0) return true; + if (total_namelen == 0) + return true; - *tabloc = bfd_zalloc (abfd,total_namelen); - if (*tabloc == NULL) { - bfd_error = no_memory; - return false; - } + *tabloc = bfd_zalloc (abfd, total_namelen); + if (*tabloc == NULL) + { + bfd_set_error (bfd_error_no_memory); + return false; + } *tablen = total_namelen; strptr = *tabloc; for (current = abfd->archive_head; current != NULL; current = - current->next) { - CONST char *normal =normalize( current->filename); - unsigned int thislen = strlen (normal); - if (thislen > maxname) { - /* Works for now; may need to be re-engineered if we encounter an oddball - archive format and want to generalise this hack. */ - struct ar_hdr *hdr = arch_hdr(current); - strcpy (strptr, normal); - strptr[thislen] = '\n'; - hdr->ar_name[0] = ' '; - /* We know there will always be enough room (one of the few cases - where you may safely use sprintf). */ - sprintf ((hdr->ar_name) + 1, "%-d", (unsigned) (strptr - *tabloc)); - /* Kinda Kludgy. We should just use the returned value of sprintf - but not all implementations get this right */ + current->next) + { + CONST char *normal = normalize (current->filename); + unsigned int thislen; + + if (!normal) + { + bfd_set_error (bfd_error_no_memory); + return false; + } + thislen = strlen (normal); + if (thislen > maxname) { - char *temp = hdr->ar_name +2; - for (; temp < hdr->ar_name + maxname; temp++) - if (*temp == '\0') *temp = ' '; + /* Works for now; may need to be re-engineered if we + encounter an oddball archive format and want to + generalise this hack. */ + struct ar_hdr *hdr = arch_hdr (current); + strcpy (strptr, normal); + strptr[thislen] = '\012'; + hdr->ar_name[0] = ar_padchar (current); + /* We know there will always be enough room (one of the few + cases where you may safely use sprintf). */ + sprintf ((hdr->ar_name) + 1, "%-d", (unsigned) (strptr - *tabloc)); + /* Kinda Kludgy. We should just use the returned value of + sprintf but not all implementations get this right */ + { + char *temp = hdr->ar_name + 2; + for (; temp < hdr->ar_name + maxname; temp++) + if (*temp == '\0') + *temp = ' '; + } + strptr += thislen + 1; } - strptr += thislen + 1; } - } return true; } /** A couple of functions for creating ar_hdrs */ -/* Takes a filename, returns an arelt_data for it, or NULL if it can't make one. - The filename must refer to a filename in the filesystem. - The filename field of the ar_hdr will NOT be initialized -*/ +/* Takes a filename, returns an arelt_data for it, or NULL if it can't + make one. The filename must refer to a filename in the filesystem. + The filename field of the ar_hdr will NOT be initialized */ -struct areltdata * -DEFUN(bfd_ar_hdr_from_filesystem, (abfd,filename), - bfd* abfd AND - CONST char *filename) +static struct areltdata * +bfd_ar_hdr_from_filesystem (abfd, filename) + bfd *abfd; + const char *filename; { struct stat status; struct areltdata *ared; struct ar_hdr *hdr; char *temp, *temp1; + if (stat (filename, &status) != 0) + { + bfd_set_error (bfd_error_system_call); + return NULL; + } - if (stat (filename, &status) != 0) { - bfd_error = system_call_error; - return NULL; - } - - ared = (struct areltdata *) bfd_zalloc(abfd, sizeof (struct ar_hdr) + - sizeof (struct areltdata)); - if (ared == NULL) { - bfd_error = no_memory; - return NULL; - } + ared = (struct areltdata *) bfd_zalloc (abfd, sizeof (struct ar_hdr) + + sizeof (struct areltdata)); + if (ared == NULL) + { + bfd_set_error (bfd_error_no_memory); + return NULL; + } hdr = (struct ar_hdr *) (((char *) ared) + sizeof (struct areltdata)); /* ar headers are space padded, not null padded! */ - temp = (char *) hdr; - temp1 = temp + sizeof (struct ar_hdr) - 2; - for (; temp < temp1; *(temp++) = ' '); + memset ((PTR) hdr, ' ', sizeof (struct ar_hdr)); + strncpy (hdr->ar_fmag, ARFMAG, 2); - + /* Goddamned sprintf doesn't permit MAXIMUM field lengths */ - sprintf ((hdr->ar_date), "%-12ld", status.st_mtime); - sprintf ((hdr->ar_uid), "%d", status.st_uid); - sprintf ((hdr->ar_gid), "%d", status.st_gid); - sprintf ((hdr->ar_mode), "%-8o", (unsigned) status.st_mode); - sprintf ((hdr->ar_size), "%-10ld", status.st_size); + sprintf ((hdr->ar_date), "%-12ld", (long) status.st_mtime); + sprintf ((hdr->ar_uid), "%ld", (long) status.st_uid); + sprintf ((hdr->ar_gid), "%ld", (long) status.st_gid); + sprintf ((hdr->ar_mode), "%-8o", (unsigned int) status.st_mode); + sprintf ((hdr->ar_size), "%-10ld", (long) status.st_size); /* Correct for a lossage in sprintf whereby it null-terminates. I cannot understand how these C losers could design such a ramshackle bunch of IO operations */ temp = (char *) hdr; temp1 = temp + sizeof (struct ar_hdr) - 2; - for (; temp < temp1; temp++) { - if (*temp == '\0') *temp = ' '; - } + for (; temp < temp1; temp++) + { + if (*temp == '\0') + *temp = ' '; + } strncpy (hdr->ar_fmag, ARFMAG, 2); ared->parsed_size = status.st_size; ared->arch_header = (char *) hdr; @@ -1165,19 +1305,18 @@ DEFUN(bfd_ar_hdr_from_filesystem, (abfd,filename), } /* This is magic required by the "ar" program. Since it's - undocumented, it's undocumented. You may think that it would - take a strong stomach to write this, and it does, but it takes - even a stronger stomach to try to code around such a thing! -*/ + undocumented, it's undocumented. You may think that it would take + a strong stomach to write this, and it does, but it takes even a + stronger stomach to try to code around such a thing! */ struct ar_hdr * -DEFUN(bfd_special_undocumented_glue, (abfd, filename), - bfd *abfd AND - char *filename) +bfd_special_undocumented_glue (abfd, filename) + bfd *abfd; + char *filename; { struct areltdata *ar_elt = bfd_ar_hdr_from_filesystem (abfd, filename); if (ar_elt == NULL) - return NULL; + return NULL; return (struct ar_hdr *) ar_elt->arch_header; } @@ -1190,18 +1329,19 @@ bfd_generic_stat_arch_elt (abfd, buf) { struct ar_hdr *hdr; char *aloser; - - if (abfd->arelt_data == NULL) { - bfd_error = invalid_operation; - return -1; - } - + + if (abfd->arelt_data == NULL) + { + bfd_set_error (bfd_error_invalid_operation); + return -1; + } + hdr = arch_hdr (abfd); #define foo(arelt, stelt, size) \ buf->stelt = strtol (hdr->arelt, &aloser, size); \ if (aloser == hdr->arelt) return -1; - + foo (ar_date, st_mtime, 10); foo (ar_uid, st_uid, 10); foo (ar_gid, st_gid, 10); @@ -1222,10 +1362,10 @@ bfd_dont_truncate_arname (abfd, pathname, arhdr) Fortunately ic960 users will never use that option. Fixing this is very hard; fortunately I know how to do it and will do so once intel's release is out the door. */ - + struct ar_hdr *hdr = (struct ar_hdr *) arhdr; int length; - CONST char *filename = normalize(pathname); + CONST char *filename = normalize (pathname); int maxlen = ar_maxnamelen (abfd); length = strlen (filename); @@ -1233,9 +1373,8 @@ bfd_dont_truncate_arname (abfd, pathname, arhdr) if (length <= maxlen) memcpy (hdr->ar_name, filename, length); - if (length < maxlen) (hdr->ar_name)[length] = ar_padchar (abfd); - return; - + if (length < maxlen) + (hdr->ar_name)[length] = ar_padchar (abfd); } void @@ -1249,7 +1388,6 @@ bfd_bsd_truncate_arname (abfd, pathname, arhdr) CONST char *filename = strrchr (pathname, '/'); int maxlen = ar_maxnamelen (abfd); - if (filename == NULL) filename = pathname; else @@ -1259,23 +1397,26 @@ bfd_bsd_truncate_arname (abfd, pathname, arhdr) if (length <= maxlen) memcpy (hdr->ar_name, filename, length); - else { - /* pathname: meet procrustes */ - memcpy (hdr->ar_name, filename, maxlen); - length = maxlen; - } + else + { + /* pathname: meet procrustes */ + memcpy (hdr->ar_name, filename, maxlen); + length = maxlen; + } - if (length < maxlen) (hdr->ar_name)[length] = ar_padchar (abfd); + if (length < maxlen) + (hdr->ar_name)[length] = ar_padchar (abfd); } /* Store name into ar header. Truncates the name to fit. 1> strip pathname to be just the basename. 2> if it's short enuf to fit, stuff it in. 3> If it doesn't end with .o, truncate it to fit - 4> truncate it before the .o, append .o, stuff THAT in. -*/ + 4> truncate it before the .o, append .o, stuff THAT in. */ + +/* This is what gnu ar does. It's better but incompatible with the + bsd ar. */ -/* This is what gnu ar does. It's better but incompatible with the bsd ar. */ void bfd_gnu_truncate_arname (abfd, pathname, arhdr) bfd *abfd; @@ -1286,7 +1427,7 @@ bfd_gnu_truncate_arname (abfd, pathname, arhdr) int length; CONST char *filename = strrchr (pathname, '/'); int maxlen = ar_maxnamelen (abfd); - + if (filename == NULL) filename = pathname; else @@ -1296,20 +1437,23 @@ bfd_gnu_truncate_arname (abfd, pathname, arhdr) if (length <= maxlen) memcpy (hdr->ar_name, filename, length); - else { /* pathname: meet procrustes */ - memcpy (hdr->ar_name, filename, maxlen); - if ((filename[length - 2] == '.') && (filename[length - 1] == 'o')) { - hdr->ar_name[maxlen - 2] = '.'; - hdr->ar_name[maxlen - 1] = 'o'; + else + { /* pathname: meet procrustes */ + memcpy (hdr->ar_name, filename, maxlen); + if ((filename[length - 2] == '.') && (filename[length - 1] == 'o')) + { + hdr->ar_name[maxlen - 2] = '.'; + hdr->ar_name[maxlen - 1] = 'o'; + } + length = maxlen; } - length = maxlen; - } - if (length < 16) (hdr->ar_name)[length] = ar_padchar (abfd); + if (length < 16) + (hdr->ar_name)[length] = ar_padchar (abfd); } - /* The BFD is open for write and has its format set to bfd_archive */ + boolean _bfd_write_archive_contents (arch) bfd *arch; @@ -1319,231 +1463,305 @@ _bfd_write_archive_contents (arch) unsigned int elength = 0; boolean makemap = bfd_has_map (arch); boolean hasobjects = false; /* if no .o's, don't bother to make a map */ + bfd_size_type wrote; unsigned int i; int tries; /* Verify the viability of all entries; if any of them live in the filesystem (as opposed to living in an archive open for input) - then construct a fresh ar_hdr for them. - */ - for (current = arch->archive_head; current; current = current->next) { - if (bfd_write_p (current)) { - bfd_error = invalid_operation; - return false; - } - if (!current->arelt_data) { - current->arelt_data = - (PTR) bfd_ar_hdr_from_filesystem (arch, current->filename); - if (!current->arelt_data) return false; - - /* Put in the file name */ - - BFD_SEND (arch, _bfd_truncate_arname,(arch, - current->filename, - (char *) arch_hdr(current))); - - - } + then construct a fresh ar_hdr for them. */ + for (current = arch->archive_head; current; current = current->next) + { + if (bfd_write_p (current)) + { + bfd_set_error (bfd_error_invalid_operation); + return false; + } + if (!current->arelt_data) + { + current->arelt_data = + (PTR) bfd_ar_hdr_from_filesystem (arch, current->filename); + if (!current->arelt_data) + return false; + + /* Put in the file name */ + BFD_SEND (arch, _bfd_truncate_arname, (arch, + current->filename, + (char *) arch_hdr (current))); + } - if (makemap) { /* don't bother if we won't make a map! */ - if ((bfd_check_format (current, bfd_object)) + if (makemap && ! hasobjects) + { /* don't bother if we won't make a map! */ + if ((bfd_check_format (current, bfd_object)) #if 0 /* FIXME -- these are not set correctly */ - && ((bfd_get_file_flags (current) & HAS_SYMS)) + && ((bfd_get_file_flags (current) & HAS_SYMS)) #endif - ) - hasobjects = true; + ) + hasobjects = true; + } } - } if (!bfd_construct_extended_name_table (arch, &etable, &elength)) return false; - bfd_seek (arch, (file_ptr) 0, SEEK_SET); + if (bfd_seek (arch, (file_ptr) 0, SEEK_SET) != 0) + return false; #ifdef GNU960 - bfd_write (BFD_GNU960_ARMAG(arch), 1, SARMAG, arch); + wrote = bfd_write (BFD_GNU960_ARMAG (arch), 1, SARMAG, arch); #else - bfd_write (ARMAG, 1, SARMAG, arch); + wrote = bfd_write (ARMAG, 1, SARMAG, arch); #endif + if (wrote != SARMAG) + return false; - if (makemap && hasobjects) { + if (makemap && hasobjects) + { + if (compute_and_write_armap (arch, elength) != true) + return false; + } - if (compute_and_write_armap (arch, elength) != true) { - return false; + if (elength != 0) + { + struct ar_hdr hdr; + + memset ((char *) (&hdr), 0, sizeof (struct ar_hdr)); + if (ar_padchar (arch) == '/') + sprintf (&(hdr.ar_name[0]), "//"); + else + sprintf (&(hdr.ar_name[0]), "ARFILENAMES/"); + sprintf (&(hdr.ar_size[0]), "%-10d", (int) elength); + strncpy (hdr.ar_fmag, ARFMAG, 2); + for (i = 0; i < sizeof (struct ar_hdr); i++) + if (((char *) (&hdr))[i] == '\0') + (((char *) (&hdr))[i]) = ' '; + if ((bfd_write ((char *) &hdr, 1, sizeof (struct ar_hdr), arch) + != sizeof (struct ar_hdr)) + || bfd_write (etable, 1, elength, arch) != elength) + return false; + if ((elength % 2) == 1) + { + if (bfd_write ("\012", 1, 1, arch) != 1) + return false; + } } - } - - if (elength != 0) { - struct ar_hdr hdr; - - memset ((char *)(&hdr), 0, sizeof (struct ar_hdr)); - sprintf (&(hdr.ar_name[0]), "ARFILENAMES/"); - sprintf (&(hdr.ar_size[0]), "%-10d", (int) elength); - hdr.ar_fmag[0] = '`'; hdr.ar_fmag[1] = '\n'; - 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_write (etable, 1, elength, arch); - if ((elength % 2) == 1) bfd_write ("\n", 1, 1, arch); - - } - - for (current = arch->archive_head; current; current = current->next) { - char buffer[DEFAULT_BUFFERSIZE]; - unsigned int remaining = arelt_size (current); - struct ar_hdr *hdr = arch_hdr(current); - /* write ar header */ - - if (bfd_write ((char *)hdr, 1, sizeof(*hdr), arch) != sizeof(*hdr)) { - syserr: - bfd_error = system_call_error; + + for (current = arch->archive_head; current; current = current->next) + { + char buffer[DEFAULT_BUFFERSIZE]; + unsigned int remaining = arelt_size (current); + struct ar_hdr *hdr = arch_hdr (current); + + /* write ar header */ + if (bfd_write ((char *) hdr, 1, sizeof (*hdr), arch) != sizeof (*hdr)) return false; - } - if (bfd_seek (current, (file_ptr) 0, SEEK_SET) != 0) goto syserr; - while (remaining) + if (bfd_seek (current, (file_ptr) 0, SEEK_SET) != 0) + return false; + while (remaining) { unsigned int amt = DEFAULT_BUFFERSIZE; - if (amt > remaining) { + if (amt > remaining) amt = remaining; - } errno = 0; - if (bfd_read (buffer, amt, 1, current) != amt) { - if (errno) goto syserr; - /* Looks like a truncated archive. */ - bfd_error = malformed_archive; + if (bfd_read (buffer, amt, 1, current) != amt) + { + if (bfd_get_error () != bfd_error_system_call) + bfd_set_error (bfd_error_malformed_archive); return false; - } - if (bfd_write (buffer, amt, 1, arch) != amt) goto syserr; + } + if (bfd_write (buffer, amt, 1, arch) != amt) + return false; remaining -= amt; } - if ((arelt_size (current) % 2) == 1) bfd_write ("\n", 1, 1, arch); - } + if ((arelt_size (current) % 2) == 1) + { + if (bfd_write ("\012", 1, 1, arch) != 1) + return false; + } + } - /* Verify the timestamp in the archive file. If it would - not be accepted by the linker, rewrite it until it would be. - If anything odd happens, break out and just return. - (The Berkeley linker checks the timestamp and refuses to read the + /* Verify the timestamp in the archive file. If it would not be + accepted by the linker, rewrite it until it would be. If + anything odd happens, break out and just return. (The Berkeley + linker checks the timestamp and refuses to read the table-of-contents if it is >60 seconds less than the file's modified-time. That painful hack requires this painful hack. */ tries = 1; - do { - /* FIXME! This kludge is to avoid adding a member to the xvec, - while generating a small patch for Adobe. FIXME! The - update_armap_timestamp function call should be in the xvec, - thus: + do + { + /* FIXME! This kludge is to avoid adding a member to the xvec, + while generating a small patch for Adobe. FIXME! The + update_armap_timestamp function call should be in the xvec, + thus: if (bfd_update_armap_timestamp (arch) == true) break; ^ - Instead, we check whether in a BSD archive, and call directly. */ + Instead, we check whether in a BSD archive, and call + directly. */ - if (arch->xvec->write_armap != bsd_write_armap) + if (arch->xvec->write_armap != bsd_write_armap) break; - if (bsd_update_armap_timestamp(arch) == true) /* FIXME!!! Vector it */ + if (bsd_update_armap_timestamp (arch) == true) /* FIXME!!! Vector it */ break; - if (tries > 0) + if (tries > 0) fprintf (stderr, - "Warning: writing archive was slow: rewriting timestamp\n"); - } while (++tries < 6 ); + "Warning: writing archive was slow: rewriting timestamp\n"); + } + while (++tries < 6); return true; } /* Note that the namidx for the first symbol is 0 */ -boolean +static boolean compute_and_write_armap (arch, elength) bfd *arch; unsigned int elength; { - bfd *current; - file_ptr elt_no = 0; - struct orl *map; - int orl_max = 15000; /* fine initial default */ - int orl_count = 0; - int stridx = 0; /* string index */ - - /* Dunno if this is the best place for this info... */ - if (elength != 0) elength += sizeof (struct ar_hdr); - elength += elength %2 ; - - map = (struct orl *) bfd_zalloc (arch,orl_max * sizeof (struct orl)); - if (map == NULL) { - bfd_error = no_memory; - return false; - } - - /* Drop all the files called __.SYMDEF, we're going to make our - own */ - while (arch->archive_head && - strcmp(arch->archive_head->filename,"__.SYMDEF") == 0) - { - arch->archive_head = arch->archive_head->next; - } - /* Map over each element */ - for (current = arch->archive_head; - current != (bfd *)NULL; - current = current->next, elt_no++) + char *first_name = NULL; + bfd *current; + file_ptr elt_no = 0; + struct orl *map = NULL; + int orl_max = 1024; /* fine initial default */ + int orl_count = 0; + int stridx = 0; /* string index */ + asymbol **syms = NULL; + long syms_max = 0; + boolean ret; + + /* Dunno if this is the best place for this info... */ + if (elength != 0) + elength += sizeof (struct ar_hdr); + elength += elength % 2; + + map = (struct orl *) malloc (orl_max * sizeof (struct orl)); + if (map == NULL) + goto no_memory_return; + + /* We put the symbol names on the arch obstack, and then discard + them when done. */ + first_name = bfd_alloc (arch, 1); + if (first_name == NULL) + goto no_memory_return; + + /* Drop all the files called __.SYMDEF, we're going to make our + own */ + while (arch->archive_head && + strcmp (arch->archive_head->filename, "__.SYMDEF") == 0) + arch->archive_head = arch->archive_head->next; + + /* Map over each element */ + for (current = arch->archive_head; + current != (bfd *) NULL; + current = current->next, elt_no++) { - if ((bfd_check_format (current, bfd_object) == true) - && ((bfd_get_file_flags (current) & HAS_SYMS))) { - asymbol **syms; - unsigned int storage; - unsigned int symcount; - unsigned int src_count; - - storage = get_symtab_upper_bound (current); - if (storage != 0) { - - syms = (asymbol **) bfd_zalloc (arch,storage); - if (syms == NULL) { - bfd_error = no_memory; /* FIXME -- memory leak */ - return false; - } - symcount = bfd_canonicalize_symtab (current, syms); - - - /* Now map over all the symbols, picking out the ones we want */ - for (src_count = 0; src_count <symcount; src_count++) { - flagword flags = - (syms[src_count])->flags; - asection *sec = - syms[src_count]->section; - - if ((flags & BSF_GLOBAL || - flags & BSF_WEAK || - flags & BSF_INDIRECT || - bfd_is_com_section (sec)) - && (sec != &bfd_und_section)) { - - /* This symbol will go into the archive header */ - if (orl_count == orl_max) - { - orl_max *= 2; - map = (struct orl *) bfd_realloc (arch, (char *) map, - orl_max * sizeof (struct orl)); - } - - (map[orl_count]).name = (char **) &((syms[src_count])->name); - (map[orl_count]).pos = (file_ptr) current; - (map[orl_count]).namidx = stridx; - - stridx += strlen ((syms[src_count])->name) + 1; - ++orl_count; - } - } + if ((bfd_check_format (current, bfd_object) == true) + && ((bfd_get_file_flags (current) & HAS_SYMS))) + { + long storage; + long symcount; + long src_count; + + storage = bfd_get_symtab_upper_bound (current); + if (storage < 0) + goto error_return; + + if (storage != 0) + { + if (storage > syms_max) + { + if (syms_max > 0) + free (syms); + syms_max = storage; + syms = (asymbol **) malloc ((size_t) syms_max); + if (syms == NULL) + goto no_memory_return; + } + symcount = bfd_canonicalize_symtab (current, syms); + if (symcount < 0) + goto error_return; + + /* Now map over all the symbols, picking out the ones we want */ + for (src_count = 0; src_count < symcount; src_count++) + { + flagword flags = (syms[src_count])->flags; + asection *sec = syms[src_count]->section; + + if ((flags & BSF_GLOBAL || + flags & BSF_WEAK || + flags & BSF_INDIRECT || + bfd_is_com_section (sec)) + && ! bfd_is_und_section (sec)) + { + size_t namelen; + struct orl *new_map; + + /* This symbol will go into the archive header */ + if (orl_count == orl_max) + { + orl_max *= 2; + new_map = ((struct orl *) + realloc ((PTR) map, + orl_max * sizeof (struct orl))); + if (new_map == (struct orl *) NULL) + goto no_memory_return; + + map = new_map; + } + + namelen = strlen (syms[src_count]->name); + map[orl_count].name = ((char **) + bfd_alloc (arch, + sizeof (char *))); + if (map[orl_count].name == NULL) + goto no_memory_return; + *(map[orl_count].name) = bfd_alloc (arch, namelen + 1); + if (*(map[orl_count].name) == NULL) + goto no_memory_return; + strcpy (*(map[orl_count].name), syms[src_count]->name); + (map[orl_count]).pos = (file_ptr) current; + (map[orl_count]).namidx = stridx; + + stridx += namelen + 1; + ++orl_count; } + } } - } - /* OK, now we have collected all the data, let's write them out */ - if (!BFD_SEND (arch, write_armap, - (arch, elength, map, orl_count, stridx))) { - return false; + /* Now ask the BFD to free up any cached information, so we + don't fill all of memory with symbol tables. */ + if (! bfd_free_cached_info (current)) + goto error_return; } + } + /* OK, now we have collected all the data, let's write them out */ + ret = BFD_SEND (arch, write_armap, + (arch, elength, map, orl_count, stridx)); - return true; + if (syms_max > 0) + free (syms); + if (map != NULL) + free (map); + if (first_name != NULL) + bfd_release (arch, first_name); + + return ret; + + no_memory_return: + bfd_set_error (bfd_error_no_memory); + + error_return: + if (syms_max > 0) + free (syms); + if (map != NULL) + free (map); + if (first_name != NULL) + bfd_release (arch, first_name); + + return false; } boolean @@ -1571,58 +1789,75 @@ bsd_write_armap (arch, elength, map, orl_count, stridx) firstreal = mapsize + elength + sizeof (struct ar_hdr) + SARMAG; stat (arch->filename, &statbuf); - memset ((char *)(&hdr), 0, sizeof (struct ar_hdr)); + memset ((char *) (&hdr), 0, sizeof (struct ar_hdr)); sprintf (hdr.ar_name, RANLIBMAG); /* Remember the timestamp, to keep it holy. But fudge it a little. */ - bfd_ardata(arch)->armap_timestamp = statbuf.st_mtime + ARMAP_TIME_OFFSET; - bfd_ardata(arch)->armap_datepos = SARMAG + - offsetof(struct ar_hdr, ar_date[0]); - sprintf (hdr.ar_date, "%ld", bfd_ardata(arch)->armap_timestamp); - sprintf (hdr.ar_uid, "%d", getuid()); - sprintf (hdr.ar_gid, "%d", getgid()); + bfd_ardata (arch)->armap_timestamp = statbuf.st_mtime + ARMAP_TIME_OFFSET; + bfd_ardata (arch)->armap_datepos = (SARMAG + + offsetof (struct ar_hdr, ar_date[0])); + sprintf (hdr.ar_date, "%ld", bfd_ardata (arch)->armap_timestamp); + sprintf (hdr.ar_uid, "%d", getuid ()); + sprintf (hdr.ar_gid, "%d", getgid ()); sprintf (hdr.ar_size, "%-10d", (int) mapsize); - hdr.ar_fmag[0] = '`'; hdr.ar_fmag[1] = '\n'; + strncpy (hdr.ar_fmag, ARFMAG, 2); 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, (bfd_vma) ranlibsize, (PTR)&temp); - bfd_write (&temp, 1, sizeof (temp), arch); - - for (count = 0; count < orl_count; count++) { - struct symdef outs; - struct symdef *outp = &outs; - - if (((bfd *)(map[count]).pos) != last_elt) { - do { - firstreal += arelt_size (current) + sizeof (struct ar_hdr); - firstreal += firstreal % 2; - current = current->next; - } while (current != (bfd *)(map[count]).pos); - } /* if new archive element */ + if (((char *) (&hdr))[i] == '\0') + (((char *) (&hdr))[i]) = ' '; + if (bfd_write ((char *) &hdr, 1, sizeof (struct ar_hdr), arch) + != sizeof (struct ar_hdr)) + return false; + bfd_h_put_32 (arch, (bfd_vma) ranlibsize, (PTR) &temp); + if (bfd_write (&temp, 1, sizeof (temp), arch) != sizeof (temp)) + return false; - last_elt = current; - 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); - } + for (count = 0; count < orl_count; count++) + { + struct symdef outs; + struct symdef *outp = &outs; + + if (((bfd *) (map[count]).pos) != last_elt) + { + do + { + firstreal += arelt_size (current) + sizeof (struct ar_hdr); + firstreal += firstreal % 2; + current = current->next; + } + while (current != (bfd *) (map[count]).pos); + } /* if new archive element */ + + last_elt = current; + bfd_h_put_32 (arch, ((map[count]).namidx), (PTR) &outs.s.string_offset); + bfd_h_put_32 (arch, firstreal, (PTR) &outs.file_offset); + if (bfd_write ((char *) outp, 1, sizeof (outs), arch) != sizeof (outs)) + return false; + } /* now write the strings themselves */ - bfd_h_put_32(arch, stringsize, (PTR)&temp); - bfd_write ((PTR)&temp, 1, sizeof (temp), arch); + bfd_h_put_32 (arch, stringsize, (PTR) &temp); + if (bfd_write ((PTR) &temp, 1, sizeof (temp), arch) != sizeof (temp)) + return false; for (count = 0; count < orl_count; count++) - bfd_write (*((map[count]).name), 1, strlen (*((map[count]).name))+1, arch); + { + size_t len = strlen (*map[count].name) + 1; + + if (bfd_write (*map[count].name, 1, len, arch) != len) + return false; + } /* The spec sez this should be a newline. But in order to be bug-compatible for sun's ar we use a null. */ if (padit) - bfd_write("\0",1,1,arch); + { + if (bfd_write ("", 1, 1, arch) != 1) + return false; + } return true; } - /* At the end of archive file handling, update the timestamp in the - file, so the linker will accept it. + file, so the linker will accept it. Return true if the timestamp was OK, or an unusual problem happened. Return false if we updated the timestamp. */ @@ -1638,48 +1873,49 @@ bsd_update_armap_timestamp (arch) /* Flush writes, get last-write timestamp from file, and compare it to the timestamp IN the file. */ bfd_flush (arch); - if (bfd_stat (arch, &archstat) == -1) { - perror ("Reading archive file mod timestamp"); - return true; /* Can't read mod time for some reason */ - } - if (archstat.st_mtime <= bfd_ardata(arch)->armap_timestamp) + if (bfd_stat (arch, &archstat) == -1) + { + perror ("Reading archive file mod timestamp"); + return true; /* Can't read mod time for some reason */ + } + if (archstat.st_mtime <= bfd_ardata (arch)->armap_timestamp) return true; /* OK by the linker's rules */ /* Update the timestamp. */ - bfd_ardata(arch)->armap_timestamp = archstat.st_mtime + ARMAP_TIME_OFFSET; + bfd_ardata (arch)->armap_timestamp = archstat.st_mtime + ARMAP_TIME_OFFSET; /* Prepare an ASCII version suitable for writing. */ memset (hdr.ar_date, 0, sizeof (hdr.ar_date)); - sprintf (hdr.ar_date, "%ld", bfd_ardata(arch)->armap_timestamp); + sprintf (hdr.ar_date, "%ld", bfd_ardata (arch)->armap_timestamp); for (i = 0; i < sizeof (hdr.ar_date); i++) - if (hdr.ar_date[i] == '\0') - (hdr.ar_date)[i] = ' '; + if (hdr.ar_date[i] == '\0') + (hdr.ar_date)[i] = ' '; /* Write it into the file. */ - bfd_seek (arch, bfd_ardata(arch)->armap_datepos, SEEK_SET); - if (bfd_write (hdr.ar_date, sizeof(hdr.ar_date), 1, arch) - != sizeof(hdr.ar_date)) { - perror ("Writing updated armap timestamp"); - return true; /* Some error while writing */ - } + if (bfd_seek (arch, bfd_ardata (arch)->armap_datepos, SEEK_SET) != 0 + || (bfd_write (hdr.ar_date, sizeof (hdr.ar_date), 1, arch) + != sizeof (hdr.ar_date))) + { + /* FIXME: bfd can't call perror. */ + perror ("Writing updated armap timestamp"); + return true; /* Some error while writing */ + } return false; /* We updated the timestamp successfully. */ } - /* A coff armap looks like : - lARMAG - struct ar_hdr with name = '/' - number of symbols - offset of file for symbol 0 - offset of file for symbol 1 - - offset of file for symbol n-1 - symbol name 0 - symbol name 1 - - symbol name n-1 + lARMAG + struct ar_hdr with name = '/' + number of symbols + offset of file for symbol 0 + offset of file for symbol 1 + + offset of file for symbol n-1 + symbol name 0 + symbol name 1 + symbol name n-1 */ boolean @@ -1690,81 +1926,91 @@ coff_write_armap (arch, elength, map, symbol_count, stridx) unsigned int symbol_count; int stridx; { - /* The size of the ranlib is the number of exported symbols in the - archive * the number of bytes in a int, + an int for the count */ - - unsigned int ranlibsize = (symbol_count * 4) + 4; - unsigned int stringsize = stridx; - unsigned int mapsize = stringsize + ranlibsize; - file_ptr archive_member_file_ptr; - bfd *current = arch->archive_head; - int count; - struct ar_hdr hdr; - unsigned int i; - int padit = mapsize & 1; - - if (padit) mapsize ++; - - /* work out where the first object file will go in the archive */ - archive_member_file_ptr = mapsize + elength + sizeof (struct ar_hdr) + SARMAG; - - memset ((char *)(&hdr), 0, sizeof (struct ar_hdr)); - hdr.ar_name[0] = '/'; - sprintf (hdr.ar_size, "%-10d", (int) mapsize); - sprintf (hdr.ar_date, "%ld", (long)time (NULL)); - /* This, at least, is what Intel coff sets the values to.: */ - sprintf ((hdr.ar_uid), "%d", 0); - sprintf ((hdr.ar_gid), "%d", 0); - sprintf ((hdr.ar_mode), "%-7o",(unsigned ) 0); - hdr.ar_fmag[0] = '`'; hdr.ar_fmag[1] = '\n'; - - for (i = 0; i < sizeof (struct ar_hdr); i++) - if (((char *)(&hdr))[i] == '\0') (((char *)(&hdr))[i]) = ' '; - - /* Write the ar header for this item and the number of symbols */ - - - bfd_write ((PTR)&hdr, 1, sizeof (struct ar_hdr), arch); - - bfd_write_bigendian_4byte_int(arch, symbol_count); - - /* Two passes, first write the file offsets for each symbol - - remembering that each offset is on a two byte boundary. */ - - /* Write out the file offset for the file associated with each - symbol, and remember to keep the offsets padded out. */ - - current = arch->archive_head; - count = 0; - while (current != (bfd *)NULL && count < symbol_count) { - /* For each symbol which is used defined in this object, write out - the object file's address in the archive */ - - while (((bfd *)(map[count]).pos) == current) { - bfd_write_bigendian_4byte_int(arch, archive_member_file_ptr); - count++; - } - /* Add size of this archive entry */ - archive_member_file_ptr += arelt_size (current) + sizeof (struct - ar_hdr); - /* remember aboout the even alignment */ - archive_member_file_ptr += archive_member_file_ptr % 2; - current = current->next; - } + /* The size of the ranlib is the number of exported symbols in the + archive * the number of bytes in a int, + an int for the count */ + unsigned int ranlibsize = (symbol_count * 4) + 4; + unsigned int stringsize = stridx; + unsigned int mapsize = stringsize + ranlibsize; + file_ptr archive_member_file_ptr; + bfd *current = arch->archive_head; + int count; + struct ar_hdr hdr; + unsigned int i; + int padit = mapsize & 1; + + if (padit) + mapsize++; + + /* work out where the first object file will go in the archive */ + archive_member_file_ptr = (mapsize + + elength + + sizeof (struct ar_hdr) + + SARMAG); + + memset ((char *) (&hdr), 0, sizeof (struct ar_hdr)); + hdr.ar_name[0] = '/'; + sprintf (hdr.ar_size, "%-10d", (int) mapsize); + sprintf (hdr.ar_date, "%ld", (long) time (NULL)); + /* This, at least, is what Intel coff sets the values to.: */ + sprintf ((hdr.ar_uid), "%d", 0); + sprintf ((hdr.ar_gid), "%d", 0); + sprintf ((hdr.ar_mode), "%-7o", (unsigned) 0); + strncpy (hdr.ar_fmag, ARFMAG, 2); + for (i = 0; i < sizeof (struct ar_hdr); i++) + if (((char *) (&hdr))[i] == '\0') + (((char *) (&hdr))[i]) = ' '; + + /* Write the ar header for this item and the number of symbols */ + + if (bfd_write ((PTR) &hdr, 1, sizeof (struct ar_hdr), arch) + != sizeof (struct ar_hdr)) + return false; + + bfd_write_bigendian_4byte_int (arch, symbol_count); + + /* Two passes, first write the file offsets for each symbol - + remembering that each offset is on a two byte boundary. */ + /* Write out the file offset for the file associated with each + symbol, and remember to keep the offsets padded out. */ - /* now write the strings themselves */ - for (count = 0; count < symbol_count; count++) { - bfd_write ((PTR)*((map[count]).name), - 1, - strlen (*((map[count]).name))+1, arch); + current = arch->archive_head; + count = 0; + while (current != (bfd *) NULL && count < symbol_count) + { + /* For each symbol which is used defined in this object, write out + the object file's address in the archive */ + while (((bfd *) (map[count]).pos) == current) + { + bfd_write_bigendian_4byte_int (arch, archive_member_file_ptr); + count++; + } + /* Add size of this archive entry */ + archive_member_file_ptr += (arelt_size (current) + + sizeof (struct ar_hdr)); + /* remember aboout the even alignment */ + archive_member_file_ptr += archive_member_file_ptr % 2; + current = current->next; } - /* The spec sez this should be a newline. But in order to be - bug-compatible for arc960 we use a null. */ - if (padit) - bfd_write("\0",1,1,arch); - return true; + /* now write the strings themselves */ + for (count = 0; count < symbol_count; count++) + { + size_t len = strlen (*map[count].name) + 1; + + if (bfd_write (*map[count].name, 1, len, arch) != len) + return false; + } + + /* The spec sez this should be a newline. But in order to be + bug-compatible for arc960 we use a null. */ + if (padit) + { + if (bfd_write ("", 1, 1, arch) != 1) + return false; + } + + return true; } diff --git a/gnu/usr.bin/gdb/bfd/archures.c b/gnu/usr.bin/gdb/bfd/archures.c index 9697904bd733..1bed6379927f 100644 --- a/gnu/usr.bin/gdb/bfd/archures.c +++ b/gnu/usr.bin/gdb/bfd/archures.c @@ -1,8 +1,7 @@ /* BFD library support routines for architectures. - Copyright (C) 1990-1991 Free Software Foundation, Inc. + Copyright (C) 1990, 91, 92, 93, 94 Free Software Foundation, Inc. Hacked by John Gilmore and Steve Chamberlain of Cygnus Support. - This file is part of BFD, the Binary File Descriptor library. This program is free software; you can redistribute it and/or modify @@ -24,19 +23,18 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ SECTION Architectures - BFD's idea of an architecture is implimented in - <<archures.c>>. BFD keeps one atom in a BFD describing the - architecture of the data attached to the BFD; a pointer to a + BFD keeps one atom in a BFD describing the + architecture of the data attached to the BFD: a pointer to a <<bfd_arch_info_type>>. - Pointers to structures can be requested independently of a bfd + Pointers to structures can be requested independently of a BFD so that an architecture's information can be interrogated - without access to an open bfd. + without access to an open BFD. - The arch information is provided by each architecture package. - The set of default architectures is selected by the #define + The architecture information is provided by each architecture package. + The set of default architectures is selected by the macro <<SELECT_ARCHITECTURES>>. This is normally set up in the - <<config/target.mt>> file of your choice. If the name is not + @file{config/@var{target}.mt} file of your choice. If the name is not defined, then all the architectures supported are included. When BFD starts up, all the architectures are called with an @@ -44,6 +42,8 @@ SECTION insert as many items into the list of architectures as it wants to; generally this would be one for each machine and one for the default case (an item with a machine field of 0). + + BFD's idea of an architecture is implemented in @file{archures.c}. */ /* @@ -53,11 +53,11 @@ SUBSECTION DESCRIPTION This enum gives the object file's CPU architecture, in a - global sense --- i.e., what processor family does it belong to? - There is another field, which indicates what processor within + global sense---i.e., what processor family does it belong to? + Another field indicates which processor within the family is in use. The machine gives a number which - distingushes different versions of the architecture, - containing for example 2 and 3 for Intel i960 KA and i960 KB, + distinguishes different versions of the architecture, + containing, for example, 2 and 3 for Intel i960 KA and i960 KB, and 68020 and 68030 for Motorola 68020 and 68030. .enum bfd_architecture @@ -97,6 +97,7 @@ DESCRIPTION . bfd_arch_h8300, {* Hitachi H8/300 *} .#define bfd_mach_h8300 1 .#define bfd_mach_h8300h 2 +. bfd_arch_powerpc, {* PowerPC *} . bfd_arch_rs6000, {* IBM RS/6000 *} . bfd_arch_hppa, {* HP PA RISC *} . bfd_arch_z8k, {* Zilog Z8000 *} @@ -105,6 +106,7 @@ DESCRIPTION . bfd_arch_h8500, {* Hitachi H8/500 *} . bfd_arch_sh, {* Hitachi SH *} . bfd_arch_alpha, {* Dec Alpha *} +. bfd_arch_ns32k, {* National Semiconductors ns32000 *} . bfd_arch_last . }; @@ -166,13 +168,13 @@ SYNOPSIS DESCRIPTION Return a printable string representing the architecture and machine - from the pointer to the arch info structure + from the pointer to the architecture info structure. */ CONST char * -DEFUN(bfd_printable_name, (abfd), - bfd *abfd) +bfd_printable_name (abfd) + bfd *abfd; { return abfd->arch_info->printable_name; } @@ -184,19 +186,18 @@ FUNCTION bfd_scan_arch SYNOPSIS - bfd_arch_info_type *bfd_scan_arch(CONST char *); + bfd_arch_info_type *bfd_scan_arch(CONST char *string); DESCRIPTION - This routine is provided with a string and tries to work out - if bfd supports any cpu which could be described with the name - provided. The routine returns a pointer to an arch_info + Figure out if BFD supports any cpu which could be described with + the name @var{string}. Return a pointer to an <<arch_info>> structure if a machine is found, otherwise NULL. */ bfd_arch_info_type * -DEFUN(bfd_scan_arch,(string), - CONST char *string) +bfd_scan_arch (string) + CONST char *string; { struct bfd_arch_info *ap; @@ -223,18 +224,17 @@ SYNOPSIS CONST bfd *bbfd); DESCRIPTION - This routine is used to determine whether two BFDs' - architectures and achine types are compatible. It calculates + Determine whether two BFDs' + architectures and machine types are compatible. Calculates the lowest common denominator between the two architectures and machine types implied by the BFDs and returns a pointer to - an arch_info structure describing the compatible machine. + an <<arch_info>> structure describing the compatible machine. */ CONST bfd_arch_info_type * -DEFUN(bfd_arch_get_compatible,(abfd, bbfd), -CONST bfd *abfd AND -CONST bfd *bbfd) - +bfd_arch_get_compatible (abfd, bbfd) + CONST bfd *abfd; + CONST bfd *bbfd; { return abfd->arch_info->compatible(abfd->arch_info,bbfd->arch_info); } @@ -268,13 +268,16 @@ FUNCTION bfd_set_arch_info SYNOPSIS - void bfd_set_arch_info(bfd *, bfd_arch_info_type *); + void bfd_set_arch_info(bfd *abfd, bfd_arch_info_type *arg); +DESCRIPTION + Set the architecture info of @var{abfd} to @var{arg}. */ -void DEFUN(bfd_set_arch_info,(abfd, arg), -bfd *abfd AND -bfd_arch_info_type *arg) +void +bfd_set_arch_info (abfd, arg) + bfd *abfd; + bfd_arch_info_type *arg; { abfd->arch_info = arg; } @@ -289,15 +292,17 @@ SYNOPSIS unsigned long mach); DESCRIPTION - Set the architecture and machine type in a bfd. This finds the - correct pointer to structure and inserts it into the arch_info + Set the architecture and machine type in BFD @var{abfd} + to @var{arch} and @var{mach}. Find the correct + pointer to a structure and insert it into the <<arch_info>> pointer. */ -boolean DEFUN(bfd_default_set_arch_mach,(abfd, arch, mach), - bfd *abfd AND - enum bfd_architecture arch AND - unsigned long mach) +boolean +bfd_default_set_arch_mach (abfd, arch, mach) + bfd *abfd; + enum bfd_architecture arch; + unsigned long mach; { static struct bfd_arch_info *old_ptr = &bfd_default_arch_struct; boolean found = false; @@ -319,7 +324,7 @@ boolean DEFUN(bfd_default_set_arch_mach,(abfd, arch, mach), if (found==false) { /*looked for it and it wasn't there, so put in the default */ old_ptr = &bfd_default_arch_struct; - bfd_error = bad_value; + bfd_set_error (bfd_error_bad_value); } } else { @@ -333,9 +338,6 @@ boolean DEFUN(bfd_default_set_arch_mach,(abfd, arch, mach), } - - - /* FUNCTION bfd_get_arch @@ -344,12 +346,14 @@ SYNOPSIS enum bfd_architecture bfd_get_arch(bfd *abfd); DESCRIPTION - Returns the enumerated type which describes the supplied bfd's - architecture + Return the enumerated type which describes the BFD @var{abfd}'s + architecture. */ -enum bfd_architecture DEFUN(bfd_get_arch, (abfd), bfd *abfd) +enum bfd_architecture +bfd_get_arch (abfd) + bfd *abfd; { return abfd->arch_info->arch; } @@ -362,12 +366,13 @@ SYNOPSIS unsigned long bfd_get_mach(bfd *abfd); DESCRIPTION - Returns the long type which describes the supplied bfd's - machine + Return the long type which describes the BFD @var{abfd}'s + machine. */ unsigned long -DEFUN(bfd_get_mach, (abfd), bfd *abfd) +bfd_get_mach (abfd) + bfd *abfd; { return abfd->arch_info->mach; } @@ -380,14 +385,17 @@ SYNOPSIS unsigned int bfd_arch_bits_per_byte(bfd *abfd); DESCRIPTION - Returns the number of bits in one of the architectures bytes + Return the number of bits in one of the BFD @var{abfd}'s + architecture's bytes. */ -unsigned int DEFUN(bfd_arch_bits_per_byte, (abfd), bfd *abfd) - { - return abfd->arch_info->bits_per_byte; - } +unsigned int +bfd_arch_bits_per_byte (abfd) + bfd *abfd; +{ + return abfd->arch_info->bits_per_byte; +} /* FUNCTION @@ -397,13 +405,16 @@ SYNOPSIS unsigned int bfd_arch_bits_per_address(bfd *abfd); DESCRIPTION - Returns the number of bits in one of the architectures addresses + Return the number of bits in one of the BFD @var{abfd}'s + architecture's addresses. */ -unsigned int DEFUN(bfd_arch_bits_per_address, (abfd), bfd *abfd) - { - return abfd->arch_info->bits_per_address; - } +unsigned int +bfd_arch_bits_per_address (abfd) + bfd *abfd; +{ + return abfd->arch_info->bits_per_address; +} extern void bfd_a29k_arch PARAMS ((void)); @@ -416,12 +427,14 @@ extern void bfd_i960_arch PARAMS ((void)); extern void bfd_m68k_arch PARAMS ((void)); extern void bfd_m88k_arch PARAMS ((void)); extern void bfd_mips_arch PARAMS ((void)); +extern void bfd_powerpc_arch PARAMS ((void)); extern void bfd_rs6000_arch PARAMS ((void)); extern void bfd_sh_arch PARAMS ((void)); extern void bfd_sparc_arch PARAMS ((void)); extern void bfd_vax_arch PARAMS ((void)); extern void bfd_we32k_arch PARAMS ((void)); extern void bfd_z8k_arch PARAMS ((void)); +extern void bfd_ns32k_arch PARAMS ((void)); static void (*archures_init_table[]) PARAMS ((void)) = { @@ -438,12 +451,14 @@ static void (*archures_init_table[]) PARAMS ((void)) = bfd_m68k_arch, bfd_m88k_arch, bfd_mips_arch, + bfd_powerpc_arch, bfd_rs6000_arch, bfd_sh_arch, bfd_sparc_arch, bfd_vax_arch, bfd_we32k_arch, bfd_z8k_arch, + bfd_ns32k_arch, #endif 0 }; @@ -455,16 +470,16 @@ INTERNAL_FUNCTION bfd_arch_init SYNOPSIS - void bfd_arch_init(void); + void bfd_arch_init(void); DESCRIPTION - This routine initializes the architecture dispatch table by + Initialize the architecture dispatch table by calling all installed architecture packages and getting them to poke around. */ void -DEFUN_VOID(bfd_arch_init) +bfd_arch_init () { void (**ptable) PARAMS ((void)); for (ptable = archures_init_table; @@ -481,14 +496,15 @@ INTERNAL_FUNCTION bfd_arch_linkin SYNOPSIS - void bfd_arch_linkin(bfd_arch_info_type *); + void bfd_arch_linkin(bfd_arch_info_type *ptr); DESCRIPTION - Link the provided arch info structure into the list + Link the architecture info structure @var{ptr} into the list. */ -void DEFUN(bfd_arch_linkin,(ptr), - bfd_arch_info_type *ptr) +void +bfd_arch_linkin (ptr) + bfd_arch_info_type *ptr; { ptr->next = bfd_arch_info_list; bfd_arch_info_list = ptr; @@ -509,9 +525,9 @@ DESCRIPTION */ CONST bfd_arch_info_type * -DEFUN(bfd_default_compatible,(a,b), - CONST bfd_arch_info_type *a AND - CONST bfd_arch_info_type *b) +bfd_default_compatible (a,b) + CONST bfd_arch_info_type *a; + CONST bfd_arch_info_type *b; { if(a->arch != b->arch) return NULL; @@ -530,7 +546,7 @@ INTERNAL_FUNCTION bfd_default_scan SYNOPSIS - boolean bfd_default_scan(CONST struct bfd_arch_info *, CONST char *); + boolean bfd_default_scan(CONST struct bfd_arch_info *info, CONST char *string); DESCRIPTION The default function for working out whether this is an @@ -538,9 +554,9 @@ DESCRIPTION */ boolean -DEFUN(bfd_default_scan,(info, string), -CONST struct bfd_arch_info *info AND -CONST char *string) +bfd_default_scan (info, string) + CONST struct bfd_arch_info *info; + CONST char *string; { CONST char *ptr_src; CONST char *ptr_tst; @@ -647,21 +663,20 @@ CONST char *string) } - - /* FUNCTION bfd_get_arch_info - SYNOPSIS - bfd_arch_info_type * bfd_get_arch_info(bfd *); + bfd_arch_info_type * bfd_get_arch_info(bfd *abfd); +DESCRIPTION + Return the architecture info struct in @var{abfd}. */ bfd_arch_info_type * -DEFUN(bfd_get_arch_info,(abfd), -bfd *abfd) +bfd_get_arch_info (abfd) + bfd *abfd; { return abfd->arch_info; } @@ -678,16 +693,16 @@ SYNOPSIS long machine); DESCRIPTION - Look for the architecure info struct which matches the - arguments given. A machine of 0 will match the + Look for the architecure info structure which matches the + arguments @var{arch} and @var{machine}. A machine of 0 matches the machine/architecture structure which marks itself as the default. */ bfd_arch_info_type * -DEFUN(bfd_lookup_arch,(arch, machine), -enum bfd_architecture arch AND -long machine) +bfd_lookup_arch (arch, machine) + enum bfd_architecture arch; + long machine; { bfd_arch_info_type *ap; bfd_check_init(); @@ -704,26 +719,25 @@ long machine) } - /* FUNCTION bfd_printable_arch_mach SYNOPSIS - CONST char * bfd_printable_arch_mach + CONST char *bfd_printable_arch_mach (enum bfd_architecture arch, unsigned long machine); DESCRIPTION Return a printable string representing the architecture and machine type. - NB. The use of this routine is depreciated. + This routine is depreciated. */ CONST char * -DEFUN(bfd_printable_arch_mach,(arch, machine), - enum bfd_architecture arch AND - unsigned long machine) +bfd_printable_arch_mach (arch, machine) + enum bfd_architecture arch; + unsigned long machine; { bfd_arch_info_type *ap = bfd_lookup_arch(arch, machine); if(ap) return ap->printable_name; diff --git a/gnu/usr.bin/gdb/bfd/bfd.c b/gnu/usr.bin/gdb/bfd/bfd.c index a994cd170a00..77e43ec3266f 100644 --- a/gnu/usr.bin/gdb/bfd/bfd.c +++ b/gnu/usr.bin/gdb/bfd/bfd.c @@ -1,5 +1,5 @@ /* Generic BFD library interface and support routines. - Copyright (C) 1990, 1991, 1992, 1993 Free Software Foundation, Inc. + Copyright (C) 1990, 91, 92, 93, 94 Free Software Foundation, Inc. Written by Cygnus Support. This file is part of BFD, the Binary File Descriptor library. @@ -22,13 +22,12 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ SECTION <<typedef bfd>> - A BFD is has type <<bfd>>; objects of this type are the - cornerstone of any application using <<libbfd>>. References - though the BFD and to data in the BFD give the entire BFD - functionality. + A BFD has type <<bfd>>; objects of this type are the + cornerstone of any application using BFD. Using BFD + consists of making references though the BFD and to data in the BFD. - Here is the struct used to define the type <<bfd>>. This - contains the major data about the file, and contains pointers + Here is the structure that defines the type <<bfd>>. It + contains the major data about the file and pointers to the rest of the data. CODE_FRAGMENT @@ -39,7 +38,7 @@ CODE_FRAGMENT . CONST char *filename; . . {* A pointer to the target jump table. *} -. struct bfd_target *xvec; +. const 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 @@ -48,13 +47,14 @@ CODE_FRAGMENT . is the result of an fopen on the filename. *} . char *iostream; . -. {* Is the file being cached *} +. {* Is the file descriptor being cached? That is, can it be closed as +. needed, and re-opened when accessed later? *} . . 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. *} +. BFD was opened. This is used to select which matching algorithm +. to use to choose the back end. *} . . boolean target_defaulted; . @@ -64,12 +64,11 @@ CODE_FRAGMENT . struct _bfd *lru_prev, *lru_next; . . {* When a file is closed by the caching routines, BFD retains -. state information on the file here: -. *} +. state information on the file here: *} . . file_ptr where; . -. {* and here:*} +. {* and here: (``once'' means at least once) *} . . boolean opened_once; . @@ -86,7 +85,7 @@ CODE_FRAGMENT . . int ifd; . -. {* The format which belongs to the BFD.*} +. {* The format which belongs to the BFD. (object, core, etc.) *} . . bfd_format format; . @@ -108,7 +107,7 @@ CODE_FRAGMENT . file_ptr origin; . . {* Remember when output has begun, to stop strange things -. happening. *} +. from happening. *} . boolean output_has_begun; . . {* Pointer to linked list of sections*} @@ -124,7 +123,7 @@ CODE_FRAGMENT . {* Used for input and output*} . unsigned int symcount; . -. {* Symbol table for output BFD*} +. {* Symbol table for output BFD (with symcount entries) *} . struct symbol_cache_entry **outsymbols; . . {* Pointer to structure which contains architecture information*} @@ -132,11 +131,18 @@ CODE_FRAGMENT . . {* Stuff only useful for archives:*} . PTR arelt_data; -. struct _bfd *my_archive; -. struct _bfd *next; -. struct _bfd *archive_head; +. struct _bfd *my_archive; {* The containing archive BFD. *} +. struct _bfd *next; {* The next BFD in the archive. *} +. struct _bfd *archive_head; {* The first BFD in the archive. *} . boolean has_armap; . +. {* A chain of BFD structures involved in a link. *} +. struct _bfd *link_next; +. +. {* A field used by _bfd_generic_link_add_archive_symbols. This will +. be used only for archive elements. *} +. int archive_pass; +. . {* Used by the back end to hold private data. *} . . union @@ -156,11 +162,13 @@ CODE_FRAGMENT . struct bout_data_struct *bout_data; . struct sun_core_struct *sun_core_data; . struct trad_core_struct *trad_core_data; -. struct hppa_data_struct *hppa_data; +. struct som_data_struct *som_data; . struct hpux_core_struct *hpux_core_data; +. struct hppabsd_core_struct *hppabsd_core_data; . struct sgi_core_struct *sgi_core_data; . struct lynx_core_struct *lynx_core_data; . struct osf_core_struct *osf_core_data; +. struct cisco_core_struct *cisco_core_data; . PTR any; . } tdata; . @@ -169,15 +177,13 @@ CODE_FRAGMENT . . {* Where all the allocated stuff under this BFD goes *} . struct obstack memory; -. -. {* Is this really needed in addition to usrdata? *} -. asymbol **ld_symbols; .}; . */ #include "bfd.h" #include "sysdep.h" +#include "bfdlink.h" #include "libbfd.h" #include "coff/internal.h" #include "coff/sym.h" @@ -186,31 +192,67 @@ CODE_FRAGMENT #undef obj_symbols #include "libelf.h" -#undef strerror -extern char *strerror(); + +/* +SECTION + Error reporting + + Most BFD functions return nonzero on success (check their + individual documentation for precise semantics). On an error, + they call <<bfd_set_error>> to set an error condition that callers + can check by calling <<bfd_get_error>>. + If that returns <<bfd_error_system_call>>, then check + <<errno>>. + + The easiest way to report a BFD error to the user is to + use <<bfd_perror>>. + +SUBSECTION + Type <<bfd_error_type>> -/** Error handling - o - Most functions return nonzero on success (check doc for - precise semantics); 0 or NULL on error. - o - Internal errors are documented by the value of bfd_error. - If that is system_call_error then check errno. - o - The easiest way to report this to the user is to use bfd_perror. + The values returned by <<bfd_get_error>> are defined by the + enumerated type <<bfd_error_type>>. + +CODE_FRAGMENT +. +.typedef enum bfd_error +.{ +. bfd_error_no_error = 0, +. bfd_error_system_call, +. bfd_error_invalid_target, +. bfd_error_wrong_format, +. bfd_error_invalid_operation, +. bfd_error_no_memory, +. bfd_error_no_symbols, +. bfd_error_no_more_archived_files, +. bfd_error_malformed_archive, +. bfd_error_file_not_recognized, +. bfd_error_file_ambiguously_recognized, +. bfd_error_no_contents, +. bfd_error_nonrepresentable_section, +. bfd_error_no_debug_section, +. bfd_error_bad_value, +. bfd_error_file_truncated, +. bfd_error_invalid_error_code +.} bfd_error_type; +. */ -bfd_ec bfd_error = no_error; +#undef strerror +extern char *strerror(); + +static bfd_error_type bfd_error = bfd_error_no_error; CONST char *CONST bfd_errmsgs[] = { "No error", "System call error", - "Invalid target", + "Invalid bfd target", "File in wrong format", "Invalid operation", "Memory exhausted", "No symbols", - "No relocation info", "No more archived files", "Malformed archive", - "Symbol not found", "File format not recognized", "File format is ambiguous", "Section has no contents", @@ -221,130 +263,128 @@ CONST char *CONST bfd_errmsgs[] = { "#<Invalid error code>" }; -static -void -DEFUN(bfd_nonrepresentable_section,(abfd, name), - CONST bfd * CONST abfd AND - CONST char * CONST name) -{ - fprintf(stderr, - "bfd error writing file %s, format %s can't represent section %s\n", - abfd->filename, - abfd->xvec->name, - name); - exit(1); -} +/* +FUNCTION + bfd_get_error -/*ARGSUSED*/ -static -void -DEFUN(bfd_undefined_symbol,(relent, seclet), - CONST arelent *relent AND - CONST struct bfd_seclet *seclet) -{ - asymbol *symbol = *(relent->sym_ptr_ptr); - fprintf(stderr, "bfd error relocating, symbol %s is undefined\n", - symbol->name); - exit(1); -} -/*ARGSUSED*/ -static -void -DEFUN(bfd_reloc_value_truncated,(relent, seclet), - CONST arelent *relent AND - struct bfd_seclet *seclet) +SYNOPSIS + bfd_error_type bfd_get_error (void); + +DESCRIPTION + Return the current BFD error condition. +*/ + +bfd_error_type +bfd_get_error () { - fprintf(stderr, "bfd error relocating, value truncated\n"); - exit(1); + return bfd_error; } -/*ARGSUSED*/ -static -void -DEFUN(bfd_reloc_is_dangerous,(relent, seclet), - CONST arelent *relent AND - CONST struct bfd_seclet *seclet) + +/* +FUNCTION + bfd_set_error + +SYNOPSIS + void bfd_set_error (bfd_error_type error_tag); + +DESCRIPTION + Set the BFD error condition to be @var{error_tag}. +*/ + +void +bfd_set_error (error_tag) + bfd_error_type error_tag; { - fprintf(stderr, "bfd error relocating, dangerous\n"); - exit(1); + bfd_error = error_tag; } -bfd_error_vector_type bfd_error_vector = - { - bfd_nonrepresentable_section , - bfd_undefined_symbol, - bfd_reloc_value_truncated, - bfd_reloc_is_dangerous, - }; +/* +FUNCTION + bfd_errmsg + +SYNOPSIS + CONST char *bfd_errmsg (bfd_error_type error_tag); +DESCRIPTION + Return a string describing the error @var{error_tag}, or + the system error if @var{error_tag} is <<bfd_error_system_call>>. +*/ CONST char * bfd_errmsg (error_tag) - bfd_ec error_tag; + bfd_error_type error_tag; { #ifndef errno extern int errno; #endif - if (error_tag == system_call_error) + if (error_tag == bfd_error_system_call) return strerror (errno); - if ((((int)error_tag <(int) no_error) || - ((int)error_tag > (int)invalid_error_code))) - error_tag = invalid_error_code;/* sanity check */ + if ((((int)error_tag <(int) bfd_error_no_error) || + ((int)error_tag > (int)bfd_error_invalid_error_code))) + error_tag = bfd_error_invalid_error_code;/* sanity check */ return bfd_errmsgs [(int)error_tag]; } -void -DEFUN (bfd_default_error_trap, (error_tag), - bfd_ec error_tag) -{ - fprintf(stderr, "bfd assert fail (%s)\n", bfd_errmsg(error_tag)); -} +/* +FUNCTION + bfd_perror -void (*bfd_error_trap) PARAMS ((bfd_ec)) = bfd_default_error_trap; -void (*bfd_error_nonrepresentabltrap) PARAMS ((bfd_ec)) = bfd_default_error_trap; +SYNOPSIS + void bfd_perror (CONST char *message); + +DESCRIPTION + Print to the standard error stream a string describing the + last BFD error that occurred, or the last system error if + the last BFD error was a system call failure. If @var{message} + is non-NULL and non-empty, the error string printed is preceded + by @var{message}, a colon, and a space. It is followed by a newline. +*/ void -DEFUN(bfd_perror,(message), - CONST char *message) +bfd_perror (message) + CONST char *message; { - if (bfd_error == system_call_error) + if (bfd_get_error () == bfd_error_system_call) perror((char *)message); /* must be system error then... */ else { if (message == NULL || *message == '\0') - fprintf (stderr, "%s\n", bfd_errmsg (bfd_error)); + fprintf (stderr, "%s\n", bfd_errmsg (bfd_get_error ())); else - fprintf (stderr, "%s: %s\n", message, bfd_errmsg (bfd_error)); + fprintf (stderr, "%s: %s\n", message, bfd_errmsg (bfd_get_error ())); } } - -/** Symbols */ - + +/* +SECTION + Symbols +*/ /* FUNCTION bfd_get_reloc_upper_bound SYNOPSIS - unsigned int bfd_get_reloc_upper_bound(bfd *abfd, asection *sect); + long bfd_get_reloc_upper_bound(bfd *abfd, asection *sect); DESCRIPTION - This function return the number of bytes required to store the - relocation information associated with section <<sect>> - attached to bfd <<abfd>> + Return the number of bytes required to store the + relocation information associated with section @var{sect} + attached to bfd @var{abfd}. If an error occurs, return -1. */ -unsigned int -DEFUN(bfd_get_reloc_upper_bound,(abfd, asect), - bfd *abfd AND - sec_ptr asect) +long +bfd_get_reloc_upper_bound (abfd, asect) + bfd *abfd; + sec_ptr asect; { if (abfd->format != bfd_object) { - bfd_error = invalid_operation; - return 0; + bfd_set_error (bfd_error_invalid_operation); + return -1; } return BFD_SEND (abfd, _get_reloc_upper_bound, (abfd, asect)); @@ -355,40 +395,66 @@ FUNCTION bfd_canonicalize_reloc SYNOPSIS - unsigned int bfd_canonicalize_reloc + long bfd_canonicalize_reloc (bfd *abfd, asection *sec, arelent **loc, asymbol **syms); DESCRIPTION - This function calls the back end associated with the open - <<abfd>> and translates the external form of the relocation - information attached to <<sec>> into the internal canonical - form. The table is placed into memory at <<loc>>, which has + Call the back end associated with the open BFD + @var{abfd} and translate the external form of the relocation + information attached to @var{sec} into the internal canonical + form. Place the table into memory at @var{loc}, which has been preallocated, usually by a call to - <<bfd_get_reloc_upper_bound>>. + <<bfd_get_reloc_upper_bound>>. Returns the number of relocs, or + -1 on error. - The <<syms>> table is also needed for horrible internal magic + The @var{syms} table is also needed for horrible internal magic reasons. */ -unsigned int -DEFUN(bfd_canonicalize_reloc,(abfd, asect, location, symbols), - bfd *abfd AND - sec_ptr asect AND - arelent **location AND - asymbol **symbols) +long +bfd_canonicalize_reloc (abfd, asect, location, symbols) + bfd *abfd; + sec_ptr asect; + arelent **location; + asymbol **symbols; { - if (abfd->format != bfd_object) { - bfd_error = invalid_operation; - return 0; - } - return BFD_SEND (abfd, _bfd_canonicalize_reloc, - (abfd, asect, location, symbols)); + if (abfd->format != bfd_object) { + bfd_set_error (bfd_error_invalid_operation); + return -1; } + return BFD_SEND (abfd, _bfd_canonicalize_reloc, + (abfd, asect, location, symbols)); +} +/* +FUNCTION + bfd_set_reloc + +SYNOPSIS + void bfd_set_reloc + (bfd *abfd, asection *sec, arelent **rel, unsigned int count) + +DESCRIPTION + Set the relocation pointer and count within + section @var{sec} to the values @var{rel} and @var{count}. + The argument @var{abfd} is ignored. + +*/ +/*ARGSUSED*/ +void +bfd_set_reloc (ignore_abfd, asect, location, count) + bfd *ignore_abfd; + sec_ptr asect; + arelent **location; + unsigned int count; +{ + asect->orelocation = location; + asect->reloc_count = count; +} /* FUNCTION @@ -398,16 +464,15 @@ SYNOPSIS boolean bfd_set_file_flags(bfd *abfd, flagword flags); DESCRIPTION - This function attempts to set the flag word in the referenced - BFD structure to the value supplied. + Set the flag word in the BFD @var{abfd} to the value @var{flags}. Possible errors are: - o wrong_format - The target bfd was not of object format. - o invalid_operation - The target bfd was open for reading. - o invalid_operation - + o <<bfd_error_wrong_format>> - The target bfd was not of object format. + o <<bfd_error_invalid_operation>> - The target bfd was open for reading. + o <<bfd_error_invalid_operation>> - The flag word contained a bit which was not applicable to the - type of file. eg, an attempt was made to set the D_PAGED bit - on a bfd format which does not support demand paging + type of file. E.g., an attempt was made to set the <<D_PAGED>> bit + on a BFD format which does not support demand paging. */ @@ -417,49 +482,24 @@ bfd_set_file_flags (abfd, flags) flagword flags; { if (abfd->format != bfd_object) { - bfd_error = wrong_format; + bfd_set_error (bfd_error_wrong_format); return false; } if (bfd_read_p (abfd)) { - bfd_error = invalid_operation; + bfd_set_error (bfd_error_invalid_operation); return false; } bfd_get_file_flags (abfd) = flags; if ((flags & bfd_applicable_file_flags (abfd)) != flags) { - bfd_error = invalid_operation; + bfd_set_error (bfd_error_invalid_operation); return false; } return true; } -/* -FUNCTION - bfd_set_reloc - -SYNOPSIS - void bfd_set_reloc - (bfd *abfd, asection *sec, arelent **rel, unsigned int count) - -DESCRIPTION - This function sets the relocation pointer and count within a - section to the supplied values. - -*/ -/*ARGSUSED*/ -void -bfd_set_reloc (ignore_abfd, asect, location, count) - bfd *ignore_abfd; - sec_ptr asect; - arelent **location; - unsigned int count; -{ - asect->orelocation = location; - asect->reloc_count = count; -} - void bfd_assert(file, line) char *file; @@ -473,14 +513,14 @@ int line; FUNCTION bfd_set_start_address +SYNOPSIS + boolean bfd_set_start_address(bfd *abfd, bfd_vma vma); + DESCRIPTION - Marks the entry point of an output BFD. + Make @var{vma} the entry point of output BFD @var{abfd}. RETURNS Returns <<true>> on success, <<false>> otherwise. - -SYNOPSIS - boolean bfd_set_start_address(bfd *, bfd_vma); */ boolean @@ -495,14 +535,14 @@ bfd_vma vma; /* FUNCTION - The bfd_get_mtime function + bfd_get_mtime SYNOPSIS - long bfd_get_mtime(bfd *); + long bfd_get_mtime(bfd *abfd); DESCRIPTION - Return file modification time (as read from file system, or - from archive header for archive members). + Return the file modification time (as read from the file system, or + from the archive header for archive members). */ @@ -526,32 +566,32 @@ bfd_get_mtime (abfd) /* FUNCTION - The bfd_get_size function + bfd_get_size SYNOPSIS - long bfd_get_size(bfd *); + long bfd_get_size(bfd *abfd); DESCRIPTION - Return file size (as read from file system) for the file - associated with a bfd. + Return the file size (as read from file system) for the file + associated with BFD @var{abfd}. - Note that the initial motivation for, and use of, this routine is not - so we can get the exact size of the object the bfd applies to, since - that might not be generally possible (archive members for example?). - Although it would be ideal if someone could eventually modify + The initial motivation for, and use of, this routine is not + so we can get the exact size of the object the BFD applies to, since + that might not be generally possible (archive members for example). + It would be ideal if someone could eventually modify it so that such results were guaranteed. Instead, we want to ask questions like "is this NNN byte sized object I'm about to try read from file offset YYY reasonable?" - As as example of where we might want to do this, some object formats - use string tables for which the first sizeof(long) bytes of the table - contain the size of the table itself, including the size bytes. + As as example of where we might do this, some object formats + use string tables for which the first <<sizeof(long)>> bytes of the + table contain the size of the table itself, including the size bytes. If an application tries to read what it thinks is one of these string tables, without some way to validate the size, and for some reason the size is wrong (byte swapping error, wrong location - for the string table, etc), the only clue is likely to be a read + for the string table, etc.), the only clue is likely to be a read error when it tries to read the table, or a "virtual memory - exhausted" error when it tries to allocated 15 bazillon bytes + exhausted" error when it tries to allocate 15 bazillon bytes of space for the 15 bazillon byte table it is about to read. This function at least allows us to answer the quesion, "is the size reasonable?". @@ -573,14 +613,14 @@ bfd_get_size (abfd) /* FUNCTION - The bfd_get_gp_size function + bfd_get_gp_size SYNOPSIS - int bfd_get_gp_size(bfd *); + int bfd_get_gp_size(bfd *abfd); DESCRIPTION - Get the maximum size of objects to be optimized using the GP - register under MIPS ECOFF. This is typically set by the -G + Return the maximum size of objects to be optimized using the GP + register under MIPS ECOFF. This is typically set by the <<-G>> argument to the compiler, assembler or linker. */ @@ -588,22 +628,27 @@ int bfd_get_gp_size (abfd) bfd *abfd; { - if (abfd->xvec->flavour == bfd_target_ecoff_flavour) - return ecoff_data (abfd)->gp_size; + if (abfd->format == bfd_object) + { + if (abfd->xvec->flavour == bfd_target_ecoff_flavour) + return ecoff_data (abfd)->gp_size; + else if (abfd->xvec->flavour == bfd_target_elf_flavour) + return elf_gp_size (abfd); + } return 0; } /* FUNCTION - The bfd_set_gp_size function + bfd_set_gp_size SYNOPSIS - void bfd_set_gp_size(bfd *, int); + void bfd_set_gp_size(bfd *abfd, int i); DESCRIPTION Set the maximum size of objects to be optimized using the GP register under ECOFF or MIPS ELF. This is typically set by - the -G argument to the compiler, assembler or linker. + the <<-G>> argument to the compiler, assembler or linker. */ void @@ -611,6 +656,9 @@ bfd_set_gp_size (abfd, i) bfd *abfd; int i; { + /* Don't try to set GP size on an archive or core file! */ + if (abfd->format != bfd_object) + return; if (abfd->xvec->flavour == bfd_target_ecoff_flavour) ecoff_data (abfd)->gp_size = i; else if (abfd->xvec->flavour == bfd_target_elf_flavour) @@ -621,27 +669,27 @@ bfd_set_gp_size (abfd, i) FUNCTION bfd_scan_vma +SYNOPSIS + bfd_vma bfd_scan_vma(CONST char *string, CONST char **end, int base); + DESCRIPTION - Converts, like strtoul, a numerical expression as a - string into a bfd_vma integer, and returns that integer. - (Though without as many bells and whistles as strtoul.) - The expression is assumed to be unsigned (i.e. positive). - If given a base, it is used as the base for conversion. + Convert, like <<strtoul>>, a numerical expression + @var{string} into a <<bfd_vma>> integer, and return that integer. + (Though without as many bells and whistles as <<strtoul>>.) + The expression is assumed to be unsigned (i.e., positive). + If given a @var{base}, it is used as the base for conversion. A base of 0 causes the function to interpret the string in hex if a leading "0x" or "0X" is found, otherwise in octal if a leading zero is found, otherwise in decimal. Overflow is not detected. - -SYNOPSIS - bfd_vma bfd_scan_vma(CONST char *string, CONST char **end, int base); */ bfd_vma -DEFUN(bfd_scan_vma,(string, end, base), - CONST char *string AND - CONST char **end AND - int base) +bfd_scan_vma (string, end, base) + CONST char *string; + CONST char **end; + int base; { bfd_vma value; int digit; @@ -693,10 +741,31 @@ DEFUN(bfd_scan_vma,(string, end, base), /* FUNCTION + bfd_copy_private_bfd_data + +SYNOPSIS + boolean bfd_copy_private_bfd_data(bfd *ibfd, bfd *obfd); + +DESCRIPTION + Copy private BFD information from the BFD @var{ibfd} to the + the BFD @var{obfd}. Return <<true>> on success, <<false>> on error. + Possible error returns are: + + o <<bfd_error_no_memory>> - + Not enough memory exists to create private data for @var{obfd}. + +.#define bfd_copy_private_bfd_data(ibfd, obfd) \ +. BFD_SEND (ibfd, _bfd_copy_private_bfd_data, \ +. (ibfd, obfd)) + +*/ + +/* +FUNCTION stuff DESCRIPTION - stuff which should be documented + Stuff which should be documented: .#define bfd_sizeof_headers(abfd, reloc) \ . BFD_SEND (abfd, _bfd_sizeof_headers, (abfd, reloc)) @@ -721,13 +790,36 @@ DESCRIPTION .#define bfd_set_arch_mach(abfd, arch, mach)\ . BFD_SEND ( abfd, _bfd_set_arch_mach, (abfd, arch, mach)) . -.#define bfd_get_relocated_section_contents(abfd, seclet, data, relocateable) \ -. BFD_SEND (abfd, _bfd_get_relocated_section_contents, (abfd, seclet, data, relocateable)) +.#define bfd_get_relocated_section_contents(abfd, link_info, link_order, data, relocateable, symbols) \ +. BFD_SEND (abfd, _bfd_get_relocated_section_contents, \ +. (abfd, link_info, link_order, data, relocateable, symbols)) . -.#define bfd_relax_section(abfd, section, symbols) \ -. BFD_SEND (abfd, _bfd_relax_section, (abfd, section, symbols)) +.#define bfd_relax_section(abfd, section, link_info, again) \ +. BFD_SEND (abfd, _bfd_relax_section, (abfd, section, link_info, again)) +. +.#define bfd_link_hash_table_create(abfd) \ +. BFD_SEND (abfd, _bfd_link_hash_table_create, (abfd)) +. +.#define bfd_link_add_symbols(abfd, info) \ +. BFD_SEND (abfd, _bfd_link_add_symbols, (abfd, info)) +. +.#define bfd_final_link(abfd, info) \ +. BFD_SEND (abfd, _bfd_final_link, (abfd, info)) +. +.#define bfd_free_cached_info(abfd) \ +. BFD_SEND (abfd, _bfd_free_cached_info, (abfd)) +. +.#define bfd_get_dynamic_symtab_upper_bound(abfd) \ +. BFD_SEND (abfd, _bfd_get_dynamic_symtab_upper_bound, (abfd)) +. +.#define bfd_canonicalize_dynamic_symtab(abfd, asymbols) \ +. BFD_SEND (abfd, _bfd_canonicalize_dynamic_symtab, (abfd, asymbols)) +. +.#define bfd_get_dynamic_reloc_upper_bound(abfd) \ +. BFD_SEND (abfd, _bfd_get_dynamic_reloc_upper_bound, (abfd)) +. +.#define bfd_canonicalize_dynamic_reloc(abfd, arels, asyms) \ +. BFD_SEND (abfd, _bfd_canonicalize_dynamic_reloc, (abfd, arels, asyms)) . -.#define bfd_seclet_link(abfd, data, relocateable) \ -. BFD_SEND (abfd, _bfd_seclet_link, (abfd, data, relocateable)) */ diff --git a/gnu/usr.bin/gdb/bfd/bfd.h b/gnu/usr.bin/gdb/bfd/bfd.h index fbe0f0f36ba4..e6159a776e9d 100644 --- a/gnu/usr.bin/gdb/bfd/bfd.h +++ b/gnu/usr.bin/gdb/bfd/bfd.h @@ -1,5 +1,5 @@ /* Main header file for the bfd library -- portable access to object files. - Copyright 1990, 1991, 1992, 1993 Free Software Foundation, Inc. + Copyright 1990, 1991, 1992, 1993, 1994 Free Software Foundation, Inc. Contributed by Cygnus Support. ** NOTE: bfd.h and bfd-in2.h are GENERATED files. Don't change them; @@ -47,8 +47,8 @@ here. */ #include "ansidecl.h" #include "obstack.h" -#define BFD_VERSION "2.2" - +/* These two lines get substitutions done by commands in Makefile.in. */ +#define BFD_VERSION "cygnus-2.3" #define BFD_ARCH_SIZE 32 #if BFD_ARCH_SIZE >= 64 @@ -81,7 +81,13 @@ typedef struct _bfd bfd; force me to change it. */ /* typedef enum boolean {false, true} boolean; */ /* Yup, SVR4 has a "typedef enum boolean" in <sys/types.h> -fnf */ +/* It gets worse if the host also defines a true/false enum... -sts */ +#ifndef TRUE_FALSE_ALREADY_DEFINED typedef enum bfd_boolean {false, true} boolean; +#define BFD_TRUE_FALSE +#else +typedef enum bfd_boolean {bfd_false, bfd_true} boolean; +#endif /* A pointer to a position in a file. */ /* FIXME: This should be using off_t from <sys/types.h>. @@ -94,9 +100,9 @@ typedef enum bfd_boolean {false, true} boolean; typedef long int file_ptr; /* Support for different sizes of target format ints and addresses. If the - host implements 64-bit values, it defines HOST_64_BIT to be the appropriate + host implements 64-bit values, it defines BFD_HOST_64_BIT to be the appropriate type. Otherwise, this code will fall back on gcc's "long long" type if gcc - is being used. HOST_64_BIT must be defined in such a way as to be a valid + is being used. BFD_HOST_64_BIT must be defined in such a way as to be a valid type name by itself or with "unsigned" prefixed. It should be a signed type by itself. @@ -105,27 +111,31 @@ typedef long int file_ptr; #ifdef BFD64 -#if defined (__GNUC__) && !defined (HOST_64_BIT) -#define HOST_64_BIT long long -typedef HOST_64_BIT int64_type; -typedef unsigned HOST_64_BIT uint64_type; +#if defined (__GNUC__) && !defined (BFD_HOST_64_BIT) +#define BFD_HOST_64_BIT long long +typedef BFD_HOST_64_BIT int64_type; +typedef unsigned BFD_HOST_64_BIT uint64_type; #endif #if !defined (uint64_type) && defined (__GNUC__) #define uint64_type unsigned long long #define int64_type long long -#define uint64_typeLOW(x) (unsigned long)(((x) & 0xffffffff)) -#define uint64_typeHIGH(x) (unsigned long)(((x) >> 32) & 0xffffffff) +#endif +#ifndef uint64_typeLOW +#define uint64_typeLOW(x) ((unsigned long)(((x) & 0xffffffff))) +#define uint64_typeHIGH(x) ((unsigned long)(((x) >> 32) & 0xffffffff)) #endif -typedef unsigned HOST_64_BIT bfd_vma; -typedef HOST_64_BIT bfd_signed_vma; -typedef unsigned HOST_64_BIT bfd_size_type; -typedef unsigned HOST_64_BIT symvalue; +typedef unsigned BFD_HOST_64_BIT bfd_vma; +typedef BFD_HOST_64_BIT bfd_signed_vma; +typedef unsigned BFD_HOST_64_BIT bfd_size_type; +typedef unsigned BFD_HOST_64_BIT symvalue; +#ifndef fprintf_vma #define fprintf_vma(s,x) \ - fprintf(s,"%08x%08x", uint64_typeHIGH(x), uint64_typeLOW(x)) + fprintf(s,"%08lx%08lx", uint64_typeHIGH(x), uint64_typeLOW(x)) #define sprintf_vma(s,x) \ - sprintf(s,"%08x%08x", uint64_typeHIGH(x), uint64_typeLOW(x)) + sprintf(s,"%08lx%08lx", uint64_typeHIGH(x), uint64_typeLOW(x)) +#endif #else /* not BFD64 */ /* Represent a target address. Also used as a generic unsigned type @@ -160,37 +170,67 @@ typedef enum bfd_format { bfd_type_end} /* marks the end; don't use it! */ bfd_format; -/* Object file flag values */ +/* Values that may appear in the flags field of a BFD. These also + appear in the object_flags field of the bfd_target structure, where + they indicate the set of flags used by that backend (not all flags + are meaningful for all object file formats) (FIXME: at the moment, + the object_flags values have mostly just been copied from backend + to another, and are not necessarily correct). */ + +/* No flags. */ #define NO_FLAGS 0x00 + +/* BFD contains relocation entries. */ #define HAS_RELOC 0x01 + +/* BFD is directly executable. */ #define EXEC_P 0x02 + +/* BFD has line number information (basically used for F_LNNO in a + COFF header). */ #define HAS_LINENO 0x04 + +/* BFD has debugging information. */ #define HAS_DEBUG 0x08 + +/* BFD has symbols. */ #define HAS_SYMS 0x10 + +/* BFD has local symbols (basically used for F_LSYMS in a COFF + header). */ #define HAS_LOCALS 0x20 + +/* BFD is a dynamic object. */ #define DYNAMIC 0x40 + +/* Text section is write protected (if D_PAGED is not set, this is + like an a.out NMAGIC file) (the linker sets this by default, but + clears it for -r or -N). */ #define WP_TEXT 0x80 + +/* BFD is dynamically paged (this is like an a.out ZMAGIC file) (the + linker sets this by default, but clears it for -r or -n or -N). */ #define D_PAGED 0x100 + +/* BFD is relaxable (this means that bfd_relax_section may be able to + do something). */ #define BFD_IS_RELAXABLE 0x200 + +/* This may be set before writing out a BFD to request using a + traditional format. For example, this is used to request that when + writing out an a.out object the symbols not be hashed to eliminate + duplicates. */ +#define BFD_TRADITIONAL_FORMAT 0x400 /* symbols and relocation */ +/* A count of carsyms (canonical archive symbols). */ typedef unsigned long symindex; #define BFD_NO_MORE_SYMBOLS ((symindex) ~0) -typedef enum bfd_symclass { - bfd_symclass_unknown = 0, - bfd_symclass_fcommon, /* fortran common symbols */ - bfd_symclass_global, /* global symbol, what a surprise */ - bfd_symclass_debugger, /* some debugger symbol */ - bfd_symclass_undefined /* none known */ - } symclass; - - -/* general purpose part of a symbol; - target specific parts will be found in libcoff.h, liba.out.h etc */ - +/* General purpose part of a symbol X; + target specific parts are in libcoff.h, libaout.h, etc. */ #define bfd_get_section(x) ((x)->section) #define bfd_get_output_section(x) ((x)->section->output_section) @@ -202,6 +242,7 @@ typedef enum bfd_symclass { #define bfd_asymbol_bfd(x) ((x)->the_bfd) #define bfd_asymbol_flavour(x) (bfd_asymbol_bfd(x)->xvec->flavour) +/* A canonical archive symbol. */ /* This is a type pun with struct ranlib on purpose! */ typedef struct carsym { char *name; @@ -209,7 +250,8 @@ typedef struct carsym { } carsym; /* to make these you call a carsymogen */ -/* Used in generating armaps. Perhaps just a forward definition would do? */ +/* Used in generating armaps (archive tables of contents). + Perhaps just a forward definition would do? */ struct orl { /* output ranlib */ char **name; /* symbol name */ file_ptr pos; /* bfd* or file position */ @@ -222,7 +264,7 @@ struct orl { /* output ranlib */ typedef struct lineno_cache_entry { unsigned int line_number; /* Linenumber from start of function*/ union { - struct symbol_cache_entry *sym; /* Function name */ + struct symbol_cache_entry *sym; /* Function name */ unsigned long offset; /* Offset into section */ } u; } alent; @@ -253,46 +295,6 @@ typedef struct sec *sec_ptr; typedef struct stat stat_type; -/** Error handling */ - -typedef enum bfd_error { - no_error = 0, system_call_error, invalid_target, - wrong_format, invalid_operation, no_memory, - no_symbols, no_relocation_info, - no_more_archived_files, malformed_archive, - symbol_not_found, file_not_recognized, - file_ambiguously_recognized, no_contents, - bfd_error_nonrepresentable_section, - no_debug_section, bad_value, - - /* An input file is shorter than expected. */ - file_truncated, - - invalid_error_code} bfd_ec; - -extern bfd_ec bfd_error; -struct reloc_cache_entry; -struct bfd_seclet; - - -typedef struct bfd_error_vector { - void (* nonrepresentable_section ) PARAMS ((CONST bfd *CONST abfd, - CONST char *CONST name)); - void (* undefined_symbol) PARAMS ((CONST struct reloc_cache_entry *rel, - CONST struct bfd_seclet *sec)); - void (* reloc_value_truncated) PARAMS ((CONST struct - reloc_cache_entry *rel, - struct bfd_seclet *sec)); - - void (* reloc_dangerous) PARAMS ((CONST struct reloc_cache_entry *rel, - CONST struct bfd_seclet *sec)); - -} bfd_error_vector_type; - -CONST char *bfd_errmsg PARAMS ((bfd_ec error_tag)); -void bfd_perror PARAMS ((CONST char *message)); - - typedef enum bfd_print_symbol { bfd_print_symbol_name, @@ -300,24 +302,99 @@ typedef enum bfd_print_symbol bfd_print_symbol_all } bfd_print_symbol_type; - /* Information about a symbol that nm needs. */ typedef struct _symbol_info { symvalue value; - char type; /* */ + char type; CONST char *name; /* Symbol name. */ char stab_other; /* Unused. */ short stab_desc; /* Info for N_TYPE. */ CONST char *stab_name; } symbol_info; -/* The code that implements targets can initialize a jump table with this - macro. It must name all its routines the same way (a prefix plus - the standard routine suffix), or it must #define the routines that - are not so named, before calling JUMP_TABLE in the initializer. */ +/* Hash table routines. There is no way to free up a hash table. */ + +/* An element in the hash table. Most uses will actually use a larger + structure, and an instance of this will be the first field. */ +struct bfd_hash_entry +{ + /* Next entry for this hash code. */ + struct bfd_hash_entry *next; + /* String being hashed. */ + const char *string; + /* Hash code. This is the full hash code, not the index into the + table. */ + unsigned long hash; +}; + +/* A hash table. */ + +struct bfd_hash_table +{ + /* The hash array. */ + struct bfd_hash_entry **table; + /* The number of slots in the hash table. */ + unsigned int size; + /* A function used to create new elements in the hash table. The + first entry is itself a pointer to an element. When this + function is first invoked, this pointer will be NULL. However, + having the pointer permits a hierarchy of method functions to be + built each of which calls the function in the superclass. Thus + each function should be written to allocate a new block of memory + only if the argument is NULL. */ + struct bfd_hash_entry *(*newfunc) PARAMS ((struct bfd_hash_entry *, + struct bfd_hash_table *, + const char *)); + /* An obstack for this hash table. */ + struct obstack memory; +}; + +/* Initialize a hash table. */ +extern boolean bfd_hash_table_init + PARAMS ((struct bfd_hash_table *, + struct bfd_hash_entry *(*) (struct bfd_hash_entry *, + struct bfd_hash_table *, + const char *))); + +/* Initialize a hash table specifying a size. */ +extern boolean bfd_hash_table_init_n + PARAMS ((struct bfd_hash_table *, + struct bfd_hash_entry *(*) (struct bfd_hash_entry *, + struct bfd_hash_table *, + const char *), + unsigned int size)); + +/* Free up a hash table. */ +extern void bfd_hash_table_free PARAMS ((struct bfd_hash_table *)); + +/* Look up a string in a hash table. If CREATE is true, a new entry + will be created for this string if one does not already exist. The + COPY argument must be true if this routine should copy the string + into newly allocated memory when adding an entry. */ +extern struct bfd_hash_entry *bfd_hash_lookup + PARAMS ((struct bfd_hash_table *, const char *, boolean create, + boolean copy)); + +/* Base method for creating a hash table entry. */ +extern struct bfd_hash_entry *bfd_hash_newfunc + PARAMS ((struct bfd_hash_entry *, struct bfd_hash_table *, + const char *)); + +/* Grab some space for a hash table entry. */ +extern PTR bfd_hash_allocate PARAMS ((struct bfd_hash_table *, + unsigned int)); + +/* Traverse a hash table in a random order, calling a function on each + element. If the function returns false, the traversal stops. The + INFO argument is passed to the function. */ +extern void bfd_hash_traverse PARAMS ((struct bfd_hash_table *, + boolean (*) (struct bfd_hash_entry *, + PTR), + PTR info)); + /* Semi-portable string concatenation in cpp. The CAT4 hack is to avoid a problem with some strict ANSI C preprocessors. The problem is, "32_" is not a valid preprocessing token, and we don't @@ -330,7 +407,7 @@ typedef struct _symbol_info #define CAT3(a,b,c) a##b##c #define CAT4(a,b,c,d) a##b##c##d #else -#ifdef __STDC__ +#if defined(__STDC__) || defined(ALMOST_STDC) #define CAT(a,b) a##b #define CAT3(a,b,c) a##b##c #define XCAT2(a,b) CAT(a,b) @@ -343,50 +420,17 @@ typedef struct _symbol_info #endif #endif -#define JUMP_TABLE(NAME)\ -CAT(NAME,_core_file_failing_command),\ -CAT(NAME,_core_file_failing_signal),\ -CAT(NAME,_core_file_matches_executable_p),\ -CAT(NAME,_slurp_armap),\ -CAT(NAME,_slurp_extended_name_table),\ -CAT(NAME,_truncate_arname),\ -CAT(NAME,_write_armap),\ -CAT(NAME,_close_and_cleanup),\ -CAT(NAME,_set_section_contents),\ -CAT(NAME,_get_section_contents),\ -CAT(NAME,_new_section_hook),\ -CAT(NAME,_get_symtab_upper_bound),\ -CAT(NAME,_get_symtab),\ -CAT(NAME,_get_reloc_upper_bound),\ -CAT(NAME,_canonicalize_reloc),\ -CAT(NAME,_make_empty_symbol),\ -CAT(NAME,_print_symbol),\ -CAT(NAME,_get_symbol_info),\ -CAT(NAME,_get_lineno),\ -CAT(NAME,_set_arch_mach),\ -CAT(NAME,_openr_next_archived_file),\ -CAT(NAME,_find_nearest_line),\ -CAT(NAME,_generic_stat_arch_elt),\ -CAT(NAME,_sizeof_headers),\ -CAT(NAME,_bfd_debug_info_start),\ -CAT(NAME,_bfd_debug_info_end),\ -CAT(NAME,_bfd_debug_info_accumulate),\ -CAT(NAME,_bfd_get_relocated_section_contents),\ -CAT(NAME,_bfd_relax_section),\ -CAT(NAME,_bfd_seclet_link),\ -CAT(NAME,_bfd_reloc_type_lookup),\ -CAT(NAME,_bfd_make_debug_symbol) - #define COFF_SWAP_TABLE (PTR) &bfd_coff_std_swap_table - /* User program access to BFD facilities */ /* Cast from const char * to char * so that caller can assign to a char * without a warning. */ #define bfd_get_filename(abfd) ((char *) (abfd)->filename) +#define bfd_get_cacheable(abfd) ((abfd)->cacheable) #define bfd_get_format(abfd) ((abfd)->format) #define bfd_get_target(abfd) ((abfd)->xvec->name) +#define bfd_get_flavour(abfd) ((abfd)->xvec->flavour) #define bfd_get_file_flags(abfd) ((abfd)->flags) #define bfd_applicable_file_flags(abfd) ((abfd)->xvec->object_flags) #define bfd_applicable_section_flags(abfd) ((abfd)->xvec->section_flags) @@ -403,33 +447,115 @@ CAT(NAME,_bfd_make_debug_symbol) #define bfd_get_symbol_leading_char(abfd) ((abfd)->xvec->symbol_leading_char) +#define bfd_set_cacheable(abfd,bool) (((abfd)->cacheable = (bool)), true) + /* Byte swapping routines. */ -bfd_vma bfd_getb64 PARAMS ((unsigned char *)); -bfd_vma bfd_getl64 PARAMS ((unsigned char *)); -bfd_signed_vma bfd_getb_signed_64 PARAMS ((unsigned char *)); -bfd_signed_vma bfd_getl_signed_64 PARAMS ((unsigned char *)); -bfd_vma bfd_getb32 PARAMS ((unsigned char *)); -bfd_vma bfd_getl32 PARAMS ((unsigned char *)); -bfd_signed_vma bfd_getb_signed_32 PARAMS ((unsigned char *)); -bfd_signed_vma bfd_getl_signed_32 PARAMS ((unsigned char *)); -bfd_vma bfd_getb16 PARAMS ((unsigned char *)); -bfd_vma bfd_getl16 PARAMS ((unsigned char *)); -bfd_signed_vma bfd_getb_signed_16 PARAMS ((unsigned char *)); -bfd_signed_vma bfd_getl_signed_16 PARAMS ((unsigned char *)); +bfd_vma bfd_getb64 PARAMS ((const unsigned char *)); +bfd_vma bfd_getl64 PARAMS ((const unsigned char *)); +bfd_signed_vma bfd_getb_signed_64 PARAMS ((const unsigned char *)); +bfd_signed_vma bfd_getl_signed_64 PARAMS ((const unsigned char *)); +bfd_vma bfd_getb32 PARAMS ((const unsigned char *)); +bfd_vma bfd_getl32 PARAMS ((const unsigned char *)); +bfd_signed_vma bfd_getb_signed_32 PARAMS ((const unsigned char *)); +bfd_signed_vma bfd_getl_signed_32 PARAMS ((const unsigned char *)); +bfd_vma bfd_getb16 PARAMS ((const unsigned char *)); +bfd_vma bfd_getl16 PARAMS ((const unsigned char *)); +bfd_signed_vma bfd_getb_signed_16 PARAMS ((const unsigned char *)); +bfd_signed_vma bfd_getl_signed_16 PARAMS ((const unsigned char *)); void bfd_putb64 PARAMS ((bfd_vma, unsigned char *)); void bfd_putl64 PARAMS ((bfd_vma, unsigned char *)); void bfd_putb32 PARAMS ((bfd_vma, unsigned char *)); void bfd_putl32 PARAMS ((bfd_vma, unsigned char *)); void bfd_putb16 PARAMS ((bfd_vma, unsigned char *)); void bfd_putl16 PARAMS ((bfd_vma, unsigned char *)); + +/* Externally visible ECOFF routines. */ + +#if defined(__STDC__) || defined(ALMOST_STDC) +struct ecoff_debug_info; +struct ecoff_debug_swap; +struct ecoff_extr; +struct symbol_cache_entry; +struct bfd_link_info; +#endif +extern bfd_vma bfd_ecoff_get_gp_value PARAMS ((bfd * abfd)); +extern boolean bfd_ecoff_set_gp_value PARAMS ((bfd *abfd, bfd_vma gp_value)); +extern boolean bfd_ecoff_set_regmasks + PARAMS ((bfd *abfd, unsigned long gprmask, unsigned long fprmask, + unsigned long *cprmask)); +extern PTR bfd_ecoff_debug_init + PARAMS ((bfd *output_bfd, struct ecoff_debug_info *output_debug, + const struct ecoff_debug_swap *output_swap, + struct bfd_link_info *)); +extern void bfd_ecoff_debug_free + PARAMS ((PTR handle, bfd *output_bfd, struct ecoff_debug_info *output_debug, + const struct ecoff_debug_swap *output_swap, + struct bfd_link_info *)); +extern boolean bfd_ecoff_debug_accumulate + PARAMS ((PTR handle, bfd *output_bfd, struct ecoff_debug_info *output_debug, + const struct ecoff_debug_swap *output_swap, + bfd *input_bfd, struct ecoff_debug_info *input_debug, + const struct ecoff_debug_swap *input_swap, + struct bfd_link_info *)); +extern boolean bfd_ecoff_debug_accumulate_other + PARAMS ((PTR handle, bfd *output_bfd, struct ecoff_debug_info *output_debug, + const struct ecoff_debug_swap *output_swap, bfd *input_bfd, + struct bfd_link_info *)); +extern boolean bfd_ecoff_debug_externals + PARAMS ((bfd *abfd, struct ecoff_debug_info *debug, + const struct ecoff_debug_swap *swap, + boolean relocateable, + boolean (*get_extr) (struct symbol_cache_entry *, + struct ecoff_extr *), + void (*set_index) (struct symbol_cache_entry *, + bfd_size_type))); +extern boolean bfd_ecoff_debug_one_external + PARAMS ((bfd *abfd, struct ecoff_debug_info *debug, + const struct ecoff_debug_swap *swap, + const char *name, struct ecoff_extr *esym)); +extern bfd_size_type bfd_ecoff_debug_size + PARAMS ((bfd *abfd, struct ecoff_debug_info *debug, + const struct ecoff_debug_swap *swap)); +extern boolean bfd_ecoff_write_debug + PARAMS ((bfd *abfd, struct ecoff_debug_info *debug, + const struct ecoff_debug_swap *swap, file_ptr where)); +extern boolean bfd_ecoff_write_accumulated_debug + PARAMS ((PTR handle, bfd *abfd, struct ecoff_debug_info *debug, + const struct ecoff_debug_swap *swap, + struct bfd_link_info *info, file_ptr where)); + +/* Externally visible ELF routines. */ + +extern boolean bfd_elf32_record_link_assignment + PARAMS ((bfd *, struct bfd_link_info *, const char *)); +extern boolean bfd_elf64_record_link_assignment + PARAMS ((bfd *, struct bfd_link_info *, const char *)); +extern boolean bfd_elf32_size_dynamic_sections + PARAMS ((bfd *, struct bfd_link_info *, struct sec **)); +extern boolean bfd_elf64_size_dynamic_sections + PARAMS ((bfd *, struct bfd_link_info *, struct sec **)); +extern void bfd_elf_set_dt_needed_name PARAMS ((bfd *, const char *)); + +/* SunOS shared library support routines for the linker. */ + +extern boolean bfd_sunos_record_link_assignment + PARAMS ((bfd *, struct bfd_link_info *, const char *)); +extern boolean bfd_sunos_size_dynamic_sections + PARAMS ((bfd *, struct bfd_link_info *, struct sec **, struct sec **, + struct sec **)); + +/* Linux shared library support routines for the linker. */ + +extern boolean bfd_linux_size_dynamic_sections + PARAMS ((bfd *, struct bfd_link_info *)); /* And more from the source. */ void bfd_init PARAMS ((void)); bfd * -bfd_openr PARAMS ((CONST char *filename, CONST char*target)); +bfd_openr PARAMS ((CONST char *filename, CONST char *target)); bfd * bfd_fdopenr PARAMS ((CONST char *filename, CONST char *target, int fd)); @@ -438,7 +564,7 @@ bfd * bfd_openw PARAMS ((CONST char *filename, CONST char *target)); boolean -bfd_close PARAMS ((bfd *)); +bfd_close PARAMS ((bfd *abfd)); boolean bfd_close_all_done PARAMS ((bfd *)); @@ -453,7 +579,7 @@ bfd_create PARAMS ((CONST char *filename, bfd *templ)); /* Byte swapping macros for user section data. */ #define bfd_put_8(abfd, val, ptr) \ - (*((unsigned char *)(ptr)) = (unsigned char)val) + (*((unsigned char *)(ptr)) = (unsigned char)(val)) #define bfd_put_signed_8 \ bfd_put_8 #define bfd_get_8(abfd, ptr) \ @@ -527,40 +653,40 @@ bfd_create PARAMS ((CONST char *filename, bfd *templ)); #define bfd_h_get_signed_64(abfd, ptr) \ BFD_SEND(abfd, bfd_h_getx_signed_64, (ptr)) -typedef struct sec +typedef struct sec { - /* The name of the section, the name isn't a copy, the pointer is + /* The name of the section; the name isn't a copy, the pointer is the same as that passed to bfd_make_section. */ CONST char *name; - /* Which section is it 0.nth */ + /* Which section is it; 0..nth. */ - int index; + int index; /* The next section in the list belonging to the BFD, or NULL. */ struct sec *next; - /* The field flags contains attributes of the section. Some of + /* The field flags contains attributes of the section. Some flags are read in from the object file, and some are - synthesized from other information. */ + synthesized from other information. */ flagword flags; #define SEC_NO_FLAGS 0x000 - /* Tells the OS to allocate space for this section when loaded. - This would clear for a section containing debug information + /* Tells the OS to allocate space for this section when loading. + This is clear for a section containing debug information only. */ #define SEC_ALLOC 0x001 - + /* Tells the OS to load the section from the file when loading. - This would be clear for a .bss section */ + This is clear for a .bss section. */ #define SEC_LOAD 0x002 - /* The section contains data still to be relocated, so there will - be some relocation information too. */ + /* The section contains data still to be relocated, so there is + some relocation information too. */ #define SEC_RELOC 0x004 #if 0 /* Obsolete ? */ @@ -584,10 +710,10 @@ typedef struct sec type is used by the linker to create lists of constructors and destructors used by <<g++>>. When a back end sees a symbol which should be used in a constructor list, it creates a new - section for the type of name (eg <<__CTOR_LIST__>>), attaches - the symbol to it and builds a relocation. To build the lists + section for the type of name (e.g., <<__CTOR_LIST__>>), attaches + the symbol to it, and builds a relocation. To build the lists of constructors, all the linker has to do is catenate all the - sections called <<__CTOR_LIST__>> and relocte the data + sections called <<__CTOR_LIST__>> and relocate the data contained within - exactly the operations it would peform on standard data. */ #define SEC_CONSTRUCTOR 0x100 @@ -599,25 +725,30 @@ typedef struct sec #define SEC_CONSTRUCTOR_BSS 0x3100 /* The section has contents - a data section could be - <<SEC_ALLOC>> | <<SEC_HAS_CONTENTS>>, a debug section could be + <<SEC_ALLOC>> | <<SEC_HAS_CONTENTS>>; a debug section could be <<SEC_HAS_CONTENTS>> */ #define SEC_HAS_CONTENTS 0x200 - /* An instruction to the linker not to output sections - containing this flag even if they have information which - would normally be written. */ + /* An instruction to the linker to not output the section + even if it has information which would normally be written. */ #define SEC_NEVER_LOAD 0x400 - /* The section is a shared library section. The linker must leave - these completely alone, as the vma and size are used when - the executable is loaded. */ -#define SEC_SHARED_LIBRARY 0x800 + /* The section is a COFF shared library section. This flag is + only for the linker. If this type of section appears in + the input file, the linker must copy it to the output file + without changing the vma or size. FIXME: Although this + was originally intended to be general, it really is COFF + specific (and the flag was renamed to indicate this). It + might be cleaner to have some more general mechanism to + allow the back end to control what the linker does with + sections. */ +#define SEC_COFF_SHARED_LIBRARY 0x800 /* The section is a common section (symbols may be defined multiple times, the value of a symbol is the amount of space it requires, and the largest symbol value is the one used). Most targets have exactly one of these (which we - translate to bfd_com_section), but ECOFF has two. */ + translate to bfd_com_section_ptr), but ECOFF has two. */ #define SEC_IS_COMMON 0x8000 /* The section contains only debugging information. For @@ -626,6 +757,12 @@ typedef struct sec discarded. */ #define SEC_DEBUGGING 0x10000 + /* The contents of this section are held in memory pointed to + by the contents field. This is checked by + bfd_get_section_contents, and the data is retrieved from + memory if appropriate. */ +#define SEC_IN_MEMORY 0x20000 + /* End of section flags. */ /* The virtual memory address of the section - where it will be @@ -639,26 +776,26 @@ typedef struct sec boolean user_set_vma; /* The load address of the section - where it would be in a - rom image, really only used for writing section header + rom image; really only used for writing section header information. */ bfd_vma lma; /* The size of the section in bytes, as it will be output. - contains a value even if the section has no contents (eg, the + contains a value even if the section has no contents (e.g., the size of <<.bss>>). This will be filled in after relocation */ - bfd_size_type _cooked_size; + bfd_size_type _cooked_size; - /* The size on disk of the section in bytes originally. Normally this + /* The original size on disk of the section, in bytes. Normally this value is the same as the size, but if some relaxing has been done, then this value will be bigger. */ - bfd_size_type _raw_size; + bfd_size_type _raw_size; /* If this section is going to be output, then this value is the offset into the output section of the first byte in the input - section. Eg, if this was going to start at the 100th byte in + section. E.g., if this was going to start at the 100th byte in the output section, this value would be 100. */ bfd_vma output_offset; @@ -667,8 +804,8 @@ typedef struct sec struct sec *output_section; - /* The alignment requirement of the section, as an exponent - eg - 3 aligns to 2^3 (or 8) */ + /* The alignment requirement of the section, as an exponent of 2 - + e.g., 3 aligns to 2^3 (or 8). */ unsigned int alignment_power; @@ -691,8 +828,8 @@ typedef struct sec /* File position of section data */ - file_ptr filepos; - + file_ptr filepos; + /* File position of relocation info */ file_ptr rel_filepos; @@ -705,12 +842,14 @@ typedef struct sec PTR userdata; - struct lang_output_section *otheruserdata; + /* If the SEC_IN_MEMORY flag is set, this points to the actual + contents. */ + unsigned char *contents; /* Attached line number information */ alent *lineno; - + /* Number of line number records */ unsigned int lineno_count; @@ -720,7 +859,7 @@ typedef struct sec file_ptr moving_line_filepos; - /* what the section number is in the target world */ + /* What the section number is in the target world */ int target_index; @@ -737,35 +876,43 @@ typedef struct sec boolean reloc_done; /* A symbol which points at this section only */ - struct symbol_cache_entry *symbol; + struct symbol_cache_entry *symbol; struct symbol_cache_entry **symbol_ptr_ptr; - struct bfd_seclet *seclets_head; - struct bfd_seclet *seclets_tail; + struct bfd_link_order *link_order_head; + struct bfd_link_order *link_order_tail; } asection ; - /* These sections are global, and are managed by BFD. The application and target back end are not permitted to change the values in - these sections. */ + these sections. New code should use the section_ptr macros rather + than referring directly to the const sections. The const sections + may eventually vanish. */ #define BFD_ABS_SECTION_NAME "*ABS*" #define BFD_UND_SECTION_NAME "*UND*" #define BFD_COM_SECTION_NAME "*COM*" #define BFD_IND_SECTION_NAME "*IND*" /* the absolute section */ -extern asection bfd_abs_section; +extern const asection bfd_abs_section; +#define bfd_abs_section_ptr ((asection *) &bfd_abs_section) +#define bfd_is_abs_section(sec) ((sec) == bfd_abs_section_ptr) /* Pointer to the undefined section */ -extern asection bfd_und_section; +extern const asection bfd_und_section; +#define bfd_und_section_ptr ((asection *) &bfd_und_section) +#define bfd_is_und_section(sec) ((sec) == bfd_und_section_ptr) /* Pointer to the common section */ -extern asection bfd_com_section; +extern const asection bfd_com_section; +#define bfd_com_section_ptr ((asection *) &bfd_com_section) /* Pointer to the indirect section */ -extern asection bfd_ind_section; - -extern struct symbol_cache_entry *bfd_abs_symbol; -extern struct symbol_cache_entry *bfd_com_symbol; -extern struct symbol_cache_entry *bfd_und_symbol; -extern struct symbol_cache_entry *bfd_ind_symbol; +extern const asection bfd_ind_section; +#define bfd_ind_section_ptr ((asection *) &bfd_ind_section) +#define bfd_is_ind_section(sec) ((sec) == bfd_ind_section_ptr) + +extern const struct symbol_cache_entry * const bfd_abs_symbol; +extern const struct symbol_cache_entry * const bfd_com_symbol; +extern const struct symbol_cache_entry * const bfd_und_symbol; +extern const struct symbol_cache_entry * const bfd_ind_symbol; #define bfd_get_section_size_before_reloc(section) \ (section->reloc_done ? (abort(),1): (section)->_raw_size) #define bfd_get_section_size_after_reloc(section) \ @@ -774,16 +921,16 @@ asection * bfd_get_section_by_name PARAMS ((bfd *abfd, CONST char *name)); asection * -bfd_make_section_old_way PARAMS ((bfd *, CONST char *name)); +bfd_make_section_old_way PARAMS ((bfd *abfd, CONST char *name)); asection * -bfd_make_section_anyway PARAMS ((bfd *, CONST char *name)); +bfd_make_section_anyway PARAMS ((bfd *abfd, CONST char *name)); asection * bfd_make_section PARAMS ((bfd *, CONST char *name)); boolean -bfd_set_section_flags PARAMS ((bfd *, asection *, flagword)); +bfd_set_section_flags PARAMS ((bfd *abfd, asection *sec, flagword flags)); void bfd_map_over_sections PARAMS ((bfd *abfd, @@ -793,21 +940,27 @@ bfd_map_over_sections PARAMS ((bfd *abfd, PTR obj)); boolean -bfd_set_section_size PARAMS ((bfd *, asection *, bfd_size_type val)); +bfd_set_section_size PARAMS ((bfd *abfd, asection *sec, bfd_size_type val)); boolean bfd_set_section_contents - PARAMS ((bfd *abfd, + PARAMS ((bfd *abfd, asection *section, PTR data, file_ptr offset, bfd_size_type count)); boolean -bfd_get_section_contents +bfd_get_section_contents PARAMS ((bfd *abfd, asection *section, PTR location, file_ptr offset, bfd_size_type count)); +boolean +bfd_copy_private_section_data PARAMS ((bfd *ibfd, asection *isec, bfd *obfd, asection *osec)); + +#define bfd_copy_private_section_data(ibfd, isection, obfd, osection) \ + BFD_SEND (ibfd, _bfd_copy_private_section_data, \ + (ibfd, isection, obfd, osection)) enum bfd_architecture { bfd_arch_unknown, /* File arch not known */ @@ -845,6 +998,7 @@ enum bfd_architecture bfd_arch_h8300, /* Hitachi H8/300 */ #define bfd_mach_h8300 1 #define bfd_mach_h8300h 2 + bfd_arch_powerpc, /* PowerPC */ bfd_arch_rs6000, /* IBM RS/6000 */ bfd_arch_hppa, /* HP PA RISC */ bfd_arch_z8k, /* Zilog Z8000 */ @@ -853,6 +1007,7 @@ enum bfd_architecture bfd_arch_h8500, /* Hitachi H8/500 */ bfd_arch_sh, /* Hitachi SH */ bfd_arch_alpha, /* Dec Alpha */ + bfd_arch_ns32k, /* National Semiconductors ns32000 */ bfd_arch_last }; @@ -887,7 +1042,7 @@ CONST char * bfd_printable_name PARAMS ((bfd *abfd)); bfd_arch_info_type * -bfd_scan_arch PARAMS ((CONST char *)); +bfd_scan_arch PARAMS ((CONST char *string)); CONST bfd_arch_info_type * bfd_arch_get_compatible PARAMS (( @@ -895,7 +1050,7 @@ bfd_arch_get_compatible PARAMS (( CONST bfd *bbfd)); void -bfd_set_arch_info PARAMS ((bfd *, bfd_arch_info_type *)); +bfd_set_arch_info PARAMS ((bfd *abfd, bfd_arch_info_type *arg)); enum bfd_architecture bfd_get_arch PARAMS ((bfd *abfd)); @@ -910,7 +1065,7 @@ unsigned int bfd_arch_bits_per_address PARAMS ((bfd *abfd)); bfd_arch_info_type * -bfd_get_arch_info PARAMS ((bfd *)); +bfd_get_arch_info PARAMS ((bfd *abfd)); bfd_arch_info_type * bfd_lookup_arch @@ -918,11 +1073,11 @@ bfd_lookup_arch arch, long machine)); -CONST char * +CONST char * bfd_printable_arch_mach PARAMS ((enum bfd_architecture arch, unsigned long machine)); -typedef enum bfd_reloc_status +typedef enum bfd_reloc_status { /* No errors detected */ bfd_reloc_ok, @@ -936,10 +1091,10 @@ typedef enum bfd_reloc_status /* Used by special functions */ bfd_reloc_continue, - /* Unused */ + /* Unsupported relocation size requested. */ bfd_reloc_notsupported, - /* Unsupported relocation size requested. */ + /* Unused */ bfd_reloc_other, /* The symbol to relocate against was undefined. */ @@ -947,13 +1102,14 @@ typedef enum bfd_reloc_status /* The relocation was performed, but may not be ok - presently generated only when linking i960 coff files with i960 b.out - symbols. */ + symbols. If this type is returned, the error_message argument + to bfd_perform_relocation will be set. */ bfd_reloc_dangerous } bfd_reloc_status_type; -typedef struct reloc_cache_entry +typedef struct reloc_cache_entry { /* A pointer into the canonical table of pointers */ struct symbol_cache_entry **sym_ptr_ptr; @@ -962,10 +1118,10 @@ typedef struct reloc_cache_entry bfd_size_type address; /* addend for relocation value */ - bfd_vma addend; + bfd_vma addend; /* Pointer to how to perform the required relocation */ - CONST struct reloc_howto_struct *howto; + const struct reloc_howto_struct *howto; } arelent; enum complain_overflow @@ -986,13 +1142,16 @@ enum complain_overflow complain_overflow_unsigned }; -typedef CONST struct reloc_howto_struct -{ +typedef unsigned char bfd_byte; +typedef struct reloc_howto_struct reloc_howto_type; + +struct reloc_howto_struct +{ /* The type field has mainly a documetary use - the back end can - to what it wants with it, though the normally the back end's - external idea of what a reloc number would be would be stored - in this field. For example, the a PC relative word relocation - in a coff environment would have the type 023 - because that's + do what it wants with it, though normally the back end's + external idea of what a reloc number is stored + in this field. For example, a PC relative word relocation + in a coff environment has the type 023 - because that's what the outside world calls a R_PCRWORD reloc. */ unsigned int type; @@ -1001,16 +1160,8 @@ typedef CONST struct reloc_howto_struct unsigned int rightshift; /* The size of the item to be relocated. This is *not* a - power-of-two measure. - 0 : one byte - 1 : two bytes - 2 : four bytes - 3 : nothing done (unless special_function is nonzero) - 4 : eight bytes - -2 : two bytes, result should be subtracted from the - data instead of added - There is currently no trivial way to extract a "number of - bytes" from a howto pointer. */ + power-of-two measure. To get the number of bytes operated + on by a type of relocation, use bfd_get_reloc_size. */ int size; /* The number of bits in the item to be relocated. This is used @@ -1035,13 +1186,14 @@ typedef CONST struct reloc_howto_struct called rather than the normal function. This allows really strange relocation methods to be accomodated (e.g., i960 callj instructions). */ - bfd_reloc_status_type (*special_function) + bfd_reloc_status_type (*special_function) PARAMS ((bfd *abfd, arelent *reloc_entry, struct symbol_cache_entry *symbol, PTR data, - asection *input_section, - bfd *output_bfd)); + asection *input_section, + bfd *output_bfd, + char **error_message)); /* The textual name of the relocation type. */ char *name; @@ -1050,7 +1202,7 @@ typedef CONST struct reloc_howto_struct relocations rather than the data - this flag signals this.*/ boolean partial_inplace; - /* The src_mask is used to select what parts of the read in data + /* The src_mask selects which parts of the read in data are to be used in the relocation sum. E.g., if this was an 8 bit bit of data which we read and relocated, this would be 0x000000ff. When we have relocs which have an addend, such as @@ -1059,21 +1211,21 @@ typedef CONST struct reloc_howto_struct the mask would be 0x00000000. */ bfd_vma src_mask; - /* The dst_mask is what parts of the instruction are replaced + /* The dst_mask selects which parts of the instruction are replaced into the instruction. In most cases src_mask == dst_mask, except in the above special case, where dst_mask would be 0x000000ff, and src_mask would be 0x00000000. */ - bfd_vma dst_mask; + bfd_vma dst_mask; /* When some formats create PC relative instructions, they leave the value of the pc of the place being relocated in the offset slot of the instruction, so that a PC relative relocation can be made just by adding in an ordinary offset (e.g., sun3 a.out). Some formats leave the displacement part of an instruction - empty (e.g., m88k bcs), this flag signals the fact.*/ + empty (e.g., m88k bcs); this flag signals the fact.*/ boolean pcrel_offset; -} reloc_howto_type; +}; #define HOWTO(C, R,S,B, P, BI, O, SF, NAME, INPLACE, MASKSRC, MASKDST, PC) \ {(unsigned)C,R,S,B, P, BI, O,SF,NAME,INPLACE,MASKSRC,MASKDST,PC} #define NEWHOWTO( FUNCTION, NAME,SIZE,REL,IN) HOWTO(0,0,SIZE,0,REL,0,complain_overflow_dont,FUNCTION, NAME,false,0,0,IN) @@ -1088,8 +1240,9 @@ typedef CONST struct reloc_howto_struct relocation = symbol->value; \ } \ } \ -} -typedef unsigned char bfd_byte; +} +int +bfd_get_reloc_size PARAMS ((const reloc_howto_type *)); typedef struct relent_chain { arelent relent; @@ -1098,18 +1251,21 @@ typedef struct relent_chain { bfd_reloc_status_type bfd_perform_relocation - PARAMS ((bfd * abfd, + PARAMS ((bfd *abfd, arelent *reloc_entry, PTR data, asection *input_section, - bfd *output_bfd)); + bfd *output_bfd, + char **error_message)); -typedef enum bfd_reloc_code_real +typedef enum bfd_reloc_code_real { /* Basic absolute relocations */ BFD_RELOC_64, BFD_RELOC_32, - BFD_RELOC_16, + BFD_RELOC_26, + BFD_RELOC_16, + BFD_RELOC_14, BFD_RELOC_8, /* PC-relative relocations */ @@ -1134,6 +1290,10 @@ typedef enum bfd_reloc_code_real /* 32-bit pc-relative, shifted right 2 bits (i.e., 30-bit word displacement, e.g. for SPARC) */ BFD_RELOC_32_PCREL_S2, + /* signed 16-bit pc-relative, shifted right 2 bits (e.g. for MIPS) */ + BFD_RELOC_16_PCREL_S2, + /* this is used on the Alpha */ + BFD_RELOC_23_PCREL_S2, /* High 22 bits of 32-bit value, placed into lower 22 bits of target word; simple reloc. */ @@ -1141,6 +1301,13 @@ typedef enum bfd_reloc_code_real /* Low 10 bits. */ BFD_RELOC_LO10, + /* For systems that allocate a Global Pointer register, these are + displacements off that register. These relocation types are + handled specially, because the value the register will have is + decided relatively late. */ + BFD_RELOC_GPREL16, + BFD_RELOC_GPREL32, + /* Reloc types used for i960/b.out. */ BFD_RELOC_I960_CALLJ, @@ -1165,14 +1332,67 @@ typedef enum bfd_reloc_code_real BFD_RELOC_SPARC_BASE13, BFD_RELOC_SPARC_BASE22, + /* some relocations we're using for sparc v9 + -- subject to change */ + BFD_RELOC_SPARC_10, + BFD_RELOC_SPARC_11, +#define BFD_RELOC_SPARC_64 BFD_RELOC_64 + BFD_RELOC_SPARC_OLO10, + BFD_RELOC_SPARC_HH22, + BFD_RELOC_SPARC_HM10, + BFD_RELOC_SPARC_LM22, + BFD_RELOC_SPARC_PC_HH22, + BFD_RELOC_SPARC_PC_HM10, + BFD_RELOC_SPARC_PC_LM22, + BFD_RELOC_SPARC_WDISP16, + BFD_RELOC_SPARC_WDISP19, + BFD_RELOC_SPARC_GLOB_JMP, + BFD_RELOC_SPARC_LO7, + + /* Alpha ECOFF relocations. Some of these treat the symbol or "addend" + in some special way. */ + /* For GPDISP_HI16 ("gpdisp") relocations, the symbol is ignored when + writing; when reading, it will be the absolute section symbol. The + addend is the displacement in bytes of the "lda" instruction from + the "ldah" instruction (which is at the address of this reloc). */ + BFD_RELOC_ALPHA_GPDISP_HI16, + /* For GPDISP_LO16 ("ignore") relocations, the symbol is handled as + with GPDISP_HI16 relocs. The addend is ignored when writing the + relocations out, and is filled in with the file's GP value on + reading, for convenience. */ + BFD_RELOC_ALPHA_GPDISP_LO16, + + /* The Alpha LITERAL/LITUSE relocs are produced by a symbol reference; + the assembler turns it into a LDQ instruction to load the address of + the symbol, and then fills in a register in the real instruction. + + The LITERAL reloc, at the LDQ instruction, refers to the .lita + section symbol. The addend is ignored when writing, but is filled + in with the file's GP value on reading, for convenience, as with the + GPDISP_LO16 reloc. + + The LITUSE reloc, on the instruction using the loaded address, gives + information to the linker that it might be able to use to optimize + away some literal section references. The symbol is ignored (read + as the absolute section symbol), and the "addend" indicates the type + of instruction using the register: + 1 - "memory" fmt insn + 2 - byte-manipulation (byte offset reg) + 3 - jsr (target of branch) + + The GNU linker currently doesn't do any of this optimizing. */ + BFD_RELOC_ALPHA_LITERAL, + BFD_RELOC_ALPHA_LITUSE, + + /* The HINT relocation indicates a value that should be filled into the + "hint" field of a jmp/jsr/ret instruction, for possible branch- + prediction logic which may be provided on some processors. */ + BFD_RELOC_ALPHA_HINT, /* Bits 27..2 of the relocation address shifted right 2 bits; simple reloc otherwise. */ BFD_RELOC_MIPS_JMP, - /* signed 16-bit pc-relative, shifted right 2 bits (e.g. for MIPS) */ - BFD_RELOC_16_PCREL_S2, - /* High 16 bits of 32-bit value; simple reloc. */ BFD_RELOC_HI16, /* High 16 bits of 32-bit value but the low 16 bits will be sign @@ -1182,106 +1402,21 @@ typedef enum bfd_reloc_code_real BFD_RELOC_HI16_S, /* Low 16 bits. */ BFD_RELOC_LO16, + /* Like BFD_RELOC_HI16_S, but PC relative. */ + BFD_RELOC_PCREL_HI16_S, + /* Like BFD_RELOC_LO16, but PC relative. */ + BFD_RELOC_PCREL_LO16, - /* 16 bit relocation relative to the global pointer. */ - BFD_RELOC_MIPS_GPREL, - - /* These are, so far, specific to HPPA processors. I'm not sure that some - don't duplicate other reloc types, such as BFD_RELOC_32 and _32_PCREL. - Also, many more were in the list I got that don't fit in well in the - model BFD uses, so I've omitted them for now. If we do make this reloc - type get used for code that really does implement the funky reloc types, - they'll have to be added to this list. */ - BFD_RELOC_HPPA_32, - BFD_RELOC_HPPA_11, - BFD_RELOC_HPPA_14, - BFD_RELOC_HPPA_17, - - BFD_RELOC_HPPA_L21, - BFD_RELOC_HPPA_R11, - BFD_RELOC_HPPA_R14, - BFD_RELOC_HPPA_R17, - BFD_RELOC_HPPA_LS21, - BFD_RELOC_HPPA_RS11, - BFD_RELOC_HPPA_RS14, - BFD_RELOC_HPPA_RS17, - BFD_RELOC_HPPA_LD21, - BFD_RELOC_HPPA_RD11, - BFD_RELOC_HPPA_RD14, - BFD_RELOC_HPPA_RD17, - BFD_RELOC_HPPA_LR21, - BFD_RELOC_HPPA_RR14, - BFD_RELOC_HPPA_RR17, - - BFD_RELOC_HPPA_GOTOFF_11, - BFD_RELOC_HPPA_GOTOFF_14, - BFD_RELOC_HPPA_GOTOFF_L21, - BFD_RELOC_HPPA_GOTOFF_R11, - BFD_RELOC_HPPA_GOTOFF_R14, - BFD_RELOC_HPPA_GOTOFF_LS21, - BFD_RELOC_HPPA_GOTOFF_RS11, - BFD_RELOC_HPPA_GOTOFF_RS14, - BFD_RELOC_HPPA_GOTOFF_LD21, - BFD_RELOC_HPPA_GOTOFF_RD11, - BFD_RELOC_HPPA_GOTOFF_RD14, - BFD_RELOC_HPPA_GOTOFF_LR21, - BFD_RELOC_HPPA_GOTOFF_RR14, - - BFD_RELOC_HPPA_DLT_32, - BFD_RELOC_HPPA_DLT_11, - BFD_RELOC_HPPA_DLT_14, - BFD_RELOC_HPPA_DLT_L21, - BFD_RELOC_HPPA_DLT_R11, - BFD_RELOC_HPPA_DLT_R14, - - BFD_RELOC_HPPA_ABS_CALL_11, - BFD_RELOC_HPPA_ABS_CALL_14, - BFD_RELOC_HPPA_ABS_CALL_17, - BFD_RELOC_HPPA_ABS_CALL_L21, - BFD_RELOC_HPPA_ABS_CALL_R11, - BFD_RELOC_HPPA_ABS_CALL_R14, - BFD_RELOC_HPPA_ABS_CALL_R17, - BFD_RELOC_HPPA_ABS_CALL_LS21, - BFD_RELOC_HPPA_ABS_CALL_RS11, - BFD_RELOC_HPPA_ABS_CALL_RS14, - BFD_RELOC_HPPA_ABS_CALL_RS17, - BFD_RELOC_HPPA_ABS_CALL_LD21, - BFD_RELOC_HPPA_ABS_CALL_RD11, - BFD_RELOC_HPPA_ABS_CALL_RD14, - BFD_RELOC_HPPA_ABS_CALL_RD17, - BFD_RELOC_HPPA_ABS_CALL_LR21, - BFD_RELOC_HPPA_ABS_CALL_RR14, - BFD_RELOC_HPPA_ABS_CALL_RR17, - - BFD_RELOC_HPPA_PCREL_CALL_11, - BFD_RELOC_HPPA_PCREL_CALL_12, - BFD_RELOC_HPPA_PCREL_CALL_14, - BFD_RELOC_HPPA_PCREL_CALL_17, - BFD_RELOC_HPPA_PCREL_CALL_L21, - BFD_RELOC_HPPA_PCREL_CALL_R11, - BFD_RELOC_HPPA_PCREL_CALL_R14, - BFD_RELOC_HPPA_PCREL_CALL_R17, - BFD_RELOC_HPPA_PCREL_CALL_LS21, - BFD_RELOC_HPPA_PCREL_CALL_RS11, - BFD_RELOC_HPPA_PCREL_CALL_RS14, - BFD_RELOC_HPPA_PCREL_CALL_RS17, - BFD_RELOC_HPPA_PCREL_CALL_LD21, - BFD_RELOC_HPPA_PCREL_CALL_RD11, - BFD_RELOC_HPPA_PCREL_CALL_RD14, - BFD_RELOC_HPPA_PCREL_CALL_RD17, - BFD_RELOC_HPPA_PCREL_CALL_LR21, - BFD_RELOC_HPPA_PCREL_CALL_RR14, - BFD_RELOC_HPPA_PCREL_CALL_RR17, - - BFD_RELOC_HPPA_PLABEL_32, - BFD_RELOC_HPPA_PLABEL_11, - BFD_RELOC_HPPA_PLABEL_14, - BFD_RELOC_HPPA_PLABEL_L21, - BFD_RELOC_HPPA_PLABEL_R11, - BFD_RELOC_HPPA_PLABEL_R14, - - BFD_RELOC_HPPA_UNWIND_ENTRY, - BFD_RELOC_HPPA_UNWIND_ENTRIES, + /* relocation relative to the global pointer. */ +#define BFD_RELOC_MIPS_GPREL BFD_RELOC_GPREL16 + + /* Relocation against a MIPS literal section. */ + BFD_RELOC_MIPS_LITERAL, + + /* MIPS ELF relocations. */ + BFD_RELOC_MIPS_GOT16, + BFD_RELOC_MIPS_CALL16, +#define BFD_RELOC_MIPS_GPREL32 BFD_RELOC_GPREL32 /* i386/elf relocations */ BFD_RELOC_386_GOT32, @@ -1293,15 +1428,38 @@ typedef enum bfd_reloc_code_real BFD_RELOC_386_GOTOFF, BFD_RELOC_386_GOTPC, + /* ns32k relocations */ + BFD_RELOC_NS32K_IMM_8, + BFD_RELOC_NS32K_IMM_16, + BFD_RELOC_NS32K_IMM_32, + BFD_RELOC_NS32K_IMM_8_PCREL, + BFD_RELOC_NS32K_IMM_16_PCREL, + BFD_RELOC_NS32K_IMM_32_PCREL, + BFD_RELOC_NS32K_DISP_8, + BFD_RELOC_NS32K_DISP_16, + BFD_RELOC_NS32K_DISP_32, + BFD_RELOC_NS32K_DISP_8_PCREL, + BFD_RELOC_NS32K_DISP_16_PCREL, + BFD_RELOC_NS32K_DISP_32_PCREL, + + /* PowerPC/POWER (RS/6000) relocs. */ + /* 26 bit relative branch. Low two bits must be zero. High 24 + bits installed in bits 6 through 29 of instruction. */ + BFD_RELOC_PPC_B26, + /* 26 bit absolute branch, like BFD_RELOC_PPC_B26 but absolute. */ + BFD_RELOC_PPC_BA26, + /* 16 bit TOC relative reference. */ + BFD_RELOC_PPC_TOC16, + /* this must be the highest numeric value */ BFD_RELOC_UNUSED } bfd_reloc_code_real_type; -CONST struct reloc_howto_struct * +const struct reloc_howto_struct * bfd_reloc_type_lookup PARAMS ((bfd *abfd, bfd_reloc_code_real_type code)); -typedef struct symbol_cache_entry +typedef struct symbol_cache_entry { /* A pointer to the BFD which owns the symbol. This information is necessary so that a back end can work out what additional @@ -1315,7 +1473,7 @@ typedef struct symbol_cache_entry struct _bfd *the_bfd; /* Use bfd_asymbol_bfd(sym) to access this field. */ - /* The text of the symbol. The name is left alone, and not copied - the + /* The text of the symbol. The name is left alone, and not copied; the application may not alter it. */ CONST char *name; @@ -1336,7 +1494,7 @@ typedef struct symbol_cache_entry value is the offset into the section of the data. */ #define BSF_GLOBAL 0x02 - /* The symbol has global scope, and is exported. The value is + /* The symbol has global scope and is exported. The value is the offset into the section of the data. */ #define BSF_EXPORT BSF_GLOBAL /* no real difference */ @@ -1397,9 +1555,12 @@ typedef struct symbol_cache_entry for ELF STT_FILE symbols. */ #define BSF_FILE 0x4000 + /* Symbol is from dynamic linking information. */ +#define BSF_DYNAMIC 0x8000 + flagword flags; - /* A pointer to the section to which this symbol is + /* A pointer to the section to which this symbol is relative. This will always be non NULL, there are special sections for undefined and absolute symbols */ struct sec *section; @@ -1409,13 +1570,18 @@ typedef struct symbol_cache_entry PTR udata; } asymbol; -#define get_symtab_upper_bound(abfd) \ - BFD_SEND (abfd, _get_symtab_upper_bound, (abfd)) +#define bfd_get_symtab_upper_bound(abfd) \ + BFD_SEND (abfd, _bfd_get_symtab_upper_bound, (abfd)) +boolean +bfd_is_local_label PARAMS ((bfd *abfd, asymbol *sym)); + +#define bfd_is_local_label(abfd, sym) \ + BFD_SEND (abfd, _bfd_is_local_label,(abfd, sym)) #define bfd_canonicalize_symtab(abfd, location) \ BFD_SEND (abfd, _bfd_canonicalize_symtab,\ (abfd, location)) boolean -bfd_set_symtab PARAMS ((bfd *, asymbol **, unsigned int )); +bfd_set_symtab PARAMS ((bfd *abfd, asymbol **location, unsigned int count)); void bfd_print_symbol_vandf PARAMS ((PTR file, asymbol *symbol)); @@ -1436,7 +1602,7 @@ struct _bfd CONST char *filename; /* A pointer to the target jump table. */ - struct bfd_target *xvec; + const 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 @@ -1445,13 +1611,14 @@ struct _bfd is the result of an fopen on the filename. */ char *iostream; - /* Is the file being cached */ + /* Is the file descriptor being cached? That is, can it be closed as + needed, and re-opened when accessed later? */ 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. */ + BFD was opened. This is used to select which matching algorithm + to use to choose the back end. */ boolean target_defaulted; @@ -1461,12 +1628,11 @@ struct _bfd struct _bfd *lru_prev, *lru_next; /* When a file is closed by the caching routines, BFD retains - state information on the file here: - */ + state information on the file here: */ file_ptr where; - /* and here:*/ + /* and here: (``once'' means at least once) */ boolean opened_once; @@ -1483,7 +1649,7 @@ struct _bfd int ifd; - /* The format which belongs to the BFD.*/ + /* The format which belongs to the BFD. (object, core, etc.) */ bfd_format format; @@ -1505,7 +1671,7 @@ struct _bfd file_ptr origin; /* Remember when output has begun, to stop strange things - happening. */ + from happening. */ boolean output_has_begun; /* Pointer to linked list of sections*/ @@ -1521,7 +1687,7 @@ struct _bfd /* Used for input and output*/ unsigned int symcount; - /* Symbol table for output BFD*/ + /* Symbol table for output BFD (with symcount entries) */ struct symbol_cache_entry **outsymbols; /* Pointer to structure which contains architecture information*/ @@ -1529,11 +1695,18 @@ struct _bfd /* Stuff only useful for archives:*/ PTR arelt_data; - struct _bfd *my_archive; - struct _bfd *next; - struct _bfd *archive_head; + struct _bfd *my_archive; /* The containing archive BFD. */ + struct _bfd *next; /* The next BFD in the archive. */ + struct _bfd *archive_head; /* The first BFD in the archive. */ boolean has_armap; + /* A chain of BFD structures involved in a link. */ + struct _bfd *link_next; + + /* A field used by _bfd_generic_link_add_archive_symbols. This will + be used only for archive elements. */ + int archive_pass; + /* Used by the back end to hold private data. */ union @@ -1553,11 +1726,13 @@ struct _bfd struct bout_data_struct *bout_data; struct sun_core_struct *sun_core_data; struct trad_core_struct *trad_core_data; - struct hppa_data_struct *hppa_data; + struct som_data_struct *som_data; struct hpux_core_struct *hpux_core_data; + struct hppabsd_core_struct *hppabsd_core_data; struct sgi_core_struct *sgi_core_data; struct lynx_core_struct *lynx_core_data; struct osf_core_struct *osf_core_data; + struct cisco_core_struct *cisco_core_data; PTR any; } tdata; @@ -1566,24 +1741,51 @@ struct _bfd /* Where all the allocated stuff under this BFD goes */ struct obstack memory; - - /* Is this really needed in addition to usrdata? */ - asymbol **ld_symbols; }; -unsigned int +typedef enum bfd_error +{ + bfd_error_no_error = 0, + bfd_error_system_call, + bfd_error_invalid_target, + bfd_error_wrong_format, + bfd_error_invalid_operation, + bfd_error_no_memory, + bfd_error_no_symbols, + bfd_error_no_more_archived_files, + bfd_error_malformed_archive, + bfd_error_file_not_recognized, + bfd_error_file_ambiguously_recognized, + bfd_error_no_contents, + bfd_error_nonrepresentable_section, + bfd_error_no_debug_section, + bfd_error_bad_value, + bfd_error_file_truncated, + bfd_error_invalid_error_code +} bfd_error_type; + +bfd_error_type +bfd_get_error PARAMS ((void)); + +void +bfd_set_error PARAMS ((bfd_error_type error_tag)); + +CONST char * +bfd_errmsg PARAMS ((bfd_error_type error_tag)); + +void +bfd_perror PARAMS ((CONST char *message)); + +long bfd_get_reloc_upper_bound PARAMS ((bfd *abfd, asection *sect)); -unsigned int +long bfd_canonicalize_reloc PARAMS ((bfd *abfd, asection *sec, arelent **loc, asymbol **syms)); -boolean -bfd_set_file_flags PARAMS ((bfd *abfd, flagword flags)); - void bfd_set_reloc PARAMS ((bfd *abfd, asection *sec, arelent **rel, unsigned int count) @@ -1591,23 +1793,32 @@ bfd_set_reloc ); boolean -bfd_set_start_address PARAMS ((bfd *, bfd_vma)); +bfd_set_file_flags PARAMS ((bfd *abfd, flagword flags)); + +boolean +bfd_set_start_address PARAMS ((bfd *abfd, bfd_vma vma)); long -bfd_get_mtime PARAMS ((bfd *)); +bfd_get_mtime PARAMS ((bfd *abfd)); long -bfd_get_size PARAMS ((bfd *)); +bfd_get_size PARAMS ((bfd *abfd)); int -bfd_get_gp_size PARAMS ((bfd *)); +bfd_get_gp_size PARAMS ((bfd *abfd)); void -bfd_set_gp_size PARAMS ((bfd *, int)); +bfd_set_gp_size PARAMS ((bfd *abfd, int i)); bfd_vma bfd_scan_vma PARAMS ((CONST char *string, CONST char **end, int base)); +boolean +bfd_copy_private_bfd_data PARAMS ((bfd *ibfd, bfd *obfd)); + +#define bfd_copy_private_bfd_data(ibfd, obfd) \ + BFD_SEND (ibfd, _bfd_copy_private_bfd_data, \ + (ibfd, obfd)) #define bfd_sizeof_headers(abfd, reloc) \ BFD_SEND (abfd, _bfd_sizeof_headers, (abfd, reloc)) @@ -1631,31 +1842,54 @@ bfd_scan_vma PARAMS ((CONST char *string, CONST char **end, int base)); #define bfd_set_arch_mach(abfd, arch, mach)\ BFD_SEND ( abfd, _bfd_set_arch_mach, (abfd, arch, mach)) -#define bfd_get_relocated_section_contents(abfd, seclet, data, relocateable) \ - BFD_SEND (abfd, _bfd_get_relocated_section_contents, (abfd, seclet, data, relocateable)) +#define bfd_get_relocated_section_contents(abfd, link_info, link_order, data, relocateable, symbols) \ + BFD_SEND (abfd, _bfd_get_relocated_section_contents, \ + (abfd, link_info, link_order, data, relocateable, symbols)) -#define bfd_relax_section(abfd, section, symbols) \ - BFD_SEND (abfd, _bfd_relax_section, (abfd, section, symbols)) +#define bfd_relax_section(abfd, section, link_info, again) \ + BFD_SEND (abfd, _bfd_relax_section, (abfd, section, link_info, again)) + +#define bfd_link_hash_table_create(abfd) \ + BFD_SEND (abfd, _bfd_link_hash_table_create, (abfd)) + +#define bfd_link_add_symbols(abfd, info) \ + BFD_SEND (abfd, _bfd_link_add_symbols, (abfd, info)) + +#define bfd_final_link(abfd, info) \ + BFD_SEND (abfd, _bfd_final_link, (abfd, info)) + +#define bfd_free_cached_info(abfd) \ + BFD_SEND (abfd, _bfd_free_cached_info, (abfd)) + +#define bfd_get_dynamic_symtab_upper_bound(abfd) \ + BFD_SEND (abfd, _bfd_get_dynamic_symtab_upper_bound, (abfd)) + +#define bfd_canonicalize_dynamic_symtab(abfd, asymbols) \ + BFD_SEND (abfd, _bfd_canonicalize_dynamic_symtab, (abfd, asymbols)) + +#define bfd_get_dynamic_reloc_upper_bound(abfd) \ + BFD_SEND (abfd, _bfd_get_dynamic_reloc_upper_bound, (abfd)) + +#define bfd_canonicalize_dynamic_reloc(abfd, arels, asyms) \ + BFD_SEND (abfd, _bfd_canonicalize_dynamic_reloc, (abfd, arels, asyms)) -#define bfd_seclet_link(abfd, data, relocateable) \ - BFD_SEND (abfd, _bfd_seclet_link, (abfd, data, relocateable)) symindex -bfd_get_next_mapent PARAMS ((bfd *, symindex previous, carsym ** sym)); +bfd_get_next_mapent PARAMS ((bfd *abfd, symindex previous, carsym **sym)); boolean bfd_set_archive_head PARAMS ((bfd *output, bfd *new_head)); bfd * -bfd_get_elt_at_index PARAMS ((bfd * archive, int index)); +bfd_get_elt_at_index PARAMS ((bfd *archive, int index)); -bfd* +bfd * bfd_openr_next_archived_file PARAMS ((bfd *archive, bfd *previous)); CONST char * -bfd_core_file_failing_command PARAMS ((bfd *)); +bfd_core_file_failing_command PARAMS ((bfd *abfd)); int -bfd_core_file_failing_signal PARAMS ((bfd *)); +bfd_core_file_failing_signal PARAMS ((bfd *abfd)); boolean core_file_matches_executable_p @@ -1663,23 +1897,45 @@ core_file_matches_executable_p #define BFD_SEND(bfd, message, arglist) \ ((*((bfd)->xvec->message)) arglist) + +#ifdef DEBUG_BFD_SEND +#undef BFD_SEND +#define BFD_SEND(bfd, message, arglist) \ + (((bfd) && (bfd)->xvec && (bfd)->xvec->message) ? \ + ((*((bfd)->xvec->message)) arglist) : \ + (bfd_assert (__FILE__,__LINE__), NULL)) +#endif #define BFD_SEND_FMT(bfd, message, arglist) \ (((bfd)->xvec->message[(int)((bfd)->format)]) arglist) + +#ifdef DEBUG_BFD_SEND +#undef BFD_SEND_FMT +#define BFD_SEND_FMT(bfd, message, arglist) \ + (((bfd) && (bfd)->xvec && (bfd)->xvec->message) ? \ + (((bfd)->xvec->message[(int)((bfd)->format)]) arglist) : \ + (bfd_assert (__FILE__,__LINE__), NULL)) +#endif +enum bfd_flavour { + bfd_target_unknown_flavour, + bfd_target_aout_flavour, + bfd_target_coff_flavour, + bfd_target_ecoff_flavour, + bfd_target_elf_flavour, + bfd_target_ieee_flavour, + bfd_target_nlm_flavour, + bfd_target_oasys_flavour, + bfd_target_tekhex_flavour, + bfd_target_srec_flavour, + bfd_target_som_flavour, + bfd_target_os9k_flavour}; + + /* Forward declaration. */ +typedef struct bfd_link_info _bfd_link_info; + typedef struct bfd_target { char *name; - enum target_flavour { - bfd_target_unknown_flavour, - bfd_target_aout_flavour, - bfd_target_coff_flavour, - bfd_target_ecoff_flavour, - bfd_target_elf_flavour, - bfd_target_ieee_flavour, - bfd_target_nlm_flavour, - bfd_target_oasys_flavour, - bfd_target_tekhex_flavour, - bfd_target_srec_flavour, - bfd_target_hppa_flavour} flavour; + enum bfd_flavour flavour; boolean byteorder_big_p; boolean header_byteorder_big_p; flagword object_flags; @@ -1688,30 +1944,73 @@ typedef struct bfd_target char ar_pad_char; unsigned short ar_max_namelen; unsigned int align_power_min; - bfd_vma (*bfd_getx64) PARAMS ((bfd_byte *)); - bfd_signed_vma (*bfd_getx_signed_64) PARAMS ((bfd_byte *)); + bfd_vma (*bfd_getx64) PARAMS ((const bfd_byte *)); + bfd_signed_vma (*bfd_getx_signed_64) PARAMS ((const bfd_byte *)); void (*bfd_putx64) PARAMS ((bfd_vma, bfd_byte *)); - bfd_vma (*bfd_getx32) PARAMS ((bfd_byte *)); - bfd_signed_vma (*bfd_getx_signed_32) PARAMS ((bfd_byte *)); + bfd_vma (*bfd_getx32) PARAMS ((const bfd_byte *)); + bfd_signed_vma (*bfd_getx_signed_32) PARAMS ((const bfd_byte *)); void (*bfd_putx32) PARAMS ((bfd_vma, bfd_byte *)); - bfd_vma (*bfd_getx16) PARAMS ((bfd_byte *)); - bfd_signed_vma (*bfd_getx_signed_16) PARAMS ((bfd_byte *)); + bfd_vma (*bfd_getx16) PARAMS ((const bfd_byte *)); + bfd_signed_vma (*bfd_getx_signed_16) PARAMS ((const bfd_byte *)); void (*bfd_putx16) PARAMS ((bfd_vma, bfd_byte *)); - bfd_vma (*bfd_h_getx64) PARAMS ((bfd_byte *)); - bfd_signed_vma (*bfd_h_getx_signed_64) PARAMS ((bfd_byte *)); + bfd_vma (*bfd_h_getx64) PARAMS ((const bfd_byte *)); + bfd_signed_vma (*bfd_h_getx_signed_64) PARAMS ((const bfd_byte *)); void (*bfd_h_putx64) PARAMS ((bfd_vma, bfd_byte *)); - bfd_vma (*bfd_h_getx32) PARAMS ((bfd_byte *)); - bfd_signed_vma (*bfd_h_getx_signed_32) PARAMS ((bfd_byte *)); + bfd_vma (*bfd_h_getx32) PARAMS ((const bfd_byte *)); + bfd_signed_vma (*bfd_h_getx_signed_32) PARAMS ((const bfd_byte *)); void (*bfd_h_putx32) PARAMS ((bfd_vma, bfd_byte *)); - bfd_vma (*bfd_h_getx16) PARAMS ((bfd_byte *)); - bfd_signed_vma (*bfd_h_getx_signed_16) PARAMS ((bfd_byte *)); + bfd_vma (*bfd_h_getx16) PARAMS ((const bfd_byte *)); + bfd_signed_vma (*bfd_h_getx_signed_16) PARAMS ((const bfd_byte *)); void (*bfd_h_putx16) PARAMS ((bfd_vma, bfd_byte *)); - struct bfd_target * (*_bfd_check_format[bfd_type_end]) PARAMS ((bfd *)); + const struct bfd_target *(*_bfd_check_format[bfd_type_end]) PARAMS ((bfd *)); boolean (*_bfd_set_format[bfd_type_end]) PARAMS ((bfd *)); boolean (*_bfd_write_contents[bfd_type_end]) PARAMS ((bfd *)); + + /* Generic entry points. */ +#define BFD_JUMP_TABLE_GENERIC(NAME)\ +CAT(NAME,_close_and_cleanup),\ +CAT(NAME,_bfd_free_cached_info),\ +CAT(NAME,_new_section_hook),\ +CAT(NAME,_get_section_contents) + /* Called when the BFD is being closed to do any necessary cleanup. */ + boolean (*_close_and_cleanup) PARAMS ((bfd *)); + /* Ask the BFD to free all cached information. */ + boolean (*_bfd_free_cached_info) PARAMS ((bfd *)); + /* Called when a new section is created. */ + boolean (*_new_section_hook) PARAMS ((bfd *, sec_ptr)); + /* Read the contents of a section. */ + boolean (*_bfd_get_section_contents) PARAMS ((bfd *, sec_ptr, PTR, + file_ptr, bfd_size_type)); + + /* Entry points to copy private data. */ +#define BFD_JUMP_TABLE_COPY(NAME)\ +CAT(NAME,_bfd_copy_private_bfd_data),\ +CAT(NAME,_bfd_copy_private_section_data) + /* Called to copy BFD general private data from one object file + to another. */ + boolean (*_bfd_copy_private_bfd_data) PARAMS ((bfd *, bfd *)); + /* Called to copy BFD private section data from one object file + to another. */ + boolean (*_bfd_copy_private_section_data) PARAMS ((bfd *, sec_ptr, + bfd *, sec_ptr)); + + /* Core file entry points. */ +#define BFD_JUMP_TABLE_CORE(NAME)\ +CAT(NAME,_core_file_failing_command),\ +CAT(NAME,_core_file_failing_signal),\ +CAT(NAME,_core_file_matches_executable_p) char * (*_core_file_failing_command) PARAMS ((bfd *)); int (*_core_file_failing_signal) PARAMS ((bfd *)); boolean (*_core_file_matches_executable_p) PARAMS ((bfd *, bfd *)); + + /* Archive entry points. */ +#define BFD_JUMP_TABLE_ARCHIVE(NAME)\ +CAT(NAME,_slurp_armap),\ +CAT(NAME,_slurp_extended_name_table),\ +CAT(NAME,_truncate_arname),\ +CAT(NAME,_write_armap),\ +CAT(NAME,_openr_next_archived_file),\ +CAT(NAME,_generic_stat_arch_elt) boolean (*_bfd_slurp_armap) PARAMS ((bfd *)); boolean (*_bfd_slurp_extended_name_table) PARAMS ((bfd *)); void (*_bfd_truncate_arname) PARAMS ((bfd *, CONST char *, char *)); @@ -1720,18 +2019,23 @@ typedef struct bfd_target struct orl *map, unsigned int orl_count, int stridx)); - boolean (*_close_and_cleanup) PARAMS ((bfd *)); - boolean (*_bfd_set_section_contents) PARAMS ((bfd *, sec_ptr, PTR, - file_ptr, bfd_size_type)); - boolean (*_bfd_get_section_contents) PARAMS ((bfd *, sec_ptr, PTR, - file_ptr, bfd_size_type)); - boolean (*_new_section_hook) PARAMS ((bfd *, sec_ptr)); - unsigned int (*_get_symtab_upper_bound) PARAMS ((bfd *)); - unsigned int (*_bfd_canonicalize_symtab) PARAMS ((bfd *, - struct symbol_cache_entry **)); - unsigned int (*_get_reloc_upper_bound) PARAMS ((bfd *, sec_ptr)); - unsigned int (*_bfd_canonicalize_reloc) PARAMS ((bfd *, sec_ptr, arelent **, - struct symbol_cache_entry **)); + bfd * (*openr_next_archived_file) PARAMS ((bfd *arch, bfd *prev)); + int (*_bfd_stat_arch_elt) PARAMS ((bfd *, struct stat *)); + + /* Entry points used for symbols. */ +#define BFD_JUMP_TABLE_SYMBOLS(NAME)\ +CAT(NAME,_get_symtab_upper_bound),\ +CAT(NAME,_get_symtab),\ +CAT(NAME,_make_empty_symbol),\ +CAT(NAME,_print_symbol),\ +CAT(NAME,_get_symbol_info),\ +CAT(NAME,_bfd_is_local_label),\ +CAT(NAME,_get_lineno),\ +CAT(NAME,_find_nearest_line),\ +CAT(NAME,_bfd_make_debug_symbol) + long (*_bfd_get_symtab_upper_bound) PARAMS ((bfd *)); + long (*_bfd_canonicalize_symtab) PARAMS ((bfd *, + struct symbol_cache_entry **)); struct symbol_cache_entry * (*_bfd_make_empty_symbol) PARAMS ((bfd *)); void (*_bfd_print_symbol) PARAMS ((bfd *, PTR, @@ -1742,40 +2046,13 @@ typedef struct bfd_target struct symbol_cache_entry *, symbol_info *)); #define bfd_get_symbol_info(b,p,e) BFD_SEND(b, _bfd_get_symbol_info, (b,p,e)) - alent * (*_get_lineno) PARAMS ((bfd *, struct symbol_cache_entry *)); + boolean (*_bfd_is_local_label) PARAMS ((bfd *, asymbol *)); - boolean (*_bfd_set_arch_mach) PARAMS ((bfd *, enum bfd_architecture, - unsigned long)); - - bfd * (*openr_next_archived_file) PARAMS ((bfd *arch, bfd *prev)); - + alent * (*_get_lineno) PARAMS ((bfd *, struct symbol_cache_entry *)); boolean (*_bfd_find_nearest_line) PARAMS ((bfd *abfd, struct sec *section, struct symbol_cache_entry **symbols, bfd_vma offset, CONST char **file, CONST char **func, unsigned int *line)); - - int (*_bfd_stat_arch_elt) PARAMS ((bfd *, struct stat *)); - - int (*_bfd_sizeof_headers) PARAMS ((bfd *, boolean)); - - void (*_bfd_debug_info_start) PARAMS ((bfd *)); - void (*_bfd_debug_info_end) PARAMS ((bfd *)); - void (*_bfd_debug_info_accumulate) PARAMS ((bfd *, struct sec *)); - - bfd_byte * (*_bfd_get_relocated_section_contents) PARAMS ((bfd *, - struct bfd_seclet *, bfd_byte *data, - boolean relocateable)); - - boolean (*_bfd_relax_section) PARAMS ((bfd *, struct sec *, - struct symbol_cache_entry **)); - - boolean (*_bfd_seclet_link) PARAMS ((bfd *, PTR data, - boolean relocateable)); - /* See documentation on reloc types. */ - CONST struct reloc_howto_struct * - (*reloc_type_lookup) PARAMS ((bfd *abfd, - bfd_reloc_code_real_type code)); - /* Back-door to allow format-aware applications to create debug symbols while using BFD for everything else. Currently used by the assembler when creating COFF files. */ @@ -1783,21 +2060,92 @@ typedef struct bfd_target bfd *abfd, void *ptr, unsigned long size)); + + /* Routines for relocs. */ +#define BFD_JUMP_TABLE_RELOCS(NAME)\ +CAT(NAME,_get_reloc_upper_bound),\ +CAT(NAME,_canonicalize_reloc),\ +CAT(NAME,_bfd_reloc_type_lookup) + long (*_get_reloc_upper_bound) PARAMS ((bfd *, sec_ptr)); + long (*_bfd_canonicalize_reloc) PARAMS ((bfd *, sec_ptr, arelent **, + struct symbol_cache_entry **)); + /* See documentation on reloc types. */ + CONST struct reloc_howto_struct * + (*reloc_type_lookup) PARAMS ((bfd *abfd, + bfd_reloc_code_real_type code)); + + /* Routines used when writing an object file. */ +#define BFD_JUMP_TABLE_WRITE(NAME)\ +CAT(NAME,_set_arch_mach),\ +CAT(NAME,_set_section_contents) + boolean (*_bfd_set_arch_mach) PARAMS ((bfd *, enum bfd_architecture, + unsigned long)); + boolean (*_bfd_set_section_contents) PARAMS ((bfd *, sec_ptr, PTR, + file_ptr, bfd_size_type)); + + /* Routines used by the linker. */ +#define BFD_JUMP_TABLE_LINK(NAME)\ +CAT(NAME,_sizeof_headers),\ +CAT(NAME,_bfd_get_relocated_section_contents),\ +CAT(NAME,_bfd_relax_section),\ +CAT(NAME,_bfd_link_hash_table_create),\ +CAT(NAME,_bfd_link_add_symbols),\ +CAT(NAME,_bfd_final_link) + int (*_bfd_sizeof_headers) PARAMS ((bfd *, boolean)); + bfd_byte * (*_bfd_get_relocated_section_contents) PARAMS ((bfd *, + struct bfd_link_info *, struct bfd_link_order *, + bfd_byte *data, boolean relocateable, + struct symbol_cache_entry **)); + + boolean (*_bfd_relax_section) PARAMS ((bfd *, struct sec *, + struct bfd_link_info *, boolean *again)); + + /* Create a hash table for the linker. Different backends store + different information in this table. */ + struct bfd_link_hash_table *(*_bfd_link_hash_table_create) PARAMS ((bfd *)); + + /* Add symbols from this object file into the hash table. */ + boolean (*_bfd_link_add_symbols) PARAMS ((bfd *, struct bfd_link_info *)); + + /* Do a link based on the link_order structures attached to each + section of the BFD. */ + boolean (*_bfd_final_link) PARAMS ((bfd *, struct bfd_link_info *)); + + /* Routines to handle dynamic symbols and relocs. */ +#define BFD_JUMP_TABLE_DYNAMIC(NAME)\ +CAT(NAME,_get_dynamic_symtab_upper_bound),\ +CAT(NAME,_canonicalize_dynamic_symtab),\ +CAT(NAME,_get_dynamic_reloc_upper_bound),\ +CAT(NAME,_canonicalize_dynamic_reloc) + /* Get the amount of memory required to hold the dynamic symbols. */ + long (*_bfd_get_dynamic_symtab_upper_bound) PARAMS ((bfd *)); + /* Read in the dynamic symbols. */ + long (*_bfd_canonicalize_dynamic_symtab) + PARAMS ((bfd *, struct symbol_cache_entry **)); + /* Get the amount of memory required to hold the dynamic relocs. */ + long (*_bfd_get_dynamic_reloc_upper_bound) PARAMS ((bfd *)); + /* Read in the dynamic relocs. */ + long (*_bfd_canonicalize_dynamic_reloc) + PARAMS ((bfd *, arelent **, struct symbol_cache_entry **)); + PTR backend_data; } bfd_target; -bfd_target * -bfd_find_target PARAMS ((CONST char *, bfd *)); +const bfd_target * +bfd_find_target PARAMS ((CONST char *target_name, bfd *abfd)); -CONST char ** +const char ** bfd_target_list PARAMS ((void)); boolean bfd_check_format PARAMS ((bfd *abfd, bfd_format format)); boolean -bfd_set_format PARAMS ((bfd *, bfd_format)); +bfd_check_format_matches PARAMS ((bfd *abfd, bfd_format format, char ***matching)); + +boolean +bfd_set_format PARAMS ((bfd *abfd, bfd_format format)); CONST char * -bfd_format_string PARAMS ((bfd_format)); +bfd_format_string PARAMS ((bfd_format format)); #endif diff --git a/gnu/usr.bin/gdb/bfd/cache.c b/gnu/usr.bin/gdb/bfd/cache.c index f8cfd19fed5c..a26c3ce57672 100644 --- a/gnu/usr.bin/gdb/bfd/cache.c +++ b/gnu/usr.bin/gdb/bfd/cache.c @@ -1,5 +1,5 @@ /* BFD library -- caching of file descriptors. - Copyright 1990, 1991, 1992 Free Software Foundation, Inc. + Copyright 1990, 1991, 1992, 1994 Free Software Foundation, Inc. Hacked by Steve Chamberlain of Cygnus Support (steve@cygnus.com). This file is part of BFD, the Binary File Descriptor library. @@ -20,7 +20,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ /* SECTION - File Caching + File caching The file caching mechanism is embedded within BFD and allows the application to open as many BFDs as it wants without @@ -28,7 +28,7 @@ SECTION limit (often as low as 20 open files). The module in <<cache.c>> maintains a least recently used list of <<BFD_CACHE_MAX_OPEN>> files, and exports the name - <<bfd_cache_lookup>> which runs around and makes sure that + <<bfd_cache_lookup>>, which runs around and makes sure that the required BFD is open. If not, then it chooses a file to close, closes it and opens the one wanted, returning its file handle. @@ -39,6 +39,11 @@ SECTION #include "sysdep.h" #include "libbfd.h" +static void insert PARAMS ((bfd *)); +static void snip PARAMS ((bfd *)); +static boolean close_one PARAMS ((void)); +static boolean bfd_cache_delete PARAMS ((bfd *)); + /* INTERNAL_FUNCTION BFD_CACHE_MAX_OPEN macro @@ -51,18 +56,10 @@ DESCRIPTION */ - -static boolean -bfd_cache_delete PARAMS ((bfd *)); - -/* Number of bfds on the chain. All such bfds have their file open; - if it closed, they get snipd()d from the chain. */ +/* The number of BFD files we have open. */ static int open_files; -static bfd *cache_sentinel; /* Chain of BFDs with active fds we've - opened */ - /* INTERNAL_FUNCTION bfd_last_cache @@ -79,233 +76,268 @@ DESCRIPTION bfd *bfd_last_cache; /* - * INTERNAL_FUNCTION - * bfd_cache_lookup - * - * DESCRIPTION - * 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)) - * - * + INTERNAL_FUNCTION + bfd_cache_lookup + + DESCRIPTION + Check to see if the required BFD is the same as the last one + looked up. If so, then it can use the stream 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)) + + */ -static void -DEFUN_VOID(close_one) +/* Insert a BFD into the cache. */ + +static INLINE void +insert (abfd) + bfd *abfd; { - bfd *kill = cache_sentinel; - if (kill == 0) /* Nothing in the cache */ - return ; - - /* We can only close files that want to play this game. */ - while (!kill->cacheable) { - kill = kill->lru_prev; - if (kill == cache_sentinel) /* Nobody wants to play */ - return ; + if (bfd_last_cache == NULL) + { + abfd->lru_next = abfd; + abfd->lru_prev = abfd; } - - kill->where = ftell((FILE *)(kill->iostream)); - (void) bfd_cache_delete(kill); + else + { + abfd->lru_next = bfd_last_cache; + abfd->lru_prev = bfd_last_cache->lru_prev; + abfd->lru_prev->lru_next = abfd; + abfd->lru_next->lru_prev = abfd; + } + bfd_last_cache = abfd; } -/* Cuts the BFD abfd out of the chain in the cache */ -static void -DEFUN(snip,(abfd), - bfd *abfd) +/* Remove a BFD from the cache. */ + +static INLINE void +snip (abfd) + bfd *abfd; { abfd->lru_prev->lru_next = abfd->lru_next; - abfd->lru_next->lru_prev = abfd->lru_prev; - if (cache_sentinel == abfd) cache_sentinel = (bfd *)NULL; + abfd->lru_next->lru_prev = abfd->lru_prev; + if (abfd == bfd_last_cache) + { + bfd_last_cache = abfd->lru_next; + if (abfd == bfd_last_cache) + bfd_last_cache = NULL; + } } +/* We need to open a new file, and the cache is full. Find the least + recently used cacheable BFD and close it. */ + static boolean -DEFUN(bfd_cache_delete,(abfd), - bfd *abfd) +close_one () +{ + register bfd *kill; + + if (bfd_last_cache == NULL) + kill = NULL; + else + { + for (kill = bfd_last_cache->lru_prev; + ! kill->cacheable; + kill = kill->lru_prev) + { + if (kill == bfd_last_cache) + { + kill = NULL; + break; + } + } + } + + if (kill == NULL) + { + /* There are no open cacheable BFD's. */ + return true; + } + + kill->where = ftell ((FILE *) kill->iostream); + + return bfd_cache_delete (kill); +} + +/* Close a BFD and remove it from the cache. */ + +static boolean +bfd_cache_delete (abfd) + bfd *abfd; { boolean ret; - if (fclose ((FILE *)(abfd->iostream)) == 0) + if (fclose ((FILE *) abfd->iostream) == 0) ret = true; else { ret = false; - bfd_error = system_call_error; + bfd_set_error (bfd_error_system_call); } + snip (abfd); + abfd->iostream = NULL; - open_files--; - bfd_last_cache = 0; + --open_files; + return ret; } - -static bfd * -DEFUN(insert,(x,y), - bfd *x AND - bfd *y) -{ - if (y) { - x->lru_next = y; - x->lru_prev = y->lru_prev; - y->lru_prev->lru_next = x; - y->lru_prev = x; - - } - else { - x->lru_prev = x; - x->lru_next = x; - } - return x; -} - -/* Initialize a BFD by putting it on the cache LRU. */ +/* +INTERNAL_FUNCTION + bfd_cache_init + +SYNOPSIS + boolean bfd_cache_init (bfd *abfd); -void -DEFUN(bfd_cache_init,(abfd), - bfd *abfd) +DESCRIPTION + Add a newly opened BFD to the cache. +*/ + +boolean +bfd_cache_init (abfd) + bfd *abfd; { + BFD_ASSERT (abfd->iostream != NULL); if (open_files >= BFD_CACHE_MAX_OPEN) - close_one (); - cache_sentinel = insert(abfd, cache_sentinel); + { + if (! close_one ()) + return false; + } + insert (abfd); ++open_files; + return true; } - /* INTERNAL_FUNCTION bfd_cache_close +SYNOPSIS + boolean bfd_cache_close (bfd *abfd); + DESCRIPTION - Remove the BFD from the cache. If the attached file is open, + Remove the BFD @var{abfd} from the cache. If the attached file is open, then close it too. -SYNOPSIS - boolean bfd_cache_close (bfd *); - RETURNS <<false>> is returned if closing the file fails, <<true>> is returned if all is well. */ + boolean -DEFUN(bfd_cache_close,(abfd), - bfd *abfd) +bfd_cache_close (abfd) + bfd *abfd; { - /* If this file is open then remove from the chain */ - if (abfd->iostream) - { - return bfd_cache_delete(abfd); - } - else - { - return true; - } + if (abfd->iostream == NULL) + return true; + + return bfd_cache_delete (abfd); } /* INTERNAL_FUNCTION bfd_open_file +SYNOPSIS + FILE* bfd_open_file(bfd *abfd); + DESCRIPTION - 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 + Call the OS to open a file for @var{abfd}. Return the <<FILE *>> + (possibly <<NULL>>) that results from this operation. Set up the + BFD so that future accesses know the file is open. If the <<FILE *>> + returned is <<NULL>>, then it won't have been put in the cache, so it won't have to be removed from it. - -SYNOPSIS - FILE* bfd_open_file(bfd *); */ FILE * -DEFUN(bfd_open_file, (abfd), - bfd *abfd) +bfd_open_file (abfd) + bfd *abfd; { abfd->cacheable = true; /* Allow it to be closed later. */ - if(open_files >= BFD_CACHE_MAX_OPEN) { - close_one(); - } - - switch (abfd->direction) { - case read_direction: - case no_direction: - abfd->iostream = (char *) fopen(abfd->filename, FOPEN_RB); - break; - case both_direction: - case write_direction: - if (abfd->opened_once == true) { - abfd->iostream = (char *) fopen(abfd->filename, FOPEN_RUB); - if (!abfd->iostream) { - abfd->iostream = (char *) fopen(abfd->filename, FOPEN_WUB); - } - } else { - /*open for creat */ - abfd->iostream = (char *) fopen(abfd->filename, FOPEN_WB); - abfd->opened_once = true; + if (open_files >= BFD_CACHE_MAX_OPEN) + { + if (! close_one ()) + return NULL; + } + + switch (abfd->direction) + { + case read_direction: + case no_direction: + abfd->iostream = (char *) fopen (abfd->filename, FOPEN_RB); + break; + case both_direction: + case write_direction: + if (abfd->opened_once == true) + { + abfd->iostream = (char *) fopen (abfd->filename, FOPEN_RUB); + if (abfd->iostream == NULL) + abfd->iostream = (char *) fopen (abfd->filename, FOPEN_WUB); + } + else + { + /*open for creat */ + abfd->iostream = (char *) fopen (abfd->filename, FOPEN_WB); + abfd->opened_once = true; + } + break; } - break; - } - if (abfd->iostream) { - bfd_cache_init (abfd); - } + if (abfd->iostream != NULL) + { + if (! bfd_cache_init (abfd)) + return NULL; + } - return (FILE *)(abfd->iostream); + return (FILE *) abfd->iostream; } /* INTERNAL_FUNCTION bfd_cache_lookup_worker +SYNOPSIS + FILE *bfd_cache_lookup_worker(bfd *abfd); + DESCRIPTION Called when the macro <<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 + quick answer. Find a file descriptor for @var{abfd}. If + necessary, it open it. If there are already more than + <<BFD_CACHE_MAX_OPEN>> files open, it tries to close one first, to avoid running out of file descriptors. - -SYNOPSIS - FILE *bfd_cache_lookup_worker(bfd *); - */ FILE * -DEFUN(bfd_cache_lookup_worker,(abfd), - bfd *abfd) +bfd_cache_lookup_worker (abfd) + bfd *abfd; { if (abfd->my_archive) - { - abfd = abfd->my_archive; - } - /* Is this file already open .. if so then quick exit */ - if (abfd->iostream) - { - if (abfd != cache_sentinel) { - /* Place onto head of lru chain */ + abfd = abfd->my_archive; + + if (abfd->iostream != NULL) + { + /* Move the file to the start of the cache. */ + if (abfd != bfd_last_cache) + { snip (abfd); - cache_sentinel = insert(abfd, cache_sentinel); + insert (abfd); } - } - /* This is a BFD without a stream - - so it must have been closed or never opened. - find an empty cache entry and use it. */ - else - { - - if (open_files >= BFD_CACHE_MAX_OPEN) - { - close_one(); - } + } + else + { + if (bfd_open_file (abfd) == NULL) + return NULL; + if (fseek ((FILE *) abfd->iostream, abfd->where, SEEK_SET) != 0) + return NULL; + } - BFD_ASSERT(bfd_open_file (abfd) != (FILE *)NULL) ; - fseek((FILE *)(abfd->iostream), abfd->where, false); - } - bfd_last_cache = abfd; - return (FILE *)(abfd->iostream); + return (FILE *) abfd->iostream; } diff --git a/gnu/usr.bin/gdb/bfd/coffgen.c b/gnu/usr.bin/gdb/bfd/coffgen.c index 94cc225d098c..f0c05c7f8b90 100644 --- a/gnu/usr.bin/gdb/bfd/coffgen.c +++ b/gnu/usr.bin/gdb/bfd/coffgen.c @@ -1,5 +1,5 @@ /* Support for the generic parts of COFF, for BFD. - Copyright 1990, 1991, 1992, 1993 Free Software Foundation, Inc. + Copyright 1990, 1991, 1992, 1993, 1994 Free Software Foundation, Inc. Written by Cygnus Support. This file is part of BFD, the Binary File Descriptor library. @@ -39,18 +39,25 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "sysdep.h" #include "libbfd.h" #include "coff/internal.h" -#include "seclet.h" #include "libcoff.h" +static boolean coff_write_symbol PARAMS ((bfd *, asymbol *, + combined_entry_type *, + unsigned int *)); +static boolean coff_write_alien_symbol PARAMS ((bfd *, asymbol *, + unsigned int *)); +static boolean coff_write_native_symbol PARAMS ((bfd *, coff_symbol_type *, + unsigned int *)); + static asection bfd_debug_section = { "*DEBUG*" }; /* Take a section header read from a coff file (in HOST byte order), and make a BFD "section" out of it. This is used by ECOFF. */ static boolean -DEFUN(make_a_section_from_file,(abfd, hdr, target_index), - bfd *abfd AND - struct internal_scnhdr *hdr AND - unsigned int target_index) +make_a_section_from_file (abfd, hdr, target_index) + bfd *abfd; + struct internal_scnhdr *hdr; + unsigned int target_index; { asection *return_section; char *name; @@ -58,7 +65,7 @@ DEFUN(make_a_section_from_file,(abfd, hdr, target_index), /* Assorted wastage to null-terminate the name, thanks AT&T! */ name = bfd_alloc(abfd, sizeof (hdr->s_name)+1); if (name == NULL) { - bfd_error = no_memory; + bfd_set_error (bfd_error_no_memory); return false; } strncpy(name, (char *) &hdr->s_name[0], sizeof (hdr->s_name)); @@ -98,7 +105,7 @@ DEFUN(make_a_section_from_file,(abfd, hdr, target_index), /* At least on i386-coff, the line number count for a shared library section must be ignored. */ - if ((return_section->flags & SEC_SHARED_LIBRARY) != 0) + if ((return_section->flags & SEC_COFF_SHARED_LIBRARY) != 0) return_section->lineno_count = 0; if (hdr->s_nreloc != 0) @@ -112,13 +119,12 @@ DEFUN(make_a_section_from_file,(abfd, hdr, target_index), /* Read in a COFF object and make it into a BFD. This is used by ECOFF as well. */ -static -bfd_target * -DEFUN(coff_real_object_p,(abfd, nscns, internal_f, internal_a), - bfd *abfd AND - unsigned nscns AND - struct internal_filehdr *internal_f AND - struct internal_aouthdr *internal_a) +static const bfd_target * +coff_real_object_p (abfd, nscns, internal_f, internal_a) + bfd *abfd; + unsigned nscns; + struct internal_filehdr *internal_f; + struct internal_aouthdr *internal_a; { PTR tdata; size_t readsize; /* length of file_info */ @@ -133,6 +139,11 @@ DEFUN(coff_real_object_p,(abfd, nscns, internal_f, internal_a), scnhsz = bfd_coff_scnhsz (abfd); readsize = nscns * scnhsz; external_sections = (char *)bfd_alloc(abfd, readsize); + if (!external_sections) + { + bfd_set_error (bfd_error_no_memory); + goto fail; + } if (bfd_read((PTR)external_sections, 1, readsize, abfd) != readsize) { goto fail; @@ -163,6 +174,9 @@ DEFUN(coff_real_object_p,(abfd, nscns, internal_f, internal_a), if (!(internal_f->f_flags & F_LSYMS)) abfd->flags |= HAS_LOCALS; + /* FIXME: How can we set D_PAGED correctly? */ + if ((internal_f->f_flags & F_EXEC) != 0) + abfd->flags |= D_PAGED; bfd_get_symcount(abfd) = internal_f->f_nsyms; if (internal_f->f_nsyms) @@ -176,15 +190,15 @@ DEFUN(coff_real_object_p,(abfd, nscns, internal_f, internal_a), return abfd->xvec; fail: bfd_release(abfd, tdata); - return (bfd_target *)NULL; + return (const bfd_target *)NULL; } -/* Turn a COFF file into a BFD, but fail with wrong_format if it is +/* Turn a COFF file into a BFD, but fail with bfd_error_wrong_format if it is not a COFF file. This is also used by ECOFF. */ -bfd_target * -DEFUN(coff_object_p,(abfd), - bfd *abfd) +const bfd_target * +coff_object_p (abfd) + bfd *abfd; { unsigned int filhsz; unsigned int aoutsz; @@ -193,8 +207,6 @@ DEFUN(coff_object_p,(abfd), struct internal_filehdr internal_f; struct internal_aouthdr internal_a; - bfd_error = system_call_error; - /* figure out how much to read */ filhsz = bfd_coff_filhsz (abfd); aoutsz = bfd_coff_aoutsz (abfd); @@ -203,12 +215,16 @@ DEFUN(coff_object_p,(abfd), if (filehdr == NULL) return 0; if (bfd_read(filehdr, 1, filhsz, abfd) != filhsz) - return 0; + { + if (bfd_get_error () != bfd_error_system_call) + bfd_set_error (bfd_error_wrong_format); + return 0; + } bfd_coff_swap_filehdr_in(abfd, filehdr, &internal_f); bfd_release (abfd, filehdr); if (bfd_coff_bad_format_hook (abfd, &internal_f) == false) { - bfd_error = wrong_format; + bfd_set_error (bfd_error_wrong_format); return 0; } nscns =internal_f.f_nscns; @@ -226,7 +242,9 @@ DEFUN(coff_object_p,(abfd), } /* Seek past the opt hdr stuff */ - bfd_seek(abfd, (file_ptr) (internal_f.f_opthdr + filhsz), SEEK_SET); + if (bfd_seek(abfd, (file_ptr) (internal_f.f_opthdr + filhsz), SEEK_SET) + != 0) + return NULL; return coff_real_object_p(abfd, nscns, &internal_f, (internal_f.f_opthdr != 0 @@ -236,20 +254,20 @@ DEFUN(coff_object_p,(abfd), /* Get the BFD section from a COFF symbol section number. */ -struct sec * -DEFUN(coff_section_from_bfd_index,(abfd, index), - bfd *abfd AND - int index) +asection * +coff_section_from_bfd_index (abfd, index) + bfd *abfd; + int index; { struct sec *answer = abfd->sections; if (index == N_ABS) { - return &bfd_abs_section; + return bfd_abs_section_ptr; } if (index == N_UNDEF) { - return &bfd_und_section; + return bfd_und_section_ptr; } if(index == N_DEBUG) { @@ -262,18 +280,20 @@ DEFUN(coff_section_from_bfd_index,(abfd, index), return answer; answer = answer->next; } - BFD_ASSERT(0); - return &bfd_und_section; /* For gcc -W and lint. Never executed. */ + + /* We should not reach this point, but the SCO 3.2v4 /lib/libc_s.a + has a bad symbol table in biglitpow.o. */ + return bfd_und_section_ptr; } /* Get the upper bound of a COFF symbol table. */ -unsigned int +long coff_get_symtab_upper_bound(abfd) bfd *abfd; { if (!bfd_coff_slurp_symbol_table(abfd)) - return 0; + return -1; return (bfd_get_symcount(abfd) + 1) * (sizeof(coff_symbol_type *)); } @@ -281,16 +301,16 @@ bfd *abfd; /* Canonicalize a COFF symbol table. */ -unsigned int -DEFUN(coff_get_symtab, (abfd, alocation), - bfd *abfd AND - asymbol **alocation) +long +coff_get_symtab (abfd, alocation) + bfd *abfd; + asymbol **alocation; { unsigned int counter = 0; coff_symbol_type *symbase; coff_symbol_type **location = (coff_symbol_type **) (alocation); if (!bfd_coff_slurp_symbol_table(abfd)) - return 0; + return -1; symbase = obj_symbols(abfd); while (counter < bfd_get_symcount(abfd)) @@ -317,8 +337,8 @@ DEFUN(coff_get_symtab, (abfd, alocation), /* Set lineno_count for the output sections of a COFF file. */ int -DEFUN(coff_count_linenumbers,(abfd), - bfd *abfd) +coff_count_linenumbers (abfd) + bfd *abfd; { unsigned int limit = bfd_get_symcount(abfd); unsigned int i; @@ -360,10 +380,11 @@ DEFUN(coff_count_linenumbers,(abfd), /* Takes a bfd and a symbol, returns a pointer to the coff specific area of the symbol if there is one. */ +/*ARGSUSED*/ coff_symbol_type * -DEFUN(coff_symbol_from,(ignore_abfd, symbol), - bfd *ignore_abfd AND - asymbol *symbol) +coff_symbol_from (ignore_abfd, symbol) + bfd *ignore_abfd; + asymbol *symbol; { if (bfd_asymbol_flavour(symbol) != bfd_target_coff_flavour) return (coff_symbol_type *)NULL; @@ -375,9 +396,9 @@ DEFUN(coff_symbol_from,(ignore_abfd, symbol), } static void -DEFUN(fixup_symbol_value,(coff_symbol_ptr, syment), -coff_symbol_type *coff_symbol_ptr AND -struct internal_syment *syment) +fixup_symbol_value (coff_symbol_ptr, syment) + coff_symbol_type *coff_symbol_ptr; + struct internal_syment *syment; { /* Normalize the symbol flags */ @@ -389,7 +410,7 @@ struct internal_syment *syment) else if (coff_symbol_ptr->symbol.flags & BSF_DEBUGGING) { syment->n_value = coff_symbol_ptr->symbol.value; } - else if (coff_symbol_ptr->symbol.section == & bfd_und_section) { + else if (bfd_is_und_section (coff_symbol_ptr->symbol.section)) { syment->n_scnum = N_UNDEF; syment->n_value = 0; } @@ -420,9 +441,9 @@ struct internal_syment *syment) do that here too. */ -void -DEFUN(coff_renumber_symbols,(bfd_ptr), - bfd *bfd_ptr) +boolean +coff_renumber_symbols (bfd_ptr) + bfd *bfd_ptr; { unsigned int symbol_count = bfd_get_symcount(bfd_ptr); asymbol **symbol_ptr_ptr = bfd_ptr->outsymbols; @@ -444,12 +465,17 @@ DEFUN(coff_renumber_symbols,(bfd_ptr), newsyms = (asymbol **) bfd_alloc_by_size_t (bfd_ptr, sizeof (asymbol *) * (symbol_count + 1)); + if (!newsyms) + { + bfd_set_error (bfd_error_no_memory); + return false; + } bfd_ptr->outsymbols = newsyms; for (i = 0; i < symbol_count; i++) - if (symbol_ptr_ptr[i]->section != &bfd_und_section) + if (! bfd_is_und_section (symbol_ptr_ptr[i]->section)) *newsyms++ = symbol_ptr_ptr[i]; for (i = 0; i < symbol_count; i++) - if (symbol_ptr_ptr[i]->section == &bfd_und_section) + if (bfd_is_und_section (symbol_ptr_ptr[i]->section)) *newsyms++ = symbol_ptr_ptr[i]; *newsyms = (asymbol *) NULL; symbol_ptr_ptr = bfd_ptr->outsymbols; @@ -485,6 +511,7 @@ DEFUN(coff_renumber_symbols,(bfd_ptr), } } obj_conv_table_size (bfd_ptr) = native_index; + return true; } /* @@ -493,48 +520,65 @@ DEFUN(coff_renumber_symbols,(bfd_ptr), */ void -DEFUN(coff_mangle_symbols,(bfd_ptr), - bfd *bfd_ptr) +coff_mangle_symbols (bfd_ptr) + bfd *bfd_ptr; { - unsigned int symbol_count = bfd_get_symcount(bfd_ptr); + unsigned int symbol_count = bfd_get_symcount (bfd_ptr); asymbol **symbol_ptr_ptr = bfd_ptr->outsymbols; unsigned int symbol_index; for (symbol_index = 0; symbol_index < symbol_count; symbol_index++) - { - coff_symbol_type *coff_symbol_ptr = - coff_symbol_from(bfd_ptr, symbol_ptr_ptr[symbol_index]); + { + coff_symbol_type *coff_symbol_ptr = + coff_symbol_from (bfd_ptr, symbol_ptr_ptr[symbol_index]); - if (coff_symbol_ptr && coff_symbol_ptr->native) { + if (coff_symbol_ptr && coff_symbol_ptr->native) + { int i; combined_entry_type *s = coff_symbol_ptr->native; - for (i = 0; i < s->u.syment.n_numaux ; i++) { - combined_entry_type *a = s + i + 1; - if (a->fix_tag) { - a->u.auxent.x_sym.x_tagndx.l = - a->u.auxent.x_sym.x_tagndx.p->offset; - a->fix_tag = 0; + if (s->fix_value) + { + /* FIXME: We should use a union here. */ + s->u.syment.n_value = + ((combined_entry_type *) s->u.syment.n_value)->offset; + s->fix_value = 0; } - if (a->fix_end) { - a->u.auxent.x_sym.x_fcnary.x_fcn.x_endndx.l = - a->u.auxent.x_sym.x_fcnary.x_fcn.x_endndx.p->offset; - a->fix_end = 0; - + for (i = 0; i < s->u.syment.n_numaux ; i++) + { + combined_entry_type *a = s + i + 1; + if (a->fix_tag) + { + a->u.auxent.x_sym.x_tagndx.l = + a->u.auxent.x_sym.x_tagndx.p->offset; + a->fix_tag = 0; + } + if (a->fix_end) + { + a->u.auxent.x_sym.x_fcnary.x_fcn.x_endndx.l = + a->u.auxent.x_sym.x_fcnary.x_fcn.x_endndx.p->offset; + a->fix_end = 0; + } + if (a->fix_scnlen) + { + a->u.auxent.x_csect.x_scnlen.l = + a->u.auxent.x_csect.x_scnlen.p->offset; + a->fix_scnlen = 0; + } } - - } } - } + } } -static int string_size; +static bfd_size_type string_size; +static bfd_size_type debug_string_size; +static asection *debug_string_section; static void -DEFUN(coff_fix_symbol_name,(abfd, symbol, native), - bfd *abfd AND - asymbol *symbol AND - combined_entry_type *native) +coff_fix_symbol_name (abfd, symbol, native) + bfd *abfd; + asymbol *symbol; + combined_entry_type *native; { unsigned int name_length; union internal_auxent *auxent; @@ -569,64 +613,108 @@ DEFUN(coff_fix_symbol_name,(abfd, symbol, native), } } else - { /* NOT A C_FILE SYMBOL */ - if (name_length <= SYMNMLEN) { + { /* NOT A C_FILE SYMBOL */ + if (name_length <= SYMNMLEN) + { /* This name will fit into the symbol neatly */ strncpy(native->u.syment._n._n_name, symbol->name, SYMNMLEN); } - else { + else if (! bfd_coff_symname_in_debug (abfd, &native->u.syment)) + { native->u.syment._n._n_n._n_offset = string_size + 4; native->u.syment._n._n_n._n_zeroes = 0; string_size += name_length + 1; } - } + else + { + long filepos; + bfd_byte buf[2]; + + /* This name should be written into the .debug section. For + some reason each name is preceded by a two byte length + and also followed by a null byte. FIXME: We assume that + the .debug section has already been created, and that it + is large enough. */ + if (debug_string_section == (asection *) NULL) + debug_string_section = bfd_get_section_by_name (abfd, ".debug"); + filepos = bfd_tell (abfd); + bfd_put_16 (abfd, name_length + 1, buf); + if (! bfd_set_section_contents (abfd, + debug_string_section, + (PTR) buf, + (file_ptr) debug_string_size, + (bfd_size_type) 2) + || ! bfd_set_section_contents (abfd, + debug_string_section, + (PTR) symbol->name, + (file_ptr) debug_string_size + 2, + (bfd_size_type) name_length + 1)) + abort (); + if (bfd_seek (abfd, filepos, SEEK_SET) != 0) + abort (); + native->u.syment._n._n_n._n_offset = debug_string_size + 2; + native->u.syment._n._n_n._n_zeroes = 0; + debug_string_size += name_length + 3; + } + } } -#define set_index(symbol, idx) ((symbol)->udata =(PTR) (idx)) +/* We need to keep track of the symbol index so that when we write out + the relocs we can get the index for a symbol. This method is a + hack. FIXME. */ -static unsigned int -DEFUN(coff_write_symbol,(abfd, symbol, native, written), -bfd *abfd AND -asymbol *symbol AND -combined_entry_type *native AND -unsigned int written) +#define set_index(symbol, idx) ((symbol)->udata = (PTR) (idx)) + +/* Write a symbol out to a COFF file. */ + +static boolean +coff_write_symbol (abfd, symbol, native, written) + bfd *abfd; + asymbol *symbol; + combined_entry_type *native; + unsigned int *written; { - unsigned int numaux = native->u.syment.n_numaux; - int type = native->u.syment.n_type; - int class = native->u.syment.n_sclass; + unsigned int numaux = native->u.syment.n_numaux; + int type = native->u.syment.n_type; + int class = native->u.syment.n_sclass; PTR buf; bfd_size_type symesz; - /* @@ bfd_debug_section isn't accessible outside this file, but we know - that C_FILE symbols belong there. So move them. */ + /* @@ bfd_debug_section isn't accessible outside this file, but we + know that C_FILE symbols belong there. So move them. */ if (native->u.syment.n_sclass == C_FILE) symbol->section = &bfd_debug_section; - if (symbol->section == &bfd_abs_section) - { - native->u.syment.n_scnum = N_ABS; - } + if (bfd_is_abs_section (symbol->section)) + { + native->u.syment.n_scnum = N_ABS; + } else if (symbol->section == &bfd_debug_section) - { - native->u.syment.n_scnum = N_DEBUG; - } - else if (symbol->section == &bfd_und_section) - { - native->u.syment.n_scnum = N_UNDEF; - } + { + native->u.syment.n_scnum = N_DEBUG; + } + else if (bfd_is_und_section (symbol->section)) + { + native->u.syment.n_scnum = N_UNDEF; + } else - { - native->u.syment.n_scnum = - symbol->section->output_section->target_index; - } - + { + native->u.syment.n_scnum = + symbol->section->output_section->target_index; + } - coff_fix_symbol_name(abfd, symbol, native); + coff_fix_symbol_name (abfd, symbol, native); symesz = bfd_coff_symesz (abfd); buf = bfd_alloc (abfd, symesz); - bfd_coff_swap_sym_out(abfd, &native->u.syment, buf); - bfd_write(buf, 1, symesz, abfd); + if (!buf) + { + bfd_set_error (bfd_error_no_memory); + return false; + } + bfd_coff_swap_sym_out (abfd, &native->u.syment, buf); + if (bfd_write (buf, 1, symesz, abfd) != symesz) + return false; bfd_release (abfd, buf); if (native->u.syment.n_numaux > 0) @@ -636,221 +724,279 @@ unsigned int written) auxesz = bfd_coff_auxesz (abfd); buf = bfd_alloc (abfd, auxesz); + if (!buf) + { + bfd_set_error (bfd_error_no_memory); + return false; + } for (j = 0; j < native->u.syment.n_numaux; j++) { - bfd_coff_swap_aux_out(abfd, - &((native + j + 1)->u.auxent), - type, - class, - buf); - bfd_write(buf, 1, auxesz, abfd); + bfd_coff_swap_aux_out (abfd, + &((native + j + 1)->u.auxent), + type, + class, + j, + native->u.syment.n_numaux, + buf); + if (bfd_write (buf, 1, auxesz, abfd)!= auxesz) + return false; } bfd_release (abfd, buf); } - /* - Reuse somewhere in the symbol to keep the index - */ - set_index(symbol, written); - return written + 1 + numaux; + + /* Store the index for use when we write out the relocs. */ + set_index (symbol, *written); + + *written += numaux + 1; + return true; } +/* Write out a symbol to a COFF file that does not come from a COFF + file originally. This symbol may have been created by the linker, + or we may be linking a non COFF file to a COFF file. */ -static unsigned int -DEFUN(coff_write_alien_symbol,(abfd, symbol, written), - bfd *abfd AND - asymbol *symbol AND - unsigned int written) +static boolean +coff_write_alien_symbol (abfd, symbol, written) + bfd *abfd; + asymbol *symbol; + unsigned int *written; { - /* - This symbol has been created by the loader, or come from a non - coff format. It has no native element to inherit, make our - own - */ combined_entry_type *native; combined_entry_type dummy; + native = &dummy; native->u.syment.n_type = T_NULL; native->u.syment.n_flags = 0; - if (symbol->section == &bfd_und_section) - { - native->u.syment.n_scnum = N_UNDEF; - native->u.syment.n_value = symbol->value; + if (bfd_is_und_section (symbol->section)) + { + native->u.syment.n_scnum = N_UNDEF; + native->u.syment.n_value = symbol->value; } else if (bfd_is_com_section (symbol->section)) - { - native->u.syment.n_scnum = N_UNDEF; - native->u.syment.n_value = symbol->value; - - } - - else if (symbol->flags & BSF_DEBUGGING) { - /* - remove name so it doesn't take up any space - */ - symbol->name = ""; + { + native->u.syment.n_scnum = N_UNDEF; + native->u.syment.n_value = symbol->value; } - else { - native->u.syment.n_scnum = symbol->section->output_section->target_index; - native->u.syment.n_value = symbol->value + - symbol->section->output_section->vma + - symbol->section->output_offset; - /* Copy the any flags from the the file hdr into the symbol */ + else if (symbol->flags & BSF_DEBUGGING) { - coff_symbol_type *c = coff_symbol_from(abfd, symbol); - if (c != (coff_symbol_type *)NULL) { - native->u.syment.n_flags = bfd_asymbol_bfd(&c->symbol)->flags; - } + /* Remove the symbol name so that it does not take up any space. + COFF won't know what to do with it anyhow. */ + symbol->name = ""; } + else + { + native->u.syment.n_scnum = + symbol->section->output_section->target_index; + native->u.syment.n_value = (symbol->value + + symbol->section->output_section->vma + + symbol->section->output_offset); + + /* Copy the any flags from the the file header into the symbol. + FIXME: Why? */ + { + coff_symbol_type *c = coff_symbol_from (abfd, symbol); + if (c != (coff_symbol_type *) NULL) + native->u.syment.n_flags = bfd_asymbol_bfd (&c->symbol)->flags; + } } - native->u.syment.n_type = 0; + native->u.syment.n_type = 0; if (symbol->flags & BSF_LOCAL) - native->u.syment.n_sclass = C_STAT; + native->u.syment.n_sclass = C_STAT; else - native->u.syment.n_sclass = C_EXT; - native->u.syment.n_numaux = 0; + native->u.syment.n_sclass = C_EXT; + native->u.syment.n_numaux = 0; - return coff_write_symbol(abfd, symbol, native, written); + return coff_write_symbol (abfd, symbol, native, written); } -static unsigned int -DEFUN(coff_write_native_symbol,(abfd, symbol, written), -bfd *abfd AND -coff_symbol_type *symbol AND -unsigned int written) +/* Write a native symbol to a COFF file. */ + +static boolean +coff_write_native_symbol (abfd, symbol, written) + bfd *abfd; + coff_symbol_type *symbol; + unsigned int *written; { - /* - Does this symbol have an ascociated line number - if so then - make it remember this symbol index. Also tag the auxent of - this symbol to point to the right place in the lineno table - */ combined_entry_type *native = symbol->native; + alent *lineno = symbol->lineno; - alent *lineno = symbol->lineno; - - if (lineno && !symbol->done_lineno) { - unsigned int count = 0; - lineno[count].u.offset = written; - if (native->u.syment.n_numaux) { - union internal_auxent *a = &((native+1)->u.auxent); + /* If this symbol has an associated line number, we must store the + symbol index in the line number field. We also tag the auxent to + point to the right place in the lineno table. */ + if (lineno && !symbol->done_lineno) + { + unsigned int count = 0; + lineno[count].u.offset = *written; + if (native->u.syment.n_numaux) + { + union internal_auxent *a = &((native+1)->u.auxent); - a->x_sym.x_fcnary.x_fcn.x_lnnoptr = - symbol->symbol.section->output_section->moving_line_filepos; - } - /* - And count and relocate all other linenumbers - */ + a->x_sym.x_fcnary.x_fcn.x_lnnoptr = + symbol->symbol.section->output_section->moving_line_filepos; + } - count++; - while (lineno[count].line_number) { + /* Count and relocate all other linenumbers. */ + count++; + while (lineno[count].line_number != 0) + { #if 0 -/* 13 april 92. sac -I've been told this, but still need proof: -> The second bug is also in `bfd/coffcode.h'. This bug causes the linker to screw -> up the pc-relocations for all the line numbers in COFF code. This bug isn't -> only specific to A29K implementations, but affects all systems using COFF -> format binaries. Note that in COFF object files, the line number core offsets -> output by the assembler are relative to the start of each procedure, not -> to the start of the .text section. This patch relocates the line numbers -> relative to the `native->u.syment.n_value' instead of the section virtual -> address. modular!olson@cs.arizona.edu (Jon Olson) -*/ - lineno[count].u.offset += native->u.syment.n_value; - + /* 13 april 92. sac + I've been told this, but still need proof: + > The second bug is also in `bfd/coffcode.h'. This bug + > causes the linker to screw up the pc-relocations for + > all the line numbers in COFF code. This bug isn't only + > specific to A29K implementations, but affects all + > systems using COFF format binaries. Note that in COFF + > object files, the line number core offsets output by + > the assembler are relative to the start of each + > procedure, not to the start of the .text section. This + > patch relocates the line numbers relative to the + > `native->u.syment.n_value' instead of the section + > virtual address. + > modular!olson@cs.arizona.edu (Jon Olson) + */ + lineno[count].u.offset += native->u.syment.n_value; #else - lineno[count].u.offset += - symbol->symbol.section->output_section->vma + - symbol->symbol.section->output_offset; + lineno[count].u.offset += + (symbol->symbol.section->output_section->vma + + symbol->symbol.section->output_offset); #endif - count++; - } - symbol->done_lineno = true; + count++; + } + symbol->done_lineno = true; - symbol->symbol.section->output_section->moving_line_filepos += - count * bfd_coff_linesz (abfd); - } - return coff_write_symbol(abfd, &( symbol->symbol), native,written); + symbol->symbol.section->output_section->moving_line_filepos += + count * bfd_coff_linesz (abfd); + } + + return coff_write_symbol (abfd, &(symbol->symbol), native, written); } -void -DEFUN(coff_write_symbols,(abfd), - bfd *abfd) -{ - unsigned int i; - unsigned int limit = bfd_get_symcount(abfd); - unsigned int written = 0; +/* Write out the COFF symbols. */ - asymbol **p; +boolean +coff_write_symbols (abfd) + bfd *abfd; +{ + unsigned int i; + unsigned int limit = bfd_get_symcount(abfd); + unsigned int written = 0; + asymbol **p; string_size = 0; - + debug_string_size = 0; /* Seek to the right place */ - bfd_seek(abfd, obj_sym_filepos(abfd), SEEK_SET); + if (bfd_seek (abfd, obj_sym_filepos(abfd), SEEK_SET) != 0) + return false; /* Output all the symbols we have */ written = 0; for (p = abfd->outsymbols, i = 0; i < limit; i++, p++) - { - asymbol *symbol = *p; - coff_symbol_type *c_symbol = coff_symbol_from(abfd, symbol); - - if (c_symbol == (coff_symbol_type *) NULL || - c_symbol->native == (combined_entry_type *)NULL) - { - written = coff_write_alien_symbol(abfd, symbol, written); - } - else - { - written = coff_write_native_symbol(abfd, c_symbol, written); - } + { + asymbol *symbol = *p; + coff_symbol_type *c_symbol = coff_symbol_from (abfd, symbol); - } + if (c_symbol == (coff_symbol_type *) NULL + || c_symbol->native == (combined_entry_type *)NULL) + { + if (! coff_write_alien_symbol (abfd, symbol, &written)) + return false; + } + else + { + if (! coff_write_native_symbol (abfd, c_symbol, &written)) + return false; + } + } - bfd_get_symcount(abfd) = written; + bfd_get_symcount (abfd) = written; /* Now write out strings */ if (string_size != 0) { - unsigned int size = string_size + 4; + unsigned int size = string_size + 4; bfd_byte buffer[4]; - bfd_h_put_32(abfd, size, buffer); - bfd_write((PTR) buffer, 1, sizeof(buffer), abfd); + bfd_h_put_32 (abfd, size, buffer); + if (bfd_write ((PTR) buffer, 1, sizeof (buffer), abfd) != sizeof (buffer)) + return false; for (p = abfd->outsymbols, i = 0; i < limit; i++, p++) - { - asymbol *q = *p; - size_t name_length = strlen(q->name); - int maxlen; - coff_symbol_type* c_symbol = coff_symbol_from(abfd, q); - maxlen = ((c_symbol != NULL && c_symbol->native != NULL) && - (c_symbol->native->u.syment.n_sclass == C_FILE)) ? - FILNMLEN : SYMNMLEN; - - if (name_length > maxlen) { - bfd_write((PTR) (q->name), 1, name_length + 1, abfd); + { + asymbol *q = *p; + size_t name_length = strlen (q->name); + coff_symbol_type *c_symbol = coff_symbol_from (abfd, q); + size_t maxlen; + + /* Figure out whether the symbol name should go in the string + table. Symbol names that are short enough are stored + directly in the syment structure. File names permit a + different, longer, length in the syment structure. On + XCOFF, some symbol names are stored in the .debug section + rather than in the string table. */ + + if (c_symbol == NULL + || c_symbol->native == NULL) + { + /* This is not a COFF symbol, so it certainly is not a + file name, nor does it go in the .debug section. */ + maxlen = SYMNMLEN; + } + else if (bfd_coff_symname_in_debug (abfd, + &c_symbol->native->u.syment)) + { + /* This symbol name is in the XCOFF .debug section. + Don't write it into the string table. */ + maxlen = name_length; } - } + else if (c_symbol->native->u.syment.n_sclass == C_FILE) + maxlen = FILNMLEN; + else + maxlen = SYMNMLEN; + + if (name_length > maxlen) + { + if (bfd_write ((PTR) (q->name), 1, name_length + 1, abfd) + != name_length + 1) + return false; + } + } } - else { - /* We would normally not write anything here, but we'll write - out 4 so that any stupid coff reader which tries to read - the string table even when there isn't one won't croak. */ - unsigned int size = 4; - bfd_byte buffer[4]; - - bfd_h_put_32 (abfd, size, buffer); - bfd_write((PTR) buffer, 1, sizeof (buffer), abfd); - } + else + { + /* We would normally not write anything here, but we'll write + out 4 so that any stupid coff reader which tries to read the + string table even when there isn't one won't croak. */ + unsigned int size = 4; + bfd_byte buffer[4]; + + bfd_h_put_32 (abfd, size, buffer); + if (bfd_write ((PTR) buffer, 1, 4, abfd) != 4) + return false; + } + + /* Make sure the .debug section was created to be the correct size. + We should create it ourselves on the fly, but we don't because + BFD won't let us write to any section until we know how large all + the sections are. We could still do it by making another pass + over the symbols. FIXME. */ + BFD_ASSERT (debug_string_size == 0 + || (debug_string_section != (asection *) NULL + && (BFD_ALIGN (debug_string_size, + 1 << debug_string_section->alignment_power) + == bfd_section_size (abfd, debug_string_section)))); + + return true; } -void -DEFUN(coff_write_linenumbers,(abfd), - bfd *abfd) +boolean +coff_write_linenumbers (abfd) + bfd *abfd; { asection *s; bfd_size_type linesz; @@ -858,10 +1004,16 @@ DEFUN(coff_write_linenumbers,(abfd), linesz = bfd_coff_linesz (abfd); buff = bfd_alloc (abfd, linesz); + if (!buff) + { + bfd_set_error (bfd_error_no_memory); + return false; + } for (s = abfd->sections; s != (asection *) NULL; s = s->next) { if (s->lineno_count) { asymbol **q = abfd->outsymbols; - bfd_seek(abfd, s->line_filepos, SEEK_SET); + if (bfd_seek(abfd, s->line_filepos, SEEK_SET) != 0) + return false; /* Find all the linenumbers in this section */ while (*q) { asymbol *p = *q; @@ -875,13 +1027,15 @@ DEFUN(coff_write_linenumbers,(abfd), out.l_lnno = 0; out.l_addr.l_symndx = l->u.offset; bfd_coff_swap_lineno_out(abfd, &out, buff); - bfd_write(buff, 1, linesz, abfd); + if (bfd_write(buff, 1, linesz, abfd) != linesz) + return false; l++; while (l->line_number) { out.l_lnno = l->line_number; out.l_addr.l_symndx = l->u.offset; bfd_coff_swap_lineno_out(abfd, &out, buff); - bfd_write(buff, 1, linesz, abfd); + if (bfd_write(buff, 1, linesz, abfd) != linesz) + return false; l++; } } @@ -891,12 +1045,14 @@ DEFUN(coff_write_linenumbers,(abfd), } } bfd_release (abfd, buff); + return true; } +/*ARGSUSED*/ alent * -DEFUN(coff_get_lineno,(ignore_abfd, symbol), - bfd *ignore_abfd AND - asymbol *symbol) +coff_get_lineno (ignore_abfd, symbol) + bfd *ignore_abfd; + asymbol *symbol; { return coffsymbol(symbol)->lineno; } @@ -922,6 +1078,11 @@ coff_section_symbol (abfd, name) }; struct foo *f; f = (struct foo *) bfd_alloc_by_size_t (abfd, sizeof (*f)); + if (!f) + { + bfd_set_error (bfd_error_no_error); + return NULL; + } memset ((char *) f, 0, sizeof (*f)); coff_symbol_from (abfd, sym)->native = csym = f->e; } @@ -945,12 +1106,12 @@ coff_section_symbol (abfd, name) pointers to syments. */ static void -DEFUN(coff_pointerize_aux,(abfd, table_base, type, class, auxent), -bfd *abfd AND -combined_entry_type *table_base AND -int type AND -int class AND -combined_entry_type *auxent) +coff_pointerize_aux (abfd, table_base, type, class, auxent) + bfd *abfd; + combined_entry_type *table_base; + int type; + int class; + combined_entry_type *auxent; { /* Don't bother if this is a file or a section */ if (class == C_STAT && type == T_NULL) return; @@ -974,8 +1135,8 @@ combined_entry_type *auxent) } static char * -DEFUN(build_string_table,(abfd), -bfd *abfd) +build_string_table (abfd) + bfd *abfd; { char string_table_size_buffer[4]; unsigned int string_table_size; @@ -985,21 +1146,17 @@ bfd *abfd) symbols === the symbol table size. */ if (bfd_read((char *) string_table_size_buffer, sizeof(string_table_size_buffer), - 1, abfd) != sizeof(string_table_size)) { - bfd_error = system_call_error; + 1, abfd) != sizeof(string_table_size)) return (NULL); - } /* on error */ string_table_size = bfd_h_get_32(abfd, (bfd_byte *) string_table_size_buffer); if ((string_table = (PTR) bfd_alloc(abfd, string_table_size -= 4)) == NULL) { - bfd_error = no_memory; + bfd_set_error (bfd_error_no_memory); return (NULL); } /* on mallocation error */ - if (bfd_read(string_table, string_table_size, 1, abfd) != string_table_size) { - bfd_error = system_call_error; + if (bfd_read(string_table, string_table_size, 1, abfd) != string_table_size) return (NULL); - } return string_table; } @@ -1008,8 +1165,8 @@ bfd *abfd) we didn't want to go to the trouble until someone needed it. */ static char * -DEFUN(build_debug_section,(abfd), - bfd *abfd) +build_debug_section (abfd) + bfd *abfd; { char *debug_section; long position; @@ -1017,14 +1174,14 @@ DEFUN(build_debug_section,(abfd), asection *sect = bfd_get_section_by_name (abfd, ".debug"); if (!sect) { - bfd_error = no_debug_section; + bfd_set_error (bfd_error_no_debug_section); return NULL; } debug_section = (PTR) bfd_alloc (abfd, bfd_get_section_size_before_reloc (sect)); if (debug_section == NULL) { - bfd_error = no_memory; + bfd_set_error (bfd_error_no_memory); return NULL; } @@ -1033,14 +1190,12 @@ DEFUN(build_debug_section,(abfd), Then read debug section and reset the file pointer. */ position = bfd_tell (abfd); - bfd_seek (abfd, sect->filepos, SEEK_SET); - if (bfd_read (debug_section, - bfd_get_section_size_before_reloc (sect), 1, abfd) - != bfd_get_section_size_before_reloc(sect)) { - bfd_error = system_call_error; + if (bfd_seek (abfd, sect->filepos, SEEK_SET) != 0 + || (bfd_read (debug_section, + bfd_get_section_size_before_reloc (sect), 1, abfd) + != bfd_get_section_size_before_reloc(sect)) + || bfd_seek (abfd, position, SEEK_SET) != 0) return NULL; - } - bfd_seek (abfd, position, SEEK_SET); return debug_section; } @@ -1049,10 +1204,10 @@ DEFUN(build_debug_section,(abfd), \0-terminated, but will not exceed 'maxlen' characters. The copy *will* be \0-terminated. */ static char * -DEFUN(copy_name,(abfd, name, maxlen), - bfd *abfd AND - char *name AND - int maxlen) +copy_name (abfd, name, maxlen) + bfd *abfd; + char *name; + int maxlen; { int len; char *newname; @@ -1064,7 +1219,7 @@ DEFUN(copy_name,(abfd, name, maxlen), } if ((newname = (PTR) bfd_alloc(abfd, len+1)) == NULL) { - bfd_error = no_memory; + bfd_set_error (bfd_error_no_memory); return (NULL); } strncpy(newname, name, len); @@ -1078,8 +1233,8 @@ DEFUN(copy_name,(abfd, name, maxlen), terminated string. */ combined_entry_type * -DEFUN(coff_get_normalized_symtab,(abfd), -bfd *abfd) +coff_get_normalized_symtab (abfd) + bfd *abfd; { combined_entry_type *internal; combined_entry_type *internal_ptr; @@ -1098,22 +1253,30 @@ bfd *abfd) return obj_raw_syments(abfd); } if ((size = bfd_get_symcount(abfd) * sizeof(combined_entry_type)) == 0) { - bfd_error = no_symbols; + bfd_set_error (bfd_error_no_symbols); return (NULL); } internal = (combined_entry_type *)bfd_alloc(abfd, size); + if (!internal) + { + bfd_set_error (bfd_error_no_memory); + return NULL; + } internal_end = internal + bfd_get_symcount(abfd); symesz = bfd_coff_symesz (abfd); raw_size = bfd_get_symcount(abfd) * symesz; raw = bfd_alloc(abfd,raw_size); + if (!raw) + { + bfd_set_error (bfd_error_no_memory); + return NULL; + } if (bfd_seek(abfd, obj_sym_filepos(abfd), SEEK_SET) == -1 - || bfd_read(raw, raw_size, 1, abfd) != raw_size) { - bfd_error = system_call_error; + || bfd_read(raw, raw_size, 1, abfd) != raw_size) return (NULL); - } /* mark the end of the symbols */ raw_end = (char *) raw + bfd_get_symcount(abfd) * symesz; /* @@ -1128,8 +1291,10 @@ bfd *abfd) unsigned int i; bfd_coff_swap_sym_in(abfd, (PTR)raw_src, (PTR)&internal_ptr->u.syment); + internal_ptr->fix_value = 0; internal_ptr->fix_tag = 0; internal_ptr->fix_end = 0; + internal_ptr->fix_scnlen = 0; symbol_ptr = internal_ptr; for (i = 0; @@ -1139,11 +1304,14 @@ bfd *abfd) internal_ptr++; raw_src += symesz; + internal_ptr->fix_value = 0; internal_ptr->fix_tag = 0; internal_ptr->fix_end = 0; + internal_ptr->fix_scnlen = 0; bfd_coff_swap_aux_in(abfd, (PTR) raw_src, symbol_ptr->u.syment.n_type, symbol_ptr->u.syment.n_sclass, + i, symbol_ptr->u.syment.n_numaux, &(internal_ptr->u.auxent)); /* Remember that bal entries arn't pointerized */ if (i != 1 || symbol_ptr->u.syment.n_sclass != C_LEAFPROC) @@ -1200,7 +1368,7 @@ bfd *abfd) } /* possible lengths of this string. */ if ((newstring = (PTR) bfd_alloc(abfd, ++i)) == NULL) { - bfd_error = no_memory; + bfd_set_error (bfd_error_no_memory); return (NULL); } /* on error */ memset(newstring, 0, i); @@ -1208,6 +1376,8 @@ bfd *abfd) internal_ptr->u.syment._n._n_n._n_offset = (long int) newstring; internal_ptr->u.syment._n._n_n._n_zeroes = 0; } + else if (internal_ptr->u.syment._n._n_n._n_offset == 0) + internal_ptr->u.syment._n._n_n._n_offset = (long int) ""; else if (!bfd_coff_symname_in_debug(abfd, &internal_ptr->u.syment)) { /* Long name already. Point symbol at the string in the table. */ if (string_table == NULL) { @@ -1234,27 +1404,28 @@ bfd *abfd) return (internal); } /* coff_get_normalized_symtab() */ -unsigned int -DEFUN (coff_get_reloc_upper_bound, (abfd, asect), - bfd *abfd AND - sec_ptr asect) +long +coff_get_reloc_upper_bound (abfd, asect) + bfd *abfd; + sec_ptr asect; { if (bfd_get_format(abfd) != bfd_object) { - bfd_error = invalid_operation; - return 0; + bfd_set_error (bfd_error_invalid_operation); + return -1; } return (asect->reloc_count + 1) * sizeof(arelent *); } asymbol * -DEFUN (coff_make_empty_symbol, (abfd), - bfd *abfd) +coff_make_empty_symbol (abfd) + bfd *abfd; { coff_symbol_type *new = (coff_symbol_type *) bfd_alloc(abfd, sizeof(coff_symbol_type)); if (new == NULL) { - bfd_error = no_memory; + bfd_set_error (bfd_error_no_memory); return (NULL); } /* on error */ + memset (new, 0, sizeof *new); new->symbol.section = 0; new->native = 0; new->lineno = (alent *) NULL; @@ -1273,11 +1444,16 @@ coff_bfd_make_debug_symbol (abfd, ptr, sz) { coff_symbol_type *new = (coff_symbol_type *) bfd_alloc(abfd, sizeof(coff_symbol_type)); if (new == NULL) { - bfd_error = no_memory; + bfd_set_error (bfd_error_no_memory); return (NULL); } /* on error */ /* @@ This shouldn't be using a constant multiplier. */ new->native = (combined_entry_type *) bfd_zalloc (abfd, sizeof (combined_entry_type) * 10); + if (!new->native) + { + bfd_set_error (bfd_error_no_memory); + return (NULL); + } /* on error */ new->symbol.section = &bfd_debug_section; new->lineno = (alent *) NULL; new->done_lineno = false; @@ -1285,6 +1461,7 @@ coff_bfd_make_debug_symbol (abfd, ptr, sz) return &new->symbol; } +/*ARGSUSED*/ void coff_get_symbol_info (abfd, symbol, ret) bfd *abfd; @@ -1328,13 +1505,13 @@ coff_print_symbol (abfd, filep, symbol, how) fprintf (file,"[%3d]", combined - root); fprintf (file, - "(sc %2d)(fl 0x%02x)(ty %3x)(sc %3d) (nx %d) 0x%08x %s", + "(sc %2d)(fl 0x%02x)(ty %3x)(sc %3d) (nx %d) 0x%08lx %s", combined->u.syment.n_scnum, combined->u.syment.n_flags, combined->u.syment.n_type, combined->u.syment.n_sclass, combined->u.syment.n_numaux, - combined->u.syment.n_value, + (unsigned long) combined->u.syment.n_value, symbol->name); for (aux = 0; aux < combined->u.syment.n_numaux; aux++) @@ -1355,7 +1532,7 @@ coff_print_symbol (abfd, filep, symbol, how) break; default: - fprintf (file, "AUX lnno %d size 0x%x tagndx %d", + fprintf (file, "AUX lnno %d size 0x%x tagndx %ld", auxp->u.auxent.x_sym.x_misc.x_lnsz.x_lnno, auxp->u.auxent.x_sym.x_misc.x_lnsz.x_size, tagndx); @@ -1369,9 +1546,10 @@ coff_print_symbol (abfd, filep, symbol, how) l++; while (l->line_number) { - fprintf (file, "\n%4d : 0x%x", - l->line_number, - l->u.offset + symbol->section->vma); + fprintf (file, "\n%4d : 0x%lx", + l->line_number, + ((unsigned long) + (l->u.offset + symbol->section->vma))); l++; } } @@ -1392,21 +1570,17 @@ coff_print_symbol (abfd, filep, symbol, how) and return the name of the source file and the line nearest to the wanted location. */ +/*ARGSUSED*/ boolean -DEFUN(coff_find_nearest_line,(abfd, - section, - ignore_symbols, - offset, - filename_ptr, - functionname_ptr, - line_ptr), - bfd *abfd AND - asection *section AND - asymbol **ignore_symbols AND - bfd_vma offset AND - CONST char **filename_ptr AND - CONST char **functionname_ptr AND - unsigned int *line_ptr) +coff_find_nearest_line (abfd, section, ignore_symbols, offset, filename_ptr, + functionname_ptr, line_ptr) + bfd *abfd; + asection *section; + asymbol **ignore_symbols; + bfd_vma offset; + CONST char **filename_ptr; + CONST char **functionname_ptr; + unsigned int *line_ptr; { static bfd *cache_abfd; static asection *cache_section; @@ -1501,9 +1675,9 @@ DEFUN(coff_find_nearest_line,(abfd, } int -DEFUN(coff_sizeof_headers,(abfd, reloc), - bfd *abfd AND - boolean reloc) +coff_sizeof_headers (abfd, reloc) + bfd *abfd; + boolean reloc; { size_t size; diff --git a/gnu/usr.bin/gdb/bfd/core.c b/gnu/usr.bin/gdb/bfd/core.c index c428775fbf3f..5d88a494c36a 100644 --- a/gnu/usr.bin/gdb/bfd/core.c +++ b/gnu/usr.bin/gdb/bfd/core.c @@ -1,5 +1,5 @@ /* Core file generic interface routines for BFD. - Copyright (C) 1990-1991 Free Software Foundation, Inc. + Copyright (C) 1990, 91, 92, 93, 94 Free Software Foundation, Inc. Written by Cygnus Support. This file is part of BFD, the Binary File Descriptor library. @@ -23,7 +23,7 @@ SECTION Core files DESCRIPTION - Buff output this facinating topic + These are functions pertaining to core files. */ #include "bfd.h" @@ -36,20 +36,20 @@ FUNCTION bfd_core_file_failing_command SYNOPSIS - CONST char *bfd_core_file_failing_command(bfd *); + CONST char *bfd_core_file_failing_command(bfd *abfd); DESCRIPTION - Returns a read-only string explaining what program was running - when it failed and produced the core file being read + Return a read-only string explaining which program was running + when it failed and produced the core file @var{abfd}. */ CONST char * -DEFUN(bfd_core_file_failing_command,(abfd), - bfd *abfd) +bfd_core_file_failing_command (abfd) + bfd *abfd; { if (abfd->format != bfd_core) { - bfd_error = invalid_operation; + bfd_set_error (bfd_error_invalid_operation); return NULL; } return BFD_SEND (abfd, _core_file_failing_command, (abfd)); @@ -60,11 +60,11 @@ FUNCTION bfd_core_file_failing_signal SYNOPSIS - int bfd_core_file_failing_signal(bfd *); + int bfd_core_file_failing_signal(bfd *abfd); DESCRIPTION Returns the signal number which caused the core dump which - generated the file the BFD is attached to. + generated the file the BFD @var{abfd} is attached to. */ int @@ -72,7 +72,7 @@ bfd_core_file_failing_signal (abfd) bfd *abfd; { if (abfd->format != bfd_core) { - bfd_error = invalid_operation; + bfd_set_error (bfd_error_invalid_operation); return 0; } return BFD_SEND (abfd, _core_file_failing_signal, (abfd)); @@ -88,16 +88,16 @@ SYNOPSIS (bfd *core_bfd, bfd *exec_bfd); DESCRIPTION - Returns <<true>> if the core file attached to @var{core_bfd} + Return <<true>> if the core file attached to @var{core_bfd} was generated by a run of the executable file attached to - @var{exec_bfd}, or else <<false>>. + @var{exec_bfd}, <<false>> otherwise. */ 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; + bfd_set_error (bfd_error_wrong_format); return false; } diff --git a/gnu/usr.bin/gdb/bfd/cpu-i386.c b/gnu/usr.bin/gdb/bfd/cpu-i386.c index b4afdb2392bb..3a8214ff3f4e 100644 --- a/gnu/usr.bin/gdb/bfd/cpu-i386.c +++ b/gnu/usr.bin/gdb/bfd/cpu-i386.c @@ -37,7 +37,8 @@ static bfd_arch_info_type arch_info_struct = 0, }; -void DEFUN_VOID(bfd_i386_arch) +void +bfd_i386_arch () { bfd_arch_linkin(&arch_info_struct); } diff --git a/gnu/usr.bin/gdb/bfd/ctor.c b/gnu/usr.bin/gdb/bfd/ctor.c index adc69195ff6a..8a6e4e4e3393 100644 --- a/gnu/usr.bin/gdb/bfd/ctor.c +++ b/gnu/usr.bin/gdb/bfd/ctor.c @@ -1,5 +1,5 @@ /* BFD library support routines for constructors - Copyright (C) 1990-1991 Free Software Foundation, Inc. + Copyright (C) 1990, 91, 92, 93, 94 Free Software Foundation, Inc. Hacked by Steve Chamberlain of Cygnus Support. With some help from Judy Chamberlain too. @@ -25,27 +25,27 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ SECTION Constructors - Classes in C++ have `constructors' and `destructors'. These + Classes in C++ have @dfn{constructors} and @dfn{destructors}. These are functions which are called automatically by the language whenever data of a class is created or destroyed. Class data - which is static data may also be have a type which requires - `construction', the contructor must be called before the data + which is static may also be have a type which requires + `construction'; the contructor must be called before the data can be referenced, so the contructor must be called before the program begins. The common solution to this problem is for the compiler to - call a magic function as the first statement <<main>>. - This magic function, (often called <<__main>>) runs around + call a magic function as the first statement before <<main>>. + This magic function (often called <<__main>>) runs around calling the constructors for all the things needing it. - With COFF the compile has a bargain with the linker et al. - All constructors are given strange names, for example + With COFF, the compiler has a bargain with the linker et al. + All constructors are given strange names; for example, <<__GLOBAL__$I$foo>> might be the label of a contructor for the class @var{foo}. The solution on unfortunate systems - (most system V machines) is to perform a partial link on all + (most System V machines) is to perform a partial link on all the <<.o>> files, do an <<nm>> on the result, run <<awk>> or some such over the result looking for strange <<__GLOBAL__$>> - symbols, generate a C program from this, compile it and link + symbols, generate a C program from this, compile it, and link with the partially linked input. This process is usually called <<collect>>. @@ -54,10 +54,10 @@ SECTION from the compiler with a special stab code saying that they are constructors, and the linker can deal with them directly. - BFD allows applications (ie the linker) to deal with + BFD allows applications (i.e., the linker) to deal with constructor information independently of their external - implimentation by providing a set of entry points for the - indiviual object back ends to call which maintains a database + implementation by providing a set of entry points for the + indiviual object back ends to call to maintain a database of the contructor information. The application can interrogate the database to find out what it wants. The construction data essential for the linker to be able to @@ -71,15 +71,15 @@ SECTION The type of symbol, i.e., is it a constructor, a destructor or something else someone dreamed up to make our lives difficult. - This module takes this information and then builds extra - sections attached to the bfds which own the entry points. It + The constructor module takes this information and builds extra + sections attached to the BFDs which own the entry points. It creates these sections as if they were tables of pointers to the entry points, and builds relocation entries to go with them so that the tables can be relocated along with the data they reference. These sections are marked with a special bit - (<<SEC_CONSTRUCTOR>>) which the linker notices and do with + (<<SEC_CONSTRUCTOR>>), which the linker notices and does with what it wants. */ @@ -95,28 +95,30 @@ INTERNAL_FUNCTION bfd_constructor_entry SYNOPSIS - void bfd_constructor_entry(bfd *abfd, + boolean bfd_constructor_entry(bfd *abfd, asymbol **symbol_ptr_ptr, CONST char*type); DESCRIPTION - This function is called with an a symbol describing the - function to be called, an string which descibes the xtor type, - e.g., something like "CTOR" or "DTOR" would be fine. And the bfd - which owns the function. Its duty is to create a section - called "CTOR" or "DTOR" or whatever if the bfd doesn't already + @var{symbol_ptr_ptr} describes the + function to be called; @var{type} descibes the xtor type, + e.g., something like "CTOR" or "DTOR" would be fine. @var{abfd} + is the BFD which owns the function. Create a section + called "CTOR" or "DTOR" or whatever if the BFD doesn't already have one, and grow a relocation table for the entry points as they accumulate. + Return <<true>> if successful, <<false>> if out of memory. + */ -void DEFUN(bfd_constructor_entry,(abfd, symbol_ptr_ptr, type), - bfd *abfd AND - asymbol **symbol_ptr_ptr AND - CONST char *type) - +boolean +bfd_constructor_entry (abfd, symbol_ptr_ptr, type) + bfd *abfd; + asymbol **symbol_ptr_ptr; + CONST char *type; { /* Look up the section we're using to store the table in */ asection *rel_section = bfd_get_section_by_name (abfd, type); @@ -131,6 +133,11 @@ void DEFUN(bfd_constructor_entry,(abfd, symbol_ptr_ptr, type), { arelent_chain *reloc = (arelent_chain *)bfd_alloc(abfd, sizeof(arelent_chain)); + if (!reloc) + { + bfd_set_error (bfd_error_no_memory); + return false; + } /* reloc->relent.section = (asection *)NULL;*/ reloc->relent.addend = 0; @@ -144,5 +151,5 @@ void DEFUN(bfd_constructor_entry,(abfd, symbol_ptr_ptr, type), rel_section->_cooked_size += sizeof(int *); rel_section->reloc_count++; } - + return true; } diff --git a/gnu/usr.bin/gdb/bfd/ecoff.c b/gnu/usr.bin/gdb/bfd/ecoff.c index e3b7c937aa05..9bf5050aad4f 100644 --- a/gnu/usr.bin/gdb/bfd/ecoff.c +++ b/gnu/usr.bin/gdb/bfd/ecoff.c @@ -21,8 +21,8 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "bfd.h" #include "sysdep.h" +#include "bfdlink.h" #include "libbfd.h" -#include "seclet.h" #include "aout/ar.h" #include "aout/ranlib.h" @@ -45,30 +45,24 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ /* Prototypes for static functions. */ static int ecoff_get_magic PARAMS ((bfd *abfd)); -static void ecoff_set_symbol_info PARAMS ((bfd *abfd, SYMR *ecoff_sym, +static long ecoff_sec_to_styp_flags PARAMS ((const char *name, + flagword flags)); +static boolean ecoff_slurp_symbolic_header PARAMS ((bfd *abfd)); +static boolean ecoff_set_symbol_info PARAMS ((bfd *abfd, SYMR *ecoff_sym, asymbol *asym, int ext, asymbol **indirect_ptr_ptr)); -static void ecoff_emit_aggregate PARAMS ((bfd *abfd, char *string, +static void ecoff_emit_aggregate PARAMS ((bfd *abfd, FDR *fdr, + char *string, RNDXR *rndx, long isym, - CONST char *which)); -static char *ecoff_type_to_string PARAMS ((bfd *abfd, union aux_ext *aux_ptr, - unsigned int indx, int bigendian)); + const char *which)); +static char *ecoff_type_to_string PARAMS ((bfd *abfd, FDR *fdr, + unsigned int indx)); static boolean ecoff_slurp_reloc_table PARAMS ((bfd *abfd, asection *section, asymbol **symbols)); -static void ecoff_clear_output_flags PARAMS ((bfd *abfd)); -static boolean ecoff_rel PARAMS ((bfd *output_bfd, bfd_seclet_type *seclet, - asection *output_section, PTR data, - boolean relocateable)); -static boolean ecoff_dump_seclet PARAMS ((bfd *abfd, bfd_seclet_type *seclet, - asection *section, PTR data, - boolean relocateable)); -static long ecoff_add_string PARAMS ((bfd *output_bfd, FDR *fdr, - CONST char *string, boolean external)); -static boolean ecoff_get_debug PARAMS ((bfd *output_bfd, - bfd_seclet_type *seclet, - asection *section, - boolean relocateable)); static void ecoff_compute_section_file_positions PARAMS ((bfd *abfd)); +static bfd_size_type ecoff_compute_reloc_file_positions PARAMS ((bfd *abfd)); +static boolean ecoff_get_extr PARAMS ((asymbol *, EXTR *)); +static void ecoff_set_index PARAMS ((asymbol *, bfd_size_type)); static unsigned int ecoff_armap_hash PARAMS ((CONST char *s, unsigned int *rehash, unsigned int size, @@ -81,22 +75,17 @@ static asection bfd_debug_section = { "*DEBUG*" }; /* Create an ECOFF object. */ boolean -ecoff_mkobject (abfd) +_bfd_ecoff_mkobject (abfd) bfd *abfd; { abfd->tdata.ecoff_obj_data = ((struct ecoff_tdata *) bfd_zalloc (abfd, sizeof (ecoff_data_type))); if (abfd->tdata.ecoff_obj_data == NULL) { - bfd_error = no_memory; + bfd_set_error (bfd_error_no_memory); return false; } - /* Always create a .scommon section for every BFD. This is a hack so - that the linker has something to attach scSCommon symbols to. */ - if (bfd_make_section (abfd, SCOMMON) == NULL) - return false; - return true; } @@ -104,7 +93,7 @@ ecoff_mkobject (abfd) specific information. */ PTR -ecoff_mkobject_hook (abfd, filehdr, aouthdr) +_bfd_ecoff_mkobject_hook (abfd, filehdr, aouthdr) bfd *abfd; PTR filehdr; PTR aouthdr; @@ -112,22 +101,14 @@ ecoff_mkobject_hook (abfd, filehdr, aouthdr) struct internal_filehdr *internal_f = (struct internal_filehdr *) filehdr; struct internal_aouthdr *internal_a = (struct internal_aouthdr *) aouthdr; ecoff_data_type *ecoff; - asection *regsec; - if (ecoff_mkobject (abfd) == false) + if (_bfd_ecoff_mkobject (abfd) == false) return NULL; ecoff = ecoff_data (abfd); ecoff->gp_size = 8; ecoff->sym_filepos = internal_f->f_symptr; - /* Create the .reginfo section to give programs outside BFD a way to - see the information stored in the a.out header. See the comment - in coff/ecoff.h. */ - regsec = bfd_make_section (abfd, REGINFO); - if (regsec == NULL) - return NULL; - if (internal_a != (struct internal_aouthdr *) NULL) { int i; @@ -154,8 +135,9 @@ ecoff_mkobject_hook (abfd, filehdr, aouthdr) /* This is a hook needed by SCO COFF, but we have nothing to do. */ +/*ARGSUSED*/ asection * -ecoff_make_section_hook (abfd, name) +_bfd_ecoff_make_section_hook (abfd, name) bfd *abfd; char *name; { @@ -165,11 +147,19 @@ ecoff_make_section_hook (abfd, name) /* Initialize a new section. */ boolean -ecoff_new_section_hook (abfd, section) +_bfd_ecoff_new_section_hook (abfd, section) bfd *abfd; asection *section; { - section->alignment_power = abfd->xvec->align_power_min; + /* For the .pdata section, which has a special meaning on the Alpha, + we set the alignment to 8. We correct this later in + ecoff_compute_section_file_positions. We do this hackery because + we need to know the exact unaligned size of the .pdata section in + order to set the lnnoptr field correctly. */ + if (strcmp (section->name, _PDATA) == 0) + section->alignment_power = 3; + else + section->alignment_power = abfd->xvec->align_power_min; if (strcmp (section->name, _TEXT) == 0) section->flags |= SEC_CODE | SEC_LOAD | SEC_ALLOC; @@ -183,10 +173,10 @@ ecoff_new_section_hook (abfd, section) else if (strcmp (section->name, _BSS) == 0 || strcmp (section->name, _SBSS) == 0) section->flags |= SEC_ALLOC; - else if (strcmp (section->name, REGINFO) == 0) + else if (strcmp (section->name, _LIB) == 0) { - section->flags |= SEC_HAS_CONTENTS | SEC_NEVER_LOAD; - section->_raw_size = sizeof (struct ecoff_reginfo); + /* An Irix 4 shared libary. */ + section->flags |= SEC_COFF_SHARED_LIBRARY; } /* Probably any other section name is SEC_NEVER_LOAD, but I'm @@ -202,7 +192,7 @@ ecoff_new_section_hook (abfd, section) for each target, but there aren't all that many ECOFF targets. */ boolean -ecoff_set_arch_mach_hook (abfd, filehdr) +_bfd_ecoff_set_arch_mach_hook (abfd, filehdr) bfd *abfd; PTR filehdr; { @@ -248,7 +238,7 @@ ecoff_set_arch_mach_hook (abfd, filehdr) } /* Get the magic number to use based on the architecture and machine. - This is the inverse of ecoff_set_arch_mach_hook, above. */ + This is the inverse of _bfd_ecoff_set_arch_mach_hook, above. */ static int ecoff_get_magic (abfd) @@ -292,9 +282,9 @@ ecoff_get_magic (abfd) /* Get the section s_flags to use for a section. */ -long +static long ecoff_sec_to_styp_flags (name, flags) - CONST char *name; + const char *name; flagword flags; { long styp; @@ -309,6 +299,8 @@ ecoff_sec_to_styp_flags (name, flags) styp = STYP_SDATA; else if (strcmp (name, _RDATA) == 0) styp = STYP_RDATA; + else if (strcmp (name, _LITA) == 0) + styp = STYP_LITA; else if (strcmp (name, _LIT8) == 0) styp = STYP_LIT8; else if (strcmp (name, _LIT4) == 0) @@ -321,6 +313,12 @@ ecoff_sec_to_styp_flags (name, flags) styp = STYP_ECOFF_INIT; else if (strcmp (name, _FINI) == 0) styp = STYP_ECOFF_FINI; + else if (strcmp (name, _PDATA) == 0) + styp = STYP_PDATA; + else if (strcmp (name, _XDATA) == 0) + styp = STYP_XDATA; + else if (strcmp (name, _LIB) == 0) + styp = STYP_ECOFF_LIB; else if (flags & SEC_CODE) styp = STYP_TEXT; else if (flags & SEC_DATA) @@ -340,8 +338,9 @@ ecoff_sec_to_styp_flags (name, flags) /* Get the BFD flags to use for a section. */ +/*ARGSUSED*/ flagword -ecoff_styp_to_sec_flags (abfd, hdr) +_bfd_ecoff_styp_to_sec_flags (abfd, hdr) bfd *abfd; PTR hdr; { @@ -359,19 +358,22 @@ ecoff_styp_to_sec_flags (abfd, hdr) || (styp_flags & STYP_ECOFF_FINI)) { if (sec_flags & SEC_NEVER_LOAD) - sec_flags |= SEC_CODE | SEC_SHARED_LIBRARY; + sec_flags |= SEC_CODE | SEC_COFF_SHARED_LIBRARY; else sec_flags |= SEC_CODE | SEC_LOAD | SEC_ALLOC; } else if ((styp_flags & STYP_DATA) || (styp_flags & STYP_RDATA) - || (styp_flags & STYP_SDATA)) + || (styp_flags & STYP_SDATA) + || styp_flags == STYP_PDATA + || styp_flags == STYP_XDATA) { if (sec_flags & SEC_NEVER_LOAD) - sec_flags |= SEC_DATA | SEC_SHARED_LIBRARY; + sec_flags |= SEC_DATA | SEC_COFF_SHARED_LIBRARY; else sec_flags |= SEC_DATA | SEC_LOAD | SEC_ALLOC; - if (styp_flags & STYP_RDATA) + if ((styp_flags & STYP_RDATA) + || styp_flags == STYP_PDATA) sec_flags |= SEC_READONLY; } else if ((styp_flags & STYP_BSS) @@ -379,15 +381,20 @@ ecoff_styp_to_sec_flags (abfd, hdr) { sec_flags |= SEC_ALLOC; } - else if (styp_flags & STYP_INFO) + else if ((styp_flags & STYP_INFO) || styp_flags == STYP_COMMENT) { sec_flags |= SEC_NEVER_LOAD; } - else if ((styp_flags & STYP_LIT8) + else if ((styp_flags & STYP_LITA) + || (styp_flags & STYP_LIT8) || (styp_flags & STYP_LIT4)) { sec_flags |= SEC_DATA | SEC_LOAD | SEC_ALLOC | SEC_READONLY; } + else if (styp_flags & STYP_ECOFF_LIB) + { + sec_flags |= SEC_COFF_SHARED_LIBRARY; + } else { sec_flags |= SEC_ALLOC | SEC_LOAD; @@ -405,9 +412,9 @@ ecoff_styp_to_sec_flags (abfd, hdr) info comes from the file header record (fh-fBigendian). */ void -ecoff_swap_tir_in (bigend, ext_copy, intern) +_bfd_ecoff_swap_tir_in (bigend, ext_copy, intern) int bigend; - struct tir_ext *ext_copy; + const struct tir_ext *ext_copy; TIR *intern; { struct tir_ext ext[1]; @@ -462,9 +469,9 @@ ecoff_swap_tir_in (bigend, ext_copy, intern) info comes from the file header record (fh-fBigendian). */ void -ecoff_swap_tir_out (bigend, intern_copy, ext) +_bfd_ecoff_swap_tir_out (bigend, intern_copy, ext) int bigend; - TIR *intern_copy; + const TIR *intern_copy; struct tir_ext *ext; { TIR intern[1]; @@ -518,9 +525,9 @@ ecoff_swap_tir_out (bigend, intern_copy, ext) big-endian or little-endian format.*/ void -ecoff_swap_rndx_in (bigend, ext_copy, intern) +_bfd_ecoff_swap_rndx_in (bigend, ext_copy, intern) int bigend; - struct rndx_ext *ext_copy; + const struct rndx_ext *ext_copy; RNDXR *intern; { struct rndx_ext ext[1]; @@ -543,7 +550,8 @@ ecoff_swap_rndx_in (bigend, ext_copy, intern) intern->index = ((ext->r_bits[1] & RNDX_BITS1_INDEX_LITTLE) >> RNDX_BITS1_INDEX_SH_LITTLE) | (ext->r_bits[2] << RNDX_BITS2_INDEX_SH_LEFT_LITTLE) - | (ext->r_bits[3] << RNDX_BITS3_INDEX_SH_LEFT_LITTLE); + | ((unsigned int) ext->r_bits[3] + << RNDX_BITS3_INDEX_SH_LEFT_LITTLE); } #ifdef TEST @@ -556,9 +564,9 @@ ecoff_swap_rndx_in (bigend, ext_copy, intern) big-endian or little-endian format.*/ void -ecoff_swap_rndx_out (bigend, intern_copy, ext) +_bfd_ecoff_swap_rndx_out (bigend, intern_copy, ext) int bigend; - RNDXR *intern_copy; + const RNDXR *intern_copy; struct rndx_ext *ext; { RNDXR intern[1]; @@ -590,30 +598,23 @@ ecoff_swap_rndx_out (bigend, intern_copy, ext) #endif } -/* Read in and swap the important symbolic information for an ECOFF - object file. This is called by gdb. */ +/* Read in the symbolic header for an ECOFF object file. */ -boolean -ecoff_slurp_symbolic_info (abfd) +static boolean +ecoff_slurp_symbolic_header (abfd) bfd *abfd; { const struct ecoff_backend_data * const backend = ecoff_backend (abfd); bfd_size_type external_hdr_size; + PTR raw = NULL; HDRR *internal_symhdr; - bfd_size_type raw_base; - bfd_size_type raw_size; - PTR raw; - bfd_size_type external_fdr_size; - char *fraw_src; - char *fraw_end; - struct fdr *fdr_ptr; - bfd_size_type raw_end; - bfd_size_type cb_end; - /* Check whether we've already gotten it, and whether there's any to - get. */ - if (ecoff_data (abfd)->raw_syments != (PTR) NULL) + /* See if we've already read it in. */ + if (ecoff_data (abfd)->debug_info.symbolic_header.magic == + backend->debug_swap.sym_magic) return true; + + /* See whether there is a symbolic header. */ if (ecoff_data (abfd)->sym_filepos == 0) { bfd_get_symcount (abfd) = 0; @@ -624,37 +625,90 @@ ecoff_slurp_symbolic_info (abfd) as read from the file header, but on ECOFF this is always the size of the symbolic information header. It would be cleaner to handle this when we first read the file in coffgen.c. */ - external_hdr_size = backend->external_hdr_size; + external_hdr_size = backend->debug_swap.external_hdr_size; if (bfd_get_symcount (abfd) != external_hdr_size) { - bfd_error = bad_value; + bfd_set_error (bfd_error_bad_value); return false; } /* Read the symbolic information header. */ - raw = (PTR) alloca (external_hdr_size); + raw = (PTR) malloc ((size_t) external_hdr_size); + if (raw == NULL) + { + bfd_set_error (bfd_error_no_memory); + goto error_return; + } + if (bfd_seek (abfd, ecoff_data (abfd)->sym_filepos, SEEK_SET) == -1 || (bfd_read (raw, external_hdr_size, 1, abfd) != external_hdr_size)) - { - bfd_error = system_call_error; - return false; - } - internal_symhdr = &ecoff_data (abfd)->symbolic_header; - (*backend->swap_hdr_in) (abfd, raw, internal_symhdr); + goto error_return; + internal_symhdr = &ecoff_data (abfd)->debug_info.symbolic_header; + (*backend->debug_swap.swap_hdr_in) (abfd, raw, internal_symhdr); - if (internal_symhdr->magic != backend->sym_magic) + if (internal_symhdr->magic != backend->debug_swap.sym_magic) { - bfd_error = bad_value; - return false; + bfd_set_error (bfd_error_bad_value); + goto error_return; } /* Now we can get the correct number of symbols. */ bfd_get_symcount (abfd) = (internal_symhdr->isymMax + internal_symhdr->iextMax); + if (raw != NULL) + free (raw); + return true; + error_return: + if (raw != NULL) + free (raw); + return false; +} + +/* Read in and swap the important symbolic information for an ECOFF + object file. This is called by gdb via the read_debug_info entry + point in the backend structure. */ + +/*ARGSUSED*/ +boolean +_bfd_ecoff_slurp_symbolic_info (abfd, ignore, debug) + bfd *abfd; + asection *ignore; + struct ecoff_debug_info *debug; +{ + const struct ecoff_backend_data * const backend = ecoff_backend (abfd); + HDRR *internal_symhdr; + bfd_size_type raw_base; + bfd_size_type raw_size; + PTR raw; + bfd_size_type external_fdr_size; + char *fraw_src; + char *fraw_end; + struct fdr *fdr_ptr; + bfd_size_type raw_end; + bfd_size_type cb_end; + + BFD_ASSERT (debug == &ecoff_data (abfd)->debug_info); + + /* Check whether we've already gotten it, and whether there's any to + get. */ + if (ecoff_data (abfd)->raw_syments != (PTR) NULL) + return true; + if (ecoff_data (abfd)->sym_filepos == 0) + { + bfd_get_symcount (abfd) = 0; + return true; + } + + if (! ecoff_slurp_symbolic_header (abfd)) + return false; + + internal_symhdr = &debug->symbolic_header; + /* Read all the symbolic information at once. */ - raw_base = ecoff_data (abfd)->sym_filepos + external_hdr_size; + raw_base = (ecoff_data (abfd)->sym_filepos + + backend->debug_swap.external_hdr_size); /* Alpha ecoff makes the determination of raw_size difficult. It has an undocumented debug data section between the symhdr and the first @@ -670,16 +724,16 @@ ecoff_slurp_symbolic_info (abfd) raw_end = cb_end UPDATE_RAW_END (cbLineOffset, cbLine, sizeof (unsigned char)); - UPDATE_RAW_END (cbDnOffset, idnMax, backend->external_dnr_size); - UPDATE_RAW_END (cbPdOffset, ipdMax, backend->external_pdr_size); - UPDATE_RAW_END (cbSymOffset, isymMax, backend->external_sym_size); - UPDATE_RAW_END (cbOptOffset, ioptMax, backend->external_opt_size); + UPDATE_RAW_END (cbDnOffset, idnMax, backend->debug_swap.external_dnr_size); + UPDATE_RAW_END (cbPdOffset, ipdMax, backend->debug_swap.external_pdr_size); + UPDATE_RAW_END (cbSymOffset, isymMax, backend->debug_swap.external_sym_size); + UPDATE_RAW_END (cbOptOffset, ioptMax, backend->debug_swap.external_opt_size); UPDATE_RAW_END (cbAuxOffset, iauxMax, sizeof (union aux_ext)); UPDATE_RAW_END (cbSsOffset, issMax, sizeof (char)); UPDATE_RAW_END (cbSsExtOffset, issExtMax, sizeof (char)); - UPDATE_RAW_END (cbFdOffset, ifdMax, backend->external_fdr_size); - UPDATE_RAW_END (cbRfdOffset, crfd, backend->external_rfd_size); - UPDATE_RAW_END (cbExtOffset, iextMax, backend->external_ext_size); + UPDATE_RAW_END (cbFdOffset, ifdMax, backend->debug_swap.external_fdr_size); + UPDATE_RAW_END (cbRfdOffset, crfd, backend->debug_swap.external_rfd_size); + UPDATE_RAW_END (cbExtOffset, iextMax, backend->debug_swap.external_ext_size); #undef UPDATE_RAW_END @@ -692,27 +746,29 @@ ecoff_slurp_symbolic_info (abfd) raw = (PTR) bfd_alloc (abfd, raw_size); if (raw == NULL) { - bfd_error = no_memory; + bfd_set_error (bfd_error_no_memory); return false; } - if (bfd_read (raw, raw_size, 1, abfd) != raw_size) + if (bfd_seek (abfd, + (ecoff_data (abfd)->sym_filepos + + backend->debug_swap.external_hdr_size), + SEEK_SET) != 0 + || bfd_read (raw, raw_size, 1, abfd) != raw_size) { - bfd_error = system_call_error; bfd_release (abfd, raw); return false; } - ecoff_data (abfd)->raw_size = raw_size; ecoff_data (abfd)->raw_syments = raw; /* Get pointers for the numeric offsets in the HDRR structure. */ #define FIX(off1, off2, type) \ if (internal_symhdr->off1 == 0) \ - ecoff_data (abfd)->off2 = (type) NULL; \ + debug->off2 = (type) NULL; \ else \ - ecoff_data (abfd)->off2 = (type) ((char *) raw \ - + internal_symhdr->off1 \ - - raw_base) + debug->off2 = (type) ((char *) raw \ + + internal_symhdr->off1 \ + - raw_base) FIX (cbLineOffset, line, unsigned char *); FIX (cbDnOffset, external_dnr, PTR); FIX (cbPdOffset, external_pdr, PTR); @@ -734,21 +790,20 @@ ecoff_slurp_symbolic_info (abfd) We need to look at the fdr to deal with a lot of information in the symbols, so we swap them here. */ - ecoff_data (abfd)->fdr = - (struct fdr *) bfd_alloc (abfd, - (internal_symhdr->ifdMax * - sizeof (struct fdr))); - if (ecoff_data (abfd)->fdr == NULL) + debug->fdr = (struct fdr *) bfd_alloc (abfd, + (internal_symhdr->ifdMax * + sizeof (struct fdr))); + if (debug->fdr == NULL) { - bfd_error = no_memory; + bfd_set_error (bfd_error_no_memory); return false; } - external_fdr_size = backend->external_fdr_size; - fdr_ptr = ecoff_data (abfd)->fdr; - fraw_src = (char *) ecoff_data (abfd)->external_fdr; + external_fdr_size = backend->debug_swap.external_fdr_size; + fdr_ptr = debug->fdr; + fraw_src = (char *) debug->external_fdr; fraw_end = fraw_src + internal_symhdr->ifdMax * external_fdr_size; for (; fraw_src < fraw_end; fraw_src += external_fdr_size, fdr_ptr++) - (*backend->swap_fdr_in) (abfd, (PTR) fraw_src, fdr_ptr); + (*backend->debug_swap.swap_fdr_in) (abfd, (PTR) fraw_src, fdr_ptr); return true; } @@ -768,7 +823,7 @@ static asymbol *ecoff_scom_symbol_ptr; /* Create an empty symbol. */ asymbol * -ecoff_make_empty_symbol (abfd) +_bfd_ecoff_make_empty_symbol (abfd) bfd *abfd; { ecoff_symbol_type *new; @@ -776,10 +831,10 @@ ecoff_make_empty_symbol (abfd) new = (ecoff_symbol_type *) bfd_alloc (abfd, sizeof (ecoff_symbol_type)); if (new == (ecoff_symbol_type *) NULL) { - bfd_error = no_memory; + bfd_set_error (bfd_error_no_memory); return (asymbol *) NULL; } - memset (new, 0, sizeof *new); + memset ((PTR) new, 0, sizeof *new); new->symbol.section = (asection *) NULL; new->fdr = (FDR *) NULL; new->local = false; @@ -790,7 +845,7 @@ ecoff_make_empty_symbol (abfd) /* Set the BFD flags and section for an ECOFF symbol. */ -static void +static boolean ecoff_set_symbol_info (abfd, ecoff_sym, asym, ext, indirect_ptr_ptr) bfd *abfd; SYMR *ecoff_sym; @@ -816,19 +871,19 @@ ecoff_set_symbol_info (abfd, ecoff_sym, asym, ext, indirect_ptr_ptr) (*indirect_ptr_ptr)->value = (bfd_vma) asym; asym->flags = BSF_DEBUGGING; - asym->section = &bfd_und_section; + asym->section = bfd_und_section_ptr; *indirect_ptr_ptr = NULL; - return; + return true; } if (ECOFF_IS_STAB (ecoff_sym) && (ECOFF_UNMARK_STAB (ecoff_sym->index) | N_EXT) == (N_INDR | N_EXT)) { asym->flags = BSF_DEBUGGING | BSF_INDIRECT; - asym->section = &bfd_ind_section; + asym->section = bfd_ind_section_ptr; /* Pass this symbol on to the next call to this function. */ *indirect_ptr_ptr = asym; - return; + return true; } /* Most symbol types are just for debugging. */ @@ -844,12 +899,12 @@ ecoff_set_symbol_info (abfd, ecoff_sym, asym, ext, indirect_ptr_ptr) if (ECOFF_IS_STAB (ecoff_sym)) { asym->flags = BSF_DEBUGGING; - return; + return true; } break; default: asym->flags = BSF_DEBUGGING; - return; + return true; } if (ext) @@ -881,10 +936,10 @@ ecoff_set_symbol_info (abfd, ecoff_sym, asym, ext, indirect_ptr_ptr) asym->flags = BSF_DEBUGGING; break; case scAbs: - asym->section = &bfd_abs_section; + asym->section = bfd_abs_section_ptr; break; case scUndefined: - asym->section = &bfd_und_section; + asym->section = bfd_und_section_ptr; asym->flags = 0; asym->value = 0; break; @@ -914,7 +969,7 @@ ecoff_set_symbol_info (abfd, ecoff_sym, asym, ext, indirect_ptr_ptr) case scCommon: if (asym->value > ecoff_data (abfd)->gp_size) { - asym->section = &bfd_com_section; + asym->section = bfd_com_section_ptr; asym->flags = 0; break; } @@ -941,7 +996,7 @@ ecoff_set_symbol_info (abfd, ecoff_sym, asym, ext, indirect_ptr_ptr) asym->flags = BSF_DEBUGGING; break; case scSUndefined: - asym->section = &bfd_und_section; + asym->section = bfd_und_section_ptr; asym->flags = 0; asym->value = 0; break; @@ -1001,6 +1056,11 @@ ecoff_set_symbol_info (abfd, ecoff_sym, asym, ext, indirect_ptr_ptr) char *copy; copy = (char *) bfd_alloc (abfd, strlen (name) + 1); + if (!copy) + { + bfd_set_error (bfd_error_no_memory); + return false; + } strcpy (copy, name); section = bfd_make_section (abfd, copy); } @@ -1008,6 +1068,11 @@ ecoff_set_symbol_info (abfd, ecoff_sym, asym, ext, indirect_ptr_ptr) /* Build a reloc pointing to this constructor. */ reloc_chain = (arelent_chain *) bfd_alloc (abfd, sizeof (arelent_chain)); + if (!reloc_chain) + { + bfd_set_error (bfd_error_no_memory); + return false; + } reloc_chain->relent.sym_ptr_ptr = bfd_get_section (asym)->symbol_ptr_ptr; reloc_chain->relent.address = section->_raw_size; @@ -1038,21 +1103,24 @@ ecoff_set_symbol_info (abfd, ecoff_sym, asym, ext, indirect_ptr_ptr) break; } } + return true; } /* Read an ECOFF symbol table. */ boolean -ecoff_slurp_symbol_table (abfd) +_bfd_ecoff_slurp_symbol_table (abfd) bfd *abfd; { const struct ecoff_backend_data * const backend = ecoff_backend (abfd); - const bfd_size_type external_ext_size = backend->external_ext_size; - const bfd_size_type external_sym_size = backend->external_sym_size; + const bfd_size_type external_ext_size + = backend->debug_swap.external_ext_size; + const bfd_size_type external_sym_size + = backend->debug_swap.external_sym_size; void (* const swap_ext_in) PARAMS ((bfd *, PTR, EXTR *)) - = backend->swap_ext_in; + = backend->debug_swap.swap_ext_in; void (* const swap_sym_in) PARAMS ((bfd *, PTR, SYMR *)) - = backend->swap_sym_in; + = backend->debug_swap.swap_sym_in; bfd_size_type internal_size; ecoff_symbol_type *internal; ecoff_symbol_type *internal_ptr; @@ -1067,7 +1135,8 @@ ecoff_slurp_symbol_table (abfd) return true; /* Get the symbolic information. */ - if (ecoff_slurp_symbolic_info (abfd) == false) + if (! _bfd_ecoff_slurp_symbolic_info (abfd, (asection *) NULL, + &ecoff_data (abfd)->debug_info)) return false; if (bfd_get_symcount (abfd) == 0) return true; @@ -1076,28 +1145,30 @@ ecoff_slurp_symbol_table (abfd) internal = (ecoff_symbol_type *) bfd_alloc (abfd, internal_size); if (internal == NULL) { - bfd_error = no_memory; + bfd_set_error (bfd_error_no_memory); return false; } internal_ptr = internal; indirect_ptr = NULL; - eraw_src = (char *) ecoff_data (abfd)->external_ext; + eraw_src = (char *) ecoff_data (abfd)->debug_info.external_ext; eraw_end = (eraw_src - + (ecoff_data (abfd)->symbolic_header.iextMax + + (ecoff_data (abfd)->debug_info.symbolic_header.iextMax * external_ext_size)); for (; eraw_src < eraw_end; eraw_src += external_ext_size, internal_ptr++) { EXTR internal_esym; (*swap_ext_in) (abfd, (PTR) eraw_src, &internal_esym); - internal_ptr->symbol.name = (ecoff_data (abfd)->ssext + internal_ptr->symbol.name = (ecoff_data (abfd)->debug_info.ssext + internal_esym.asym.iss); - ecoff_set_symbol_info (abfd, &internal_esym.asym, - &internal_ptr->symbol, 1, &indirect_ptr); + if (!ecoff_set_symbol_info (abfd, &internal_esym.asym, + &internal_ptr->symbol, 1, &indirect_ptr)) + return false; /* The alpha uses a negative ifd field for section symbols. */ if (internal_esym.ifd >= 0) - internal_ptr->fdr = ecoff_data (abfd)->fdr + internal_esym.ifd; + internal_ptr->fdr = (ecoff_data (abfd)->debug_info.fdr + + internal_esym.ifd); else internal_ptr->fdr = NULL; internal_ptr->local = false; @@ -1107,14 +1178,14 @@ ecoff_slurp_symbol_table (abfd) /* The local symbols must be accessed via the fdr's, because the string and aux indices are relative to the fdr information. */ - fdr_ptr = ecoff_data (abfd)->fdr; - fdr_end = fdr_ptr + ecoff_data (abfd)->symbolic_header.ifdMax; + fdr_ptr = ecoff_data (abfd)->debug_info.fdr; + fdr_end = fdr_ptr + ecoff_data (abfd)->debug_info.symbolic_header.ifdMax; for (; fdr_ptr < fdr_end; fdr_ptr++) { char *lraw_src; char *lraw_end; - lraw_src = ((char *) ecoff_data (abfd)->external_sym + lraw_src = ((char *) ecoff_data (abfd)->debug_info.external_sym + fdr_ptr->isymBase * external_sym_size); lraw_end = lraw_src + fdr_ptr->csym * external_sym_size; for (; @@ -1124,11 +1195,12 @@ ecoff_slurp_symbol_table (abfd) SYMR internal_sym; (*swap_sym_in) (abfd, (PTR) lraw_src, &internal_sym); - internal_ptr->symbol.name = (ecoff_data (abfd)->ss + internal_ptr->symbol.name = (ecoff_data (abfd)->debug_info.ss + fdr_ptr->issBase + internal_sym.iss); - ecoff_set_symbol_info (abfd, &internal_sym, - &internal_ptr->symbol, 0, &indirect_ptr); + if (!ecoff_set_symbol_info (abfd, &internal_sym, + &internal_ptr->symbol, 0, &indirect_ptr)) + return false; internal_ptr->fdr = fdr_ptr; internal_ptr->local = true; internal_ptr->native = (PTR) lraw_src; @@ -1143,21 +1215,24 @@ ecoff_slurp_symbol_table (abfd) /* Return the amount of space needed for the canonical symbols. */ -unsigned int -ecoff_get_symtab_upper_bound (abfd) +long +_bfd_ecoff_get_symtab_upper_bound (abfd) bfd *abfd; { - if (ecoff_slurp_symbolic_info (abfd) == false - || bfd_get_symcount (abfd) == 0) + if (! _bfd_ecoff_slurp_symbolic_info (abfd, (asection *) NULL, + &ecoff_data (abfd)->debug_info)) + return -1; + + if (bfd_get_symcount (abfd) == 0) return 0; return (bfd_get_symcount (abfd) + 1) * (sizeof (ecoff_symbol_type *)); } -/* Get the canonicals symbols. */ +/* Get the canonical symbols. */ -unsigned int -ecoff_get_symtab (abfd, alocation) +long +_bfd_ecoff_get_symtab (abfd, alocation) bfd *abfd; asymbol **alocation; { @@ -1165,8 +1240,9 @@ ecoff_get_symtab (abfd, alocation) ecoff_symbol_type *symbase; ecoff_symbol_type **location = (ecoff_symbol_type **) alocation; - if (ecoff_slurp_symbol_table (abfd) == false - || bfd_get_symcount (abfd) == 0) + if (_bfd_ecoff_slurp_symbol_table (abfd) == false) + return -1; + if (bfd_get_symcount (abfd) == 0) return 0; symbase = ecoff_data (abfd)->canonical_symbols; @@ -1186,54 +1262,76 @@ ecoff_get_symtab (abfd, alocation) /* Write aggregate information to a string. */ static void -ecoff_emit_aggregate (abfd, string, rndx, isym, which) +ecoff_emit_aggregate (abfd, fdr, string, rndx, isym, which) bfd *abfd; + FDR *fdr; char *string; RNDXR *rndx; long isym; - CONST char *which; + const char *which; { - int ifd = rndx->rfd; - int indx = rndx->index; - int sym_base, ss_base; - CONST char *name; + const struct ecoff_debug_swap * const debug_swap = + &ecoff_backend (abfd)->debug_swap; + struct ecoff_debug_info * const debug_info = &ecoff_data (abfd)->debug_info; + unsigned int ifd = rndx->rfd; + unsigned int indx = rndx->index; + const char *name; if (ifd == 0xfff) ifd = isym; - sym_base = ecoff_data (abfd)->fdr[ifd].isymBase; - ss_base = ecoff_data (abfd)->fdr[ifd].issBase; - - if (indx == indexNil) - name = "/* no name */"; + /* An ifd of -1 is an opaque type. An escaped index of 0 is a + struct return type of a procedure compiled without -g. */ + if (ifd == 0xffffffff + || (rndx->rfd == 0xfff && indx == 0)) + name = "<undefined>"; + else if (indx == indexNil) + name = "<no name>"; else { - const struct ecoff_backend_data * const backend = ecoff_backend (abfd); SYMR sym; - indx += sym_base; - (*backend->swap_sym_in) (abfd, - ((char *) ecoff_data (abfd)->external_sym - + indx * backend->external_sym_size), - &sym); - name = ecoff_data (abfd)->ss + ss_base + sym.iss; + if (debug_info->external_rfd == NULL) + fdr = debug_info->fdr + ifd; + else + { + RFDT rfd; + + (*debug_swap->swap_rfd_in) (abfd, + ((char *) debug_info->external_rfd + + ((fdr->rfdBase + ifd) + * debug_swap->external_rfd_size)), + &rfd); + fdr = debug_info->fdr + rfd; + } + + indx += fdr->isymBase; + + (*debug_swap->swap_sym_in) (abfd, + ((char *) debug_info->external_sym + + indx * debug_swap->external_sym_size), + &sym); + + name = debug_info->ss + fdr->issBase + sym.iss; } sprintf (string, - "%s %s { ifd = %d, index = %d }", + "%s %s { ifd = %u, index = %lu }", which, name, ifd, - indx + ecoff_data (abfd)->symbolic_header.iextMax); + ((long) indx + + debug_info->symbolic_header.iextMax)); } /* Convert the type information to string format. */ static char * -ecoff_type_to_string (abfd, aux_ptr, indx, bigendian) +ecoff_type_to_string (abfd, fdr, indx) bfd *abfd; - union aux_ext *aux_ptr; + FDR *fdr; unsigned int indx; - int bigendian; { + union aux_ext *aux_ptr; + int bigendian; AUXU u; struct qual { unsigned int type; @@ -1241,7 +1339,6 @@ ecoff_type_to_string (abfd, aux_ptr, indx, bigendian) int high_bound; int stride; } qualifiers[7]; - unsigned int basic_type; int i; static char buffer1[1024]; @@ -1250,6 +1347,9 @@ ecoff_type_to_string (abfd, aux_ptr, indx, bigendian) char *p2 = buffer2; RNDXR rndx; + aux_ptr = ecoff_data (abfd)->debug_info.external_aux + fdr->iauxBase; + bigendian = fdr->fBigendian; + for (i = 0; i < 7; i++) { qualifiers[i].low_bound = 0; @@ -1259,7 +1359,7 @@ ecoff_type_to_string (abfd, aux_ptr, indx, bigendian) if (AUX_GET_ISYM (bigendian, &aux_ptr[indx]) == -1) return "-1 (no type)"; - ecoff_swap_tir_in (bigendian, &aux_ptr[indx++].a_ti, &u.ti); + _bfd_ecoff_swap_tir_in (bigendian, &aux_ptr[indx++].a_ti, &u.ti); basic_type = u.ti.bt; qualifiers[0].type = u.ti.tq0; @@ -1328,9 +1428,9 @@ ecoff_type_to_string (abfd, aux_ptr, indx, bigendian) 2nd word is file index if 1st word rfd is ST_RFDESCAPE. */ case btStruct: /* Structure (Record) */ - ecoff_swap_rndx_in (bigendian, &aux_ptr[indx].a_rndx, &rndx); - ecoff_emit_aggregate (abfd, p1, &rndx, - AUX_GET_ISYM (bigendian, &aux_ptr[indx+1]), + _bfd_ecoff_swap_rndx_in (bigendian, &aux_ptr[indx].a_rndx, &rndx); + ecoff_emit_aggregate (abfd, fdr, p1, &rndx, + (long) AUX_GET_ISYM (bigendian, &aux_ptr[indx+1]), "struct"); indx++; /* skip aux words */ break; @@ -1340,9 +1440,9 @@ ecoff_type_to_string (abfd, aux_ptr, indx, bigendian) 2nd word is file index if 1st word rfd is ST_RFDESCAPE. */ case btUnion: /* Union */ - ecoff_swap_rndx_in (bigendian, &aux_ptr[indx].a_rndx, &rndx); - ecoff_emit_aggregate (abfd, p1, &rndx, - AUX_GET_ISYM (bigendian, &aux_ptr[indx+1]), + _bfd_ecoff_swap_rndx_in (bigendian, &aux_ptr[indx].a_rndx, &rndx); + ecoff_emit_aggregate (abfd, fdr, p1, &rndx, + (long) AUX_GET_ISYM (bigendian, &aux_ptr[indx+1]), "union"); indx++; /* skip aux words */ break; @@ -1352,9 +1452,9 @@ ecoff_type_to_string (abfd, aux_ptr, indx, bigendian) 2nd word is file index if 1st word rfd is ST_RFDESCAPE. */ case btEnum: /* Enumeration */ - ecoff_swap_rndx_in (bigendian, &aux_ptr[indx].a_rndx, &rndx); - ecoff_emit_aggregate (abfd, p1, &rndx, - AUX_GET_ISYM (bigendian, &aux_ptr[indx+1]), + _bfd_ecoff_swap_rndx_in (bigendian, &aux_ptr[indx].a_rndx, &rndx); + ecoff_emit_aggregate (abfd, fdr, p1, &rndx, + (long) AUX_GET_ISYM (bigendian, &aux_ptr[indx+1]), "enum"); indx++; /* skip aux words */ break; @@ -1533,8 +1633,9 @@ ecoff_type_to_string (abfd, aux_ptr, indx, bigendian) /* Return information about ECOFF symbol SYMBOL in RET. */ +/*ARGSUSED*/ void -ecoff_get_symbol_info (abfd, symbol, ret) +_bfd_ecoff_get_symbol_info (abfd, symbol, ret) bfd *abfd; /* Ignored. */ asymbol *symbol; symbol_info *ret; @@ -1545,13 +1646,14 @@ ecoff_get_symbol_info (abfd, symbol, ret) /* Print information about an ECOFF symbol. */ void -ecoff_print_symbol (abfd, filep, symbol, how) +_bfd_ecoff_print_symbol (abfd, filep, symbol, how) bfd *abfd; PTR filep; asymbol *symbol; bfd_print_symbol_type how; { - const struct ecoff_backend_data * const backend = ecoff_backend (abfd); + const struct ecoff_debug_swap * const debug_swap + = &ecoff_backend (abfd)->debug_swap; FILE *file = (FILE *)filep; switch (how) @@ -1564,8 +1666,8 @@ ecoff_print_symbol (abfd, filep, symbol, how) { SYMR ecoff_sym; - (*backend->swap_sym_in) (abfd, ecoffsymbol (symbol)->native, - &ecoff_sym); + (*debug_swap->swap_sym_in) (abfd, ecoffsymbol (symbol)->native, + &ecoff_sym); fprintf (file, "ecoff local "); fprintf_vma (file, (bfd_vma) ecoff_sym.value); fprintf (file, " %x %x", (unsigned) ecoff_sym.st, @@ -1575,8 +1677,8 @@ ecoff_print_symbol (abfd, filep, symbol, how) { EXTR ecoff_ext; - (*backend->swap_ext_in) (abfd, ecoffsymbol (symbol)->native, - &ecoff_ext); + (*debug_swap->swap_ext_in) (abfd, ecoffsymbol (symbol)->native, + &ecoff_ext); fprintf (file, "ecoff extern "); fprintf_vma (file, (bfd_vma) ecoff_ext.asym.value); fprintf (file, " %x %x", (unsigned) ecoff_ext.asym.st, @@ -1595,25 +1697,25 @@ ecoff_print_symbol (abfd, filep, symbol, how) if (ecoffsymbol (symbol)->local) { - (*backend->swap_sym_in) (abfd, ecoffsymbol (symbol)->native, - &ecoff_ext.asym); + (*debug_swap->swap_sym_in) (abfd, ecoffsymbol (symbol)->native, + &ecoff_ext.asym); type = 'l'; pos = ((((char *) ecoffsymbol (symbol)->native - - (char *) ecoff_data (abfd)->external_sym) - / backend->external_sym_size) - + ecoff_data (abfd)->symbolic_header.iextMax); + - (char *) ecoff_data (abfd)->debug_info.external_sym) + / debug_swap->external_sym_size) + + ecoff_data (abfd)->debug_info.symbolic_header.iextMax); jmptbl = ' '; cobol_main = ' '; weakext = ' '; } else { - (*backend->swap_ext_in) (abfd, ecoffsymbol (symbol)->native, - &ecoff_ext); + (*debug_swap->swap_ext_in) (abfd, ecoffsymbol (symbol)->native, + &ecoff_ext); type = 'e'; pos = (((char *) ecoffsymbol (symbol)->native - - (char *) ecoff_data (abfd)->external_ext) - / backend->external_ext_size); + - (char *) ecoff_data (abfd)->debug_info.external_ext) + / debug_swap->external_ext_size); jmptbl = ecoff_ext.jmptbl ? 'j' : ' '; cobol_main = ecoff_ext.cobol_main ? 'c' : ' '; weakext = ecoff_ext.weakext ? 'w' : ' '; @@ -1632,28 +1734,31 @@ ecoff_print_symbol (abfd, filep, symbol, how) if (ecoffsymbol (symbol)->fdr != NULL && ecoff_ext.asym.index != indexNil) { + FDR *fdr; unsigned int indx; int bigendian; bfd_size_type sym_base; union aux_ext *aux_base; + fdr = ecoffsymbol (symbol)->fdr; indx = ecoff_ext.asym.index; /* sym_base is used to map the fdr relative indices which appear in the file to the position number which we are using. */ - sym_base = ecoffsymbol (symbol)->fdr->isymBase; + sym_base = fdr->isymBase; if (ecoffsymbol (symbol)->local) - sym_base += ecoff_data (abfd)->symbolic_header.iextMax; + sym_base += + ecoff_data (abfd)->debug_info.symbolic_header.iextMax; /* aux_base is the start of the aux entries for this file; asym.index is an offset from this. */ - aux_base = (ecoff_data (abfd)->external_aux - + ecoffsymbol (symbol)->fdr->iauxBase); + aux_base = (ecoff_data (abfd)->debug_info.external_aux + + fdr->iauxBase); /* The aux entries are stored in host byte order; the order is indicated by a bit in the fdr. */ - bigendian = ecoffsymbol (symbol)->fdr->fBigendian; + bigendian = fdr->fBigendian; /* This switch is basically from gcc/mips-tdump.c */ switch (ecoff_ext.asym.st) @@ -1675,9 +1780,10 @@ ecoff_print_symbol (abfd, filep, symbol, how) (long) (indx + sym_base)); else fprintf (file, "\n First symbol: %ld", - (long) (AUX_GET_ISYM (bigendian, - &aux_base[ecoff_ext.asym.index]) - + sym_base)); + ((long) + (AUX_GET_ISYM (bigendian, + &aux_base[ecoff_ext.asym.index]) + + sym_base))); break; case stProc: @@ -1686,23 +1792,38 @@ ecoff_print_symbol (abfd, filep, symbol, how) ; else if (ecoffsymbol (symbol)->local) fprintf (file, "\n End+1 symbol: %-7ld Type: %s", - (long) (AUX_GET_ISYM (bigendian, - &aux_base[ecoff_ext.asym.index]) - + sym_base), - ecoff_type_to_string (abfd, aux_base, indx + 1, - bigendian)); + ((long) + (AUX_GET_ISYM (bigendian, + &aux_base[ecoff_ext.asym.index]) + + sym_base)), + ecoff_type_to_string (abfd, fdr, indx + 1)); else - fprintf (file, "\n Local symbol: %d", - (indx - + sym_base - + ecoff_data (abfd)->symbolic_header.iextMax)); + fprintf (file, "\n Local symbol: %ld", + ((long) indx + + (long) sym_base + + (ecoff_data (abfd) + ->debug_info.symbolic_header.iextMax))); + break; + + case stStruct: + fprintf (file, "\n struct; End+1 symbol: %ld", + (long) (indx + sym_base)); + break; + + case stUnion: + fprintf (file, "\n union; End+1 symbol: %ld", + (long) (indx + sym_base)); + break; + + case stEnum: + fprintf (file, "\n enum; End+1 symbol: %ld", + (long) (indx + sym_base)); break; default: if (! ECOFF_IS_STAB (&ecoff_ext.asym)) fprintf (file, "\n Type: %s", - ecoff_type_to_string (abfd, aux_base, indx, - bigendian)); + ecoff_type_to_string (abfd, fdr, indx)); break; } } @@ -1732,7 +1853,7 @@ ecoff_slurp_reloc_table (abfd, section, symbols) || (section->flags & SEC_CONSTRUCTOR) != 0) return true; - if (ecoff_slurp_symbol_table (abfd) == false) + if (_bfd_ecoff_slurp_symbol_table (abfd) == false) return false; internal_relocs = (arelent *) bfd_alloc (abfd, @@ -1744,17 +1865,14 @@ ecoff_slurp_reloc_table (abfd, section, symbols) if (internal_relocs == (arelent *) NULL || external_relocs == (char *) NULL) { - bfd_error = no_memory; + bfd_set_error (bfd_error_no_memory); return false; } if (bfd_seek (abfd, section->rel_filepos, SEEK_SET) != 0) return false; if (bfd_read (external_relocs, 1, external_relocs_size, abfd) != external_relocs_size) - { - bfd_error = system_call_error; - return false; - } + return false; for (i = 0, rptr = internal_relocs; i < section->reloc_count; i++, rptr++) { @@ -1769,14 +1887,15 @@ ecoff_slurp_reloc_table (abfd, section, symbols) /* r_symndx is an index into the external symbols. */ BFD_ASSERT (intern.r_symndx >= 0 && (intern.r_symndx - < ecoff_data (abfd)->symbolic_header.iextMax)); + < (ecoff_data (abfd) + ->debug_info.symbolic_header.iextMax))); rptr->sym_ptr_ptr = symbols + intern.r_symndx; rptr->addend = 0; } else if (intern.r_symndx == RELOC_SECTION_NONE || intern.r_symndx == RELOC_SECTION_ABS) { - rptr->sym_ptr_ptr = bfd_abs_section.symbol_ptr_ptr; + rptr->sym_ptr_ptr = bfd_abs_section_ptr->symbol_ptr_ptr; rptr->addend = 0; } else @@ -1798,6 +1917,7 @@ ecoff_slurp_reloc_table (abfd, section, symbols) case RELOC_SECTION_LIT4: sec_name = ".lit4"; break; case RELOC_SECTION_XDATA: sec_name = ".xdata"; break; case RELOC_SECTION_PDATA: sec_name = ".pdata"; break; + case RELOC_SECTION_FINI: sec_name = ".fini"; break; case RELOC_SECTION_LITA: sec_name = ".lita"; break; default: abort (); } @@ -1814,7 +1934,7 @@ ecoff_slurp_reloc_table (abfd, section, symbols) /* Let the backend select the howto field and do any other required processing. */ - (*backend->finish_reloc) (abfd, &intern, rptr); + (*backend->adjust_reloc_in) (abfd, &intern, rptr); } bfd_release (abfd, external_relocs); @@ -1826,8 +1946,8 @@ ecoff_slurp_reloc_table (abfd, section, symbols) /* Get a canonical list of relocs. */ -unsigned int -ecoff_canonicalize_reloc (abfd, section, relptr, symbols) +long +_bfd_ecoff_canonicalize_reloc (abfd, section, relptr, symbols) bfd *abfd; asection *section; arelent **relptr; @@ -1852,11 +1972,9 @@ ecoff_canonicalize_reloc (abfd, section, relptr, symbols) arelent *tblptr; if (ecoff_slurp_reloc_table (abfd, section, symbols) == false) - return 0; + return -1; tblptr = section->relocation; - if (tblptr == (arelent *) NULL) - return 0; for (count = 0; count < section->reloc_count; count++) *relptr++ = tblptr++; @@ -1871,14 +1989,10 @@ ecoff_canonicalize_reloc (abfd, section, relptr, symbols) and return the name of the source file and the line nearest to the wanted location. */ +/*ARGSUSED*/ boolean -ecoff_find_nearest_line (abfd, - section, - ignore_symbols, - offset, - filename_ptr, - functionname_ptr, - retline_ptr) +_bfd_ecoff_find_nearest_line (abfd, section, ignore_symbols, offset, + filename_ptr, functionname_ptr, retline_ptr) bfd *abfd; asection *section; asymbol **ignore_symbols; @@ -1887,7 +2001,8 @@ ecoff_find_nearest_line (abfd, CONST char **functionname_ptr; unsigned int *retline_ptr; { - const struct ecoff_backend_data * const backend = ecoff_backend (abfd); + const struct ecoff_debug_swap * const debug_swap + = &ecoff_backend (abfd)->debug_swap; FDR *fdr_ptr; FDR *fdr_start; FDR *fdr_end; @@ -1896,6 +2011,7 @@ ecoff_find_nearest_line (abfd, char *pdr_ptr; char *pdr_end; PDR pdr; + bfd_vma first_off; unsigned char *line_ptr; unsigned char *line_end; int lineno; @@ -1908,7 +2024,8 @@ ecoff_find_nearest_line (abfd, return false; /* Make sure we have the FDR's. */ - if (ecoff_slurp_symbolic_info (abfd) == false + if (! _bfd_ecoff_slurp_symbolic_info (abfd, (asection *) NULL, + &ecoff_data (abfd)->debug_info) || bfd_get_symcount (abfd) == 0) return false; @@ -1917,8 +2034,8 @@ ecoff_find_nearest_line (abfd, memory order. If speed is ever important, this can become a binary search. We must ignore FDR's with no PDR entries; they will have the adr of the FDR before or after them. */ - fdr_start = ecoff_data (abfd)->fdr; - fdr_end = fdr_start + ecoff_data (abfd)->symbolic_header.ifdMax; + fdr_start = ecoff_data (abfd)->debug_info.fdr; + fdr_end = fdr_start + ecoff_data (abfd)->debug_info.symbolic_header.ifdMax; fdr_hold = (FDR *) NULL; for (fdr_ptr = fdr_start; fdr_ptr < fdr_end; fdr_ptr++) { @@ -1936,21 +2053,23 @@ ecoff_find_nearest_line (abfd, have an address, which is relative to the FDR address, and are also stored in increasing memory order. */ offset -= fdr_ptr->adr; - external_pdr_size = backend->external_pdr_size; - pdr_ptr = ((char *) ecoff_data (abfd)->external_pdr + external_pdr_size = debug_swap->external_pdr_size; + pdr_ptr = ((char *) ecoff_data (abfd)->debug_info.external_pdr + fdr_ptr->ipdFirst * external_pdr_size); pdr_end = pdr_ptr + fdr_ptr->cpd * external_pdr_size; - (*backend->swap_pdr_in) (abfd, (PTR) pdr_ptr, &pdr); + (*debug_swap->swap_pdr_in) (abfd, (PTR) pdr_ptr, &pdr); + if (offset < pdr.adr) + return false; /* The address of the first PDR is an offset which applies to the addresses of all the PDR's. */ - offset += pdr.adr; + first_off = pdr.adr; for (pdr_ptr += external_pdr_size; pdr_ptr < pdr_end; pdr_ptr += external_pdr_size) { - (*backend->swap_pdr_in) (abfd, (PTR) pdr_ptr, &pdr); + (*debug_swap->swap_pdr_in) (abfd, (PTR) pdr_ptr, &pdr); if (offset < pdr.adr) break; } @@ -1959,7 +2078,7 @@ ecoff_find_nearest_line (abfd, stored in a very funky format, which I won't try to describe. Note that right here pdr_ptr and pdr hold the PDR *after* the one we want; we need this to compute line_end. */ - line_end = ecoff_data (abfd)->line; + line_end = ecoff_data (abfd)->debug_info.line; if (pdr_ptr == pdr_end) line_end += fdr_ptr->cbLineOffset + fdr_ptr->cbLine; else @@ -1967,11 +2086,11 @@ ecoff_find_nearest_line (abfd, /* Now change pdr and pdr_ptr to the one we want. */ pdr_ptr -= external_pdr_size; - (*backend->swap_pdr_in) (abfd, (PTR) pdr_ptr, &pdr); + (*debug_swap->swap_pdr_in) (abfd, (PTR) pdr_ptr, &pdr); - offset -= pdr.adr; + offset -= pdr.adr - first_off; lineno = pdr.lnLow; - line_ptr = (ecoff_data (abfd)->line + line_ptr = (ecoff_data (abfd)->debug_info.line + fdr_ptr->cbLineOffset + pdr.cbLineOffset); while (line_ptr < line_end) @@ -2008,24 +2127,28 @@ ecoff_find_nearest_line (abfd, { EXTR proc_ext; - (*backend->swap_ext_in) (abfd, - ((char *) ecoff_data (abfd)->external_ext - + pdr.isym * backend->external_ext_size), - &proc_ext); - *functionname_ptr = ecoff_data (abfd)->ssext + proc_ext.asym.iss; + (*debug_swap->swap_ext_in) + (abfd, + ((char *) ecoff_data (abfd)->debug_info.external_ext + + pdr.isym * debug_swap->external_ext_size), + &proc_ext); + *functionname_ptr = (ecoff_data (abfd)->debug_info.ssext + + proc_ext.asym.iss); } } else { SYMR proc_sym; - *filename_ptr = ecoff_data (abfd)->ss + fdr_ptr->issBase + fdr_ptr->rss; - (*backend->swap_sym_in) (abfd, - ((char *) ecoff_data (abfd)->external_sym - + ((fdr_ptr->isymBase + pdr.isym) - * backend->external_sym_size)), - &proc_sym); - *functionname_ptr = (ecoff_data (abfd)->ss + *filename_ptr = (ecoff_data (abfd)->debug_info.ss + + fdr_ptr->issBase + + fdr_ptr->rss); + (*debug_swap->swap_sym_in) + (abfd, + ((char *) ecoff_data (abfd)->debug_info.external_sym + + (fdr_ptr->isymBase + pdr.isym) * debug_swap->external_sym_size), + &proc_sym); + *functionname_ptr = (ecoff_data (abfd)->debug_info.ss + fdr_ptr->issBase + proc_sym.iss); } @@ -2035,913 +2158,122 @@ ecoff_find_nearest_line (abfd, return true; } -/* We can't use the generic linking routines for ECOFF, because we - have to handle all the debugging information. The generic link - routine just works out the section contents and attaches a list of - symbols. - - We link by looping over all the seclets. We make two passes. On - the first we set the actual section contents and determine the size - of the debugging information. On the second we accumulate the - debugging information and write it out. - - This currently always accumulates the debugging information, which - is incorrect, because it ignores the -s and -S options of the - linker. The linker needs to be modified to give us that - information in a more useful format (currently it just provides a - list of symbols which should appear in the output file). */ - -/* Clear the output_has_begun flag for all the input BFD's. We use it - to avoid linking in the debugging information for a BFD more than - once. */ - -static void -ecoff_clear_output_flags (abfd) - bfd *abfd; -{ - register asection *o; - register bfd_seclet_type *p; - - for (o = abfd->sections; o != (asection *) NULL; o = o->next) - for (p = o->seclets_head; - p != (bfd_seclet_type *) NULL; - p = p->next) - if (p->type == bfd_indirect_seclet) - p->u.indirect.section->owner->output_has_begun = false; -} - -/* Handle an indirect seclet on the first pass. Set the contents of - the output section, and accumulate the debugging information if - any. */ - -static boolean -ecoff_rel (output_bfd, seclet, output_section, data, relocateable) - bfd *output_bfd; - bfd_seclet_type *seclet; - asection *output_section; - PTR data; - boolean relocateable; -{ - bfd *input_bfd; - HDRR *output_symhdr; - HDRR *input_symhdr; - - if ((output_section->flags & SEC_HAS_CONTENTS) - && !(output_section->flags & SEC_NEVER_LOAD) - && (output_section->flags & SEC_LOAD) - && seclet->size) - { - data = (PTR) bfd_get_relocated_section_contents (output_bfd, - seclet, - data, - relocateable); - if (bfd_set_section_contents (output_bfd, - output_section, - data, - seclet->offset, - seclet->size) - == false) - { - abort(); - } - } - - input_bfd = seclet->u.indirect.section->owner; - - /* We want to figure out how much space will be required to - incorporate all the debugging information from input_bfd. We use - the output_has_begun field to avoid adding it in more than once. - The actual incorporation is done in the second pass, in - ecoff_get_debug. The code has to parallel that code in its - manipulations of output_symhdr. */ - - if (input_bfd->output_has_begun) - return true; - input_bfd->output_has_begun = true; - - output_symhdr = &ecoff_data (output_bfd)->symbolic_header; - - if (input_bfd->xvec->flavour != bfd_target_ecoff_flavour) - { - asymbol **symbols; - asymbol **sym_ptr; - asymbol **sym_end; - - /* We just accumulate local symbols from a non-ECOFF BFD. The - external symbols are handled separately. */ - - symbols = (asymbol **) bfd_alloc (output_bfd, - get_symtab_upper_bound (input_bfd)); - if (symbols == (asymbol **) NULL) - { - bfd_error = no_memory; - return false; - } - sym_end = symbols + bfd_canonicalize_symtab (input_bfd, symbols); - - for (sym_ptr = symbols; sym_ptr < sym_end; sym_ptr++) - { - size_t len; - - len = strlen ((*sym_ptr)->name); - if (((*sym_ptr)->flags & BSF_EXPORT) == 0) - { - ++output_symhdr->isymMax; - output_symhdr->issMax += len + 1; - } - } - - bfd_release (output_bfd, (PTR) symbols); - - ++output_symhdr->ifdMax; - - return true; - } - - /* We simply add in the information from another ECOFF BFD. First - we make sure we have the symbolic information. */ - if (ecoff_slurp_symbol_table (input_bfd) == false) - return false; - if (bfd_get_symcount (input_bfd) == 0) - return true; - - input_symhdr = &ecoff_data (input_bfd)->symbolic_header; - - /* Figure out how much information we are going to be putting in. - The external symbols are handled separately. */ - output_symhdr->ilineMax += input_symhdr->ilineMax; - output_symhdr->cbLine += input_symhdr->cbLine; - output_symhdr->idnMax += input_symhdr->idnMax; - output_symhdr->ipdMax += input_symhdr->ipdMax; - output_symhdr->isymMax += input_symhdr->isymMax; - output_symhdr->ioptMax += input_symhdr->ioptMax; - output_symhdr->iauxMax += input_symhdr->iauxMax; - output_symhdr->issMax += input_symhdr->issMax; - output_symhdr->ifdMax += input_symhdr->ifdMax; - - /* The RFD's are special, since we create them if needed. */ - if (input_symhdr->crfd > 0) - output_symhdr->crfd += input_symhdr->crfd; - else - output_symhdr->crfd += input_symhdr->ifdMax; +/* Copy private BFD data. This is called by objcopy and strip. We + use it to copy the ECOFF debugging information from one BFD to the + other. It would be theoretically possible to represent the ECOFF + debugging information in the symbol table. However, it would be a + lot of work, and there would be little gain (gas, gdb, and ld + already access the ECOFF debugging information via the + ecoff_debug_info structure, and that structure would have to be + retained in order to support ECOFF debugging in MIPS ELF). + + The debugging information for the ECOFF external symbols comes from + the symbol table, so this function only handles the other debugging + information. */ - return true; -} - -/* Handle an arbitrary seclet on the first pass. */ - -static boolean -ecoff_dump_seclet (abfd, seclet, section, data, relocateable) - bfd *abfd; - bfd_seclet_type *seclet; - asection *section; - PTR data; - boolean relocateable; -{ - switch (seclet->type) - { - case bfd_indirect_seclet: - /* The contents of this section come from another one somewhere - else. */ - return ecoff_rel (abfd, seclet, section, data, relocateable); - - case bfd_fill_seclet: - /* Fill in the section with fill.value. This is used to pad out - sections, but we must avoid padding the .bss section. */ - if ((section->flags & SEC_HAS_CONTENTS) == 0) - { - if (seclet->u.fill.value != 0) - abort (); - } - else - { - char *d = (char *) bfd_alloc (abfd, seclet->size); - unsigned int i; - boolean ret; - - for (i = 0; i < seclet->size; i+=2) - d[i] = seclet->u.fill.value >> 8; - for (i = 1; i < seclet->size; i+=2) - d[i] = seclet->u.fill.value; - ret = bfd_set_section_contents (abfd, section, d, seclet->offset, - seclet->size); - bfd_release (abfd, (PTR) d); - return ret; - } - break; - - default: - abort(); - } - - return true; -} - -/* Add a string to the debugging information we are accumulating for a - file. Return the offset from the fdr string base or from the - external string base. */ - -static long -ecoff_add_string (output_bfd, fdr, string, external) - bfd *output_bfd; - FDR *fdr; - CONST char *string; - boolean external; -{ - HDRR *symhdr; - size_t len; - long ret; - - symhdr = &ecoff_data (output_bfd)->symbolic_header; - len = strlen (string); - if (external) - { - strcpy (ecoff_data (output_bfd)->ssext + symhdr->issExtMax, string); - ret = symhdr->issExtMax; - symhdr->issExtMax += len + 1; - } - else - { - strcpy (ecoff_data (output_bfd)->ss + symhdr->issMax, string); - ret = fdr->cbSs; - symhdr->issMax += len + 1; - fdr->cbSs += len + 1; - } - return ret; -} - -/* Accumulate the debugging information from an input section. */ - -static boolean -ecoff_get_debug (output_bfd, seclet, section, relocateable) - bfd *output_bfd; - bfd_seclet_type *seclet; - asection *section; - boolean relocateable; +boolean +_bfd_ecoff_bfd_copy_private_bfd_data (ibfd, obfd) + bfd *ibfd; + bfd *obfd; { - const struct ecoff_backend_data * const backend = ecoff_backend (output_bfd); - const bfd_size_type external_sym_size = backend->external_sym_size; - const bfd_size_type external_pdr_size = backend->external_pdr_size; - const bfd_size_type external_fdr_size = backend->external_fdr_size; - const bfd_size_type external_rfd_size = backend->external_rfd_size; - void (* const swap_sym_in) PARAMS ((bfd *, PTR, SYMR *)) - = backend->swap_sym_in; - void (* const swap_sym_out) PARAMS ((bfd *, const SYMR *, PTR)) - = backend->swap_sym_out; - void (* const swap_pdr_in) PARAMS ((bfd *, PTR, PDR *)) - = backend->swap_pdr_in; - void (* const swap_fdr_out) PARAMS ((bfd *, const FDR *, PTR)) - = backend->swap_fdr_out; - void (* const swap_rfd_out) PARAMS ((bfd *, const RFDT *, PTR)) - = backend->swap_rfd_out; - bfd *input_bfd; - HDRR *output_symhdr; - HDRR *input_symhdr; - ecoff_data_type *output_ecoff; - ecoff_data_type *input_ecoff; - unsigned int count; - char *sym_out; - ecoff_symbol_type *esym_ptr; - ecoff_symbol_type *esym_end; - FDR *fdr_ptr; - FDR *fdr_end; - char *fdr_out; - - input_bfd = seclet->u.indirect.section->owner; + struct ecoff_debug_info *iinfo = &ecoff_data (ibfd)->debug_info; + struct ecoff_debug_info *oinfo = &ecoff_data (obfd)->debug_info; + register int i; + asymbol **sym_ptr_ptr; + size_t c; + boolean local; - /* Don't get the information more than once. */ - if (input_bfd->output_has_begun) + /* This function is selected based on the input vector. We only + want to copy information over if the output BFD also uses ECOFF + format. */ + if (bfd_get_flavour (obfd) != bfd_target_ecoff_flavour) return true; - input_bfd->output_has_begun = true; - - output_ecoff = ecoff_data (output_bfd); - output_symhdr = &output_ecoff->symbolic_header; - - if (input_bfd->xvec->flavour != bfd_target_ecoff_flavour) - { - FDR fdr; - asymbol **symbols; - asymbol **sym_ptr; - asymbol **sym_end; - - /* This is not an ECOFF BFD. Just gather the symbols. */ - - memset (&fdr, 0, sizeof fdr); - - fdr.adr = bfd_get_section_vma (output_bfd, section) + seclet->offset; - fdr.issBase = output_symhdr->issMax; - fdr.cbSs = 0; - fdr.rss = ecoff_add_string (output_bfd, - &fdr, - bfd_get_filename (input_bfd), - false); - fdr.isymBase = output_symhdr->isymMax; - /* Get the local symbols from the input BFD. */ - symbols = (asymbol **) bfd_alloc (output_bfd, - get_symtab_upper_bound (input_bfd)); - if (symbols == (asymbol **) NULL) - { - bfd_error = no_memory; - return false; - } - sym_end = symbols + bfd_canonicalize_symtab (input_bfd, symbols); + /* Copy the GP value and the register masks. */ + ecoff_data (obfd)->gp = ecoff_data (ibfd)->gp; + ecoff_data (obfd)->gprmask = ecoff_data (ibfd)->gprmask; + ecoff_data (obfd)->fprmask = ecoff_data (ibfd)->fprmask; + for (i = 0; i < 3; i++) + ecoff_data (obfd)->cprmask[i] = ecoff_data (ibfd)->cprmask[i]; - /* Handle the local symbols. Any external symbols are handled - separately. */ - fdr.csym = 0; - for (sym_ptr = symbols; sym_ptr != sym_end; sym_ptr++) - { - SYMR internal_sym; + /* Copy the version stamp. */ + oinfo->symbolic_header.vstamp = iinfo->symbolic_header.vstamp; - if (((*sym_ptr)->flags & BSF_EXPORT) != 0) - continue; - memset (&internal_sym, 0, sizeof internal_sym); - internal_sym.iss = ecoff_add_string (output_bfd, - &fdr, - (*sym_ptr)->name, - false); - - if (bfd_is_com_section ((*sym_ptr)->section) - || (*sym_ptr)->section == &bfd_und_section) - internal_sym.value = (*sym_ptr)->value; - else - internal_sym.value = ((*sym_ptr)->value - + (*sym_ptr)->section->output_offset - + (*sym_ptr)->section->output_section->vma); - internal_sym.st = stNil; - internal_sym.sc = scUndefined; - internal_sym.index = indexNil; - (*swap_sym_out) (output_bfd, &internal_sym, - ((char *) output_ecoff->external_sym - + output_symhdr->isymMax * external_sym_size)); - ++fdr.csym; - ++output_symhdr->isymMax; - } - - bfd_release (output_bfd, (PTR) symbols); - - /* Leave everything else in the FDR zeroed out. This will cause - the lang field to be langC. The fBigendian field will - indicate little endian format, but it doesn't matter because - it only applies to aux fields and there are none. */ - - (*swap_fdr_out) (output_bfd, &fdr, - ((char *) output_ecoff->external_fdr - + output_symhdr->ifdMax * external_fdr_size)); - ++output_symhdr->ifdMax; - return true; - } - - /* This is an ECOFF BFD. We want to grab the information from - input_bfd and attach it to output_bfd. */ - count = bfd_get_symcount (input_bfd); - if (count == 0) + /* If there are no symbols, don't copy any debugging information. */ + c = bfd_get_symcount (obfd); + sym_ptr_ptr = bfd_get_outsymbols (obfd); + if (c == 0 || sym_ptr_ptr == (asymbol **) NULL) return true; - input_ecoff = ecoff_data (input_bfd); - input_symhdr = &input_ecoff->symbolic_header; - - /* I think that it is more efficient to simply copy the debugging - information from the input BFD to the output BFD. Because ECOFF - uses relative pointers for most of the debugging information, - only a little of it has to be changed at all. */ - /* Swap in the local symbols, adjust their values, and swap them out - again. The external symbols are handled separately. */ - sym_out = ((char *) output_ecoff->external_sym - + output_symhdr->isymMax * external_sym_size); - - esym_ptr = ecoff_data (input_bfd)->canonical_symbols; - esym_end = esym_ptr + count; - for (; esym_ptr < esym_end; esym_ptr++) + /* See if there are any local symbols. */ + local = false; + for (; c > 0; c--, sym_ptr_ptr++) { - if (esym_ptr->local) + if (ecoffsymbol (*sym_ptr_ptr)->local) { - SYMR sym; - - (*swap_sym_in) (input_bfd, esym_ptr->native, &sym); - - /* If we're producing an executable, move common symbols - into bss. */ - if (relocateable == false) - { - if (sym.sc == scCommon) - sym.sc = scBss; - else if (sym.sc == scSCommon) - sym.sc = scSBss; - } - - if (! bfd_is_com_section (esym_ptr->symbol.section) - && (esym_ptr->symbol.flags & BSF_DEBUGGING) == 0 - && esym_ptr->symbol.section != &bfd_und_section) - sym.value = (esym_ptr->symbol.value - + esym_ptr->symbol.section->output_offset - + esym_ptr->symbol.section->output_section->vma); - (*swap_sym_out) (output_bfd, &sym, sym_out); - sym_out += external_sym_size; + local = true; + break; } } - /* That should have accounted for all the local symbols in - input_bfd. */ - - /* Copy the information that does not need swapping. */ - memcpy (output_ecoff->line + output_symhdr->cbLine, - input_ecoff->line, - input_symhdr->cbLine * sizeof (unsigned char)); - memcpy (output_ecoff->external_aux + output_symhdr->iauxMax, - input_ecoff->external_aux, - input_symhdr->iauxMax * sizeof (union aux_ext)); - memcpy (output_ecoff->ss + output_symhdr->issMax, - input_ecoff->ss, - input_symhdr->issMax * sizeof (char)); - - /* Some of the information may need to be swapped. */ - if (output_bfd->xvec->header_byteorder_big_p - == input_bfd->xvec->header_byteorder_big_p) - { - /* The two BFD's have the same endianness, so memcpy will - suffice. */ - if (input_symhdr->idnMax > 0) - memcpy (((char *) output_ecoff->external_dnr - + output_symhdr->idnMax * backend->external_dnr_size), - input_ecoff->external_dnr, - input_symhdr->idnMax * backend->external_dnr_size); - if (input_symhdr->ipdMax > 0) - memcpy (((char *) output_ecoff->external_pdr - + output_symhdr->ipdMax * external_pdr_size), - input_ecoff->external_pdr, - input_symhdr->ipdMax * external_pdr_size); - if (input_symhdr->ioptMax > 0) - memcpy (((char *) output_ecoff->external_opt - + output_symhdr->ioptMax * backend->external_opt_size), - input_ecoff->external_opt, - input_symhdr->ioptMax * backend->external_opt_size); - } - else + if (local) { - bfd_size_type sz; - char *in; - char *end; - char *out; - - /* The two BFD's have different endianness, so we must swap - everything in and out. This code would always work, but it - would be slow in the normal case. */ - sz = backend->external_dnr_size; - in = (char *) input_ecoff->external_dnr; - end = in + input_symhdr->idnMax * sz; - out = (char *) output_ecoff->external_dnr + output_symhdr->idnMax * sz; - for (; in < end; in += sz, out += sz) - { - DNR dnr; - - (*backend->swap_dnr_in) (input_bfd, in, &dnr); - (*backend->swap_dnr_out) (output_bfd, &dnr, out); - } - - sz = external_pdr_size; - in = (char *) input_ecoff->external_pdr; - end = in + input_symhdr->ipdMax * sz; - out = (char *) output_ecoff->external_pdr + output_symhdr->ipdMax * sz; - for (; in < end; in += sz, out += sz) - { - PDR pdr; - - (*swap_pdr_in) (input_bfd, in, &pdr); - (*backend->swap_pdr_out) (output_bfd, &pdr, out); - } + /* There are some local symbols. We just bring over all the + debugging information. FIXME: This is not quite the right + thing to do. If the user has asked us to discard all + debugging information, then we are probably going to wind up + keeping it because there will probably be some local symbol + which objcopy did not discard. We should actually break + apart the debugging information and only keep that which + applies to the symbols we want to keep. */ + oinfo->symbolic_header.ilineMax = iinfo->symbolic_header.ilineMax; + oinfo->symbolic_header.cbLine = iinfo->symbolic_header.cbLine; + oinfo->line = iinfo->line; - sz = backend->external_opt_size; - in = (char *) input_ecoff->external_opt; - end = in + input_symhdr->ioptMax * sz; - out = (char *) output_ecoff->external_opt + output_symhdr->ioptMax * sz; - for (; in < end; in += sz, out += sz) - { - OPTR opt; + oinfo->symbolic_header.idnMax = iinfo->symbolic_header.idnMax; + oinfo->external_dnr = iinfo->external_dnr; - (*backend->swap_opt_in) (input_bfd, in, &opt); - (*backend->swap_opt_out) (output_bfd, &opt, out); - } - } + oinfo->symbolic_header.ipdMax = iinfo->symbolic_header.ipdMax; + oinfo->external_pdr = iinfo->external_pdr; - /* Set ifdbase so that the external symbols know how to adjust their - ifd values. */ - input_ecoff->ifdbase = output_symhdr->ifdMax; + oinfo->symbolic_header.isymMax = iinfo->symbolic_header.isymMax; + oinfo->external_sym = iinfo->external_sym; - fdr_ptr = input_ecoff->fdr; - fdr_end = fdr_ptr + input_symhdr->ifdMax; - fdr_out = ((char *) output_ecoff->external_fdr - + output_symhdr->ifdMax * external_fdr_size); - for (; fdr_ptr < fdr_end; fdr_ptr++, fdr_out += external_fdr_size) - { - FDR fdr; - unsigned long pdr_off; + oinfo->symbolic_header.ioptMax = iinfo->symbolic_header.ioptMax; + oinfo->external_opt = iinfo->external_opt; - fdr = *fdr_ptr; + oinfo->symbolic_header.iauxMax = iinfo->symbolic_header.iauxMax; + oinfo->external_aux = iinfo->external_aux; - /* The memory address for this fdr is the address for the seclet - plus the offset to this fdr within input_bfd. For some - reason the offset of the first procedure pointer is also - added in. */ - if (fdr.cpd == 0) - pdr_off = 0; - else - { - PDR pdr; + oinfo->symbolic_header.issMax = iinfo->symbolic_header.issMax; + oinfo->ss = iinfo->ss; - (*swap_pdr_in) (input_bfd, - ((char *) input_ecoff->external_pdr - + fdr.ipdFirst * external_pdr_size), - &pdr); - pdr_off = pdr.adr; - } - fdr.adr = (bfd_get_section_vma (output_bfd, section) - + seclet->offset - + (fdr_ptr->adr - input_ecoff->fdr->adr) - + pdr_off); - - fdr.issBase += output_symhdr->issMax; - fdr.isymBase += output_symhdr->isymMax; - fdr.ilineBase += output_symhdr->ilineMax; - fdr.ioptBase += output_symhdr->ioptMax; - fdr.ipdFirst += output_symhdr->ipdMax; - fdr.iauxBase += output_symhdr->iauxMax; - fdr.rfdBase += output_symhdr->crfd; - - /* If there are no RFD's, we are going to add some. We don't - want to adjust irfd for this, so that all the FDR's can share - the RFD's. */ - if (input_symhdr->crfd == 0) - fdr.crfd = input_symhdr->ifdMax; - - if (fdr.cbLine != 0) - fdr.cbLineOffset += output_symhdr->cbLine; - - (*swap_fdr_out) (output_bfd, &fdr, fdr_out); - } - - if (input_symhdr->crfd > 0) - { - void (* const swap_rfd_in) PARAMS ((bfd *, PTR, RFDT *)) - = backend->swap_rfd_in; - char *rfd_in; - char *rfd_end; - char *rfd_out; - - /* Swap and adjust the RFD's. RFD's are only created by the - linker, so this will only be necessary if one of the input - files is the result of a partial link. Presumably all - necessary RFD's are present. */ - rfd_in = (char *) input_ecoff->external_rfd; - rfd_end = rfd_in + input_symhdr->crfd * external_rfd_size; - rfd_out = ((char *) output_ecoff->external_rfd - + output_symhdr->crfd * external_rfd_size); - for (; - rfd_in < rfd_end; - rfd_in += external_rfd_size, rfd_out += external_rfd_size) - { - RFDT rfd; + oinfo->symbolic_header.ifdMax = iinfo->symbolic_header.ifdMax; + oinfo->external_fdr = iinfo->external_fdr; - (*swap_rfd_in) (input_bfd, rfd_in, &rfd); - rfd += output_symhdr->ifdMax; - (*swap_rfd_out) (output_bfd, &rfd, rfd_out); - } - output_symhdr->crfd += input_symhdr->crfd; + oinfo->symbolic_header.crfd = iinfo->symbolic_header.crfd; + oinfo->external_rfd = iinfo->external_rfd; } else { - char *rfd_out; - char *rfd_end; - RFDT rfd; - - /* Create RFD's. Some of the debugging information includes - relative file indices. These indices are taken as indices to - the RFD table if there is one, or to the global table if - there is not. If we did not create RFD's, we would have to - parse and adjust all the debugging information which contains - file indices. */ - rfd = output_symhdr->ifdMax; - rfd_out = ((char *) output_ecoff->external_rfd - + output_symhdr->crfd * external_rfd_size); - rfd_end = rfd_out + input_symhdr->ifdMax * external_rfd_size; - for (; rfd_out < rfd_end; rfd_out += external_rfd_size, rfd++) - (*swap_rfd_out) (output_bfd, &rfd, rfd_out); - output_symhdr->crfd += input_symhdr->ifdMax; - } - - /* Combine the register masks. Not all of these are used on all - targets, but that's OK because only the relevant ones will be - swapped in and out. */ - { - int i; - - output_ecoff->gprmask |= input_ecoff->gprmask; - output_ecoff->fprmask |= input_ecoff->fprmask; - for (i = 0; i < 4; i++) - output_ecoff->cprmask[i] |= input_ecoff->cprmask[i]; - } - - /* Update the counts. */ - output_symhdr->ilineMax += input_symhdr->ilineMax; - output_symhdr->cbLine += input_symhdr->cbLine; - output_symhdr->idnMax += input_symhdr->idnMax; - output_symhdr->ipdMax += input_symhdr->ipdMax; - output_symhdr->isymMax += input_symhdr->isymMax; - output_symhdr->ioptMax += input_symhdr->ioptMax; - output_symhdr->iauxMax += input_symhdr->iauxMax; - output_symhdr->issMax += input_symhdr->issMax; - output_symhdr->ifdMax += input_symhdr->ifdMax; - - return true; -} - -/* This is the actual link routine. It makes two passes over all the - seclets. */ - -boolean -ecoff_bfd_seclet_link (abfd, data, relocateable) - bfd *abfd; - PTR data; - boolean relocateable; -{ - const struct ecoff_backend_data * const backend = ecoff_backend (abfd); - HDRR *symhdr; - int ipass; - register asection *o; - register bfd_seclet_type *p; - asymbol **sym_ptr_ptr; - bfd_size_type debug_align; - bfd_size_type size; - char *raw; - - /* We accumulate the debugging information counts in the symbolic - header. */ - symhdr = &ecoff_data (abfd)->symbolic_header; - symhdr->magic = backend->sym_magic; - /* FIXME: What should the version stamp be? */ - symhdr->vstamp = 0; - symhdr->ilineMax = 0; - symhdr->cbLine = 0; - symhdr->idnMax = 0; - symhdr->ipdMax = 0; - symhdr->isymMax = 0; - symhdr->ioptMax = 0; - symhdr->iauxMax = 0; - symhdr->issMax = 0; - symhdr->issExtMax = 0; - symhdr->ifdMax = 0; - symhdr->crfd = 0; - symhdr->iextMax = 0; - - /* We need to copy over the debugging symbols from each input BFD. - When we do this copying, we have to adjust the text address in - the FDR structures, so we have to know the text address used for - the input BFD. Since we only want to copy the symbols once per - input BFD, but we are going to look at each input BFD multiple - times (once for each section it provides), we arrange to always - look at the text section first. That means that when we copy the - debugging information, we always know the text address. So we - actually do each pass in two sub passes; first the text sections, - then the non-text sections. We use the output_has_begun flag to - determine whether we have copied over the debugging information - yet. */ - - /* Do the first pass: set the output section contents and count the - debugging information. */ - ecoff_clear_output_flags (abfd); - for (ipass = 0; ipass < 2; ipass++) - { - for (o = abfd->sections; o != (asection *) NULL; o = o->next) + /* We are discarding all the local symbol information. Look + through the external symbols and remove all references to FDR + or aux information. */ + c = bfd_get_symcount (obfd); + sym_ptr_ptr = bfd_get_outsymbols (obfd); + for (; c > 0; c--, sym_ptr_ptr++) { - /* If this is a fake section, just forget it. The register - information is handled in another way. */ - if (strcmp (o->name, SCOMMON) == 0 - || strcmp (o->name, REGINFO) == 0) - continue; - - /* For SEC_CODE sections, (flags & SEC_CODE) == 0 is false, - so they are done on pass 0. For other sections the - expression is true, so they are done on pass 1. */ - if (((o->flags & SEC_CODE) == 0) != ipass) - continue; - - for (p = o->seclets_head; - p != (bfd_seclet_type *) NULL; - p = p->next) - { - if (ecoff_dump_seclet (abfd, p, o, data, relocateable) - == false) - return false; - } - } - } - - /* We handle the external symbols differently. We use the ones - attached to the output_bfd. The linker will have already - determined which symbols are to be attached. Here we just - determine how much space we will need for them. */ - sym_ptr_ptr = bfd_get_outsymbols (abfd); - if (sym_ptr_ptr != NULL) - { - asymbol **sym_end; - - sym_end = sym_ptr_ptr + bfd_get_symcount (abfd); - for (; sym_ptr_ptr < sym_end; sym_ptr_ptr++) - { - if (((*sym_ptr_ptr)->flags & BSF_DEBUGGING) == 0 - && ((*sym_ptr_ptr)->flags & BSF_LOCAL) == 0) - { - ++symhdr->iextMax; - symhdr->issExtMax += strlen ((*sym_ptr_ptr)->name) + 1; - } - } - } - - /* Adjust the counts so that structures are longword aligned. */ - debug_align = backend->debug_align; - --debug_align; - symhdr->cbLine = (symhdr->cbLine + debug_align) &~ debug_align; - symhdr->issMax = (symhdr->issMax + debug_align) &~ debug_align; - symhdr->issExtMax = (symhdr->issExtMax + debug_align) &~ debug_align; - - /* Now the counts in symhdr are the correct size for the debugging - information. We allocate the right amount of space, and reset - the counts so that the second pass can use them as indices. It - would be possible to output the debugging information directly to - the file in pass 2, rather than to build it in memory and then - write it out. Outputting to the file would require a lot of - seeks and small writes, though, and I think this approach is - faster. */ - size = (symhdr->cbLine * sizeof (unsigned char) - + symhdr->idnMax * backend->external_dnr_size - + symhdr->ipdMax * backend->external_pdr_size - + symhdr->isymMax * backend->external_sym_size - + symhdr->ioptMax * backend->external_opt_size - + symhdr->iauxMax * sizeof (union aux_ext) - + symhdr->issMax * sizeof (char) - + symhdr->issExtMax * sizeof (char) - + symhdr->ifdMax * backend->external_fdr_size - + symhdr->crfd * backend->external_rfd_size - + symhdr->iextMax * backend->external_ext_size); - raw = (char *) bfd_alloc (abfd, size); - if (raw == (char *) NULL) - { - bfd_error = no_memory; - return false; - } - ecoff_data (abfd)->raw_size = size; - ecoff_data (abfd)->raw_syments = (PTR) raw; - - /* Initialize the raw pointers. */ -#define SET(field, count, type, size) \ - ecoff_data (abfd)->field = (type) raw; \ - raw += symhdr->count * size - - SET (line, cbLine, unsigned char *, sizeof (unsigned char)); - SET (external_dnr, idnMax, PTR, backend->external_dnr_size); - SET (external_pdr, ipdMax, PTR, backend->external_pdr_size); - SET (external_sym, isymMax, PTR, backend->external_sym_size); - SET (external_opt, ioptMax, PTR, backend->external_opt_size); - SET (external_aux, iauxMax, union aux_ext *, sizeof (union aux_ext)); - SET (ss, issMax, char *, sizeof (char)); - SET (ssext, issExtMax, char *, sizeof (char)); - SET (external_fdr, ifdMax, PTR, backend->external_fdr_size); - SET (external_rfd, crfd, PTR, backend->external_rfd_size); - SET (external_ext, iextMax, PTR, backend->external_ext_size); -#undef SET - - /* Reset the counts so the second pass can use them to know how far - it has gotten. */ - symhdr->ilineMax = 0; - symhdr->cbLine = 0; - symhdr->idnMax = 0; - symhdr->ipdMax = 0; - symhdr->isymMax = 0; - symhdr->ioptMax = 0; - symhdr->iauxMax = 0; - symhdr->issMax = 0; - symhdr->issExtMax = 0; - symhdr->ifdMax = 0; - symhdr->crfd = 0; - symhdr->iextMax = 0; - - /* Do the second pass: accumulate the debugging information. */ - ecoff_clear_output_flags (abfd); - for (ipass = 0; ipass < 2; ipass++) - { - for (o = abfd->sections; o != (asection *) NULL; o = o->next) - { - if (strcmp (o->name, SCOMMON) == 0 - || strcmp (o->name, REGINFO) == 0) - continue; - if (((o->flags & SEC_CODE) == 0) != ipass) - continue; - for (p = o->seclets_head; - p != (bfd_seclet_type *) NULL; - p = p->next) - { - if (p->type == bfd_indirect_seclet) - { - if (ecoff_get_debug (abfd, p, o, relocateable) == false) - return false; - } - } - } - } - - /* Put in the external symbols. */ - sym_ptr_ptr = bfd_get_outsymbols (abfd); - if (sym_ptr_ptr != NULL) - { - const bfd_size_type external_ext_size = backend->external_ext_size; - void (* const swap_ext_in) PARAMS ((bfd *, PTR, EXTR *)) - = backend->swap_ext_in; - void (* const swap_ext_out) PARAMS ((bfd *, const EXTR *, PTR)) - = backend->swap_ext_out; - char *ssext; - char *external_ext; - - ssext = ecoff_data (abfd)->ssext; - external_ext = (char *) ecoff_data (abfd)->external_ext; - for (; *sym_ptr_ptr != NULL; sym_ptr_ptr++) - { - asymbol *sym_ptr; EXTR esym; - sym_ptr = *sym_ptr_ptr; - - if ((sym_ptr->flags & BSF_DEBUGGING) != 0 - || (sym_ptr->flags & BSF_LOCAL) != 0) - continue; - - /* The native pointer can be NULL for a symbol created by - the linker via ecoff_make_empty_symbol. */ - if (bfd_asymbol_flavour (sym_ptr) != bfd_target_ecoff_flavour - || ecoffsymbol (sym_ptr)->native == NULL) - { - esym.jmptbl = 0; - esym.cobol_main = 0; - esym.weakext = 0; - esym.reserved = 0; - esym.ifd = ifdNil; - /* FIXME: we can do better than this for st and sc. */ - esym.asym.st = stGlobal; - esym.asym.sc = scAbs; - esym.asym.reserved = 0; - esym.asym.index = indexNil; - } - else - { - ecoff_symbol_type *ecoff_sym_ptr; - - ecoff_sym_ptr = ecoffsymbol (sym_ptr); - if (ecoff_sym_ptr->local) - abort (); - (*swap_ext_in) (abfd, ecoff_sym_ptr->native, &esym); - - /* If we're producing an executable, move common symbols - into bss. */ - if (relocateable == false) - { - if (esym.asym.sc == scCommon) - esym.asym.sc = scBss; - else if (esym.asym.sc == scSCommon) - esym.asym.sc = scSBss; - } - - /* Adjust the FDR index for the symbol by that used for - the input BFD. */ - esym.ifd += ecoff_data (bfd_asymbol_bfd (sym_ptr))->ifdbase; - } - - esym.asym.iss = symhdr->issExtMax; - - if (bfd_is_com_section (sym_ptr->section) - || sym_ptr->section == &bfd_und_section) - esym.asym.value = sym_ptr->value; - else - esym.asym.value = (sym_ptr->value - + sym_ptr->section->output_offset - + sym_ptr->section->output_section->vma); - - (*swap_ext_out) (abfd, &esym, external_ext); - - ecoff_set_sym_index (sym_ptr, symhdr->iextMax); - - external_ext += external_ext_size; - ++symhdr->iextMax; - - strcpy (ssext + symhdr->issExtMax, sym_ptr->name); - symhdr->issExtMax += strlen (sym_ptr->name) + 1; + (*(ecoff_backend (obfd)->debug_swap.swap_ext_in)) + (obfd, ecoffsymbol (*sym_ptr_ptr)->native, &esym); + esym.ifd = ifdNil; + esym.asym.index = indexNil; + (*(ecoff_backend (obfd)->debug_swap.swap_ext_out)) + (obfd, &esym, ecoffsymbol (*sym_ptr_ptr)->native); } } - /* Adjust the counts so that structures are longword aligned. */ - symhdr->cbLine = (symhdr->cbLine + debug_align) &~ debug_align; - symhdr->issMax = (symhdr->issMax + debug_align) &~ debug_align; - symhdr->issExtMax = (symhdr->issExtMax + debug_align) &~ debug_align; - return true; } @@ -2950,7 +2282,7 @@ ecoff_bfd_seclet_link (abfd, data, relocateable) callers ignore the return value. */ boolean -ecoff_set_arch_mach (abfd, arch, machine) +_bfd_ecoff_set_arch_mach (abfd, arch, machine) bfd *abfd; enum bfd_architecture arch; unsigned long machine; @@ -2959,64 +2291,42 @@ ecoff_set_arch_mach (abfd, arch, machine) return arch == ecoff_backend (abfd)->arch; } -/* Get the size of the section headers. We do not output the .scommon - section which we created in ecoff_mkobject, nor do we output any - .reginfo section. */ +/* Get the size of the section headers. */ +/*ARGSUSED*/ int -ecoff_sizeof_headers (abfd, reloc) +_bfd_ecoff_sizeof_headers (abfd, reloc) bfd *abfd; boolean reloc; { asection *current; int c; + int ret; c = 0; for (current = abfd->sections; current != (asection *)NULL; current = current->next) - if (strcmp (current->name, SCOMMON) != 0 - && strcmp (current->name, REGINFO) != 0) - ++c; + ++c; - return (bfd_coff_filhsz (abfd) - + bfd_coff_aoutsz (abfd) - + c * bfd_coff_scnhsz (abfd)); + ret = (bfd_coff_filhsz (abfd) + + bfd_coff_aoutsz (abfd) + + c * bfd_coff_scnhsz (abfd)); + return BFD_ALIGN (ret, 16); } - -/* Get the contents of a section. This is where we handle reading the - .reginfo section, which implicitly holds the contents of an - ecoff_reginfo structure. */ +/* Get the contents of a section. */ boolean -ecoff_get_section_contents (abfd, section, location, offset, count) +_bfd_ecoff_get_section_contents (abfd, section, location, offset, count) bfd *abfd; asection *section; PTR location; file_ptr offset; bfd_size_type count; { - ecoff_data_type *tdata = ecoff_data (abfd); - struct ecoff_reginfo s; - int i; - - if (strcmp (section->name, REGINFO) != 0) - return bfd_generic_get_section_contents (abfd, section, location, - offset, count); - - s.gp_value = tdata->gp; - s.gprmask = tdata->gprmask; - for (i = 0; i < 4; i++) - s.cprmask[i] = tdata->cprmask[i]; - s.fprmask = tdata->fprmask; - - /* bfd_get_section_contents has already checked that the offset and - size is reasonable. We don't have to worry about swapping or any - such thing; the .reginfo section is defined such that the - contents are an ecoff_reginfo structure as seen on the host. */ - memcpy (location, ((char *) &s) + offset, count); - return true; + return _bfd_generic_get_section_contents (abfd, section, location, + offset, count); } /* Calculate the file position for each section, and set @@ -3031,41 +2341,64 @@ ecoff_compute_section_file_positions (abfd) file_ptr old_sofar; boolean first_data; - if (bfd_get_start_address (abfd)) - abfd->flags |= EXEC_P; - - sofar = ecoff_sizeof_headers (abfd, false); + sofar = _bfd_ecoff_sizeof_headers (abfd, false); first_data = true; for (current = abfd->sections; current != (asection *) NULL; current = current->next) { + unsigned int alignment_power; + /* Only deal with sections which have contents */ - if ((current->flags & (SEC_HAS_CONTENTS | SEC_LOAD)) == 0 - || strcmp (current->name, SCOMMON) == 0 - || strcmp (current->name, REGINFO) == 0) + if ((current->flags & (SEC_HAS_CONTENTS | SEC_LOAD)) == 0) continue; + /* For the Alpha ECOFF .pdata section the lnnoptr field is + supposed to indicate the number of .pdata entries that are + really in the section. Each entry is 8 bytes. We store this + away in line_filepos before increasing the section size. */ + if (strcmp (current->name, _PDATA) != 0) + alignment_power = current->alignment_power; + else + { + current->line_filepos = current->_raw_size / 8; + alignment_power = 4; + } + /* On Ultrix, the data sections in an executable file must be aligned to a page boundary within the file. This does not affect the section size, though. FIXME: Does this work for - other platforms? */ + other platforms? It requires some modification for the + Alpha, because .rdata on the Alpha goes with the text, not + the data. */ if ((abfd->flags & EXEC_P) != 0 && (abfd->flags & D_PAGED) != 0 && first_data != false - && (current->flags & SEC_CODE) == 0) + && (current->flags & SEC_CODE) == 0 + && (! ecoff_backend (abfd)->rdata_in_text + || strcmp (current->name, _RDATA) != 0) + && strcmp (current->name, _PDATA) != 0) { const bfd_vma round = ecoff_backend (abfd)->round; sofar = (sofar + round - 1) &~ (round - 1); first_data = false; } + else if (strcmp (current->name, _LIB) == 0) + { + const bfd_vma round = ecoff_backend (abfd)->round; + /* On Irix 4, the location of contents of the .lib section + from a shared library section is also rounded up to a + page boundary. */ + + sofar = (sofar + round - 1) &~ (round - 1); + } /* Align the sections in the file to the same boundary on which they are aligned in virtual memory. */ old_sofar = sofar; - sofar = BFD_ALIGN (sofar, 1 << current->alignment_power); + sofar = BFD_ALIGN (sofar, 1 << alignment_power); current->filepos = sofar; @@ -3073,74 +2406,250 @@ ecoff_compute_section_file_positions (abfd) /* make sure that this section is of the right size too */ old_sofar = sofar; - sofar = BFD_ALIGN (sofar, 1 << current->alignment_power); + sofar = BFD_ALIGN (sofar, 1 << alignment_power); current->_raw_size += sofar - old_sofar; } ecoff_data (abfd)->reloc_filepos = sofar; } -/* Set the contents of a section. This is where we handle setting the - contents of the .reginfo section, which implicitly holds a - ecoff_reginfo structure. */ +/* Determine the location of the relocs for all the sections in the + output file, as well as the location of the symbolic debugging + information. */ + +static bfd_size_type +ecoff_compute_reloc_file_positions (abfd) + bfd *abfd; +{ + const bfd_size_type external_reloc_size = + ecoff_backend (abfd)->external_reloc_size; + file_ptr reloc_base; + bfd_size_type reloc_size; + asection *current; + file_ptr sym_base; + + if (! abfd->output_has_begun) + { + ecoff_compute_section_file_positions (abfd); + abfd->output_has_begun = true; + } + + reloc_base = ecoff_data (abfd)->reloc_filepos; + + reloc_size = 0; + for (current = abfd->sections; + current != (asection *)NULL; + current = current->next) + { + if (current->reloc_count == 0) + current->rel_filepos = 0; + else + { + bfd_size_type relsize; + + current->rel_filepos = reloc_base; + relsize = current->reloc_count * external_reloc_size; + reloc_size += relsize; + reloc_base += relsize; + } + } + + sym_base = ecoff_data (abfd)->reloc_filepos + reloc_size; + + /* At least on Ultrix, the symbol table of an executable file must + be aligned to a page boundary. FIXME: Is this true on other + platforms? */ + if ((abfd->flags & EXEC_P) != 0 + && (abfd->flags & D_PAGED) != 0) + sym_base = ((sym_base + ecoff_backend (abfd)->round - 1) + &~ (ecoff_backend (abfd)->round - 1)); + + ecoff_data (abfd)->sym_filepos = sym_base; + + return reloc_size; +} + +/* Set the contents of a section. */ boolean -ecoff_set_section_contents (abfd, section, location, offset, count) +_bfd_ecoff_set_section_contents (abfd, section, location, offset, count) bfd *abfd; asection *section; PTR location; file_ptr offset; bfd_size_type count; { + /* This must be done first, because bfd_set_section_contents is + going to set output_has_begun to true. */ if (abfd->output_has_begun == false) ecoff_compute_section_file_positions (abfd); - if (strcmp (section->name, REGINFO) == 0) + /* If this is a .lib section, bump the vma address so that it winds + up being the number of .lib sections output. This is right for + Irix 4. Ian Taylor <ian@cygnus.com>. */ + if (strcmp (section->name, _LIB) == 0) + ++section->vma; + + if (count == 0) + return true; + + if (bfd_seek (abfd, (file_ptr) (section->filepos + offset), SEEK_SET) != 0 + || bfd_write (location, 1, count, abfd) != count) + return false; + + return true; +} + +/* Get the GP value for an ECOFF file. This is a hook used by + nlmconv. */ + +bfd_vma +bfd_ecoff_get_gp_value (abfd) + bfd *abfd; +{ + if (bfd_get_flavour (abfd) != bfd_target_ecoff_flavour + || bfd_get_format (abfd) != bfd_object) { - ecoff_data_type *tdata = ecoff_data (abfd); - struct ecoff_reginfo s; - int i; + bfd_set_error (bfd_error_invalid_operation); + return 0; + } + + return ecoff_data (abfd)->gp; +} - /* If the caller is only changing part of the structure, we must - retrieve the current information before the memcpy. */ - if (offset != 0 || count != sizeof (struct ecoff_reginfo)) - { - s.gp_value = tdata->gp; - s.gprmask = tdata->gprmask; - for (i = 0; i < 4; i++) - s.cprmask[i] = tdata->cprmask[i]; - s.fprmask = tdata->fprmask; - } +/* Set the GP value for an ECOFF file. This is a hook used by the + assembler. */ - /* bfd_set_section_contents has already checked that the offset - and size is reasonable. We don't have to worry about - swapping or any such thing; the .reginfo section is defined - such that the contents are an ecoff_reginfo structure as seen - on the host. */ - memcpy (((char *) &s) + offset, location, count); +boolean +bfd_ecoff_set_gp_value (abfd, gp_value) + bfd *abfd; + bfd_vma gp_value; +{ + if (bfd_get_flavour (abfd) != bfd_target_ecoff_flavour + || bfd_get_format (abfd) != bfd_object) + { + bfd_set_error (bfd_error_invalid_operation); + return false; + } - tdata->gp = s.gp_value; - tdata->gprmask = s.gprmask; - for (i = 0; i < 4; i++) - tdata->cprmask[i] = s.cprmask[i]; - tdata->fprmask = s.fprmask; + ecoff_data (abfd)->gp = gp_value; - return true; + return true; +} +/* Set the register masks for an ECOFF file. This is a hook used by + the assembler. */ + +boolean +bfd_ecoff_set_regmasks (abfd, gprmask, fprmask, cprmask) + bfd *abfd; + unsigned long gprmask; + unsigned long fprmask; + unsigned long *cprmask; +{ + ecoff_data_type *tdata; + + if (bfd_get_flavour (abfd) != bfd_target_ecoff_flavour + || bfd_get_format (abfd) != bfd_object) + { + bfd_set_error (bfd_error_invalid_operation); + return false; } - bfd_seek (abfd, (file_ptr) (section->filepos + offset), SEEK_SET); + tdata = ecoff_data (abfd); + tdata->gprmask = gprmask; + tdata->fprmask = fprmask; + if (cprmask != (unsigned long *) NULL) + { + register int i; - if (count != 0) - return (bfd_write (location, 1, count, abfd) == count) ? true : false; + for (i = 0; i < 3; i++) + tdata->cprmask[i] = cprmask[i]; + } return true; } +/* Get ECOFF EXTR information for an external symbol. This function + is passed to bfd_ecoff_debug_externals. */ + +static boolean +ecoff_get_extr (sym, esym) + asymbol *sym; + EXTR *esym; +{ + ecoff_symbol_type *ecoff_sym_ptr; + bfd *input_bfd; + + if (bfd_asymbol_flavour (sym) != bfd_target_ecoff_flavour + || ecoffsymbol (sym)->native == NULL) + { + /* Don't include debugging, local, or section symbols. */ + if ((sym->flags & BSF_DEBUGGING) != 0 + || (sym->flags & BSF_LOCAL) != 0 + || (sym->flags & BSF_SECTION_SYM) != 0) + return false; + + esym->jmptbl = 0; + esym->cobol_main = 0; + esym->weakext = 0; + esym->reserved = 0; + esym->ifd = ifdNil; + /* FIXME: we can do better than this for st and sc. */ + esym->asym.st = stGlobal; + esym->asym.sc = scAbs; + esym->asym.reserved = 0; + esym->asym.index = indexNil; + return true; + } + + ecoff_sym_ptr = ecoffsymbol (sym); + + if (ecoff_sym_ptr->local) + return false; + + input_bfd = bfd_asymbol_bfd (sym); + (*(ecoff_backend (input_bfd)->debug_swap.swap_ext_in)) + (input_bfd, ecoff_sym_ptr->native, esym); + + /* If the symbol was defined by the linker, then esym will be + undefined but sym will not be. Get a better class for such a + symbol. */ + if ((esym->asym.sc == scUndefined + || esym->asym.sc == scSUndefined) + && ! bfd_is_und_section (bfd_get_section (sym))) + esym->asym.sc = scAbs; + + /* Adjust the FDR index for the symbol by that used for the input + BFD. */ + if (esym->ifd != -1) + { + struct ecoff_debug_info *input_debug; + + input_debug = &ecoff_data (input_bfd)->debug_info; + BFD_ASSERT (esym->ifd < input_debug->symbolic_header.ifdMax); + if (input_debug->ifdmap != (RFDT *) NULL) + esym->ifd = input_debug->ifdmap[esym->ifd]; + } + + return true; +} + +/* Set the external symbol index. This routine is passed to + bfd_ecoff_debug_externals. */ + +static void +ecoff_set_index (sym, indx) + asymbol *sym; + bfd_size_type indx; +{ + ecoff_set_sym_index (sym, indx); +} + /* Write out an ECOFF file. */ boolean -ecoff_write_object_contents (abfd) +_bfd_ecoff_write_object_contents (abfd) bfd *abfd; { const struct ecoff_backend_data * const backend = ecoff_backend (abfd); @@ -3148,89 +2657,81 @@ ecoff_write_object_contents (abfd) const bfd_size_type filhsz = bfd_coff_filhsz (abfd); const bfd_size_type aoutsz = bfd_coff_aoutsz (abfd); const bfd_size_type scnhsz = bfd_coff_scnhsz (abfd); - const bfd_size_type external_hdr_size = backend->external_hdr_size; + const bfd_size_type external_hdr_size + = backend->debug_swap.external_hdr_size; const bfd_size_type external_reloc_size = backend->external_reloc_size; + void (* const adjust_reloc_out) PARAMS ((bfd *, + const arelent *, + struct internal_reloc *)) + = backend->adjust_reloc_out; void (* const swap_reloc_out) PARAMS ((bfd *, const struct internal_reloc *, PTR)) = backend->swap_reloc_out; + struct ecoff_debug_info * const debug = &ecoff_data (abfd)->debug_info; + HDRR * const symhdr = &debug->symbolic_header; asection *current; unsigned int count; - file_ptr scn_base; - file_ptr reloc_base; - file_ptr sym_base; - unsigned long reloc_size; - unsigned long text_size; - unsigned long text_start; - unsigned long data_size; - unsigned long data_start; - unsigned long bss_size; - PTR buff; + bfd_size_type reloc_size; + bfd_size_type text_size; + bfd_vma text_start; + boolean set_text_start; + bfd_size_type data_size; + bfd_vma data_start; + boolean set_data_start; + bfd_size_type bss_size; + PTR buff = NULL; + PTR reloc_buff = NULL; struct internal_filehdr internal_f; struct internal_aouthdr internal_a; int i; - bfd_error = system_call_error; - - if(abfd->output_has_begun == false) - ecoff_compute_section_file_positions(abfd); - - if (abfd->sections != (asection *) NULL) - scn_base = abfd->sections->filepos; - else - scn_base = 0; - reloc_base = ecoff_data (abfd)->reloc_filepos; + /* Determine where the sections and relocs will go in the output + file. */ + reloc_size = ecoff_compute_reloc_file_positions (abfd); count = 1; - reloc_size = 0; for (current = abfd->sections; current != (asection *)NULL; current = current->next) { - if (strcmp (current->name, SCOMMON) == 0 - || strcmp (current->name, REGINFO) == 0) - continue; current->target_index = count; ++count; - if (current->reloc_count != 0) - { - bfd_size_type relsize; - - current->rel_filepos = reloc_base; - relsize = current->reloc_count * external_reloc_size; - reloc_size += relsize; - reloc_base += relsize; - } - else - current->rel_filepos = 0; } - sym_base = reloc_base + reloc_size; - - /* At least on Ultrix, the symbol table of an executable file must - be aligned to a page boundary. FIXME: Is this true on other - platforms? */ - if ((abfd->flags & EXEC_P) != 0 - && (abfd->flags & D_PAGED) != 0) - sym_base = (sym_base + round - 1) &~ (round - 1); - - ecoff_data (abfd)->sym_filepos = sym_base; - if ((abfd->flags & D_PAGED) != 0) - text_size = ecoff_sizeof_headers (abfd, false); + text_size = _bfd_ecoff_sizeof_headers (abfd, false); else text_size = 0; text_start = 0; + set_text_start = false; data_size = 0; data_start = 0; + set_data_start = false; bss_size = 0; /* Write section headers to the file. */ - buff = (PTR) alloca (scnhsz); + /* Allocate buff big enough to hold a section header, + file header, or a.out header. */ + { + bfd_size_type siz; + siz = scnhsz; + if (siz < filhsz) + siz = filhsz; + if (siz < aoutsz) + siz = aoutsz; + buff = (PTR) malloc (siz); + if (buff == NULL) + { + bfd_set_error (bfd_error_no_memory); + goto error_return; + } + } + internal_f.f_nscns = 0; if (bfd_seek (abfd, (file_ptr) (filhsz + aoutsz), SEEK_SET) != 0) - return false; + goto error_return; for (current = abfd->sections; current != (asection *) NULL; current = current->next) @@ -3238,24 +2739,11 @@ ecoff_write_object_contents (abfd) struct internal_scnhdr section; bfd_vma vma; - if (strcmp (current->name, SCOMMON) == 0) - { - BFD_ASSERT (bfd_get_section_size_before_reloc (current) == 0 - && current->reloc_count == 0); - continue; - } - if (strcmp (current->name, REGINFO) == 0) - { - BFD_ASSERT (current->reloc_count == 0); - continue; - } - ++internal_f.f_nscns; strncpy (section.s_name, current->name, sizeof section.s_name); - /* FIXME: is this correct for shared libraries? I think it is - but I have no platform to check. Ian Lance Taylor. */ + /* This seems to be correct for Irix 4 shared libraries. */ vma = bfd_get_section_vma (abfd, current); if (strcmp (current->name, _LIB) == 0) section.s_vaddr = 0; @@ -3279,7 +2767,16 @@ ecoff_write_object_contents (abfd) want the linker to compute the best size to use, or something. I don't know what happens if the information is not present. */ - section.s_lnnoptr = 0; + if (strcmp (current->name, _PDATA) != 0) + section.s_lnnoptr = 0; + else + { + /* The Alpha ECOFF .pdata section uses the lnnoptr field to + hold the number of entries in the section (each entry is + 8 bytes). We stored this in the line_filepos field in + ecoff_compute_section_file_positions. */ + section.s_lnnoptr = current->line_filepos; + } section.s_nreloc = current->reloc_count; section.s_nlnno = 0; @@ -3288,27 +2785,42 @@ ecoff_write_object_contents (abfd) bfd_coff_swap_scnhdr_out (abfd, (PTR) §ion, buff); if (bfd_write (buff, 1, scnhsz, abfd) != scnhsz) - return false; + goto error_return; - if ((section.s_flags & STYP_TEXT) != 0) + if ((section.s_flags & STYP_TEXT) != 0 + || ((section.s_flags & STYP_RDATA) != 0 + && backend->rdata_in_text) + || strcmp (current->name, _PDATA) == 0) { text_size += bfd_get_section_size_before_reloc (current); - if (text_start == 0 || text_start > vma) - text_start = vma; + if (! set_text_start || text_start > vma) + { + text_start = vma; + set_text_start = true; + } } else if ((section.s_flags & STYP_RDATA) != 0 || (section.s_flags & STYP_DATA) != 0 + || (section.s_flags & STYP_LITA) != 0 || (section.s_flags & STYP_LIT8) != 0 || (section.s_flags & STYP_LIT4) != 0 - || (section.s_flags & STYP_SDATA) != 0) + || (section.s_flags & STYP_SDATA) != 0 + || strcmp (current->name, _XDATA) == 0) { data_size += bfd_get_section_size_before_reloc (current); - if (data_start == 0 || data_start > vma) - data_start = vma; + if (! set_data_start || data_start > vma) + { + data_start = vma; + set_data_start = true; + } } else if ((section.s_flags & STYP_BSS) != 0 || (section.s_flags & STYP_SBSS) != 0) bss_size += bfd_get_section_size_before_reloc (current); + else if ((section.s_flags & STYP_ECOFF_LIB) != 0) + /* Do nothing */ ; + else + abort (); } /* Set up the file header. */ @@ -3327,7 +2839,7 @@ ecoff_write_object_contents (abfd) /* The ECOFF f_nsyms field is not actually the number of symbols, it's the size of symbolic information header. */ internal_f.f_nsyms = external_hdr_size; - internal_f.f_symptr = sym_base; + internal_f.f_symptr = ecoff_data (abfd)->sym_filepos; } else { @@ -3356,9 +2868,8 @@ ecoff_write_object_contents (abfd) else internal_a.magic = ECOFF_AOUT_OMAGIC; - /* FIXME: This is what Ultrix puts in, and it makes the Ultrix - linker happy. But, is it right? */ - internal_a.vstamp = 0x20a; + /* FIXME: Is this really correct? */ + internal_a.vstamp = symhdr->vstamp; /* At least on Ultrix, these have to be rounded to page boundaries. FIXME: Is this true on other platforms? */ @@ -3401,171 +2912,182 @@ ecoff_write_object_contents (abfd) /* Write out the file header and the optional header. */ if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0) - return false; + goto error_return; - buff = (PTR) alloca (filhsz); bfd_coff_swap_filehdr_out (abfd, (PTR) &internal_f, buff); if (bfd_write (buff, 1, filhsz, abfd) != filhsz) - return false; + goto error_return; - buff = (PTR) alloca (aoutsz); bfd_coff_swap_aouthdr_out (abfd, (PTR) &internal_a, buff); if (bfd_write (buff, 1, aoutsz, abfd) != aoutsz) - return false; + goto error_return; - /* Write out the relocs. */ - for (current = abfd->sections; - current != (asection *) NULL; - current = current->next) + /* Build the external symbol information. This must be done before + writing out the relocs so that we know the symbol indices. We + don't do this if this BFD was created by the backend linker, + since it will have already handled the symbols and relocs. */ + if (! ecoff_data (abfd)->linker) { - arelent **reloc_ptr_ptr; - arelent **reloc_end; - char *out_ptr; - - if (current->reloc_count == 0) - continue; - - buff = bfd_alloc (abfd, current->reloc_count * external_reloc_size); - if (buff == NULL) - { - bfd_error = no_memory; - return false; - } + symhdr->iextMax = 0; + symhdr->issExtMax = 0; + debug->external_ext = debug->external_ext_end = NULL; + debug->ssext = debug->ssext_end = NULL; + if (bfd_ecoff_debug_externals (abfd, debug, &backend->debug_swap, + (((abfd->flags & EXEC_P) == 0) + ? true : false), + ecoff_get_extr, ecoff_set_index) + == false) + goto error_return; - reloc_ptr_ptr = current->orelocation; - reloc_end = reloc_ptr_ptr + current->reloc_count; - out_ptr = (char *) buff; - for (; - reloc_ptr_ptr < reloc_end; - reloc_ptr_ptr++, out_ptr += external_reloc_size) + /* Write out the relocs. */ + for (current = abfd->sections; + current != (asection *) NULL; + current = current->next) { - arelent *reloc; - asymbol *sym; - struct internal_reloc in; - - memset (&in, 0, sizeof in); + arelent **reloc_ptr_ptr; + arelent **reloc_end; + char *out_ptr; - reloc = *reloc_ptr_ptr; - sym = *reloc->sym_ptr_ptr; - - in.r_vaddr = reloc->address + bfd_get_section_vma (abfd, current); - in.r_type = reloc->howto->type; + if (current->reloc_count == 0) + continue; - if ((sym->flags & BSF_SECTION_SYM) == 0) + reloc_buff = + bfd_alloc (abfd, current->reloc_count * external_reloc_size); + if (reloc_buff == NULL) { - in.r_symndx = ecoff_get_sym_index (*reloc->sym_ptr_ptr); - in.r_extern = 1; + bfd_set_error (bfd_error_no_memory); + goto error_return; } - else + + reloc_ptr_ptr = current->orelocation; + reloc_end = reloc_ptr_ptr + current->reloc_count; + out_ptr = (char *) reloc_buff; + for (; + reloc_ptr_ptr < reloc_end; + reloc_ptr_ptr++, out_ptr += external_reloc_size) { - CONST char *name; - - name = bfd_get_section_name (abfd, bfd_get_section (sym)); - if (strcmp (name, ".text") == 0) - in.r_symndx = RELOC_SECTION_TEXT; - else if (strcmp (name, ".rdata") == 0) - in.r_symndx = RELOC_SECTION_RDATA; - else if (strcmp (name, ".data") == 0) - in.r_symndx = RELOC_SECTION_DATA; - else if (strcmp (name, ".sdata") == 0) - in.r_symndx = RELOC_SECTION_SDATA; - else if (strcmp (name, ".sbss") == 0) - in.r_symndx = RELOC_SECTION_SBSS; - else if (strcmp (name, ".bss") == 0) - in.r_symndx = RELOC_SECTION_BSS; - else if (strcmp (name, ".init") == 0) - in.r_symndx = RELOC_SECTION_INIT; - else if (strcmp (name, ".lit8") == 0) - in.r_symndx = RELOC_SECTION_LIT8; - else if (strcmp (name, ".lit4") == 0) - in.r_symndx = RELOC_SECTION_LIT4; + arelent *reloc; + asymbol *sym; + struct internal_reloc in; + + memset ((PTR) &in, 0, sizeof in); + + reloc = *reloc_ptr_ptr; + sym = *reloc->sym_ptr_ptr; + + in.r_vaddr = (reloc->address + + bfd_get_section_vma (abfd, current)); + in.r_type = reloc->howto->type; + + if ((sym->flags & BSF_SECTION_SYM) == 0) + { + in.r_symndx = ecoff_get_sym_index (*reloc->sym_ptr_ptr); + in.r_extern = 1; + } else - abort (); - in.r_extern = 0; + { + CONST char *name; + + name = bfd_get_section_name (abfd, bfd_get_section (sym)); + if (strcmp (name, ".text") == 0) + in.r_symndx = RELOC_SECTION_TEXT; + else if (strcmp (name, ".rdata") == 0) + in.r_symndx = RELOC_SECTION_RDATA; + else if (strcmp (name, ".data") == 0) + in.r_symndx = RELOC_SECTION_DATA; + else if (strcmp (name, ".sdata") == 0) + in.r_symndx = RELOC_SECTION_SDATA; + else if (strcmp (name, ".sbss") == 0) + in.r_symndx = RELOC_SECTION_SBSS; + else if (strcmp (name, ".bss") == 0) + in.r_symndx = RELOC_SECTION_BSS; + else if (strcmp (name, ".init") == 0) + in.r_symndx = RELOC_SECTION_INIT; + else if (strcmp (name, ".lit8") == 0) + in.r_symndx = RELOC_SECTION_LIT8; + else if (strcmp (name, ".lit4") == 0) + in.r_symndx = RELOC_SECTION_LIT4; + else if (strcmp (name, ".xdata") == 0) + in.r_symndx = RELOC_SECTION_XDATA; + else if (strcmp (name, ".pdata") == 0) + in.r_symndx = RELOC_SECTION_PDATA; + else if (strcmp (name, ".fini") == 0) + in.r_symndx = RELOC_SECTION_FINI; + else if (strcmp (name, ".lita") == 0) + in.r_symndx = RELOC_SECTION_LITA; + else if (strcmp (name, "*ABS*") == 0) + in.r_symndx = RELOC_SECTION_ABS; + else + abort (); + in.r_extern = 0; + } + + (*adjust_reloc_out) (abfd, reloc, &in); + + (*swap_reloc_out) (abfd, &in, (PTR) out_ptr); } - (*swap_reloc_out) (abfd, &in, (PTR) out_ptr); + if (bfd_seek (abfd, current->rel_filepos, SEEK_SET) != 0) + goto error_return; + if (bfd_write (reloc_buff, + external_reloc_size, current->reloc_count, abfd) + != external_reloc_size * current->reloc_count) + goto error_return; + bfd_release (abfd, reloc_buff); + reloc_buff = NULL; } - if (bfd_seek (abfd, current->rel_filepos, SEEK_SET) != 0) - return false; - if (bfd_write (buff, external_reloc_size, current->reloc_count, abfd) - != external_reloc_size * current->reloc_count) - return false; - bfd_release (abfd, buff); + /* Write out the symbolic debugging information. */ + if (bfd_get_symcount (abfd) > 0) + { + /* Write out the debugging information. */ + if (bfd_ecoff_write_debug (abfd, debug, &backend->debug_swap, + ecoff_data (abfd)->sym_filepos) + == false) + goto error_return; + } } - /* Write out the symbolic debugging information. */ - if (bfd_get_symcount (abfd) > 0) - { - HDRR *symhdr; - unsigned long sym_offset; - - /* Set up the offsets in the symbolic header. */ - symhdr = &ecoff_data (abfd)->symbolic_header; - sym_offset = ecoff_data (abfd)->sym_filepos + external_hdr_size; - -#define SET(offset, size, ptr) \ - if (symhdr->size == 0) \ - symhdr->offset = 0; \ - else \ - symhdr->offset = (((char *) ecoff_data (abfd)->ptr \ - - (char *) ecoff_data (abfd)->raw_syments) \ - + sym_offset); - - SET (cbLineOffset, cbLine, line); - SET (cbDnOffset, idnMax, external_dnr); - SET (cbPdOffset, ipdMax, external_pdr); - SET (cbSymOffset, isymMax, external_sym); - SET (cbOptOffset, ioptMax, external_opt); - SET (cbAuxOffset, iauxMax, external_aux); - SET (cbSsOffset, issMax, ss); - SET (cbSsExtOffset, issExtMax, ssext); - SET (cbFdOffset, ifdMax, external_fdr); - SET (cbRfdOffset, crfd, external_rfd); - SET (cbExtOffset, iextMax, external_ext); -#undef SET - - if (bfd_seek (abfd, (file_ptr) ecoff_data (abfd)->sym_filepos, - SEEK_SET) != 0) - return false; - buff = (PTR) alloca (external_hdr_size); - (*backend->swap_hdr_out) (abfd, &ecoff_data (abfd)->symbolic_header, - buff); - if (bfd_write (buff, 1, external_hdr_size, abfd) != external_hdr_size) - return false; - if (bfd_write ((PTR) ecoff_data (abfd)->raw_syments, 1, - ecoff_data (abfd)->raw_size, abfd) - != ecoff_data (abfd)->raw_size) - return false; - } - else if ((abfd->flags & EXEC_P) != 0 - && (abfd->flags & D_PAGED) != 0) + /* The .bss section of a demand paged executable must receive an + entire page. If there are symbols, the symbols will start on the + next page. If there are no symbols, we must fill out the page by + hand. */ + if (bfd_get_symcount (abfd) == 0 + && (abfd->flags & EXEC_P) != 0 + && (abfd->flags & D_PAGED) != 0) { char c; - /* A demand paged executable must occupy an even number of - pages. */ if (bfd_seek (abfd, (file_ptr) ecoff_data (abfd)->sym_filepos - 1, SEEK_SET) != 0) - return false; + goto error_return; if (bfd_read (&c, 1, 1, abfd) == 0) c = 0; if (bfd_seek (abfd, (file_ptr) ecoff_data (abfd)->sym_filepos - 1, SEEK_SET) != 0) - return false; + goto error_return; if (bfd_write (&c, 1, 1, abfd) != 1) - return false; + goto error_return; } + if (reloc_buff != NULL) + bfd_release (abfd, reloc_buff); + if (buff != NULL) + free (buff); return true; + error_return: + if (reloc_buff != NULL) + bfd_release (abfd, reloc_buff); + if (buff != NULL) + free (buff); + return false; } /* Archive handling. ECOFF uses what appears to be a unique type of - archive header (which I call an armap). The byte ordering of the - armap and the contents are encoded in the name of the armap itself. - At least for now, we only support archives with the same byte - ordering in the armap and the contents. + archive header (armap). The byte ordering of the armap and the + contents are encoded in the name of the armap itself. At least for + now, we only support archives with the same byte ordering in the + armap and the contents. The first four bytes in the armap are the number of symbol definitions. This is always a power of two. @@ -3581,10 +3103,6 @@ ecoff_write_object_contents (abfd) The symbols are hashed into the armap with a closed hashing scheme. See the functions below for the details of the algorithm. - We could use the hash table when looking up symbols in a library. - This would require a new BFD target entry point to replace the - bfd_get_next_mapent function used by the linker. - After the symbol definitions comes four bytes holding the size of the string table, followed by the string table itself. */ @@ -3634,7 +3152,7 @@ ecoff_armap_hash (s, rehash, size, hlog) /* Read in the armap. */ boolean -ecoff_slurp_armap (abfd) +_bfd_ecoff_slurp_armap (abfd) bfd *abfd; { char nextname[17]; @@ -3655,7 +3173,8 @@ ecoff_slurp_armap (abfd) if (i != 16) return false; - bfd_seek (abfd, (file_ptr) -16, SEEK_CUR); + if (bfd_seek (abfd, (file_ptr) -16, SEEK_CUR) != 0) + return false; /* Irix 4.0.5F apparently can use either an ECOFF armap or a standard COFF armap. We could move the ECOFF armap stuff into @@ -3687,13 +3206,13 @@ ecoff_slurp_armap (abfd) || ((nextname[ARMAP_OBJECT_ENDIAN_INDEX] == ARMAP_BIG_ENDIAN) ^ (abfd->xvec->byteorder_big_p != false))) { - bfd_error = wrong_format; + bfd_set_error (bfd_error_wrong_format); return false; } /* Read in the armap. */ ardata = bfd_ardata (abfd); - mapdata = snarf_ar_hdr (abfd); + mapdata = _bfd_snarf_ar_hdr (abfd); if (mapdata == (struct areltdata *) NULL) return false; parsed_size = mapdata->parsed_size; @@ -3702,17 +3221,20 @@ ecoff_slurp_armap (abfd) raw_armap = (char *) bfd_alloc (abfd, parsed_size); if (raw_armap == (char *) NULL) { - bfd_error = no_memory; + bfd_set_error (bfd_error_no_memory); return false; } if (bfd_read ((PTR) raw_armap, 1, parsed_size, abfd) != parsed_size) { - bfd_error = malformed_archive; + if (bfd_get_error () != bfd_error_system_call) + bfd_set_error (bfd_error_malformed_archive); bfd_release (abfd, (PTR) raw_armap); return false; } + ardata->tdata = (PTR) raw_armap; + count = bfd_h_get_32 (abfd, (PTR) raw_armap); ardata->symdef_count = 0; @@ -3769,6 +3291,12 @@ ecoff_slurp_armap (abfd) symdef_ptr = ((struct symdef *) bfd_alloc (abfd, ardata->symdef_count * sizeof (struct symdef))); + if (!symdef_ptr) + { + bfd_set_error (bfd_error_no_memory); + return false; + } + ardata->symdefs = (carsym *) symdef_ptr; raw_ptr = raw_armap + 4; @@ -3797,7 +3325,7 @@ ecoff_slurp_armap (abfd) /* Write out an armap. */ boolean -ecoff_write_armap (abfd, elength, map, orl_count, stridx) +_bfd_ecoff_write_armap (abfd, elength, map, orl_count, stridx) bfd *abfd; unsigned int elength; struct orl *map; @@ -3864,7 +3392,7 @@ ecoff_write_armap (abfd, elength, map, orl_count, stridx) sprintf (hdr.ar_size, "%-10d", (int) mapsize); hdr.ar_fmag[0] = '`'; - hdr.ar_fmag[1] = '\n'; + hdr.ar_fmag[1] = '\012'; /* Turn all null bytes in the header into spaces. */ for (i = 0; i < sizeof (struct ar_hdr); i++) @@ -3875,11 +3403,16 @@ ecoff_write_armap (abfd, elength, map, orl_count, stridx) != sizeof (struct ar_hdr)) return false; - bfd_h_put_32 (abfd, hashsize, temp); - if (bfd_write (temp, 1, 4, abfd) != 4) + bfd_h_put_32 (abfd, (bfd_vma) hashsize, temp); + if (bfd_write ((PTR) temp, 1, 4, abfd) != 4) return false; hashtable = (bfd_byte *) bfd_zalloc (abfd, symdefsize); + if (!hashtable) + { + bfd_set_error (bfd_error_no_memory); + return false; + } current = abfd->archive_head; last_elt = current; @@ -3919,18 +3452,20 @@ ecoff_write_armap (abfd, elength, map, orl_count, stridx) hash = srch; } - bfd_h_put_32 (abfd, map[i].namidx, (PTR) (hashtable + hash * 8)); - bfd_h_put_32 (abfd, firstreal, (PTR) (hashtable + hash * 8 + 4)); + bfd_h_put_32 (abfd, (bfd_vma) map[i].namidx, + (PTR) (hashtable + hash * 8)); + bfd_h_put_32 (abfd, (bfd_vma) firstreal, + (PTR) (hashtable + hash * 8 + 4)); } - if (bfd_write (hashtable, 1, symdefsize, abfd) != symdefsize) + if (bfd_write ((PTR) hashtable, 1, symdefsize, abfd) != symdefsize) return false; bfd_release (abfd, hashtable); /* Now write the strings. */ - bfd_h_put_32 (abfd, stringsize, temp); - if (bfd_write (temp, 1, 4, abfd) != 4) + bfd_h_put_32 (abfd, (bfd_vma) stringsize, temp); + if (bfd_write ((PTR) temp, 1, 4, abfd) != 4) return false; for (i = 0; i < orl_count; i++) { @@ -3945,7 +3480,7 @@ ecoff_write_armap (abfd, elength, map, orl_count, stridx) bug-compatible for DECstation ar we use a null. */ if (padit) { - if (bfd_write ("\0", 1, 1, abfd) != 1) + if (bfd_write ("", 1, 1, abfd) != 1) return false; } @@ -3955,8 +3490,8 @@ ecoff_write_armap (abfd, elength, map, orl_count, stridx) /* See whether this BFD is an archive. If it is, read in the armap and the extended name table. */ -bfd_target * -ecoff_archive_p (abfd) +const bfd_target * +_bfd_ecoff_archive_p (abfd) bfd *abfd; { char armag[SARMAG + 1]; @@ -3964,8 +3499,9 @@ ecoff_archive_p (abfd) if (bfd_read ((PTR) armag, 1, SARMAG, abfd) != SARMAG || strncmp (armag, ARMAG, SARMAG) != 0) { - bfd_error = wrong_format; - return (bfd_target *) NULL; + if (bfd_get_error () != bfd_error_system_call) + bfd_set_error (bfd_error_wrong_format); + return (const bfd_target *) NULL; } /* We are setting bfd_ardata(abfd) here, but since bfd_ardata @@ -3976,19 +3512,1442 @@ ecoff_archive_p (abfd) if (bfd_ardata (abfd) == (struct artdata *) NULL) { - bfd_error = no_memory; - return (bfd_target *) NULL; + bfd_set_error (bfd_error_no_memory); + return (const bfd_target *) NULL; } bfd_ardata (abfd)->first_file_filepos = SARMAG; + bfd_ardata (abfd)->cache = NULL; + bfd_ardata (abfd)->archive_head = NULL; + bfd_ardata (abfd)->symdefs = NULL; + bfd_ardata (abfd)->extended_names = NULL; + bfd_ardata (abfd)->tdata = NULL; - if (ecoff_slurp_armap (abfd) == false - || ecoff_slurp_extended_name_table (abfd) == false) + if (_bfd_ecoff_slurp_armap (abfd) == false + || _bfd_ecoff_slurp_extended_name_table (abfd) == false) { bfd_release (abfd, bfd_ardata (abfd)); abfd->tdata.aout_ar_data = (struct artdata *) NULL; - return (bfd_target *) NULL; + return (const bfd_target *) NULL; } return abfd->xvec; } + +/* ECOFF linker code. */ + +static struct bfd_hash_entry *ecoff_link_hash_newfunc + PARAMS ((struct bfd_hash_entry *entry, + struct bfd_hash_table *table, + const char *string)); +static boolean ecoff_link_add_archive_symbols + PARAMS ((bfd *, struct bfd_link_info *)); +static boolean ecoff_link_check_archive_element + PARAMS ((bfd *, struct bfd_link_info *, boolean *pneeded)); +static boolean ecoff_link_add_object_symbols + PARAMS ((bfd *, struct bfd_link_info *)); +static boolean ecoff_link_add_externals + PARAMS ((bfd *, struct bfd_link_info *, PTR, char *)); + +/* Routine to create an entry in an ECOFF link hash table. */ + +static struct bfd_hash_entry * +ecoff_link_hash_newfunc (entry, table, string) + struct bfd_hash_entry *entry; + struct bfd_hash_table *table; + const char *string; +{ + struct ecoff_link_hash_entry *ret = (struct ecoff_link_hash_entry *) entry; + + /* Allocate the structure if it has not already been allocated by a + subclass. */ + if (ret == (struct ecoff_link_hash_entry *) NULL) + ret = ((struct ecoff_link_hash_entry *) + bfd_hash_allocate (table, sizeof (struct ecoff_link_hash_entry))); + if (ret == (struct ecoff_link_hash_entry *) NULL) + { + bfd_set_error (bfd_error_no_memory); + return NULL; + } + + /* Call the allocation method of the superclass. */ + ret = ((struct ecoff_link_hash_entry *) + _bfd_link_hash_newfunc ((struct bfd_hash_entry *) ret, + table, string)); + + if (ret) + { + /* Set local fields. */ + ret->indx = -1; + ret->abfd = NULL; + ret->written = 0; + ret->small = 0; + } + memset ((PTR) &ret->esym, 0, sizeof ret->esym); + + return (struct bfd_hash_entry *) ret; +} + +/* Create an ECOFF link hash table. */ + +struct bfd_link_hash_table * +_bfd_ecoff_bfd_link_hash_table_create (abfd) + bfd *abfd; +{ + struct ecoff_link_hash_table *ret; + + ret = ((struct ecoff_link_hash_table *) + malloc (sizeof (struct ecoff_link_hash_table))); + if (!ret) + { + bfd_set_error (bfd_error_no_memory); + return NULL; + } + if (! _bfd_link_hash_table_init (&ret->root, abfd, + ecoff_link_hash_newfunc)) + { + free (ret); + return (struct bfd_link_hash_table *) NULL; + } + return &ret->root; +} + +/* Look up an entry in an ECOFF link hash table. */ + +#define ecoff_link_hash_lookup(table, string, create, copy, follow) \ + ((struct ecoff_link_hash_entry *) \ + bfd_link_hash_lookup (&(table)->root, (string), (create), (copy), (follow))) + +/* Traverse an ECOFF link hash table. */ + +#define ecoff_link_hash_traverse(table, func, info) \ + (bfd_link_hash_traverse \ + (&(table)->root, \ + (boolean (*) PARAMS ((struct bfd_link_hash_entry *, PTR))) (func), \ + (info))) + +/* Get the ECOFF link hash table from the info structure. This is + just a cast. */ + +#define ecoff_hash_table(p) ((struct ecoff_link_hash_table *) ((p)->hash)) + +/* Given an ECOFF BFD, add symbols to the global hash table as + appropriate. */ + +boolean +_bfd_ecoff_bfd_link_add_symbols (abfd, info) + bfd *abfd; + struct bfd_link_info *info; +{ + switch (bfd_get_format (abfd)) + { + case bfd_object: + return ecoff_link_add_object_symbols (abfd, info); + case bfd_archive: + return ecoff_link_add_archive_symbols (abfd, info); + default: + bfd_set_error (bfd_error_wrong_format); + return false; + } +} + +/* Add the symbols from an archive file to the global hash table. + This looks through the undefined symbols, looks each one up in the + archive hash table, and adds any associated object file. We do not + use _bfd_generic_link_add_archive_symbols because ECOFF archives + already have a hash table, so there is no reason to construct + another one. */ + +static boolean +ecoff_link_add_archive_symbols (abfd, info) + bfd *abfd; + struct bfd_link_info *info; +{ + const bfd_byte *raw_armap; + struct bfd_link_hash_entry **pundef; + unsigned int armap_count; + unsigned int armap_log; + unsigned int i; + const bfd_byte *hashtable; + const char *stringbase; + + if (! bfd_has_map (abfd)) + { + bfd_set_error (bfd_error_no_symbols); + return false; + } + + /* If we don't have any raw data for this archive, as can happen on + Irix 4.0.5F, we call the generic routine. + FIXME: We should be more clever about this, since someday tdata + may get to something for a generic archive. */ + raw_armap = (const bfd_byte *) bfd_ardata (abfd)->tdata; + if (raw_armap == (bfd_byte *) NULL) + return (_bfd_generic_link_add_archive_symbols + (abfd, info, ecoff_link_check_archive_element)); + + armap_count = bfd_h_get_32 (abfd, raw_armap); + + armap_log = 0; + for (i = 1; i < armap_count; i <<= 1) + armap_log++; + BFD_ASSERT (i == armap_count); + + hashtable = raw_armap + 4; + stringbase = (const char *) raw_armap + armap_count * 8 + 8; + + /* Look through the list of undefined symbols. */ + pundef = &info->hash->undefs; + while (*pundef != (struct bfd_link_hash_entry *) NULL) + { + struct bfd_link_hash_entry *h; + unsigned int hash, rehash; + unsigned int file_offset; + const char *name; + bfd *element; + + h = *pundef; + + /* When a symbol is defined, it is not necessarily removed from + the list. */ + if (h->type != bfd_link_hash_undefined + && h->type != bfd_link_hash_common) + { + /* Remove this entry from the list, for general cleanliness + and because we are going to look through the list again + if we search any more libraries. We can't remove the + entry if it is the tail, because that would lose any + entries we add to the list later on. */ + if (*pundef != info->hash->undefs_tail) + *pundef = (*pundef)->next; + else + pundef = &(*pundef)->next; + continue; + } + + /* Native ECOFF linkers do not pull in archive elements merely + to satisfy common definitions, so neither do we. We leave + them on the list, though, in case we are linking against some + other object format. */ + if (h->type != bfd_link_hash_undefined) + { + pundef = &(*pundef)->next; + continue; + } + + /* Look for this symbol in the archive hash table. */ + hash = ecoff_armap_hash (h->root.string, &rehash, armap_count, + armap_log); + + file_offset = bfd_h_get_32 (abfd, hashtable + (hash * 8) + 4); + if (file_offset == 0) + { + /* Nothing in this slot. */ + pundef = &(*pundef)->next; + continue; + } + + name = stringbase + bfd_h_get_32 (abfd, hashtable + (hash * 8)); + if (name[0] != h->root.string[0] + || strcmp (name, h->root.string) != 0) + { + unsigned int srch; + boolean found; + + /* That was the wrong symbol. Try rehashing. */ + found = false; + for (srch = (hash + rehash) & (armap_count - 1); + srch != hash; + srch = (srch + rehash) & (armap_count - 1)) + { + file_offset = bfd_h_get_32 (abfd, hashtable + (srch * 8) + 4); + if (file_offset == 0) + break; + name = stringbase + bfd_h_get_32 (abfd, hashtable + (srch * 8)); + if (name[0] == h->root.string[0] + && strcmp (name, h->root.string) == 0) + { + found = true; + break; + } + } + + if (! found) + { + pundef = &(*pundef)->next; + continue; + } + + hash = srch; + } + + element = _bfd_get_elt_at_filepos (abfd, file_offset); + if (element == (bfd *) NULL) + return false; + + if (! bfd_check_format (element, bfd_object)) + return false; + + /* Unlike the generic linker, we know that this element provides + a definition for an undefined symbol and we know that we want + to include it. We don't need to check anything. */ + if (! (*info->callbacks->add_archive_element) (info, element, name)) + return false; + if (! ecoff_link_add_object_symbols (element, info)) + return false; + + pundef = &(*pundef)->next; + } + + return true; +} + +/* This is called if we used _bfd_generic_link_add_archive_symbols + because we were not dealing with an ECOFF archive. */ + +static boolean +ecoff_link_check_archive_element (abfd, info, pneeded) + bfd *abfd; + struct bfd_link_info *info; + boolean *pneeded; +{ + const struct ecoff_backend_data * const backend = ecoff_backend (abfd); + void (* const swap_ext_in) PARAMS ((bfd *, PTR, EXTR *)) + = backend->debug_swap.swap_ext_in; + HDRR *symhdr; + bfd_size_type external_ext_size; + PTR external_ext = NULL; + size_t esize; + char *ssext = NULL; + char *ext_ptr; + char *ext_end; + + *pneeded = false; + + if (! ecoff_slurp_symbolic_header (abfd)) + goto error_return; + + /* If there are no symbols, we don't want it. */ + if (bfd_get_symcount (abfd) == 0) + goto successful_return; + + symhdr = &ecoff_data (abfd)->debug_info.symbolic_header; + + /* Read in the external symbols and external strings. */ + external_ext_size = backend->debug_swap.external_ext_size; + esize = symhdr->iextMax * external_ext_size; + external_ext = (PTR) malloc (esize); + if (external_ext == NULL && esize != 0) + { + bfd_set_error (bfd_error_no_memory); + goto error_return; + } + + if (bfd_seek (abfd, symhdr->cbExtOffset, SEEK_SET) != 0 + || bfd_read (external_ext, 1, esize, abfd) != esize) + goto error_return; + + ssext = (char *) malloc (symhdr->issExtMax); + if (ssext == NULL && symhdr->issExtMax != 0) + { + bfd_set_error (bfd_error_no_memory); + goto error_return; + } + + if (bfd_seek (abfd, symhdr->cbSsExtOffset, SEEK_SET) != 0 + || bfd_read (ssext, 1, symhdr->issExtMax, abfd) != symhdr->issExtMax) + goto error_return; + + /* Look through the external symbols to see if they define some + symbol that is currently undefined. */ + ext_ptr = (char *) external_ext; + ext_end = ext_ptr + esize; + for (; ext_ptr < ext_end; ext_ptr += external_ext_size) + { + EXTR esym; + boolean def; + const char *name; + struct bfd_link_hash_entry *h; + + (*swap_ext_in) (abfd, (PTR) ext_ptr, &esym); + + /* See if this symbol defines something. */ + if (esym.asym.st != stGlobal + && esym.asym.st != stLabel + && esym.asym.st != stProc) + continue; + + switch (esym.asym.sc) + { + case scText: + case scData: + case scBss: + case scAbs: + case scSData: + case scSBss: + case scRData: + case scCommon: + case scSCommon: + case scInit: + case scFini: + def = true; + break; + default: + def = false; + break; + } + + if (! def) + continue; + + name = ssext + esym.asym.iss; + h = bfd_link_hash_lookup (info->hash, name, false, false, true); + + /* Unlike the generic linker, we do not pull in elements because + of common symbols. */ + if (h == (struct bfd_link_hash_entry *) NULL + || h->type != bfd_link_hash_undefined) + continue; + + /* Include this element. */ + if (! (*info->callbacks->add_archive_element) (info, abfd, name)) + goto error_return; + if (! ecoff_link_add_externals (abfd, info, external_ext, ssext)) + goto error_return; + + *pneeded = true; + goto successful_return; + } + + successful_return: + if (external_ext != NULL) + free (external_ext); + if (ssext != NULL) + free (ssext); + return true; + error_return: + if (external_ext != NULL) + free (external_ext); + if (ssext != NULL) + free (ssext); + return false; +} + +/* Add symbols from an ECOFF object file to the global linker hash + table. */ + +static boolean +ecoff_link_add_object_symbols (abfd, info) + bfd *abfd; + struct bfd_link_info *info; +{ + HDRR *symhdr; + bfd_size_type external_ext_size; + PTR external_ext = NULL; + size_t esize; + char *ssext = NULL; + boolean result; + + if (! ecoff_slurp_symbolic_header (abfd)) + return false; + + /* If there are no symbols, we don't want it. */ + if (bfd_get_symcount (abfd) == 0) + return true; + + symhdr = &ecoff_data (abfd)->debug_info.symbolic_header; + + /* Read in the external symbols and external strings. */ + external_ext_size = ecoff_backend (abfd)->debug_swap.external_ext_size; + esize = symhdr->iextMax * external_ext_size; + external_ext = (PTR) malloc (esize); + if (external_ext == NULL && esize != 0) + { + bfd_set_error (bfd_error_no_memory); + goto error_return; + } + + if (bfd_seek (abfd, symhdr->cbExtOffset, SEEK_SET) != 0 + || bfd_read (external_ext, 1, esize, abfd) != esize) + goto error_return; + + ssext = (char *) malloc (symhdr->issExtMax); + if (ssext == NULL && symhdr->issExtMax != 0) + { + bfd_set_error (bfd_error_no_memory); + goto error_return; + } + + if (bfd_seek (abfd, symhdr->cbSsExtOffset, SEEK_SET) != 0 + || bfd_read (ssext, 1, symhdr->issExtMax, abfd) != symhdr->issExtMax) + goto error_return; + + result = ecoff_link_add_externals (abfd, info, external_ext, ssext); + + if (ssext != NULL) + free (ssext); + if (external_ext != NULL) + free (external_ext); + return result; + + error_return: + if (ssext != NULL) + free (ssext); + if (external_ext != NULL) + free (external_ext); + return false; +} + +/* Add the external symbols of an object file to the global linker + hash table. The external symbols and strings we are passed are + just allocated on the stack, and will be discarded. We must + explicitly save any information we may need later on in the link. + We do not want to read the external symbol information again. */ + +static boolean +ecoff_link_add_externals (abfd, info, external_ext, ssext) + bfd *abfd; + struct bfd_link_info *info; + PTR external_ext; + char *ssext; +{ + const struct ecoff_backend_data * const backend = ecoff_backend (abfd); + void (* const swap_ext_in) PARAMS ((bfd *, PTR, EXTR *)) + = backend->debug_swap.swap_ext_in; + bfd_size_type external_ext_size = backend->debug_swap.external_ext_size; + unsigned long ext_count; + struct ecoff_link_hash_entry **sym_hash; + char *ext_ptr; + char *ext_end; + + ext_count = ecoff_data (abfd)->debug_info.symbolic_header.iextMax; + + sym_hash = ((struct ecoff_link_hash_entry **) + bfd_alloc (abfd, + ext_count * sizeof (struct bfd_link_hash_entry *))); + if (!sym_hash) + { + bfd_set_error (bfd_error_no_memory); + return false; + } + ecoff_data (abfd)->sym_hashes = sym_hash; + + ext_ptr = (char *) external_ext; + ext_end = ext_ptr + ext_count * external_ext_size; + for (; ext_ptr < ext_end; ext_ptr += external_ext_size, sym_hash++) + { + EXTR esym; + boolean skip; + bfd_vma value; + asection *section; + const char *name; + struct ecoff_link_hash_entry *h; + + *sym_hash = NULL; + + (*swap_ext_in) (abfd, (PTR) ext_ptr, &esym); + + /* Skip debugging symbols. */ + skip = false; + switch (esym.asym.st) + { + case stGlobal: + case stStatic: + case stLabel: + case stProc: + case stStaticProc: + break; + default: + skip = true; + break; + } + + if (skip) + continue; + + /* Get the information for this symbol. */ + value = esym.asym.value; + switch (esym.asym.sc) + { + default: + case scNil: + case scRegister: + case scCdbLocal: + case scBits: + case scCdbSystem: + case scRegImage: + case scInfo: + case scUserStruct: + case scVar: + case scVarRegister: + case scVariant: + case scBasedVar: + case scXData: + case scPData: + section = NULL; + break; + case scText: + section = bfd_make_section_old_way (abfd, ".text"); + value -= section->vma; + break; + case scData: + section = bfd_make_section_old_way (abfd, ".data"); + value -= section->vma; + break; + case scBss: + section = bfd_make_section_old_way (abfd, ".bss"); + value -= section->vma; + break; + case scAbs: + section = bfd_abs_section_ptr; + break; + case scUndefined: + section = bfd_und_section_ptr; + break; + case scSData: + section = bfd_make_section_old_way (abfd, ".sdata"); + value -= section->vma; + break; + case scSBss: + section = bfd_make_section_old_way (abfd, ".sbss"); + value -= section->vma; + break; + case scRData: + section = bfd_make_section_old_way (abfd, ".rdata"); + value -= section->vma; + break; + case scCommon: + if (value > ecoff_data (abfd)->gp_size) + { + section = bfd_com_section_ptr; + break; + } + /* Fall through. */ + case scSCommon: + if (ecoff_scom_section.name == NULL) + { + /* Initialize the small common section. */ + ecoff_scom_section.name = SCOMMON; + ecoff_scom_section.flags = SEC_IS_COMMON; + ecoff_scom_section.output_section = &ecoff_scom_section; + ecoff_scom_section.symbol = &ecoff_scom_symbol; + ecoff_scom_section.symbol_ptr_ptr = &ecoff_scom_symbol_ptr; + ecoff_scom_symbol.name = SCOMMON; + ecoff_scom_symbol.flags = BSF_SECTION_SYM; + ecoff_scom_symbol.section = &ecoff_scom_section; + ecoff_scom_symbol_ptr = &ecoff_scom_symbol; + } + section = &ecoff_scom_section; + break; + case scSUndefined: + section = bfd_und_section_ptr; + break; + case scInit: + section = bfd_make_section_old_way (abfd, ".init"); + value -= section->vma; + break; + case scFini: + section = bfd_make_section_old_way (abfd, ".fini"); + value -= section->vma; + break; + } + + if (section == (asection *) NULL) + continue; + + name = ssext + esym.asym.iss; + + h = NULL; + if (! (_bfd_generic_link_add_one_symbol + (info, abfd, name, BSF_GLOBAL, section, value, + (const char *) NULL, true, true, + (struct bfd_link_hash_entry **) &h))) + return false; + + *sym_hash = h; + + /* If we are building an ECOFF hash table, save the external + symbol information. */ + if (info->hash->creator->flavour == bfd_get_flavour (abfd)) + { + if (h->abfd == (bfd *) NULL + || (! bfd_is_und_section (section) + && (! bfd_is_com_section (section) + || h->root.type != bfd_link_hash_defined))) + { + h->abfd = abfd; + h->esym = esym; + } + + /* Remember whether this symbol was small undefined. */ + if (esym.asym.sc == scSUndefined) + h->small = 1; + + /* If this symbol was ever small undefined, it needs to wind + up in a GP relative section. We can't control the + section of a defined symbol, but we can control the + section of a common symbol. This case is actually needed + on Ultrix 4.2 to handle the symbol cred in -lckrb. */ + if (h->small + && h->root.type == bfd_link_hash_common + && strcmp (h->root.u.c.section->name, SCOMMON) != 0) + { + h->root.u.c.section = bfd_make_section_old_way (abfd, SCOMMON); + h->root.u.c.section->flags = SEC_ALLOC; + if (h->esym.asym.sc == scCommon) + h->esym.asym.sc = scSCommon; + } + } + } + + return true; +} + +/* ECOFF final link routines. */ + +static boolean ecoff_final_link_debug_accumulate + PARAMS ((bfd *output_bfd, bfd *input_bfd, struct bfd_link_info *, + PTR handle)); +static boolean ecoff_link_write_external + PARAMS ((struct ecoff_link_hash_entry *, PTR)); +static boolean ecoff_indirect_link_order + PARAMS ((bfd *, struct bfd_link_info *, asection *, + struct bfd_link_order *)); +static boolean ecoff_reloc_link_order + PARAMS ((bfd *, struct bfd_link_info *, asection *, + struct bfd_link_order *)); + +/* ECOFF final link routine. This looks through all the input BFDs + and gathers together all the debugging information, and then + processes all the link order information. This may cause it to + close and reopen some input BFDs; I'll see how bad this is. */ + +boolean +_bfd_ecoff_bfd_final_link (abfd, info) + bfd *abfd; + struct bfd_link_info *info; +{ + const struct ecoff_backend_data * const backend = ecoff_backend (abfd); + struct ecoff_debug_info * const debug = &ecoff_data (abfd)->debug_info; + HDRR *symhdr; + PTR handle; + register bfd *input_bfd; + asection *o; + struct bfd_link_order *p; + + /* We accumulate the debugging information counts in the symbolic + header. */ + symhdr = &debug->symbolic_header; + symhdr->vstamp = 0; + symhdr->ilineMax = 0; + symhdr->cbLine = 0; + symhdr->idnMax = 0; + symhdr->ipdMax = 0; + symhdr->isymMax = 0; + symhdr->ioptMax = 0; + symhdr->iauxMax = 0; + symhdr->issMax = 0; + symhdr->issExtMax = 0; + symhdr->ifdMax = 0; + symhdr->crfd = 0; + symhdr->iextMax = 0; + + /* We accumulate the debugging information itself in the debug_info + structure. */ + debug->line = NULL; + debug->external_dnr = NULL; + debug->external_pdr = NULL; + debug->external_sym = NULL; + debug->external_opt = NULL; + debug->external_aux = NULL; + debug->ss = NULL; + debug->ssext = debug->ssext_end = NULL; + debug->external_fdr = NULL; + debug->external_rfd = NULL; + debug->external_ext = debug->external_ext_end = NULL; + + handle = bfd_ecoff_debug_init (abfd, debug, &backend->debug_swap, info); + if (handle == (PTR) NULL) + return false; + + /* Accumulate the debugging symbols from each input BFD. */ + for (input_bfd = info->input_bfds; + input_bfd != (bfd *) NULL; + input_bfd = input_bfd->link_next) + { + boolean ret; + + if (bfd_get_flavour (input_bfd) == bfd_target_ecoff_flavour) + { + /* Abitrarily set the symbolic header vstamp to the vstamp + of the first object file in the link. */ + if (symhdr->vstamp == 0) + symhdr->vstamp + = ecoff_data (input_bfd)->debug_info.symbolic_header.vstamp; + ret = ecoff_final_link_debug_accumulate (abfd, input_bfd, info, + handle); + } + else + ret = bfd_ecoff_debug_accumulate_other (handle, abfd, + debug, &backend->debug_swap, + input_bfd, info); + if (! ret) + return false; + + /* Combine the register masks. */ + ecoff_data (abfd)->gprmask |= ecoff_data (input_bfd)->gprmask; + ecoff_data (abfd)->fprmask |= ecoff_data (input_bfd)->fprmask; + ecoff_data (abfd)->cprmask[0] |= ecoff_data (input_bfd)->cprmask[0]; + ecoff_data (abfd)->cprmask[1] |= ecoff_data (input_bfd)->cprmask[1]; + ecoff_data (abfd)->cprmask[2] |= ecoff_data (input_bfd)->cprmask[2]; + ecoff_data (abfd)->cprmask[3] |= ecoff_data (input_bfd)->cprmask[3]; + } + + /* Write out the external symbols. */ + ecoff_link_hash_traverse (ecoff_hash_table (info), + ecoff_link_write_external, + (PTR) abfd); + + if (info->relocateable) + { + /* We need to make a pass over the link_orders to count up the + number of relocations we will need to output, so that we know + how much space they will take up. */ + for (o = abfd->sections; o != (asection *) NULL; o = o->next) + { + o->reloc_count = 0; + for (p = o->link_order_head; + p != (struct bfd_link_order *) NULL; + p = p->next) + if (p->type == bfd_indirect_link_order) + o->reloc_count += p->u.indirect.section->reloc_count; + else if (p->type == bfd_section_reloc_link_order + || p->type == bfd_symbol_reloc_link_order) + ++o->reloc_count; + } + } + + /* Compute the reloc and symbol file positions. */ + ecoff_compute_reloc_file_positions (abfd); + + /* Write out the debugging information. */ + if (! bfd_ecoff_write_accumulated_debug (handle, abfd, debug, + &backend->debug_swap, info, + ecoff_data (abfd)->sym_filepos)) + return false; + + bfd_ecoff_debug_free (handle, abfd, debug, &backend->debug_swap, info); + + if (info->relocateable) + { + /* Now reset the reloc_count field of the sections in the output + BFD to 0, so that we can use them to keep track of how many + relocs we have output thus far. */ + for (o = abfd->sections; o != (asection *) NULL; o = o->next) + o->reloc_count = 0; + } + + /* Get a value for the GP register. */ + if (ecoff_data (abfd)->gp == 0) + { + struct bfd_link_hash_entry *h; + + h = bfd_link_hash_lookup (info->hash, "_gp", false, false, true); + if (h != (struct bfd_link_hash_entry *) NULL + && h->type == bfd_link_hash_defined) + ecoff_data (abfd)->gp = (h->u.def.value + + h->u.def.section->output_section->vma + + h->u.def.section->output_offset); + else if (info->relocateable) + { + bfd_vma lo; + + /* Make up a value. */ + lo = (bfd_vma) -1; + for (o = abfd->sections; o != (asection *) NULL; o = o->next) + { + if (o->vma < lo + && (strcmp (o->name, _SBSS) == 0 + || strcmp (o->name, _SDATA) == 0 + || strcmp (o->name, _LIT4) == 0 + || strcmp (o->name, _LIT8) == 0 + || strcmp (o->name, _LITA) == 0)) + lo = o->vma; + } + ecoff_data (abfd)->gp = lo + 0x8000; + } + else + { + /* If the relocate_section function needs to do a reloc + involving the GP value, it should make a reloc_dangerous + callback to warn that GP is not defined. */ + } + } + + for (o = abfd->sections; o != (asection *) NULL; o = o->next) + { + for (p = o->link_order_head; + p != (struct bfd_link_order *) NULL; + p = p->next) + { + if (p->type == bfd_indirect_link_order + && (bfd_get_flavour (p->u.indirect.section->owner) + == bfd_target_ecoff_flavour)) + { + if (! ecoff_indirect_link_order (abfd, info, o, p)) + return false; + } + else if (p->type == bfd_section_reloc_link_order + || p->type == bfd_symbol_reloc_link_order) + { + if (! ecoff_reloc_link_order (abfd, info, o, p)) + return false; + } + else + { + if (! _bfd_default_link_order (abfd, info, o, p)) + return false; + } + } + } + + bfd_get_symcount (abfd) = symhdr->iextMax + symhdr->isymMax; + + ecoff_data (abfd)->linker = true; + + return true; +} + +/* Accumulate the debugging information for an input BFD into the + output BFD. This must read in the symbolic information of the + input BFD. */ + +static boolean +ecoff_final_link_debug_accumulate (output_bfd, input_bfd, info, handle) + bfd *output_bfd; + bfd *input_bfd; + struct bfd_link_info *info; + PTR handle; +{ + struct ecoff_debug_info * const debug = &ecoff_data (input_bfd)->debug_info; + const struct ecoff_debug_swap * const swap = + &ecoff_backend (input_bfd)->debug_swap; + HDRR *symhdr = &debug->symbolic_header; + boolean ret; + +#define READ(ptr, offset, count, size, type) \ + if (symhdr->count == 0) \ + debug->ptr = NULL; \ + else \ + { \ + debug->ptr = (type) malloc (size * symhdr->count); \ + if (debug->ptr == NULL) \ + { \ + bfd_set_error (bfd_error_no_memory); \ + ret = false; \ + goto return_something; \ + } \ + if ((bfd_seek (input_bfd, (file_ptr) symhdr->offset, SEEK_SET) \ + != 0) \ + || (bfd_read (debug->ptr, size, symhdr->count, \ + input_bfd) != size * symhdr->count)) \ + { \ + ret = false; \ + goto return_something; \ + } \ + } + + /* If raw_syments is not NULL, then the data was already by read by + _bfd_ecoff_slurp_symbolic_info. */ + if (ecoff_data (input_bfd)->raw_syments == NULL) + { + READ (line, cbLineOffset, cbLine, sizeof (unsigned char), + unsigned char *); + READ (external_dnr, cbDnOffset, idnMax, swap->external_dnr_size, PTR); + READ (external_pdr, cbPdOffset, ipdMax, swap->external_pdr_size, PTR); + READ (external_sym, cbSymOffset, isymMax, swap->external_sym_size, PTR); + READ (external_opt, cbOptOffset, ioptMax, swap->external_opt_size, PTR); + READ (external_aux, cbAuxOffset, iauxMax, sizeof (union aux_ext), + union aux_ext *); + READ (ss, cbSsOffset, issMax, sizeof (char), char *); + READ (external_fdr, cbFdOffset, ifdMax, swap->external_fdr_size, PTR); + READ (external_rfd, cbRfdOffset, crfd, swap->external_rfd_size, PTR); + } +#undef READ + + /* We do not read the external strings or the external symbols. */ + + ret = (bfd_ecoff_debug_accumulate + (handle, output_bfd, &ecoff_data (output_bfd)->debug_info, + &ecoff_backend (output_bfd)->debug_swap, + input_bfd, debug, swap, info)); + + return_something: + if (ecoff_data (input_bfd)->raw_syments == NULL) + { + if (debug->line != NULL) + free (debug->line); + if (debug->external_dnr != NULL) + free (debug->external_dnr); + if (debug->external_pdr != NULL) + free (debug->external_pdr); + if (debug->external_sym != NULL) + free (debug->external_sym); + if (debug->external_opt != NULL) + free (debug->external_opt); + if (debug->external_aux != NULL) + free (debug->external_aux); + if (debug->ss != NULL) + free (debug->ss); + if (debug->external_fdr != NULL) + free (debug->external_fdr); + if (debug->external_rfd != NULL) + free (debug->external_rfd); + + /* Make sure we don't accidentally follow one of these pointers + into freed memory. */ + debug->line = NULL; + debug->external_dnr = NULL; + debug->external_pdr = NULL; + debug->external_sym = NULL; + debug->external_opt = NULL; + debug->external_aux = NULL; + debug->ss = NULL; + debug->external_fdr = NULL; + debug->external_rfd = NULL; + } + + return ret; +} + +/* Put out information for an external symbol. These come only from + the hash table. */ + +static boolean +ecoff_link_write_external (h, data) + struct ecoff_link_hash_entry *h; + PTR data; +{ + bfd *output_bfd = (bfd *) data; + + /* FIXME: We should check if this symbol is being stripped. */ + + if (h->written) + return true; + + if (h->abfd == (bfd *) NULL) + { + h->esym.jmptbl = 0; + h->esym.cobol_main = 0; + h->esym.weakext = 0; + h->esym.reserved = 0; + h->esym.ifd = ifdNil; + h->esym.asym.value = 0; + h->esym.asym.st = stGlobal; + + if (h->root.type != bfd_link_hash_defined) + h->esym.asym.sc = scAbs; + else + { + asection *output_section; + const char *name; + + output_section = h->root.u.def.section->output_section; + name = bfd_section_name (output_section->owner, output_section); + + if (strcmp (name, _TEXT) == 0) + h->esym.asym.sc = scText; + else if (strcmp (name, _DATA) == 0) + h->esym.asym.sc = scData; + else if (strcmp (name, _SDATA) == 0) + h->esym.asym.sc = scSData; + else if (strcmp (name, _RDATA) == 0) + h->esym.asym.sc = scRData; + else if (strcmp (name, _BSS) == 0) + h->esym.asym.sc = scBss; + else if (strcmp (name, _SBSS) == 0) + h->esym.asym.sc = scSBss; + else if (strcmp (name, _INIT) == 0) + h->esym.asym.sc = scInit; + else if (strcmp (name, _FINI) == 0) + h->esym.asym.sc = scFini; + else if (strcmp (name, _PDATA) == 0) + h->esym.asym.sc = scPData; + else if (strcmp (name, _XDATA) == 0) + h->esym.asym.sc = scXData; + else + h->esym.asym.sc = scAbs; + } + + h->esym.asym.reserved = 0; + h->esym.asym.index = indexNil; + } + else if (h->esym.ifd != -1) + { + struct ecoff_debug_info *debug; + + /* Adjust the FDR index for the symbol by that used for the + input BFD. */ + debug = &ecoff_data (h->abfd)->debug_info; + BFD_ASSERT (h->esym.ifd >= 0 + && h->esym.ifd < debug->symbolic_header.ifdMax); + h->esym.ifd = debug->ifdmap[h->esym.ifd]; + } + + switch (h->root.type) + { + default: + case bfd_link_hash_new: + abort (); + case bfd_link_hash_undefined: + case bfd_link_hash_weak: + if (h->esym.asym.sc != scUndefined + && h->esym.asym.sc != scSUndefined) + h->esym.asym.sc = scUndefined; + break; + case bfd_link_hash_defined: + if (h->esym.asym.sc == scUndefined + || h->esym.asym.sc == scSUndefined) + h->esym.asym.sc = scAbs; + else if (h->esym.asym.sc == scCommon) + h->esym.asym.sc = scBss; + else if (h->esym.asym.sc == scSCommon) + h->esym.asym.sc = scSBss; + h->esym.asym.value = (h->root.u.def.value + + h->root.u.def.section->output_section->vma + + h->root.u.def.section->output_offset); + break; + case bfd_link_hash_common: + if (h->esym.asym.sc != scCommon + && h->esym.asym.sc != scSCommon) + h->esym.asym.sc = scCommon; + h->esym.asym.value = h->root.u.c.size; + break; + case bfd_link_hash_indirect: + case bfd_link_hash_warning: + /* FIXME: Ignore these for now. The circumstances under which + they should be written out are not clear to me. */ + return true; + } + + /* bfd_ecoff_debug_one_external uses iextMax to keep track of the + symbol number. */ + h->indx = ecoff_data (output_bfd)->debug_info.symbolic_header.iextMax; + h->written = 1; + + return (bfd_ecoff_debug_one_external + (output_bfd, &ecoff_data (output_bfd)->debug_info, + &ecoff_backend (output_bfd)->debug_swap, h->root.root.string, + &h->esym)); +} + +/* Relocate and write an ECOFF section into an ECOFF output file. */ + +static boolean +ecoff_indirect_link_order (output_bfd, info, output_section, link_order) + bfd *output_bfd; + struct bfd_link_info *info; + asection *output_section; + struct bfd_link_order *link_order; +{ + asection *input_section; + bfd *input_bfd; + struct ecoff_section_tdata *section_tdata; + bfd_size_type raw_size; + bfd_size_type cooked_size; + bfd_byte *contents = NULL; + bfd_size_type external_reloc_size; + bfd_size_type external_relocs_size; + PTR external_relocs = NULL; + + BFD_ASSERT ((output_section->flags & SEC_HAS_CONTENTS) != 0); + + if (link_order->size == 0) + return true; + + input_section = link_order->u.indirect.section; + input_bfd = input_section->owner; + section_tdata = ecoff_section_data (input_bfd, input_section); + + raw_size = input_section->_raw_size; + cooked_size = input_section->_cooked_size; + if (cooked_size == 0) + cooked_size = raw_size; + + BFD_ASSERT (input_section->output_section == output_section); + BFD_ASSERT (input_section->output_offset == link_order->offset); + BFD_ASSERT (cooked_size == link_order->size); + + /* Get the section contents. We allocate memory for the larger of + the size before relocating and the size after relocating. */ + contents = (bfd_byte *) malloc (raw_size >= cooked_size + ? raw_size + : cooked_size); + if (contents == NULL && raw_size != 0) + { + bfd_set_error (bfd_error_no_memory); + goto error_return; + } + + /* If we are relaxing, the contents may have already been read into + memory, in which case we copy them into our new buffer. We don't + simply reuse the old buffer in case cooked_size > raw_size. */ + if (section_tdata != (struct ecoff_section_tdata *) NULL + && section_tdata->contents != (bfd_byte *) NULL) + memcpy (contents, section_tdata->contents, raw_size); + else + { + if (! bfd_get_section_contents (input_bfd, input_section, + (PTR) contents, + (file_ptr) 0, raw_size)) + goto error_return; + } + + /* Get the relocs. If we are relaxing MIPS code, they will already + have been read in. Otherwise, we read them in now. */ + external_reloc_size = ecoff_backend (input_bfd)->external_reloc_size; + external_relocs_size = external_reloc_size * input_section->reloc_count; + + if (section_tdata != (struct ecoff_section_tdata *) NULL) + external_relocs = section_tdata->external_relocs; + else + { + external_relocs = (PTR) malloc (external_relocs_size); + if (external_relocs == NULL && external_relocs_size != 0) + { + bfd_set_error (bfd_error_no_memory); + goto error_return; + } + + if (bfd_seek (input_bfd, input_section->rel_filepos, SEEK_SET) != 0 + || (bfd_read (external_relocs, 1, external_relocs_size, input_bfd) + != external_relocs_size)) + goto error_return; + } + + /* Relocate the section contents. */ + if (! ((*ecoff_backend (input_bfd)->relocate_section) + (output_bfd, info, input_bfd, input_section, contents, + external_relocs))) + goto error_return; + + /* Write out the relocated section. */ + if (! bfd_set_section_contents (output_bfd, + output_section, + (PTR) contents, + input_section->output_offset, + cooked_size)) + goto error_return; + + /* If we are producing relocateable output, the relocs were + modified, and we write them out now. We use the reloc_count + field of output_section to keep track of the number of relocs we + have output so far. */ + if (info->relocateable) + { + if (bfd_seek (output_bfd, + (output_section->rel_filepos + + output_section->reloc_count * external_reloc_size), + SEEK_SET) != 0 + || (bfd_write (external_relocs, 1, external_relocs_size, output_bfd) + != external_relocs_size)) + goto error_return; + output_section->reloc_count += input_section->reloc_count; + } + + if (contents != NULL) + free (contents); + if (external_relocs != NULL && section_tdata == NULL) + free (external_relocs); + return true; + + error_return: + if (contents != NULL) + free (contents); + if (external_relocs != NULL && section_tdata == NULL) + free (external_relocs); + return false; +} + +/* Generate a reloc when linking an ECOFF file. This is a reloc + requested by the linker, and does come from any input file. This + is used to build constructor and destructor tables when linking + with -Ur. */ + +static boolean +ecoff_reloc_link_order (output_bfd, info, output_section, link_order) + bfd *output_bfd; + struct bfd_link_info *info; + asection *output_section; + struct bfd_link_order *link_order; +{ + arelent rel; + struct internal_reloc in; + bfd_size_type external_reloc_size; + bfd_byte *rbuf; + boolean ok; + + /* We set up an arelent to pass to the backend adjust_reloc_out + routine. */ + rel.address = link_order->offset; + + rel.howto = bfd_reloc_type_lookup (output_bfd, link_order->u.reloc.p->reloc); + if (rel.howto == (const reloc_howto_type *) NULL) + { + bfd_set_error (bfd_error_bad_value); + return false; + } + + if (link_order->type == bfd_section_reloc_link_order) + rel.sym_ptr_ptr = link_order->u.reloc.p->u.section->symbol_ptr_ptr; + else + { + /* We can't set up a reloc against a symbol correctly, because + we have no asymbol structure. Currently no adjust_reloc_out + routine cases. */ + rel.sym_ptr_ptr = (asymbol **) NULL; + } + + /* All ECOFF relocs are in-place. Put the addend into the object + file. */ + + BFD_ASSERT (rel.howto->partial_inplace); + if (link_order->u.reloc.p->addend != 0) + { + bfd_size_type size; + bfd_reloc_status_type rstat; + bfd_byte *buf; + boolean ok; + + size = bfd_get_reloc_size (rel.howto); + buf = (bfd_byte *) bfd_zmalloc (size); + if (buf == (bfd_byte *) NULL) + { + bfd_set_error (bfd_error_no_memory); + return false; + } + rstat = _bfd_relocate_contents (rel.howto, output_bfd, + link_order->u.reloc.p->addend, buf); + switch (rstat) + { + case bfd_reloc_ok: + break; + default: + case bfd_reloc_outofrange: + abort (); + case bfd_reloc_overflow: + if (! ((*info->callbacks->reloc_overflow) + (info, + (link_order->type == bfd_section_reloc_link_order + ? bfd_section_name (output_bfd, + link_order->u.reloc.p->u.section) + : link_order->u.reloc.p->u.name), + rel.howto->name, link_order->u.reloc.p->addend, + (bfd *) NULL, (asection *) NULL, (bfd_vma) 0))) + { + free (buf); + return false; + } + break; + } + ok = bfd_set_section_contents (output_bfd, output_section, (PTR) buf, + (file_ptr) link_order->offset, size); + free (buf); + if (! ok) + return false; + } + + rel.addend = 0; + + /* Move the information into a internal_reloc structure. */ + in.r_vaddr = (rel.address + + bfd_get_section_vma (output_bfd, output_section)); + in.r_type = rel.howto->type; + + if (link_order->type == bfd_symbol_reloc_link_order) + { + struct ecoff_link_hash_entry *h; + + h = ecoff_link_hash_lookup (ecoff_hash_table (info), + link_order->u.reloc.p->u.name, + false, false, true); + if (h != (struct ecoff_link_hash_entry *) NULL + && h->indx != -1) + in.r_symndx = h->indx; + else + { + if (! ((*info->callbacks->unattached_reloc) + (info, link_order->u.reloc.p->u.name, (bfd *) NULL, + (asection *) NULL, (bfd_vma) 0))) + return false; + in.r_symndx = 0; + } + in.r_extern = 1; + } + else + { + CONST char *name; + + name = bfd_get_section_name (output_bfd, + link_order->u.reloc.p->u.section); + if (strcmp (name, ".text") == 0) + in.r_symndx = RELOC_SECTION_TEXT; + else if (strcmp (name, ".rdata") == 0) + in.r_symndx = RELOC_SECTION_RDATA; + else if (strcmp (name, ".data") == 0) + in.r_symndx = RELOC_SECTION_DATA; + else if (strcmp (name, ".sdata") == 0) + in.r_symndx = RELOC_SECTION_SDATA; + else if (strcmp (name, ".sbss") == 0) + in.r_symndx = RELOC_SECTION_SBSS; + else if (strcmp (name, ".bss") == 0) + in.r_symndx = RELOC_SECTION_BSS; + else if (strcmp (name, ".init") == 0) + in.r_symndx = RELOC_SECTION_INIT; + else if (strcmp (name, ".lit8") == 0) + in.r_symndx = RELOC_SECTION_LIT8; + else if (strcmp (name, ".lit4") == 0) + in.r_symndx = RELOC_SECTION_LIT4; + else if (strcmp (name, ".xdata") == 0) + in.r_symndx = RELOC_SECTION_XDATA; + else if (strcmp (name, ".pdata") == 0) + in.r_symndx = RELOC_SECTION_PDATA; + else if (strcmp (name, ".fini") == 0) + in.r_symndx = RELOC_SECTION_FINI; + else if (strcmp (name, ".lita") == 0) + in.r_symndx = RELOC_SECTION_LITA; + else if (strcmp (name, "*ABS*") == 0) + in.r_symndx = RELOC_SECTION_ABS; + else + abort (); + in.r_extern = 0; + } + + /* Let the BFD backend adjust the reloc. */ + (*ecoff_backend (output_bfd)->adjust_reloc_out) (output_bfd, &rel, &in); + + /* Get some memory and swap out the reloc. */ + external_reloc_size = ecoff_backend (output_bfd)->external_reloc_size; + rbuf = (bfd_byte *) malloc (external_reloc_size); + if (rbuf == (bfd_byte *) NULL) + { + bfd_set_error (bfd_error_no_memory); + return false; + } + + (*ecoff_backend (output_bfd)->swap_reloc_out) (output_bfd, &in, (PTR) rbuf); + + ok = (bfd_seek (output_bfd, + (output_section->rel_filepos + + output_section->reloc_count * external_reloc_size), + SEEK_SET) == 0 + && (bfd_write ((PTR) rbuf, 1, external_reloc_size, output_bfd) + == external_reloc_size)); + + if (ok) + ++output_section->reloc_count; + + free (rbuf); + + return ok; +} diff --git a/gnu/usr.bin/gdb/bfd/elf.c b/gnu/usr.bin/gdb/bfd/elf.c index 2fcf2f143439..af3e202c3979 100644 --- a/gnu/usr.bin/gdb/bfd/elf.c +++ b/gnu/usr.bin/gdb/bfd/elf.c @@ -33,6 +33,7 @@ SECTION #include "bfd.h" #include "sysdep.h" +#include "bfdlink.h" #include "libbfd.h" #define ARCH_SIZE 0 #include "libelf.h" @@ -41,8 +42,8 @@ SECTION cause invalid hash tables to be generated. (Well, you would if this were being used yet.) */ unsigned long -DEFUN (bfd_elf_hash, (name), - CONST unsigned char *name) +bfd_elf_hash (name) + CONST unsigned char *name; { unsigned long h = 0; unsigned long g; @@ -65,33 +66,32 @@ DEFUN (bfd_elf_hash, (name), buffer. */ static char * -DEFUN (elf_read, (abfd, offset, size), - bfd * abfd AND - long offset AND - int size) +elf_read (abfd, offset, size) + bfd * abfd; + long offset; + int size; { char *buf; if ((buf = bfd_alloc (abfd, size)) == NULL) { - bfd_error = no_memory; + bfd_set_error (bfd_error_no_memory); return NULL; } if (bfd_seek (abfd, offset, SEEK_SET) == -1) - { - bfd_error = system_call_error; - return NULL; - } + return NULL; if (bfd_read ((PTR) buf, size, 1, abfd) != size) { - bfd_error = system_call_error; + if (bfd_get_error () != bfd_error_system_call) + bfd_set_error (bfd_error_file_truncated); return NULL; } return buf; } boolean -DEFUN (elf_mkobject, (abfd), bfd * abfd) +elf_mkobject (abfd) + bfd * abfd; { /* this just does initialization */ /* coff_mkobject zalloc's space for tdata.coff_obj_data ... */ @@ -99,7 +99,7 @@ DEFUN (elf_mkobject, (abfd), bfd * abfd) bfd_zalloc (abfd, sizeof (struct elf_obj_tdata)); if (elf_tdata (abfd) == 0) { - bfd_error = no_memory; + bfd_set_error (bfd_error_no_memory); return false; } /* since everything is done at close time, do we need any @@ -109,9 +109,9 @@ DEFUN (elf_mkobject, (abfd), bfd * abfd) } char * -DEFUN (elf_get_str_section, (abfd, shindex), - bfd * abfd AND - unsigned int shindex) +elf_get_str_section (abfd, shindex) + bfd * abfd; + unsigned int shindex; { Elf_Internal_Shdr **i_shdrp; char *shstrtab = NULL; @@ -135,10 +135,10 @@ DEFUN (elf_get_str_section, (abfd, shindex), } char * -DEFUN (elf_string_from_elf_section, (abfd, shindex, strindex), - bfd * abfd AND - unsigned int shindex AND - unsigned int strindex) +elf_string_from_elf_section (abfd, shindex, strindex) + bfd * abfd; + unsigned int shindex; + unsigned int strindex; { Elf_Internal_Shdr *hdr; @@ -154,6 +154,68 @@ DEFUN (elf_string_from_elf_section, (abfd, shindex, strindex), return ((char *) hdr->rawdata) + strindex; } +/* Make a BFD section from an ELF section. We store a pointer to the + BFD section in the rawdata field of the header. */ + +boolean +_bfd_elf_make_section_from_shdr (abfd, hdr, name) + bfd *abfd; + Elf_Internal_Shdr *hdr; + const char *name; +{ + asection *newsect; + flagword flags; + + if (hdr->rawdata != NULL) + { + BFD_ASSERT (strcmp (name, ((asection *) hdr->rawdata)->name) == 0); + return true; + } + + newsect = bfd_make_section_anyway (abfd, name); + if (newsect == NULL) + return false; + + newsect->filepos = hdr->sh_offset; + + if (! bfd_set_section_vma (abfd, newsect, hdr->sh_addr) + || ! bfd_set_section_size (abfd, newsect, hdr->sh_size) + || ! bfd_set_section_alignment (abfd, newsect, + bfd_log2 (hdr->sh_addralign))) + return false; + + flags = SEC_NO_FLAGS; + if (hdr->sh_type != SHT_NOBITS) + flags |= SEC_HAS_CONTENTS; + if ((hdr->sh_flags & SHF_ALLOC) != 0) + { + flags |= SEC_ALLOC; + if (hdr->sh_type != SHT_NOBITS) + flags |= SEC_LOAD; + } + if ((hdr->sh_flags & SHF_WRITE) == 0) + flags |= SEC_READONLY; + if ((hdr->sh_flags & SHF_EXECINSTR) != 0) + flags |= SEC_CODE; + else if ((flags & SEC_LOAD) != 0) + flags |= SEC_DATA; + + /* The debugging sections appear to be recognized only by name, not + any sort of flag. */ + if (strncmp (name, ".debug", sizeof ".debug" - 1) == 0 + || strncmp (name, ".line", sizeof ".line" - 1) == 0 + || strncmp (name, ".stab", sizeof ".stab" - 1) == 0) + flags |= SEC_DEBUGGING; + + if (! bfd_set_section_flags (abfd, newsect, flags)) + return false; + + hdr->rawdata = (PTR) newsect; + elf_section_data (newsect)->this_hdr = *hdr; + + return true; +} + /* INTERNAL_FUNCTION bfd_elf_find_section @@ -170,9 +232,9 @@ DESCRIPTION */ struct elf_internal_shdr * -DEFUN (bfd_elf_find_section, (abfd, name), - bfd * abfd AND - char *name) +bfd_elf_find_section (abfd, name) + bfd * abfd; + char *name; { Elf_Internal_Shdr **i_shdrp; char *shstrtab; @@ -194,18 +256,6 @@ DEFUN (bfd_elf_find_section, (abfd, name), return 0; } -const struct bfd_elf_arch_map bfd_elf_arch_map[] = { - { bfd_arch_sparc, EM_SPARC }, - { bfd_arch_i386, EM_386 }, - { bfd_arch_m68k, EM_68K }, - { bfd_arch_m88k, EM_88K }, - { bfd_arch_i860, EM_860 }, - { bfd_arch_mips, EM_MIPS }, - { bfd_arch_hppa, EM_HPPA }, -}; - -const int bfd_elf_arch_map_size = sizeof (bfd_elf_arch_map) / sizeof (bfd_elf_arch_map[0]); - const char *const bfd_elf_section_type_names[] = { "SHT_NULL", "SHT_PROGBITS", "SHT_SYMTAB", "SHT_STRTAB", "SHT_RELA", "SHT_HASH", "SHT_DYNAMIC", "SHT_NOTE", @@ -222,23 +272,27 @@ const char *const bfd_elf_section_type_names[] = { function. It just short circuits the reloc if producing relocateable output against an external symbol. */ +/*ARGSUSED*/ bfd_reloc_status_type bfd_elf_generic_reloc (abfd, reloc_entry, symbol, data, input_section, - output_bfd) + output_bfd, + error_message) bfd *abfd; arelent *reloc_entry; asymbol *symbol; PTR data; asection *input_section; bfd *output_bfd; + char **error_message; { if (output_bfd != (bfd *) NULL && (symbol->flags & BSF_SECTION_SYM) == 0 - && reloc_entry->addend == 0) + && (! reloc_entry->howto->partial_inplace + || reloc_entry->addend == 0)) { reloc_entry->address += input_section->output_offset; return bfd_reloc_ok; @@ -246,3 +300,98 @@ bfd_elf_generic_reloc (abfd, return bfd_reloc_continue; } + +/* Create an entry in an ELF linker hash table. */ + +struct bfd_hash_entry * +_bfd_elf_link_hash_newfunc (entry, table, string) + struct bfd_hash_entry *entry; + struct bfd_hash_table *table; + const char *string; +{ + struct elf_link_hash_entry *ret = (struct elf_link_hash_entry *) entry; + + /* Allocate the structure if it has not already been allocated by a + subclass. */ + if (ret == (struct elf_link_hash_entry *) NULL) + ret = ((struct elf_link_hash_entry *) + bfd_hash_allocate (table, sizeof (struct elf_link_hash_entry))); + if (ret == (struct elf_link_hash_entry *) NULL) + { + bfd_set_error (bfd_error_no_memory); + return (struct bfd_hash_entry *) ret; + } + + /* Call the allocation method of the superclass. */ + ret = ((struct elf_link_hash_entry *) + _bfd_link_hash_newfunc ((struct bfd_hash_entry *) ret, + table, string)); + if (ret != (struct elf_link_hash_entry *) NULL) + { + /* Set local fields. */ + ret->indx = -1; + ret->size = 0; + ret->align = 0; + ret->dynindx = -1; + ret->dynstr_index = 0; + ret->weakdef = NULL; + ret->type = STT_NOTYPE; + ret->elf_link_hash_flags = 0; + } + + return (struct bfd_hash_entry *) ret; +} + +/* Initialize an ELF linker hash table. */ + +boolean +_bfd_elf_link_hash_table_init (table, abfd, newfunc) + struct elf_link_hash_table *table; + bfd *abfd; + struct bfd_hash_entry *(*newfunc) PARAMS ((struct bfd_hash_entry *, + struct bfd_hash_table *, + const char *)); +{ + table->dynobj = NULL; + table->dynsymcount = 0; + table->dynstr = NULL; + table->bucketcount = 0; + return _bfd_link_hash_table_init (&table->root, abfd, newfunc); +} + +/* Create an ELF linker hash table. */ + +struct bfd_link_hash_table * +_bfd_elf_link_hash_table_create (abfd) + bfd *abfd; +{ + struct elf_link_hash_table *ret; + + ret = ((struct elf_link_hash_table *) + bfd_alloc (abfd, sizeof (struct elf_link_hash_table))); + if (ret == (struct elf_link_hash_table *) NULL) + { + bfd_set_error (bfd_error_no_memory); + return NULL; + } + + if (! _bfd_elf_link_hash_table_init (ret, abfd, _bfd_elf_link_hash_newfunc)) + { + bfd_release (abfd, ret); + return NULL; + } + + return &ret->root; +} + +/* This is a hook for the ELF emulation code in the generic linker to + tell the backend linker what file name to use for the DT_NEEDED + entry for a dynamic object. */ + +void +bfd_elf_set_dt_needed_name (abfd, name) + bfd *abfd; + const char *name; +{ + elf_dt_needed_name (abfd) = name; +} diff --git a/gnu/usr.bin/gdb/bfd/format.c b/gnu/usr.bin/gdb/bfd/format.c index 6a80ed7082ae..b4c8471beda1 100644 --- a/gnu/usr.bin/gdb/bfd/format.c +++ b/gnu/usr.bin/gdb/bfd/format.c @@ -1,5 +1,5 @@ /* Generic BFD support for file formats. - Copyright (C) 1990-1991 Free Software Foundation, Inc. + Copyright (C) 1990, 91, 92, 93, 94 Free Software Foundation, Inc. Written by Cygnus Support. This file is part of BFD, the Binary File Descriptor library. @@ -20,20 +20,20 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ /* SECTION - File Formats + File formats - A format is a BFD concept of high level file contents. The + A format is a BFD concept of high level file contents type. The formats supported by BFD are: - o bfd_object + o <<bfd_object>> The BFD may contain data, symbols, relocations and debug info. - o bfd_archive + o <<bfd_archive>> The BFD contains other BFDs and an optional index. - o bfd_core + o <<bfd_core>> The BFD contains the result of an executable core dump. @@ -44,9 +44,8 @@ SECTION #include "sysdep.h" #include "libbfd.h" -extern bfd_target *target_vector[]; -extern bfd_target *default_vector[]; - +/* IMPORT from targets.c. */ +extern const size_t _bfd_target_vector_entries; /* FUNCTION @@ -56,15 +55,14 @@ SYNOPSIS boolean bfd_check_format(bfd *abfd, bfd_format format); DESCRIPTION - This routine is supplied a BFD and a format. It attempts to - verify if the file attached to the BFD is indeed compatible - with the format specified (ie, one of <<bfd_object>>, + Verify if the file attached to the BFD @var{abfd} is compatible + with the format @var{format} (i.e., one of <<bfd_object>>, <<bfd_archive>> or <<bfd_core>>). - If the BFD has been set to a specific @var{target} before the - call, only the named target and format combination will be + If the BFD has been set to a specific target before the + call, only the named target and format combination is checked. If the target has not been set, or has been set to - <<default>> then all the known target backends will be + <<default>>, then all the known target backends is interrogated to determine a match. If the default target matches, it is used. If not, exactly one target must recognize the file, or an error results. @@ -72,34 +70,62 @@ DESCRIPTION The function returns <<true>> on success, otherwise <<false>> with one of the following error codes: - o invalid_operation - + o <<bfd_error_invalid_operation>> - if <<format>> is not one of <<bfd_object>>, <<bfd_archive>> or <<bfd_core>>. - o system_call_error - + o <<bfd_error_system_call>> - if an error occured during a read - even some file mismatches - can cause system_call_errors + can cause bfd_error_system_calls. - o file_not_recognised - - none of the backends recognised the file format + o <<file_not_recognised>> - + none of the backends recognised the file format. - o file_ambiguously_recognized - + o <<bfd_error_file_ambiguously_recognized>> - more than one backend recognised the file format. +*/ + +boolean +bfd_check_format (abfd, format) + bfd *abfd; + bfd_format format; +{ + return bfd_check_format_matches (abfd, format, NULL); +} + +/* +FUNCTION + bfd_check_format_matches + +SYNOPSIS + boolean bfd_check_format_matches(bfd *abfd, bfd_format format, char ***matching); +DESCRIPTION + Like <<bfd_check_format>>, except when it returns false with + <<bfd_errno>> set to <<bfd_error_file_ambiguously_recognized>>. In that + case, if @var{matching} is not NULL, it will be filled in with + a NULL-terminated list of the names of the formats that matched, + allocated with <<malloc>>. + Then the user may choose a format and try again. + + When done with the list that @var{matching} points to, the caller + should free it. */ boolean -DEFUN(bfd_check_format,(abfd, format), - bfd *abfd AND - bfd_format format) +bfd_check_format_matches (abfd, format, matching) + bfd *abfd; + bfd_format format; + char ***matching; { - bfd_target **target, *save_targ, *right_targ; + const bfd_target * const *target, *save_targ, *right_targ; + char **matching_vector = NULL; 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; + bfd_set_error (bfd_error_invalid_operation); return false; } @@ -112,6 +138,19 @@ DEFUN(bfd_check_format,(abfd, format), save_targ = abfd->xvec; match_count = 0; + if (matching) + { + matching_vector = + (char **) malloc (sizeof (char *) * + (_bfd_target_vector_entries + 1)); + if (!matching_vector) + { + bfd_set_error (bfd_error_no_memory); + return false; + } + matching_vector[0] = NULL; + *matching = matching_vector; + } right_targ = 0; @@ -121,33 +160,46 @@ DEFUN(bfd_check_format,(abfd, 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! */ - + if (bfd_seek (abfd, (file_ptr)0, SEEK_SET) != 0) /* rewind! */ + return false; right_targ = BFD_SEND_FMT (abfd, _bfd_check_format, (abfd)); if (right_targ) { abfd->xvec = right_targ; /* Set the target as returned */ + if (matching) + free (matching_vector); return true; /* File position has moved, BTW */ } } - for (target = target_vector; *target != NULL; target++) { - bfd_target *temp; + for (target = bfd_target_vector; *target != NULL; target++) { + const bfd_target *temp; abfd->xvec = *target; /* Change BFD's target temporarily */ - bfd_seek (abfd, (file_ptr)0, SEEK_SET); - /* If _bfd_check_format neglects to set bfd_error, assume wrong_format. + if (bfd_seek (abfd, (file_ptr)0, SEEK_SET) != 0) + return false; + /* If _bfd_check_format neglects to set bfd_error, assume bfd_error_wrong_format. We didn't used to even pay any attention to bfd_error, so I suspect that some _bfd_check_format might have this problem. */ - bfd_error = wrong_format; + bfd_set_error (bfd_error_wrong_format); temp = BFD_SEND_FMT (abfd, _bfd_check_format, (abfd)); if (temp) { /* This format checks out as ok! */ right_targ = temp; + if (matching) + { + matching_vector[match_count] = temp->name; + matching_vector[match_count + 1] = NULL; + } 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]) + if (temp == bfd_default_vector[0]) { + if (matching) + { + matching_vector[0] = temp->name; + matching_vector[1] = NULL; + } match_count = 1; break; } @@ -160,51 +212,60 @@ DEFUN(bfd_check_format,(abfd, format), */ break; #endif - } else if (bfd_error != wrong_format) { + } else if (bfd_get_error () != bfd_error_wrong_format) { abfd->xvec = save_targ; abfd->format = bfd_unknown; + if (matching && bfd_get_error () != bfd_error_file_ambiguously_recognized) + free (matching_vector); return false; } } if (match_count == 1) { abfd->xvec = right_targ; /* Change BFD's target permanently */ + if (matching) + free (matching_vector); 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); + if (match_count == 0) + { + bfd_set_error (bfd_error_file_not_recognized); + if (matching) + free (matching_vector); + } + else + bfd_set_error (bfd_error_file_ambiguously_recognized); return false; } - /* FUNCTION bfd_set_format SYNOPSIS - boolean bfd_set_format(bfd *, bfd_format); + boolean bfd_set_format(bfd *abfd, bfd_format format); DESCRIPTION - This function sets the file format of the supplied BFD to the - format requested. If the target set in the BFD does not - support the format requested, the format is illegal or the BFD - is not open for writing than an error occurs. + This function sets the file format of the BFD @var{abfd} to the + format @var{format}. If the target set in the BFD does not + support the format requested, the format is invalid, or the BFD + is not open for writing, then an error occurs. */ boolean -DEFUN(bfd_set_format,(abfd, format), - bfd *abfd AND - bfd_format format) +bfd_set_format (abfd, format) + bfd *abfd; + 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; + bfd_set_error (bfd_error_invalid_operation); return false; } @@ -228,18 +289,17 @@ FUNCTION bfd_format_string SYNOPSIS - CONST char *bfd_format_string(bfd_format); + CONST char *bfd_format_string(bfd_format format); DESCRIPTION - This function takes one argument, and enumerated type - (bfd_format) and returns a pointer to a const string - <<invalid>>, <<object>>, <<archive>>, <<core>> or <<unknown>> - depending upon the value of the enumeration. + Return a pointer to a const string + <<invalid>>, <<object>>, <<archive>>, <<core>>, or <<unknown>>, + depending upon the value of @var{format}. */ CONST char * -DEFUN(bfd_format_string,(format), - bfd_format format) +bfd_format_string (format) + bfd_format format; { if (((int)format <(int) bfd_unknown) || ((int)format >=(int) bfd_type_end)) diff --git a/gnu/usr.bin/gdb/bfd/freebsd386.c b/gnu/usr.bin/gdb/bfd/freebsd386.c index 22cbd6ad1701..9c2690974700 100644 --- a/gnu/usr.bin/gdb/bfd/freebsd386.c +++ b/gnu/usr.bin/gdb/bfd/freebsd386.c @@ -29,6 +29,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ /* ZMAGIC files start at address 0. This does not apply to QMAGIC. */ #define TEXT_START_ADDR 0 +#define PAGE_SIZE 4096 #define SEGMENT_SIZE PAGE_SIZE #define DEFAULT_ARCH bfd_arch_i386 diff --git a/gnu/usr.bin/gdb/bfd/init.c b/gnu/usr.bin/gdb/bfd/init.c index 30a275935c10..3b9326210a0b 100644 --- a/gnu/usr.bin/gdb/bfd/init.c +++ b/gnu/usr.bin/gdb/bfd/init.c @@ -1,5 +1,5 @@ /* bfd initialization stuff - Copyright (C) 1990-1991 Free Software Foundation, Inc. + Copyright (C) 1990, 91, 92, 93, 94 Free Software Foundation, Inc. Written by Steve Chamberlain of Cygnus Support. This file is part of BFD, the Binary File Descriptor library. @@ -22,7 +22,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "sysdep.h" #include "libbfd.h" -extern void DEFUN_VOID (bfd_section_init); +extern void bfd_section_init (); static boolean initialized = false; @@ -30,8 +30,7 @@ static boolean initialized = false; SECTION Initialization - This is the initialization section - + These are the functions that handle initializing a BFD. */ /* @@ -42,11 +41,12 @@ SYNOPSIS void bfd_init(void); DESCRIPTION - This routine must be called before any other bfd function to + This routine must be called before any other BFD function to initialize magical internal data structures. */ -void DEFUN_VOID(bfd_init) +void +bfd_init () { if (initialized == false) { initialized = true; @@ -60,17 +60,18 @@ void DEFUN_VOID(bfd_init) INTERNAL_FUNCTION bfd_check_init -DESCRIPTION - This routine is called before any other bfd function using - initialized data is used to ensure that the structures have - been initialized. Soon this function will go away, and the bfd - library will assume that bfd_init has been called. - SYNOPSIS void bfd_check_init(void); + +DESCRIPTION + This routine is called before any other BFD function using + initialized data. It ensures that the structures have + been initialized. Soon this function will go away, and the BFD + library will assume that <<bfd_init>> has been called. */ -void DEFUN_VOID(bfd_check_init) +void +bfd_check_init () { if (initialized == false) { bfd_init(); diff --git a/gnu/usr.bin/gdb/bfd/libaout.h b/gnu/usr.bin/gdb/bfd/libaout.h index 0d99d0c43dba..74babf2747ab 100644 --- a/gnu/usr.bin/gdb/bfd/libaout.h +++ b/gnu/usr.bin/gdb/bfd/libaout.h @@ -18,10 +18,15 @@ You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ +#ifndef LIBAOUT_H +#define LIBAOUT_H + /* We try to encapsulate the differences in the various a.out file variants in a few routines, and otherwise share large masses of code. This means we only have to fix bugs in one place, most of the time. */ +#include "bfdlink.h" + /* Parameterize the a.out code based on whether it is being built for a 32-bit architecture or a 64-bit architecture. */ #if ARCH_SIZE==64 @@ -44,11 +49,50 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #define BYTES_IN_WORD 4 #endif /* ARCH_SIZE==32 */ -/* Declare these types at file level, since they are used in parameter - lists, which have wierd scope. */ +/* Declare at file level, since used in parameter lists, which have + weird scope. */ struct external_exec; -struct internal_exec; +struct external_nlist; +struct reloc_ext_external; +struct reloc_std_external; + +/* a.out backend linker hash table entries. */ + +struct aout_link_hash_entry +{ + struct bfd_link_hash_entry root; + /* Whether this symbol has been written out. */ + boolean written; + /* Symbol index in output file. */ + int indx; +}; + +/* a.out backend linker hash table. */ + +struct aout_link_hash_table +{ + struct bfd_link_hash_table root; +}; + +/* Look up an entry in an a.out link hash table. */ + +#define aout_link_hash_lookup(table, string, create, copy, follow) \ + ((struct aout_link_hash_entry *) \ + bfd_link_hash_lookup (&(table)->root, (string), (create), (copy), (follow))) + +/* Traverse an a.out link hash table. */ + +#define aout_link_hash_traverse(table, func, info) \ + (bfd_link_hash_traverse \ + (&(table)->root, \ + (boolean (*) PARAMS ((struct bfd_link_hash_entry *, PTR))) (func), \ + (info))) +/* Get the a.out link hash table from the info structure. This is + just a cast. */ + +#define aout_hash_table(p) ((struct aout_link_hash_table *) ((p)->hash)) + /* Back-end information for various a.out targets. */ struct aout_backend_data { @@ -61,6 +105,9 @@ struct aout_backend_data If not, the text section starts on the next page. */ unsigned char text_includes_header; + /* The value to pass to N_SET_FLAGS. */ + unsigned char exec_hdr_flags; + /* If the text section VMA isn't specified, and we need an absolute address, use this as the default. If we're producing a relocatable file, zero is always used. */ @@ -77,6 +124,39 @@ struct aout_backend_data to the size of the text section in the file for alignment purposes but does *not* get counted in the length of the text section. */ unsigned char exec_header_not_counted; + + /* Callback from the add symbols phase of the linker code to handle + a dynamic object. */ + boolean (*add_dynamic_symbols) PARAMS ((bfd *, struct bfd_link_info *)); + + /* Callback from the add symbols phase of the linker code to handle + adding a single symbol to the global linker hash table. */ + boolean (*add_one_symbol) PARAMS ((struct bfd_link_info *, bfd *, + const char *, flagword, asection *, + bfd_vma, const char *, boolean, + boolean, + struct bfd_link_hash_entry **)); + + /* Called to handle linking a dynamic object. */ + boolean (*link_dynamic_object) PARAMS ((struct bfd_link_info *, bfd *)); + + /* Called for each global symbol being written out by the linker. + This should write out the dynamic symbol information. */ + boolean (*write_dynamic_symbol) PARAMS ((bfd *, struct bfd_link_info *, + struct aout_link_hash_entry *)); + + /* This callback is called by the linker for each reloc against an + external symbol. RELOC is a pointer to the unswapped reloc. If + *SKIP is set to true, the reloc will be skipped. */ + boolean (*check_dynamic_reloc) PARAMS ((struct bfd_link_info *info, + bfd *input_bfd, + asection *input_section, + struct aout_link_hash_entry *h, + PTR reloc, boolean *skip)); + + /* Called at the end of a link to finish up any dynamic linking + information. */ + boolean (*finish_dynamic_link) PARAMS ((bfd *, struct bfd_link_info *)); }; #define aout_backend_info(abfd) \ ((CONST struct aout_backend_data *)((abfd)->xvec->backend_data)) @@ -123,10 +203,15 @@ enum machine_type { M_68020 = 2, M_SPARC = 3, /* skip a bunch so we don't run into any of suns numbers */ + /* make these up for the ns32k*/ + M_NS32032 = (64), /* ns32032 running ? */ + M_NS32532 = (64 + 5), /* ns32532 running mach */ + M_386 = 100, M_29K = 101, /* AMD 29000 */ M_386_DYNIX = 102, /* Sequent running dynix */ M_386_NETBSD = 134, /* NetBSD/386 binary */ + M_532_NETBSD = 137, /* MetBSD/523 binary */ M_MIPS1 = 151, /* MIPS R2000/R3000 binary */ M_MIPS2 = 152, /* MIPS R4000/R6000 binary */ M_HP200 = 200, /* HP 200 (68010) BSD binary */ @@ -134,7 +219,7 @@ enum machine_type { M_HPUX = (0x20c % 256)/* HP 200/300 HPUX binary */ }; -#define N_DYNAMIC(exec) ((exec).a_info & 0x8000000) +#define N_DYNAMIC(exec) ((exec).a_info & 0x80000000) #ifndef N_MAGIC # define N_MAGIC(exec) ((exec).a_info & 0xffff) @@ -155,6 +240,12 @@ enum machine_type { | (((flags) & 0xff) << 24)) #endif +#ifndef N_SET_DYNAMIC +# define N_SET_DYNAMIC(exec, dynamic) \ +((exec).a_info = (dynamic) ? ((exec).a_info | 0x80000000) : \ +((exec).a_info & 0x7fffffff)) +#endif + #ifndef N_SET_MAGIC # define N_SET_MAGIC(exec, magic) \ ((exec).a_info = (((exec).a_info & 0xffff0000) | ((magic) & 0xffff))) @@ -209,19 +300,40 @@ struct aoutdata { /* Segment size - needed for alignment of demand paged files. */ unsigned long segment_size; + /* Zmagic disk block size - need to align the start of the text + section in ZMAGIC binaries. Normally the same as page_size. */ + unsigned long zmagic_disk_block_size; + unsigned exec_bytes_size; unsigned vma_adjusted : 1; /* used when a bfd supports several highly similar formats */ - enum { - default_format = 0, - gnu_encap_format } subformat; - - enum { - undecided_magic = 0, - z_magic, - o_magic, - n_magic } magic; + enum + { + default_format = 0, + /* Used on HP 9000/300 running HP/UX. See hp300hpux.c. */ + gnu_encap_format, + /* Used on Linux, 386BSD, etc. See include/aout/aout64.h. */ + q_magic_format + } subformat; + + enum + { + undecided_magic = 0, + z_magic, + o_magic, + n_magic + } magic; + + /* The external symbol information. */ + struct external_nlist *external_syms; + bfd_size_type external_sym_count; + char *external_strings; + bfd_size_type external_string_size; + struct aout_link_hash_entry **sym_hashes; + + /* A pointer for shared library information. */ + PTR dynamic_info; }; struct aout_data_struct { @@ -240,27 +352,49 @@ struct aout_data_struct { #define obj_reloc_entry_size(bfd) (adata(bfd).reloc_entry_size) #define obj_symbol_entry_size(bfd) (adata(bfd).symbol_entry_size) #define obj_aout_subformat(bfd) (adata(bfd).subformat) +#define obj_aout_external_syms(bfd) (adata(bfd).external_syms) +#define obj_aout_external_sym_count(bfd) (adata(bfd).external_sym_count) +#define obj_aout_external_strings(bfd) (adata(bfd).external_strings) +#define obj_aout_external_string_size(bfd) (adata(bfd).external_string_size) +#define obj_aout_sym_hashes(bfd) (adata(bfd).sym_hashes) +#define obj_aout_dynamic_info(bfd) (adata(bfd).dynamic_info) /* We take the address of the first element of an asymbol to ensure that the macro is only ever applied to an asymbol */ #define aout_symbol(asymbol) ((aout_symbol_type *)(&(asymbol)->the_bfd)) +/* Information we keep for each a.out section. This is currently only + used by the a.out backend linker. */ + +struct aout_section_data_struct +{ + /* The unswapped relocation entries for this section. */ + PTR relocs; +}; + +#define aout_section_data(s) \ + ((struct aout_section_data_struct *) (s)->used_by_bfd) + /* Prototype declarations for functions defined in aoutx.h */ boolean NAME(aout,squirt_out_relocs) PARAMS ((bfd *abfd, asection *section)); -bfd_target * +boolean +NAME(aout,make_sections) PARAMS ((bfd *)); + +const bfd_target * NAME(aout,some_aout_object_p) PARAMS ((bfd *abfd, - struct internal_exec *execp, - bfd_target * (*callback)(bfd *))); + struct internal_exec *execp, + const bfd_target *(*callback)(bfd *))); boolean NAME(aout,mkobject) PARAMS ((bfd *abfd)); enum machine_type NAME(aout,machine_type) PARAMS ((enum bfd_architecture arch, - unsigned long machine)); + unsigned long machine, + boolean *unknown)); boolean NAME(aout,set_arch_mach) PARAMS ((bfd *abfd, enum bfd_architecture arch, @@ -277,29 +411,43 @@ asymbol * NAME(aout,make_empty_symbol) PARAMS ((bfd *abfd)); boolean +NAME(aout,translate_symbol_table) PARAMS ((bfd *, aout_symbol_type *, + struct external_nlist *, + bfd_size_type, char *, + bfd_size_type, + boolean dynamic)); + +boolean NAME(aout,slurp_symbol_table) PARAMS ((bfd *abfd)); -void +boolean NAME(aout,write_syms) PARAMS ((bfd *abfd)); void NAME(aout,reclaim_symbol_table) PARAMS ((bfd *abfd)); -unsigned int +long NAME(aout,get_symtab_upper_bound) PARAMS ((bfd *abfd)); -unsigned int +long NAME(aout,get_symtab) PARAMS ((bfd *abfd, asymbol **location)); +void +NAME(aout,swap_ext_reloc_in) PARAMS ((bfd *, struct reloc_ext_external *, + arelent *, asymbol **)); +void +NAME(aout,swap_std_reloc_in) PARAMS ((bfd *, struct reloc_std_external *, + arelent *, asymbol **)); + boolean NAME(aout,slurp_reloc_table) PARAMS ((bfd *abfd, sec_ptr asect, asymbol **symbols)); -unsigned int +long NAME(aout,canonicalize_reloc) PARAMS ((bfd *abfd, sec_ptr section, arelent **relptr, asymbol **symbols)); -unsigned int +long NAME(aout,get_reloc_upper_bound) PARAMS ((bfd *abfd, sec_ptr asect)); void @@ -317,9 +465,6 @@ NAME(aout,get_symbol_info) PARAMS ((bfd *ignore_abfd, asymbol *symbol, symbol_info *ret)); boolean -NAME(aout,close_and_cleanup) PARAMS ((bfd *abfd)); - -boolean NAME(aout,find_nearest_line) PARAMS ((bfd *abfd, asection *section, asymbol **symbols, bfd_vma offset, CONST char **filename_ptr, CONST char **functionname_ptr, unsigned int *line_ptr)); @@ -339,6 +484,31 @@ void NAME(aout,swap_exec_header_out) PARAMS ((bfd *abfd, struct internal_exec *execp, struct external_exec *raw_bytes)); +struct bfd_hash_entry * +NAME(aout,link_hash_newfunc) + PARAMS ((struct bfd_hash_entry *, struct bfd_hash_table *, const char *)); + +boolean +NAME(aout,link_hash_table_init) + PARAMS ((struct aout_link_hash_table *, bfd *, + struct bfd_hash_entry *(*) (struct bfd_hash_entry *, + struct bfd_hash_table *, + const char *))); + +struct bfd_link_hash_table * +NAME(aout,link_hash_table_create) PARAMS ((bfd *)); + +boolean +NAME(aout,link_add_symbols) PARAMS ((bfd *, struct bfd_link_info *)); + +boolean +NAME(aout,final_link) PARAMS ((bfd *, struct bfd_link_info *, + void (*) (bfd *, file_ptr *, file_ptr *, + file_ptr *))); + +boolean +NAME(aout,bfd_free_cached_info) PARAMS ((bfd *)); + /* Prototypes for functions in stab-syms.c. */ CONST char * @@ -346,15 +516,17 @@ aout_stab_name PARAMS ((int code)); /* A.out uses the generic versions of these routines... */ -#define aout_32_get_section_contents bfd_generic_get_section_contents -#define aout_32_close_and_cleanup bfd_generic_close_and_cleanup +#define aout_32_get_section_contents _bfd_generic_get_section_contents -#define aout_64_get_section_contents bfd_generic_get_section_contents -#define aout_64_close_and_cleanup bfd_generic_close_and_cleanup +#define aout_64_get_section_contents _bfd_generic_get_section_contents #ifndef NO_WRITE_HEADER_KLUDGE #define NO_WRITE_HEADER_KLUDGE 0 #endif +#ifndef aout_32_bfd_is_local_label +#define aout_32_bfd_is_local_label bfd_generic_is_local_label +#endif + #ifndef WRITE_HEADERS #define WRITE_HEADERS(abfd, execp) \ { \ @@ -372,22 +544,35 @@ aout_stab_name PARAMS ((int code)); obj_reloc_entry_size (abfd)); \ NAME(aout,swap_exec_header_out) (abfd, execp, &exec_bytes); \ \ - bfd_seek (abfd, (file_ptr) 0, SEEK_SET); \ - bfd_write ((PTR) &exec_bytes, 1, EXEC_BYTES_SIZE, abfd); \ + if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0) return false; \ + if (bfd_write ((PTR) &exec_bytes, 1, EXEC_BYTES_SIZE, abfd) \ + != EXEC_BYTES_SIZE) \ + return false; \ /* Now write out reloc info, followed by syms and strings */ \ \ - if (bfd_get_symcount (abfd) != 0) \ + if (bfd_get_outsymbols (abfd) != (asymbol **) NULL \ + && bfd_get_symcount (abfd) != 0) \ { \ - bfd_seek (abfd, (file_ptr)(N_SYMOFF(*execp)), SEEK_SET); \ + if (bfd_seek (abfd, (file_ptr)(N_SYMOFF(*execp)), SEEK_SET) \ + != 0) \ + return false; \ \ - NAME(aout,write_syms)(abfd); \ + if (! NAME(aout,write_syms)(abfd)) return false; \ \ - bfd_seek (abfd, (file_ptr)(N_TRELOFF(*execp)), SEEK_SET); \ + if (bfd_seek (abfd, (file_ptr)(N_TRELOFF(*execp)), SEEK_SET) \ + != 0) \ + return false; \ \ - if (!NAME(aout,squirt_out_relocs) (abfd, obj_textsec (abfd))) return false; \ - bfd_seek (abfd, (file_ptr)(N_DRELOFF(*execp)), SEEK_SET); \ + if (!NAME(aout,squirt_out_relocs) (abfd, obj_textsec (abfd))) \ + return false; \ + if (bfd_seek (abfd, (file_ptr)(N_DRELOFF(*execp)), SEEK_SET) \ + != 0) \ + return false; \ \ - if (!NAME(aout,squirt_out_relocs)(abfd, obj_datasec (abfd))) return false; \ + if (!NAME(aout,squirt_out_relocs)(abfd, obj_datasec (abfd))) \ + return false; \ } \ } #endif + +#endif /* ! defined (LIBAOUT_H) */ diff --git a/gnu/usr.bin/gdb/bfd/libbfd.c b/gnu/usr.bin/gdb/bfd/libbfd.c index 1bf8f7fb8e02..a66eb6ea1d3a 100644 --- a/gnu/usr.bin/gdb/bfd/libbfd.c +++ b/gnu/usr.bin/gdb/bfd/libbfd.c @@ -1,5 +1,5 @@ /* Assorted BFD support routines, only used internally. - Copyright 1990, 1991, 1992 Free Software Foundation, Inc. + Copyright 1990, 91, 92, 93, 94 Free Software Foundation, Inc. Written by Cygnus Support. This file is part of BFD, the Binary File Descriptor library. @@ -24,161 +24,151 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ /* SECTION - libbfd + Internal functions DESCRIPTION - This file contains various routines which are used within BFD. + These routines are used within BFD. They are not intended for export, but are documented here for completeness. */ -boolean -DEFUN(_bfd_dummy_new_section_hook,(ignore, ignore_newsect), - bfd *ignore AND - asection *ignore_newsect) -{ - return true; -} +/* A routine which is used in target vectors for unsupported + operations. */ +/*ARGSUSED*/ boolean -DEFUN(bfd_false ,(ignore), - bfd *ignore) +bfd_false (ignore) + bfd *ignore; { + bfd_set_error (bfd_error_invalid_operation); return false; } +/* A routine which is used in target vectors for supported operations + which do not actually do anything. */ + +/*ARGSUSED*/ boolean -DEFUN(bfd_true,(ignore), - bfd *ignore) +bfd_true (ignore) + bfd *ignore; { return true; } +/* A routine which is used in target vectors for unsupported + operations which return a pointer value. */ + +/*ARGSUSED*/ PTR -DEFUN(bfd_nullvoidptr,(ignore), - bfd *ignore) +bfd_nullvoidptr (ignore) + bfd *ignore; { - return (PTR)NULL; + bfd_set_error (bfd_error_invalid_operation); + return NULL; } +/*ARGSUSED*/ int -DEFUN(bfd_0,(ignore), - bfd *ignore) +bfd_0 (ignore) + bfd *ignore; { return 0; } +/*ARGSUSED*/ unsigned int -DEFUN(bfd_0u,(ignore), - bfd *ignore) +bfd_0u (ignore) + bfd *ignore; { return 0; } +/*ARGUSED*/ +long +bfd_0l (ignore) + bfd *ignore; +{ + return 0; +} + +/* A routine which is used in target vectors for unsupported + operations which return -1 on error. */ + +/*ARGSUSED*/ +long +_bfd_n1 (ignore_abfd) + bfd *ignore_abfd; +{ + bfd_set_error (bfd_error_invalid_operation); + return -1; +} + +/*ARGSUSED*/ void -DEFUN(bfd_void,(ignore), - bfd *ignore) +bfd_void (ignore) + bfd *ignore; { } +/*ARGSUSED*/ boolean -DEFUN(_bfd_dummy_core_file_matches_executable_p,(ignore_core_bfd, ignore_exec_bfd), - bfd *ignore_core_bfd AND - bfd *ignore_exec_bfd) +_bfd_nocore_core_file_matches_executable_p (ignore_core_bfd, ignore_exec_bfd) + bfd *ignore_core_bfd; + bfd *ignore_exec_bfd; { - bfd_error = invalid_operation; + bfd_set_error (bfd_error_invalid_operation); return false; } -/* of course you can't initialize a function to be the same as another, grr */ +/* Routine to handle core_file_failing_command entry point for targets + without core file support. */ +/*ARGSUSED*/ char * -DEFUN(_bfd_dummy_core_file_failing_command,(ignore_abfd), - bfd *ignore_abfd) +_bfd_nocore_core_file_failing_command (ignore_abfd) + bfd *ignore_abfd; { + bfd_set_error (bfd_error_invalid_operation); return (char *)NULL; } +/* Routine to handle core_file_failing_signal entry point for targets + without core file support. */ + +/*ARGSUSED*/ int -DEFUN(_bfd_dummy_core_file_failing_signal,(ignore_abfd), - bfd *ignore_abfd) +_bfd_nocore_core_file_failing_signal (ignore_abfd) + bfd *ignore_abfd; { + bfd_set_error (bfd_error_invalid_operation); return 0; } -bfd_target * -DEFUN(_bfd_dummy_target,(ignore_abfd), - bfd *ignore_abfd) +/*ARGSUSED*/ +const bfd_target * +_bfd_dummy_target (ignore_abfd) + bfd *ignore_abfd; { + bfd_set_error (bfd_error_wrong_format); return 0; } -/** zalloc -- allocate and clear storage */ +#ifndef bfd_zmalloc +/* allocate and clear storage */ -#ifndef zalloc char * -DEFUN(zalloc,(size), - bfd_size_type size) +bfd_zmalloc (size) + bfd_size_type size; { - char *ptr = (char *) malloc ((size_t)size); + char *ptr = (char *) malloc ((size_t) size); - if ((ptr != NULL) && (size != 0)) - memset(ptr,0, (size_t) size); + if (ptr && size) + memset(ptr, 0, (size_t) size); return ptr; } -#endif - -/* -INTERNAL_FUNCTION - bfd_xmalloc - -SYNOPSIS - PTR bfd_xmalloc( bfd_size_type size); - -DESCRIPTION - Like malloc, but exit if no more memory. - -*/ - -/** There is major inconsistency in how running out of memory is handled. - Some routines return a NULL, and set bfd_error to no_memory. - However, obstack routines can't do this ... */ - - -DEFUN(PTR bfd_xmalloc,(size), - bfd_size_type size) -{ - static CONST char no_memory_message[] = "Virtual memory exhausted!\n"; - PTR ptr; - if (size == 0) size = 1; - ptr = (PTR)malloc((size_t) size); - if (!ptr) - { - write (2, no_memory_message, sizeof(no_memory_message)-1); - exit (-1); - } - return ptr; -} - -/* -INTERNAL_FUNCTION - bfd_xmalloc_by_size_t - -SYNOPSIS - PTR bfd_xmalloc_by_size_t ( size_t size); - -DESCRIPTION - Like malloc, but exit if no more memory. - Uses size_t, so it's suitable for use as obstack_chunk_alloc. - */ -PTR -DEFUN(bfd_xmalloc_by_size_t, (size), - size_t size) -{ - return bfd_xmalloc ((bfd_size_type) size); -} +#endif /* bfd_zmalloc */ /* Some IO code */ @@ -191,20 +181,25 @@ DEFUN(bfd_xmalloc_by_size_t, (size), first octet in the file, NOT the beginning of the archive header. */ static -int DEFUN(real_read,(where, a,b, file), - PTR where AND - int a AND - int b AND - FILE *file) +int +real_read (where, a,b, file) + PTR where; + int a; + int b; + FILE *file; { return fread(where, a,b,file); } + +/* Return value is amount read (FIXME: how are errors and end of file dealt + with? We never call bfd_set_error, which is probably a mistake). */ + bfd_size_type -DEFUN(bfd_read,(ptr, size, nitems, abfd), - PTR ptr AND - bfd_size_type size AND - bfd_size_type nitems AND - bfd *abfd) +bfd_read (ptr, size, nitems, abfd) + PTR ptr; + bfd_size_type size; + bfd_size_type nitems; + bfd *abfd; { int nread; nread = real_read (ptr, 1, (int)(size*nitems), bfd_cache_lookup(abfd)); @@ -212,21 +207,45 @@ DEFUN(bfd_read,(ptr, size, nitems, abfd), if (nread > 0) abfd->where += nread; #endif + + /* Set bfd_error if we did not read as much data as we expected. + + If the read failed due to an error set the bfd_error_system_call, + else set bfd_error_file_truncated. + + A BFD backend may wish to override bfd_error_file_truncated to + provide something more useful (eg. no_symbols or wrong_format). */ + if (nread < (int)(size * nitems)) + { + if (ferror (bfd_cache_lookup (abfd))) + bfd_set_error (bfd_error_system_call); + else + bfd_set_error (bfd_error_file_truncated); + } + return nread; } bfd_size_type -DEFUN(bfd_write,(ptr, size, nitems, abfd), - CONST PTR ptr AND - bfd_size_type size AND - bfd_size_type nitems AND - bfd *abfd) +bfd_write (ptr, size, nitems, abfd) + CONST PTR ptr; + bfd_size_type size; + bfd_size_type nitems; + bfd *abfd; { - int nwrote = fwrite (ptr, 1, (int)(size*nitems), bfd_cache_lookup(abfd)); + int nwrote = fwrite (ptr, 1, (int) (size * nitems), bfd_cache_lookup (abfd)); #ifdef FILE_OFFSET_IS_CHAR_INDEX if (nwrote > 0) abfd->where += nwrote; #endif + if (nwrote != size * nitems) + { +#ifdef ENOSPC + if (nwrote >= 0) + errno = ENOSPC; +#endif + bfd_set_error (bfd_error_system_call); + } return nwrote; } @@ -238,24 +257,25 @@ SYNOPSIS void bfd_write_bigendian_4byte_int(bfd *abfd, int i); DESCRIPTION - Writes a 4 byte integer to the outputing bfd, in big endian - mode regardless of what else is going on. This is useful in + Write a 4 byte integer @var{i} to the output BFD @var{abfd}, in big + endian order regardless of what else is going on. This is useful in archives. */ void -DEFUN(bfd_write_bigendian_4byte_int,(abfd, i), - bfd *abfd AND - int i) +bfd_write_bigendian_4byte_int (abfd, i) + bfd *abfd; + int i; { bfd_byte buffer[4]; bfd_putb32(i, buffer); - bfd_write((PTR)buffer, 4, 1, abfd); + if (bfd_write((PTR)buffer, 4, 1, abfd) != 4) + abort (); } long -DEFUN(bfd_tell,(abfd), - bfd *abfd) +bfd_tell (abfd) + bfd *abfd; { file_ptr ptr; @@ -268,25 +288,28 @@ DEFUN(bfd_tell,(abfd), } int -DEFUN(bfd_flush,(abfd), - bfd *abfd) +bfd_flush (abfd) + bfd *abfd; { return fflush (bfd_cache_lookup(abfd)); } int -DEFUN(bfd_stat,(abfd, statbuf), - bfd *abfd AND - struct stat *statbuf) +bfd_stat (abfd, statbuf) + bfd *abfd; + struct stat *statbuf; { return fstat (fileno(bfd_cache_lookup(abfd)), statbuf); } +/* Returns 0 for success, nonzero for failure (in which case bfd_get_error + can retrieve the error code). */ + int -DEFUN(bfd_seek,(abfd, position, direction), - bfd * CONST abfd AND - CONST file_ptr position AND - CONST int direction) +bfd_seek (abfd, position, direction) + bfd * CONST abfd; + CONST file_ptr position; + CONST int direction; { int result; FILE *f; @@ -302,7 +325,7 @@ DEFUN(bfd_seek,(abfd, position, direction), #ifdef FILE_OFFSET_IS_CHAR_INDEX if (abfd->format != bfd_archive && abfd->my_archive == 0) { -#ifndef NDEBUG +#if 0 /* Explanation for this code: I'm only about 95+% sure that the above conditions are sufficient and that all i/o calls are properly adjusting the `where' field. So this is sort of an `assert' @@ -343,8 +366,11 @@ DEFUN(bfd_seek,(abfd, position, direction), result = fseek (f, file_position, direction); if (result != 0) - /* Force redetermination of `where' field. */ - bfd_tell (abfd); + { + /* Force redetermination of `where' field. */ + bfd_tell (abfd); + bfd_set_error (bfd_error_system_call); + } else { #ifdef FILE_OFFSET_IS_CHAR_INDEX @@ -366,11 +392,11 @@ DEFUN(bfd_seek,(abfd, position, direction), table_length). Updates free_ptr, table, table_length */ boolean -DEFUN(bfd_add_to_string_table,(table, new_string, table_length, free_ptr), - char **table AND - char *new_string AND - unsigned int *table_length AND - char **free_ptr) +bfd_add_to_string_table (table, new_string, table_length, free_ptr) + char **table; + char *new_string; + unsigned int *table_length; + char **free_ptr; { size_t string_length = strlen (new_string) + 1; /* include null here */ char *base = *table; @@ -379,13 +405,13 @@ DEFUN(bfd_add_to_string_table,(table, new_string, table_length, free_ptr), if (base == NULL) { /* Avoid a useless regrow if we can (but of course we still - take it next time */ + take it next time). */ space_length = (string_length < DEFAULT_STRING_SPACE_SIZE ? DEFAULT_STRING_SPACE_SIZE : string_length+1); - base = zalloc ((bfd_size_type) space_length); + base = bfd_zmalloc ((bfd_size_type) space_length); if (base == NULL) { - bfd_error = no_memory; + bfd_set_error (bfd_error_no_memory); return false; } } @@ -397,7 +423,7 @@ DEFUN(bfd_add_to_string_table,(table, new_string, table_length, free_ptr), base = (char *) realloc (base, space_length); if (base == NULL) { - bfd_error = no_memory; + bfd_set_error (bfd_error_no_memory); return false; } @@ -435,22 +461,22 @@ DESCRIPTION mangling performs any necessary endian translations and removes alignment restrictions. Note that types accepted and returned by these macros are identical so they can be swapped - around in macros--for example libaout.h defines GET_WORD to - either bfd_get_32 or bfd_get_64. + around in macros---for example, @file{libaout.h} defines <<GET_WORD>> + to either <<bfd_get_32>> or <<bfd_get_64>>. - In the put routines, val must be a bfd_vma. If we are on a + In the put routines, @var{val} must be a <<bfd_vma>>. If we are on a system without prototypes, the caller is responsible for making sure that is true, with a cast if necessary. We don't cast - them in the macro definitions because that would prevent lint - or gcc -Wall from detecting sins such as passing a pointer. - To detect calling these with less than a bfd_vma, use gcc - -Wconversion on a host with 64 bit bfd_vma's. + them in the macro definitions because that would prevent <<lint>> + or <<gcc -Wall>> from detecting sins such as passing a pointer. + To detect calling these with less than a <<bfd_vma>>, use + <<gcc -Wconversion>> on a host with 64 bit <<bfd_vma>>'s. . .{* Byte swapping macros for user section data. *} . .#define bfd_put_8(abfd, val, ptr) \ -. (*((unsigned char *)(ptr)) = (unsigned char)val) +. (*((unsigned char *)(ptr)) = (unsigned char)(val)) .#define bfd_put_signed_8 \ . bfd_put_8 .#define bfd_get_8(abfd, ptr) \ @@ -490,15 +516,14 @@ DESCRIPTION /* FUNCTION bfd_h_put_size -FUNCTION bfd_h_get_size DESCRIPTION These macros have the same function as their <<bfd_get_x>> - bretherin, except that they are used for removing information + bretheren, 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 endian order. + order and their data in little endian order. . .{* Byte swapping macros for file header data. *} . @@ -543,91 +568,91 @@ DESCRIPTION /* Sign extension to bfd_signed_vma. */ #define COERCE16(x) (((bfd_signed_vma) (x) ^ 0x8000) - 0x8000) #define COERCE32(x) (((bfd_signed_vma) (x) ^ 0x80000000) - 0x80000000) -#define EIGHT_GAZILLION (((HOST_64_BIT)0x80000000) << 32) +#define EIGHT_GAZILLION (((BFD_HOST_64_BIT)0x80000000) << 32) #define COERCE64(x) \ (((bfd_signed_vma) (x) ^ EIGHT_GAZILLION) - EIGHT_GAZILLION) bfd_vma -DEFUN(bfd_getb16,(addr), - register bfd_byte *addr) +bfd_getb16 (addr) + register const bfd_byte *addr; { - return (addr[0] << 8) | addr[1]; + return (addr[0] << 8) | addr[1]; } bfd_vma -DEFUN(bfd_getl16,(addr), - register bfd_byte *addr) +bfd_getl16 (addr) + register const bfd_byte *addr; { - return (addr[1] << 8) | addr[0]; + return (addr[1] << 8) | addr[0]; } bfd_signed_vma -DEFUN(bfd_getb_signed_16,(addr), - register bfd_byte *addr) +bfd_getb_signed_16 (addr) + register const bfd_byte *addr; { - return COERCE16((addr[0] << 8) | addr[1]); + return COERCE16((addr[0] << 8) | addr[1]); } bfd_signed_vma -DEFUN(bfd_getl_signed_16,(addr), - register bfd_byte *addr) +bfd_getl_signed_16 (addr) + register const bfd_byte *addr; { - return COERCE16((addr[1] << 8) | addr[0]); + return COERCE16((addr[1] << 8) | addr[0]); } void -DEFUN(bfd_putb16,(data, addr), - bfd_vma data AND - register bfd_byte *addr) +bfd_putb16 (data, addr) + bfd_vma data; + 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(bfd_putl16,(data, addr), - bfd_vma data AND - register bfd_byte *addr) +bfd_putl16 (data, addr) + bfd_vma data; + 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); } bfd_vma bfd_getb32 (addr) - register bfd_byte *addr; + register const bfd_byte *addr; { - return (((((bfd_vma)addr[0] << 8) | addr[1]) << 8) - | addr[2]) << 8 | addr[3]; + return (((((bfd_vma)addr[0] << 8) | addr[1]) << 8) + | addr[2]) << 8 | addr[3]; } bfd_vma bfd_getl32 (addr) - register bfd_byte *addr; + register const bfd_byte *addr; { - return (((((bfd_vma)addr[3] << 8) | addr[2]) << 8) - | addr[1]) << 8 | addr[0]; + return (((((bfd_vma)addr[3] << 8) | addr[2]) << 8) + | addr[1]) << 8 | addr[0]; } bfd_signed_vma bfd_getb_signed_32 (addr) - register bfd_byte *addr; + register const bfd_byte *addr; { - return COERCE32((((((bfd_vma)addr[0] << 8) | addr[1]) << 8) - | addr[2]) << 8 | addr[3]); + return COERCE32((((((bfd_vma)addr[0] << 8) | addr[1]) << 8) + | addr[2]) << 8 | addr[3]); } bfd_signed_vma bfd_getl_signed_32 (addr) - register bfd_byte *addr; + register const bfd_byte *addr; { - return COERCE32((((((bfd_vma)addr[3] << 8) | addr[2]) << 8) - | addr[1]) << 8 | addr[0]); + return COERCE32((((((bfd_vma)addr[3] << 8) | addr[2]) << 8) + | addr[1]) << 8 | addr[0]); } bfd_vma -DEFUN(bfd_getb64,(addr), - register bfd_byte *addr) +bfd_getb64 (addr) + register const bfd_byte *addr; { #ifdef BFD64 bfd_vma low, high; @@ -647,14 +672,12 @@ DEFUN(bfd_getb64,(addr), BFD_FAIL(); return 0; #endif - } bfd_vma -DEFUN(bfd_getl64,(addr), - register bfd_byte *addr) +bfd_getl64 (addr) + register const bfd_byte *addr; { - #ifdef BFD64 bfd_vma low, high; high= (((((((addr[7] << 8) | @@ -676,8 +699,8 @@ DEFUN(bfd_getl64,(addr), } bfd_signed_vma -DEFUN(bfd_getb_signed_64,(addr), - register bfd_byte *addr) +bfd_getb_signed_64 (addr) + register const bfd_byte *addr; { #ifdef BFD64 bfd_vma low, high; @@ -697,14 +720,12 @@ DEFUN(bfd_getb_signed_64,(addr), BFD_FAIL(); return 0; #endif - } bfd_signed_vma -DEFUN(bfd_getl_signed_64,(addr), - register bfd_byte *addr) +bfd_getl_signed_64 (addr) + register const bfd_byte *addr; { - #ifdef BFD64 bfd_vma low, high; high= (((((((addr[7] << 8) | @@ -722,13 +743,12 @@ DEFUN(bfd_getl_signed_64,(addr), BFD_FAIL(); return 0; #endif - } void -DEFUN(bfd_putb32,(data, addr), - bfd_vma data AND - register bfd_byte *addr) +bfd_putb32 (data, addr) + bfd_vma data; + register bfd_byte *addr; { addr[0] = (bfd_byte)(data >> 24); addr[1] = (bfd_byte)(data >> 16); @@ -737,19 +757,20 @@ DEFUN(bfd_putb32,(data, addr), } void -DEFUN(bfd_putl32,(data, addr), - bfd_vma data AND - register bfd_byte *addr) +bfd_putl32 (data, addr) + bfd_vma data; + 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); } + void -DEFUN(bfd_putb64,(data, addr), - bfd_vma data AND - register bfd_byte *addr) +bfd_putb64 (data, addr) + bfd_vma data; + register bfd_byte *addr; { #ifdef BFD64 addr[0] = (bfd_byte)(data >> (7*8)); @@ -763,13 +784,12 @@ DEFUN(bfd_putb64,(data, addr), #else BFD_FAIL(); #endif - } void -DEFUN(bfd_putl64,(data, addr), - bfd_vma data AND - register bfd_byte *addr) +bfd_putl64 (data, addr) + bfd_vma data; + register bfd_byte *addr; { #ifdef BFD64 addr[7] = (bfd_byte)(data >> (7*8)); @@ -783,19 +803,17 @@ DEFUN(bfd_putl64,(data, addr), #else BFD_FAIL(); #endif - } - /* Default implementation */ boolean -DEFUN(bfd_generic_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) +_bfd_generic_get_section_contents (abfd, section, location, offset, count) + bfd *abfd; + sec_ptr section; + PTR location; + file_ptr offset; + bfd_size_type count; { if (count == 0) return true; @@ -811,32 +829,33 @@ DEFUN(bfd_generic_get_section_contents, (abfd, section, location, offset, count) in read-write files, though. See other set_section_contents functions to see why it doesn't work for new sections. */ boolean -DEFUN(bfd_generic_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) +_bfd_generic_set_section_contents (abfd, section, location, offset, count) + bfd *abfd; + sec_ptr section; + PTR location; + file_ptr offset; + bfd_size_type count; { - if (count == 0) - return true; - if ((bfd_size_type)(offset+count) > bfd_get_section_size_after_reloc(section) - || bfd_seek(abfd, (file_ptr)(section->filepos + offset), SEEK_SET) == -1 - || bfd_write(location, (bfd_size_type)1, count, abfd) != count) - return (false); /* on error */ - return (true); + if (count == 0) + return true; + + if (bfd_seek (abfd, (file_ptr) (section->filepos + offset), SEEK_SET) == -1 + || bfd_write (location, (bfd_size_type) 1, count, abfd) != count) + return false; + + return true; } /* INTERNAL_FUNCTION bfd_log2 -DESCRIPTION - Return the log base 2 of the value supplied, rounded up. eg an - arg of 1025 would return 11. - SYNOPSIS unsigned int bfd_log2(bfd_vma x); + +DESCRIPTION + Return the log base 2 of the value supplied, rounded up. E.g., an + @var{x} of 1025 returns 11. */ unsigned @@ -848,3 +867,14 @@ bfd_log2(x) result++; return result; } + +boolean +bfd_generic_is_local_label (abfd, sym) + bfd *abfd; + asymbol *sym; +{ + char locals_prefix = (bfd_get_symbol_leading_char (abfd) == '_') ? 'L' : '.'; + + return (sym->name[0] == locals_prefix); +} + diff --git a/gnu/usr.bin/gdb/bfd/libbfd.h b/gnu/usr.bin/gdb/bfd/libbfd.h index fcd5bbca8de8..908f08aa98f7 100644 --- a/gnu/usr.bin/gdb/bfd/libbfd.h +++ b/gnu/usr.bin/gdb/bfd/libbfd.h @@ -1,8 +1,12 @@ /* libbfd.h -- Declarations used by bfd library *implementation*. (This include file is not for users of the library.) - Copyright 1990, 1991, 1992, 1993 Free Software Foundation, Inc. + Copyright 1990, 1991, 1992, 1993, 1994 Free Software Foundation, Inc. Written by Cygnus Support. +** NOTE: libbfd.h is a GENERATED file. Don't change it; instead, +** change libbfd-in.h or the other BFD source files processed to +** generate this file. + This file is part of BFD, the Binary File Descriptor library. This program is free software; you can redistribute it and/or modify @@ -19,7 +23,6 @@ You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ - /* Align an address upward to a boundary, expressed as a number of bytes. E.g. align to an 8-byte boundary with argument of 8. */ #define BFD_ALIGN(this, boundary) \ @@ -44,7 +47,8 @@ struct artdata { carsym *symdefs; /* the symdef entries */ symindex symdef_count; /* how many there are */ char *extended_names; /* clever intel extension */ - time_t armap_timestamp; /* Timestamp value written into armap. + /* when more compilers are standard C, this can be a time_t */ + long armap_timestamp; /* Timestamp value written into armap. This is used for BSD archives to check that the timestamp is recent enough for the BSD linker to not complain, @@ -52,6 +56,7 @@ struct artdata { archive. */ file_ptr armap_datepos; /* Position within archive to seek to rewrite the date field. */ + PTR tdata; /* Backend specific information. */ }; #define bfd_ardata(bfd) ((bfd)->tdata.aout_ar_data) @@ -65,14 +70,14 @@ struct areltdata { #define arelt_size(bfd) (((struct areltdata *)((bfd)->arelt_data))->parsed_size) -char *zalloc PARAMS ((bfd_size_type size)); +char *bfd_zmalloc PARAMS ((bfd_size_type size)); /* These routines allocate and free things on the BFD's obstack. Note that realloc can never occur in place. */ PTR bfd_alloc PARAMS ((bfd *abfd, size_t size)); PTR bfd_zalloc PARAMS ((bfd *abfd, size_t size)); -PTR bfd_realloc PARAMS ((bfd *abfd, PTR orig, size_t new)); +PTR bfd_realloc PARAMS ((bfd *abfd, PTR orig, size_t size)); void bfd_alloc_grow PARAMS ((bfd *abfd, PTR thing, size_t size)); PTR bfd_alloc_finish PARAMS ((bfd *abfd)); PTR bfd_alloc_by_size_t PARAMS ((bfd *abfd, size_t wanted)); @@ -92,17 +97,19 @@ int bfd_flush PARAMS ((bfd *abfd)); int bfd_stat PARAMS ((bfd *abfd, struct stat *)); bfd * _bfd_create_empty_archive_element_shell PARAMS ((bfd *obfd)); -bfd * look_for_bfd_in_cache PARAMS ((bfd *arch_bfd, file_ptr index)); +bfd * _bfd_look_for_bfd_in_cache PARAMS ((bfd *arch_bfd, file_ptr index)); +boolean _bfd_add_bfd_to_archive_cache PARAMS ((bfd *, file_ptr, bfd *)); boolean _bfd_generic_mkarchive PARAMS ((bfd *abfd)); -struct areltdata * snarf_ar_hdr PARAMS ((bfd *abfd)); -bfd_target * bfd_generic_archive_p PARAMS ((bfd *abfd)); +struct areltdata *_bfd_snarf_ar_hdr PARAMS ((bfd *abfd)); +const bfd_target *bfd_generic_archive_p PARAMS ((bfd *abfd)); boolean bfd_slurp_armap PARAMS ((bfd *abfd)); boolean bfd_slurp_bsd_armap_f2 PARAMS ((bfd *abfd)); #define bfd_slurp_bsd_armap bfd_slurp_armap #define bfd_slurp_coff_armap bfd_slurp_armap boolean _bfd_slurp_extended_name_table PARAMS ((bfd *abfd)); boolean _bfd_write_archive_contents PARAMS ((bfd *abfd)); -bfd * new_bfd PARAMS (()); +bfd *_bfd_get_elt_at_filepos PARAMS ((bfd *archive, file_ptr filepos)); +bfd * _bfd_new_bfd PARAMS ((void)); #define DEFAULT_STRING_SPACE_SIZE 0x2000 boolean bfd_add_to_string_table PARAMS ((char **table, char *new_string, @@ -114,15 +121,12 @@ boolean bfd_true PARAMS ((bfd *ignore)); PTR bfd_nullvoidptr PARAMS ((bfd *ignore)); int bfd_0 PARAMS ((bfd *ignore)); unsigned int bfd_0u PARAMS ((bfd *ignore)); +long bfd_0l PARAMS ((bfd *ignore)); +long _bfd_n1 PARAMS ((bfd *ignore)); void bfd_void PARAMS ((bfd *ignore)); -bfd * new_bfd_contained_in PARAMS ((bfd *)); -boolean _bfd_dummy_new_section_hook PARAMS ((bfd *ignore, asection *newsect)); -char * _bfd_dummy_core_file_failing_command PARAMS ((bfd *abfd)); -int _bfd_dummy_core_file_failing_signal PARAMS ((bfd *abfd)); -boolean _bfd_dummy_core_file_matches_executable_p PARAMS ((bfd *core_bfd, - bfd *exec_bfd)); -bfd_target * _bfd_dummy_target PARAMS ((bfd *abfd)); +bfd *_bfd_new_bfd_contained_in PARAMS ((bfd *)); +const bfd_target *_bfd_dummy_target PARAMS ((bfd *abfd)); void bfd_dont_truncate_arname PARAMS ((bfd *abfd, CONST char *filename, char *hdr)); @@ -142,14 +146,230 @@ bfd * bfd_generic_openr_next_archived_file PARAMS ((bfd *archive, int bfd_generic_stat_arch_elt PARAMS ((bfd *, struct stat *)); -boolean bfd_generic_get_section_contents PARAMS ((bfd *abfd, sec_ptr section, - PTR location, file_ptr offset, - bfd_size_type count)); - -boolean bfd_generic_set_section_contents PARAMS ((bfd *abfd, sec_ptr section, - PTR location, file_ptr offset, - bfd_size_type count)); - + +/* Generic routines to use for BFD_JUMP_TABLE_GENERIC. Use + BFD_JUMP_TABLE_GENERIC (_bfd_generic). */ + +#define _bfd_generic_close_and_cleanup bfd_true +#define _bfd_generic_bfd_free_cached_info bfd_true +#define _bfd_generic_new_section_hook \ + ((boolean (*) PARAMS ((bfd *, asection *))) bfd_true) +extern boolean _bfd_generic_get_section_contents + PARAMS ((bfd *, asection *, PTR location, file_ptr offset, + bfd_size_type count)); + +/* Generic routines to use for BFD_JUMP_TABLE_COPY. Use + BFD_JUMP_TABLE_COPY (_bfd_generic). */ + +#define _bfd_generic_bfd_copy_private_bfd_data \ + ((boolean (*) PARAMS ((bfd *, bfd *))) bfd_true) +#define _bfd_generic_bfd_copy_private_section_data \ + ((boolean (*) PARAMS ((bfd *, asection *, bfd *, asection *))) bfd_true) + +/* Routines to use for BFD_JUMP_TABLE_CORE when there is no core file + support. Use BFD_JUMP_TABLE_CORE (_bfd_nocore). */ + +extern char *_bfd_nocore_core_file_failing_command PARAMS ((bfd *)); +extern int _bfd_nocore_core_file_failing_signal PARAMS ((bfd *)); +extern boolean _bfd_nocore_core_file_matches_executable_p + PARAMS ((bfd *, bfd *)); + +/* Routines to use for BFD_JUMP_TABLE_ARCHIVE when there is no archive + file support. Use BFD_JUMP_TABLE_ARCHIVE (_bfd_noarchive). */ + +#define _bfd_noarchive_slurp_armap bfd_false +#define _bfd_noarchive_slurp_extended_name_table bfd_false +#define _bfd_noarchive_truncate_arname \ + ((void (*) PARAMS ((bfd *, const char *, char *))) bfd_void) +#define _bfd_noarchive_write_armap \ + ((boolean (*) \ + PARAMS ((bfd *, unsigned int, struct orl *, unsigned int, int))) \ + bfd_false) +#define _bfd_noarchive_openr_next_archived_file \ + ((bfd *(*) PARAMS ((bfd *, bfd *))) bfd_nullvoidptr) +#define _bfd_noarchive_generic_stat_arch_elt bfd_generic_stat_arch_elt + +/* Routines to use for BFD_JUMP_TABLE_ARCHIVE to get BSD style + archives. Use BFD_JUMP_TABLE_ARCHIVE (_bfd_archive_bsd). */ + +#define _bfd_archive_bsd_slurp_armap bfd_slurp_bsd_armap +#define _bfd_archive_bsd_slurp_extended_name_table \ + _bfd_slurp_extended_name_table +#define _bfd_archive_bsd_truncate_arname bfd_bsd_truncate_arname +#define _bfd_archive_bsd_write_armap bsd_write_armap +#define _bfd_archive_bsd_openr_next_archived_file \ + bfd_generic_openr_next_archived_file +#define _bfd_archive_bsd_generic_stat_arch_elt \ + bfd_generic_stat_arch_elt + +/* Routines to use for BFD_JUMP_TABLE_ARCHIVE to get COFF style + archives. Use BFD_JUMP_TABLE_ARCHIVE (_bfd_archive_coff). */ + +#define _bfd_archive_coff_slurp_armap bfd_slurp_coff_armap +#define _bfd_archive_coff_slurp_extended_name_table \ + _bfd_slurp_extended_name_table +#define _bfd_archive_coff_truncate_arname bfd_dont_truncate_arname +#define _bfd_archive_coff_write_armap coff_write_armap +#define _bfd_archive_coff_openr_next_archived_file \ + bfd_generic_openr_next_archived_file +#define _bfd_archive_coff_generic_stat_arch_elt \ + bfd_generic_stat_arch_elt + +/* Routines to use for BFD_JUMP_TABLE_SYMBOLS where there is no symbol + support. Use BFD_JUMP_TABLE_SYMBOLS (_bfd_nosymbols). */ + +#define _bfd_nosymbols_get_symtab_upper_bound _bfd_n1 +#define _bfd_nosymbols_get_symtab \ + ((long (*) PARAMS ((bfd *, asymbol **))) _bfd_n1) +#define _bfd_nosymbols_make_empty_symbol \ + ((asymbol *(*) PARAMS ((bfd *))) bfd_nullvoidptr) +#define _bfd_nosymbols_print_symbol \ + ((void (*) PARAMS ((bfd *, PTR, asymbol *, bfd_print_symbol_type))) bfd_void) +#define _bfd_nosymbols_get_symbol_info \ + ((void (*) PARAMS ((bfd *, asymbol *, symbol_info *))) bfd_void) +#define _bfd_nosymbols_bfd_is_local_label \ + ((boolean (*) PARAMS ((bfd *, asymbol *))) bfd_false) +#define _bfd_nosymbols_get_lineno \ + ((alent *(*) PARAMS ((bfd *, asymbol *))) bfd_nullvoidptr) +#define _bfd_nosymbols_find_nearest_line \ + ((boolean (*) \ + PARAMS ((bfd *, asection *, asymbol **, bfd_vma, const char **, \ + const char **, unsigned int *))) \ + bfd_false) +#define _bfd_nosymbols_bfd_make_debug_symbol \ + ((asymbol *(*) PARAMS ((bfd *, PTR, unsigned long))) bfd_nullvoidptr) + +/* Routines to use for BFD_JUMP_TABLE_RELOCS when there is no reloc + support. Use BFD_JUMP_TABLE_RELOCS (_bfd_norelocs). */ + +#define _bfd_norelocs_get_reloc_upper_bound \ + ((long (*) PARAMS ((bfd *, asection *))) _bfd_n1) +#define _bfd_norelocs_canonicalize_reloc \ + ((long (*) PARAMS ((bfd *, asection *, arelent **, asymbol **))) _bfd_n1) +#define _bfd_norelocs_bfd_reloc_type_lookup \ + ((const reloc_howto_type *(*) PARAMS ((bfd *, bfd_reloc_code_real_type))) \ + bfd_nullvoidptr) + +/* Routines to use for BFD_JUMP_TABLE_WRITE for targets which may not + be written. Use BFD_JUMP_TABLE_WRITE (_bfd_nowrite). */ + +#define _bfd_nowrite_set_arch_mach \ + ((boolean (*) PARAMS ((bfd *, enum bfd_architecture, unsigned long))) \ + bfd_false) +#define _bfd_nowrite_set_section_contents \ + ((boolean (*) PARAMS ((bfd *, asection *, PTR, file_ptr, bfd_size_type))) \ + bfd_false) + +/* Generic routines to use for BFD_JUMP_TABLE_WRITE. Use + BFD_JUMP_TABLE_WRITE (_bfd_generic). */ + +#define _bfd_generic_set_arch_mach bfd_default_set_arch_mach +extern boolean _bfd_generic_set_section_contents + PARAMS ((bfd *, asection *, PTR, file_ptr, bfd_size_type)); + +/* Routines to use for BFD_JUMP_TABLE_LINK for targets which do not + support linking. Use BFD_JUMP_TABLE_LINK (_bfd_nolink). */ + +#define _bfd_nolink_sizeof_headers ((int (*) PARAMS ((bfd *, boolean))) bfd_0) +#define _bfd_nolink_bfd_get_relocated_section_contents \ + ((bfd_byte *(*) \ + PARAMS ((bfd *, struct bfd_link_info *, struct bfd_link_order *, \ + bfd_byte *, boolean, asymbol **))) \ + bfd_nullvoidptr) +#define _bfd_nolink_bfd_relax_section \ + ((boolean (*) \ + PARAMS ((bfd *, asection *, struct bfd_link_info *, boolean *))) \ + bfd_false) +#define _bfd_nolink_bfd_link_hash_table_create \ + ((struct bfd_link_hash_table *(*) PARAMS ((bfd *))) bfd_nullvoidptr) +#define _bfd_nolink_bfd_link_add_symbols \ + ((boolean (*) PARAMS ((bfd *, struct bfd_link_info *))) bfd_false) +#define _bfd_nolink_bfd_final_link \ + ((boolean (*) PARAMS ((bfd *, struct bfd_link_info *))) bfd_false) + +/* Routines to use for BFD_JUMP_TABLE_DYNAMIC for targets which do not + have dynamic symbols or relocs. Use BFD_JUMP_TABLE_DYNAMIC + (_bfd_nodynamic). */ + +#define _bfd_nodynamic_get_dynamic_symtab_upper_bound _bfd_n1 +#define _bfd_nodynamic_canonicalize_dynamic_symtab \ + ((long (*) PARAMS ((bfd *, asymbol **))) _bfd_n1) +#define _bfd_nodynamic_get_dynamic_reloc_upper_bound _bfd_n1 +#define _bfd_nodynamic_canonicalize_dynamic_reloc \ + ((long (*) PARAMS ((bfd *, arelent **, asymbol **))) _bfd_n1) + +/* Generic routine to determine of the given symbol is a local + label. */ +extern boolean bfd_generic_is_local_label PARAMS ((bfd *, asymbol *)); + +/* A routine to create entries for a bfd_link_hash_table. */ +extern struct bfd_hash_entry *_bfd_link_hash_newfunc + PARAMS ((struct bfd_hash_entry *entry, + struct bfd_hash_table *table, + const char *string)); + +/* Initialize a bfd_link_hash_table. */ +extern boolean _bfd_link_hash_table_init + PARAMS ((struct bfd_link_hash_table *, bfd *, + struct bfd_hash_entry *(*) (struct bfd_hash_entry *, + struct bfd_hash_table *, + const char *))); + +/* Generic link hash table creation routine. */ +extern struct bfd_link_hash_table *_bfd_generic_link_hash_table_create + PARAMS ((bfd *)); + +/* Generic add symbol routine. */ +extern boolean _bfd_generic_link_add_symbols + PARAMS ((bfd *, struct bfd_link_info *)); + +/* Generic add symbol routine. This version is used by targets for + which the linker must collect constructors and destructors by name, + as the collect2 program does. */ +extern boolean _bfd_generic_link_add_symbols_collect + PARAMS ((bfd *, struct bfd_link_info *)); + +/* Generic archive add symbol routine. */ +extern boolean _bfd_generic_link_add_archive_symbols + PARAMS ((bfd *, struct bfd_link_info *, + boolean (*checkfn) (bfd *, struct bfd_link_info *, boolean *))); + +/* Forward declaration to avoid prototype errors. */ +typedef struct bfd_link_hash_entry _bfd_link_hash_entry; + +/* Generic routine to add a single symbol. */ +extern boolean _bfd_generic_link_add_one_symbol + PARAMS ((struct bfd_link_info *, bfd *, const char *name, flagword, + asection *, bfd_vma, const char *, boolean copy, + boolean constructor, struct bfd_link_hash_entry **)); + +/* Generic link routine. */ +extern boolean _bfd_generic_final_link + PARAMS ((bfd *, struct bfd_link_info *)); + +/* Generic reloc_link_order processing routine. */ +extern boolean _bfd_generic_reloc_link_order + PARAMS ((bfd *, struct bfd_link_info *, asection *, + struct bfd_link_order *)); + +/* Default link order processing routine. */ +extern boolean _bfd_default_link_order + PARAMS ((bfd *, struct bfd_link_info *, asection *, + struct bfd_link_order *)); + +/* Count the number of reloc entries in a link order list. */ +extern unsigned int _bfd_count_link_order_relocs + PARAMS ((struct bfd_link_order *)); + +/* Final link relocation routine. */ +extern bfd_reloc_status_type _bfd_final_link_relocate + PARAMS ((const reloc_howto_type *, bfd *, asection *, bfd_byte *, + bfd_vma address, bfd_vma value, bfd_vma addend)); + +/* Relocate a particular location by a howto and a value. */ +extern bfd_reloc_status_type _bfd_relocate_contents + PARAMS ((const reloc_howto_type *, bfd *, bfd_vma, bfd_byte *)); + /* Macros to tell if bfds are read or write enabled. Note that bfds open for read may be scribbled into if the fd passed @@ -183,20 +403,16 @@ extern bfd *bfd_last_cache; #define stoi(x) ((int)(x)) #endif -/* Generic routine for close_and_cleanup is really just bfd_true. */ -#define bfd_generic_close_and_cleanup bfd_true +/* List of supported target vectors, and the default vector (if + bfd_default_vector[0] is NULL, there is no default). */ +extern const bfd_target * const bfd_target_vector[]; +extern const bfd_target * const bfd_default_vector[]; /* And more follows */ void bfd_check_init PARAMS ((void)); -PTR -bfd_xmalloc PARAMS (( bfd_size_type size)); - -PTR -bfd_xmalloc_by_size_t PARAMS (( size_t size)); - void bfd_write_bigendian_4byte_int PARAMS ((bfd *abfd, int i)); @@ -211,42 +427,41 @@ extern bfd *bfd_last_cache; (FILE*)(bfd_last_cache->iostream): \ bfd_cache_lookup_worker(x)) boolean -bfd_cache_close PARAMS ((bfd *)); +bfd_cache_init PARAMS ((bfd *abfd)); + +boolean +bfd_cache_close PARAMS ((bfd *abfd)); FILE* -bfd_open_file PARAMS ((bfd *)); +bfd_open_file PARAMS ((bfd *abfd)); FILE * -bfd_cache_lookup_worker PARAMS ((bfd *)); +bfd_cache_lookup_worker PARAMS ((bfd *abfd)); -void +boolean bfd_constructor_entry PARAMS ((bfd *abfd, asymbol **symbol_ptr_ptr, CONST char*type)); -CONST struct reloc_howto_struct * +const struct reloc_howto_struct * bfd_default_reloc_type_lookup - PARAMS ((bfd *abfd AND - bfd_reloc_code_real_type code)); + PARAMS ((bfd *abfd, bfd_reloc_code_real_type code)); boolean bfd_generic_relax_section PARAMS ((bfd *abfd, asection *section, - asymbol **symbols)); + struct bfd_link_info *, + boolean *)); bfd_byte * bfd_generic_get_relocated_section_contents PARAMS ((bfd *abfd, - struct bfd_seclet *seclet, + struct bfd_link_info *link_info, + struct bfd_link_order *link_order, bfd_byte *data, - boolean relocateable)); - -boolean -bfd_generic_seclet_link - PARAMS ((bfd *abfd, - PTR data, - boolean relocateable)); + boolean relocateable, + asymbol **symbols)); extern bfd_arch_info_type bfd_default_arch_struct; boolean @@ -254,11 +469,11 @@ bfd_default_set_arch_mach PARAMS ((bfd *abfd, enum bfd_architecture arch, unsigned long mach)); -void +void bfd_arch_init PARAMS ((void)); void -bfd_arch_linkin PARAMS ((bfd_arch_info_type *)); +bfd_arch_linkin PARAMS ((bfd_arch_info_type *ptr)); CONST bfd_arch_info_type * bfd_default_compatible @@ -266,7 +481,7 @@ bfd_default_compatible CONST bfd_arch_info_type *b)); boolean -bfd_default_scan PARAMS ((CONST struct bfd_arch_info *, CONST char *)); +bfd_default_scan PARAMS ((CONST struct bfd_arch_info *info, CONST char *string)); struct elf_internal_shdr * bfd_elf_find_section PARAMS ((bfd *abfd, char *name)); diff --git a/gnu/usr.bin/gdb/bfd/libcoff.h b/gnu/usr.bin/gdb/bfd/libcoff.h index 2aa6ad4b1615..a564f118641b 100644 --- a/gnu/usr.bin/gdb/bfd/libcoff.h +++ b/gnu/usr.bin/gdb/bfd/libcoff.h @@ -1,5 +1,5 @@ /* BFD COFF object file private structure. - Copyright (C) 1990, 1991, 1992, 1993 Free Software Foundation, Inc. + Copyright (C) 1990, 1991, 1992, 1993, 1994 Free Software Foundation, Inc. Written by Cygnus Support. This file is part of BFD, the Binary File Descriptor library. @@ -75,20 +75,20 @@ typedef struct coff_tdata #define coffsymbol(asymbol) ((coff_symbol_type *)(&((asymbol)->the_bfd))) /* Functions in coffgen.c. */ -extern bfd_target *coff_object_p PARAMS ((bfd *)); +extern const bfd_target *coff_object_p PARAMS ((bfd *)); extern struct sec *coff_section_from_bfd_index PARAMS ((bfd *, int)); -extern unsigned int coff_get_symtab_upper_bound PARAMS ((bfd *)); -extern unsigned int coff_get_symtab PARAMS ((bfd *, asymbol **)); +extern long coff_get_symtab_upper_bound PARAMS ((bfd *)); +extern long coff_get_symtab PARAMS ((bfd *, asymbol **)); extern int coff_count_linenumbers PARAMS ((bfd *)); extern struct coff_symbol_struct *coff_symbol_from PARAMS ((bfd *, asymbol *)); -extern void coff_renumber_symbols PARAMS ((bfd *)); +extern boolean coff_renumber_symbols PARAMS ((bfd *)); extern void coff_mangle_symbols PARAMS ((bfd *)); -extern void coff_write_symbols PARAMS ((bfd *)); -extern void coff_write_linenumbers PARAMS ((bfd *)); +extern boolean coff_write_symbols PARAMS ((bfd *)); +extern boolean coff_write_linenumbers PARAMS ((bfd *)); extern alent *coff_get_lineno PARAMS ((bfd *, asymbol *)); extern asymbol *coff_section_symbol PARAMS ((bfd *, char *)); extern struct coff_ptr_struct *coff_get_normalized_symtab PARAMS ((bfd *)); -extern unsigned int coff_get_reloc_upper_bound PARAMS ((bfd *, sec_ptr)); +extern long coff_get_reloc_upper_bound PARAMS ((bfd *, sec_ptr)); extern asymbol *coff_make_empty_symbol PARAMS ((bfd *)); extern void coff_print_symbol PARAMS ((bfd *, PTR filep, asymbol *, bfd_print_symbol_type how)); @@ -104,30 +104,42 @@ extern boolean coff_find_nearest_line PARAMS ((bfd *, CONST char **functionname_ptr, unsigned int *line_ptr)); extern int coff_sizeof_headers PARAMS ((bfd *, boolean reloc)); -extern boolean bfd_coff_reloc16_relax_section PARAMS ((bfd *, - asection *, - asymbol **)); +extern boolean bfd_coff_reloc16_relax_section + PARAMS ((bfd *, asection *, struct bfd_link_info *, boolean *)); extern bfd_byte *bfd_coff_reloc16_get_relocated_section_contents - PARAMS ((bfd *, struct bfd_seclet *, bfd_byte *, boolean relocateable)); + PARAMS ((bfd *, struct bfd_link_info *, struct bfd_link_order *, + bfd_byte *, boolean relocateable, asymbol **)); extern bfd_vma bfd_coff_reloc16_get_value PARAMS ((arelent *, - struct bfd_seclet *)); + struct bfd_link_info *, + asection *)); +extern void bfd_perform_slip PARAMS ((bfd *abfd, unsigned int slip, + asection *input_section, + bfd_vma val)); /* And more taken from the source .. */ -typedef struct coff_ptr_struct +typedef struct coff_ptr_struct { /* Remembers the offset from the first symbol in the file for this symbol. Generated by coff_renumber_symbols. */ unsigned int offset; + /* Should the value of this symbol be renumbered. Used for + XCOFF C_BSTAT symbols. Set by coff_slurp_symbol_table. */ +unsigned int fix_value : 1; + /* Should the tag field of this symbol be renumbered. Created by coff_pointerize_aux. */ -char fix_tag; +unsigned int fix_tag : 1; /* Should the endidx field of this symbol be renumbered. Created by coff_pointerize_aux. */ -char fix_end; +unsigned int fix_end : 1; + + /* Should the x_csect.x_scnlen field be renumbered. + Created by coff_slurp_symbol_table. */ +unsigned int fix_scnlen : 1; /* The container for the symbol structure as read and translated from the file. */ @@ -155,13 +167,15 @@ struct lineno_cache_entry *lineno; /* Have the line numbers been relocated yet ? */ boolean done_lineno; } coff_symbol_type; -typedef struct +typedef struct { void (*_bfd_coff_swap_aux_in) PARAMS (( - bfd *abfd , + bfd *abfd, PTR ext, int type, - int class , + int class, + int indaux, + int numaux, PTR in)); void (*_bfd_coff_swap_sym_in) PARAMS (( @@ -179,6 +193,8 @@ typedef struct PTR in, int type, int class, + int indaux, + int numaux, PTR ext)); unsigned int (*_bfd_coff_swap_sym_out) PARAMS (( @@ -257,23 +273,25 @@ typedef struct struct internal_syment *sym)); void (*_bfd_coff_reloc16_extra_cases) PARAMS (( bfd *abfd, - struct bfd_seclet *seclet, + struct bfd_link_info *link_info, + struct bfd_link_order *link_order, arelent *reloc, bfd_byte *data, unsigned int *src_ptr, unsigned int *dst_ptr)); int (*_bfd_coff_reloc16_estimate) PARAMS (( + bfd *abfd, asection *input_section, - asymbol **symbols, arelent *r, - unsigned int shrink)); + unsigned int shrink, + struct bfd_link_info *link_info)); } bfd_coff_backend_data; #define coff_backend_info(abfd) ((bfd_coff_backend_data *) (abfd)->xvec->backend_data) -#define bfd_coff_swap_aux_in(a,e,t,c,i) \ - ((coff_backend_info (a)->_bfd_coff_swap_aux_in) (a,e,t,c,i)) +#define bfd_coff_swap_aux_in(a,e,t,c,ind,num,i) \ + ((coff_backend_info (a)->_bfd_coff_swap_aux_in) (a,e,t,c,ind,num,i)) #define bfd_coff_swap_sym_in(a,e,i) \ ((coff_backend_info (a)->_bfd_coff_swap_sym_in) (a,e,i)) @@ -287,8 +305,8 @@ typedef struct #define bfd_coff_swap_lineno_out(abfd, i, o) \ ((coff_backend_info (abfd)->_bfd_coff_swap_lineno_out) (abfd, i, o)) -#define bfd_coff_swap_aux_out(abfd, i, t,c,o) \ - ((coff_backend_info (abfd)->_bfd_coff_swap_aux_out) (abfd, i,t,c, o)) +#define bfd_coff_swap_aux_out(a,i,t,c,ind,num,o) \ + ((coff_backend_info (a)->_bfd_coff_swap_aux_out) (a,i,t,c,ind,num,o)) #define bfd_coff_swap_sym_out(abfd, i,o) \ ((coff_backend_info (abfd)->_bfd_coff_swap_sym_out) (abfd, i, o)) @@ -341,12 +359,11 @@ typedef struct #define bfd_coff_symname_in_debug(abfd, sym)\ ((coff_backend_info (abfd)->_bfd_coff_symname_in_debug) (abfd, sym)) -#define bfd_coff_reloc16_extra_cases(abfd, seclet, reloc, data, src_ptr, dst_ptr)\ +#define bfd_coff_reloc16_extra_cases(abfd, link_info, link_order, reloc, data, src_ptr, dst_ptr)\ ((coff_backend_info (abfd)->_bfd_coff_reloc16_extra_cases)\ - (abfd, seclet, reloc, data, src_ptr, dst_ptr)) + (abfd, link_info, link_order, reloc, data, src_ptr, dst_ptr)) -#define bfd_coff_reloc16_estimate(abfd, section, symbols, reloc, shrink)\ +#define bfd_coff_reloc16_estimate(abfd, section, reloc, shrink, link_info)\ ((coff_backend_info (abfd)->_bfd_coff_reloc16_estimate)\ - (section, symbols, reloc, shrink)) - - + (abfd, section, reloc, shrink, link_info)) + diff --git a/gnu/usr.bin/gdb/bfd/libecoff.h b/gnu/usr.bin/gdb/bfd/libecoff.h index ad3e8f223aa4..2f7b852872a3 100644 --- a/gnu/usr.bin/gdb/bfd/libecoff.h +++ b/gnu/usr.bin/gdb/bfd/libecoff.h @@ -18,6 +18,12 @@ You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ +#include "bfdlink.h" + +#ifndef ECOFF_H +#include "coff/ecoff.h" +#endif + /* This is the backend information kept for ECOFF files. This structure is constant for a particular backend. The first element is the COFF backend data structure, so that ECOFF targets can use @@ -32,57 +38,36 @@ struct ecoff_backend_data bfd_coff_backend_data coff; /* Supported architecture. */ enum bfd_architecture arch; - /* Symbol table magic number. */ - int sym_magic; /* Initial portion of armap string. */ const char *armap_start; - /* Alignment of debugging information. E.g., 4. */ - bfd_size_type debug_align; /* The page boundary used to align sections in a demand-paged executable file. E.g., 0x1000. */ bfd_vma round; + /* True if the .rdata section is part of the text segment, as on the + Alpha. False if .rdata is part of the data segment, as on the + MIPS. */ + boolean rdata_in_text; /* Bitsize of constructor entries. */ unsigned int constructor_bitsize; /* Reloc to use for constructor entries. */ CONST struct reloc_howto_struct *constructor_reloc; - /* Sizes of external symbolic information. */ - bfd_size_type external_hdr_size; - bfd_size_type external_dnr_size; - bfd_size_type external_pdr_size; - bfd_size_type external_sym_size; - bfd_size_type external_opt_size; - bfd_size_type external_fdr_size; - bfd_size_type external_rfd_size; - bfd_size_type external_ext_size; - /* Functions to swap in external symbolic data. */ - void (*swap_hdr_in) PARAMS ((bfd *, PTR, HDRR *)); - void (*swap_dnr_in) PARAMS ((bfd *, PTR, DNR *)); - void (*swap_pdr_in) PARAMS ((bfd *, PTR, PDR *)); - void (*swap_sym_in) PARAMS ((bfd *, PTR, SYMR *)); - void (*swap_opt_in) PARAMS ((bfd *, PTR, OPTR *)); - void (*swap_fdr_in) PARAMS ((bfd *, PTR, FDR *)); - void (*swap_rfd_in) PARAMS ((bfd *, PTR, RFDT *)); - void (*swap_ext_in) PARAMS ((bfd *, PTR, EXTR *)); - /* Functions to swap out external symbolic data. */ - void (*swap_hdr_out) PARAMS ((bfd *, const HDRR *, PTR)); - void (*swap_dnr_out) PARAMS ((bfd *, const DNR *, PTR)); - void (*swap_pdr_out) PARAMS ((bfd *, const PDR *, PTR)); - void (*swap_sym_out) PARAMS ((bfd *, const SYMR *, PTR)); - void (*swap_opt_out) PARAMS ((bfd *, const OPTR *, PTR)); - void (*swap_fdr_out) PARAMS ((bfd *, const FDR *, PTR)); - void (*swap_rfd_out) PARAMS ((bfd *, const RFDT *, PTR)); - void (*swap_ext_out) PARAMS ((bfd *, const EXTR *, PTR)); - /* It so happens that the auxiliary type information has the same - type and format for all known ECOFF targets. I don't see any - reason that that should change, so at least for now the auxiliary - swapping information is not in this table. */ + /* How to swap debugging information. */ + struct ecoff_debug_swap debug_swap; /* External reloc size. */ bfd_size_type external_reloc_size; /* Reloc swapping functions. */ void (*swap_reloc_in) PARAMS ((bfd *, PTR, struct internal_reloc *)); void (*swap_reloc_out) PARAMS ((bfd *, const struct internal_reloc *, PTR)); /* Backend reloc tweaking. */ - void (*finish_reloc) PARAMS ((bfd *, struct internal_reloc *, arelent *)); + void (*adjust_reloc_in) PARAMS ((bfd *, const struct internal_reloc *, + arelent *)); + void (*adjust_reloc_out) PARAMS ((bfd *, const arelent *, + struct internal_reloc *)); + /* Relocate section contents while linking. */ + boolean (*relocate_section) PARAMS ((bfd *output_bfd, struct bfd_link_info *, + bfd *input_bfd, asection *input_section, + bfd_byte *contents, + PTR external_relocs)); }; /* This is the target specific information kept for ECOFF files. */ @@ -95,7 +80,7 @@ typedef struct ecoff_tdata ecoff_compute_section_file_positions. */ file_ptr reloc_filepos; - /* The symbol table file position, set by ecoff_mkobject_hook. */ + /* The symbol table file position, set by _bfd_ecoff_mkobject_hook. */ file_ptr sym_filepos; /* The start and end of the text segment. Only valid for an @@ -119,38 +104,26 @@ typedef struct ecoff_tdata unsigned long fprmask; unsigned long cprmask[4]; - /* The size of the unswapped ECOFF symbolic information. */ - bfd_size_type raw_size; + /* The ECOFF symbolic debugging information. */ + struct ecoff_debug_info debug_info; /* The unswapped ECOFF symbolic information. */ PTR raw_syments; - /* The swapped ECOFF symbolic header. */ - HDRR symbolic_header; - - /* Pointers to the unswapped symbolic information. */ - unsigned char *line; - PTR external_dnr; /* struct dnr_ext */ - PTR external_pdr; /* struct pdr_ext */ - PTR external_sym; /* struct sym_ext */ - PTR external_opt; /* struct opt_ext */ - union aux_ext *external_aux; - char *ss; - char *ssext; - PTR external_fdr; /* struct fdr_ext */ - PTR external_rfd; /* struct rfd_ext */ - PTR external_ext; /* struct ext_ext */ - - /* The swapped FDR information. */ - FDR *fdr; - - /* The FDR index. This is set for an input BFD to a link so that - the external symbols can set their FDR index correctly. */ - unsigned int ifdbase; - /* The canonical BFD symbols. */ struct ecoff_symbol_struct *canonical_symbols; + /* A mapping from external symbol numbers to entries in the linker + hash table, used when linking. */ + struct ecoff_link_hash_entry **sym_hashes; + + /* A mapping from reloc symbol indices to sections, used when + linking. */ + asection **symndx_to_section; + + /* True if this BFD was written by the backend linker. */ + boolean linker; + } ecoff_data_type; /* Each canonical asymbol really looks like this. */ @@ -182,84 +155,143 @@ typedef struct ecoff_symbol_struct #define ecoff_get_sym_index(symbol) ((unsigned long) (symbol)->udata) #define ecoff_set_sym_index(symbol, idx) ((symbol)->udata = (PTR) (idx)) +/* When generating MIPS embedded PIC code, the linker relaxes the code + to turn PC relative branches into longer code sequences when the PC + relative branch is out of range. This involves reading the relocs + in bfd_relax_section as well as in bfd_final_link, and requires the + code to keep track of which relocs have been expanded. A pointer + to this structure is put in the used_by_bfd pointer of a section to + keep track of this information. The user_by_bfd pointer will be + NULL if the information was not needed. */ + +struct ecoff_section_tdata +{ + /* The unswapped relocs for this section. These are stored in + memory so the input file does not have to be read twice. */ + PTR external_relocs; + + /* The contents of the section. These bytes may or may not be saved + in memory, but if it is this is a pointer to them. */ + bfd_byte *contents; + + /* Offset adjustments for PC relative branches. A number other than + 1 is an addend for a PC relative branch, or a switch table entry + which is the difference of two .text locations; this addend + arises because the branch or difference crosses one or more + branches which were expanded into a larger code sequence. A 1 + means that this branch was itself expanded into a larger code + sequence. 1 is not a possible offset, since all offsets must be + multiples of the instruction size, which is 4; also, the only + relocs with non-zero offsets will be PC relative branches or + switch table entries within the same object file. If this field + is NULL, no branches were expanded and no offsets are required. + Otherwise there are as many entries as there are relocs in the + section, and the entry for any reloc that is not PC relative is + zero. */ + long *offsets; +}; + +/* An accessor macro for the ecoff_section_tdata structure. */ +#define ecoff_section_data(abfd, sec) \ + ((struct ecoff_section_tdata *) (sec)->used_by_bfd) + +/* ECOFF linker hash table entries. */ + +struct ecoff_link_hash_entry +{ + struct bfd_link_hash_entry root; + /* Symbol index in output file. */ + long indx; + /* BFD that ext field value came from. */ + bfd *abfd; + /* ECOFF external symbol information. */ + EXTR esym; + /* Nonzero if this symbol has been written out. */ + char written; + /* Nonzero if this symbol was referred to as small undefined. */ + char small; +}; + +/* ECOFF linker hash table. */ + +struct ecoff_link_hash_table +{ + struct bfd_link_hash_table root; +}; + /* Make an ECOFF object. */ -extern boolean ecoff_mkobject PARAMS ((bfd *)); +extern boolean _bfd_ecoff_mkobject PARAMS ((bfd *)); /* Read in the ECOFF symbolic debugging information. */ -extern boolean ecoff_slurp_symbolic_info PARAMS ((bfd *)); +extern boolean _bfd_ecoff_slurp_symbolic_info + PARAMS ((bfd *, asection *, struct ecoff_debug_info *)); /* Generic ECOFF BFD backend vectors. */ -extern asymbol *ecoff_make_empty_symbol PARAMS ((bfd *abfd)); -extern unsigned int ecoff_get_symtab_upper_bound PARAMS ((bfd *abfd)); -extern unsigned int ecoff_get_symtab PARAMS ((bfd *abfd, - asymbol **alocation)); -extern void ecoff_get_symbol_info PARAMS ((bfd *abfd, - asymbol *symbol, - symbol_info *ret)); -extern void ecoff_print_symbol PARAMS ((bfd *abfd, PTR filep, - asymbol *symbol, - bfd_print_symbol_type how)); -extern unsigned int ecoff_canonicalize_reloc PARAMS ((bfd *abfd, - asection *section, - arelent **relptr, - asymbol **symbols)); -extern boolean ecoff_find_nearest_line PARAMS ((bfd *abfd, - asection *section, - asymbol **symbols, - bfd_vma offset, - CONST char **filename_ptr, - CONST char **fnname_ptr, - unsigned int *retline_ptr)); -extern boolean ecoff_bfd_seclet_link PARAMS ((bfd *abfd, PTR data, - boolean relocateable)); -extern boolean ecoff_set_arch_mach PARAMS ((bfd *abfd, - enum bfd_architecture arch, - unsigned long machine)); -extern int ecoff_sizeof_headers PARAMS ((bfd *abfd, boolean reloc)); -extern boolean ecoff_set_section_contents PARAMS ((bfd *abfd, - asection *section, - PTR location, - file_ptr offset, - bfd_size_type count)); -extern boolean ecoff_get_section_contents PARAMS ((bfd *abfd, - asection *section, - PTR location, - file_ptr offset, - bfd_size_type count)); -extern boolean ecoff_write_object_contents PARAMS ((bfd *abfd)); -extern boolean ecoff_slurp_armap PARAMS ((bfd *abfd)); -extern boolean ecoff_write_armap PARAMS ((bfd *abfd, unsigned int elength, - struct orl *map, - unsigned int orl_count, - int stridx)); -#define ecoff_slurp_extended_name_table _bfd_slurp_extended_name_table -extern bfd_target *ecoff_archive_p PARAMS ((bfd *abfd)); -#define ecoff_get_lineno \ - ((alent *(*) PARAMS ((bfd *, asymbol *))) bfd_nullvoidptr) -#define ecoff_truncate_arname bfd_dont_truncate_arname -#define ecoff_openr_next_archived_file bfd_generic_openr_next_archived_file -#define ecoff_generic_stat_arch_elt bfd_generic_stat_arch_elt -#define ecoff_get_reloc_upper_bound coff_get_reloc_upper_bound -#define ecoff_close_and_cleanup bfd_generic_close_and_cleanup -#define ecoff_bfd_debug_info_start bfd_void -#define ecoff_bfd_debug_info_end bfd_void -#define ecoff_bfd_debug_info_accumulate \ - ((void (*) PARAMS ((bfd *, struct sec *))) bfd_void) -#define ecoff_bfd_get_relocated_section_contents \ - bfd_generic_get_relocated_section_contents -#define ecoff_bfd_relax_section bfd_generic_relax_section -#define ecoff_bfd_make_debug_symbol \ - ((asymbol *(*) PARAMS ((bfd *, void *, unsigned long))) bfd_nullvoidptr) + +extern boolean _bfd_ecoff_write_object_contents PARAMS ((bfd *abfd)); +extern const bfd_target *_bfd_ecoff_archive_p PARAMS ((bfd *abfd)); + +#define _bfd_ecoff_close_and_cleanup _bfd_generic_close_and_cleanup +#define _bfd_ecoff_bfd_free_cached_info _bfd_generic_bfd_free_cached_info +extern boolean _bfd_ecoff_new_section_hook + PARAMS ((bfd *, asection *)); +extern boolean _bfd_ecoff_get_section_contents + PARAMS ((bfd *, asection *, PTR location, file_ptr, bfd_size_type)); + +extern boolean _bfd_ecoff_bfd_copy_private_bfd_data PARAMS ((bfd *, bfd *)); +#define _bfd_ecoff_bfd_copy_private_section_data \ + _bfd_generic_bfd_copy_private_section_data + +extern boolean _bfd_ecoff_slurp_armap PARAMS ((bfd *abfd)); +#define _bfd_ecoff_slurp_extended_name_table _bfd_slurp_extended_name_table +#define _bfd_ecoff_truncate_arname bfd_dont_truncate_arname +extern boolean _bfd_ecoff_write_armap + PARAMS ((bfd *, unsigned int, struct orl *, unsigned int, int)); +#define _bfd_ecoff_openr_next_archived_file \ + bfd_generic_openr_next_archived_file +#define _bfd_ecoff_generic_stat_arch_elt bfd_generic_stat_arch_elt + +extern long _bfd_ecoff_get_symtab_upper_bound PARAMS ((bfd *abfd)); +extern long _bfd_ecoff_get_symtab PARAMS ((bfd *abfd, asymbol **alocation)); +extern asymbol *_bfd_ecoff_make_empty_symbol PARAMS ((bfd *abfd)); +extern void _bfd_ecoff_print_symbol + PARAMS ((bfd *, PTR filep, asymbol *, bfd_print_symbol_type)); +extern void _bfd_ecoff_get_symbol_info + PARAMS ((bfd *, asymbol *, symbol_info *)); +#define _bfd_ecoff_bfd_is_local_label bfd_generic_is_local_label +#define _bfd_ecoff_get_lineno _bfd_nosymbols_get_lineno +extern boolean _bfd_ecoff_find_nearest_line + PARAMS ((bfd *, asection *, asymbol **, bfd_vma offset, + const char **filename_ptr, const char **fnname_ptr, + unsigned int *retline_ptr)); +#define _bfd_ecoff_bfd_make_debug_symbol _bfd_nosymbols_bfd_make_debug_symbol + +#define _bfd_ecoff_get_reloc_upper_bound coff_get_reloc_upper_bound +extern long _bfd_ecoff_canonicalize_reloc + PARAMS ((bfd *, asection *, arelent **, asymbol **symbols)); +/* ecoff_bfd_reloc_type_lookup defined by backend. */ + +extern boolean _bfd_ecoff_set_arch_mach + PARAMS ((bfd *, enum bfd_architecture, unsigned long machine)); +extern boolean _bfd_ecoff_set_section_contents + PARAMS ((bfd *, asection *, PTR location, file_ptr, bfd_size_type)); + +extern int _bfd_ecoff_sizeof_headers PARAMS ((bfd *abfd, boolean reloc)); +/* ecoff_bfd_get_relocated_section_contents defined by backend. */ +/* ecoff_bfd_relax_section defined by backend. */ +extern struct bfd_link_hash_table *_bfd_ecoff_bfd_link_hash_table_create + PARAMS ((bfd *)); +extern boolean _bfd_ecoff_bfd_link_add_symbols + PARAMS ((bfd *, struct bfd_link_info *)); +extern boolean _bfd_ecoff_bfd_final_link + PARAMS ((bfd *, struct bfd_link_info *)); /* Hook functions for the generic COFF section reading code. */ -extern PTR ecoff_mkobject_hook PARAMS ((bfd *, PTR filehdr, PTR aouthdr)); -extern asection *ecoff_make_section_hook PARAMS ((bfd *abfd, char *name)); -extern boolean ecoff_new_section_hook PARAMS ((bfd *abfd, - asection *section)); -#define ecoff_set_alignment_hook \ + +extern PTR _bfd_ecoff_mkobject_hook PARAMS ((bfd *, PTR filehdr, PTR aouthdr)); +extern asection *_bfd_ecoff_make_section_hook PARAMS ((bfd *abfd, char *name)); +#define _bfd_ecoff_set_alignment_hook \ ((void (*) PARAMS ((bfd *, asection *, PTR))) bfd_void) -extern boolean ecoff_set_arch_mach_hook PARAMS ((bfd *abfd, PTR filehdr)); -extern long ecoff_sec_to_styp_flags PARAMS ((CONST char *name, - flagword flags)); -extern flagword ecoff_styp_to_sec_flags PARAMS ((bfd *abfd, PTR hdr)); -extern boolean ecoff_slurp_symbol_table PARAMS ((bfd *abfd)); +extern boolean _bfd_ecoff_set_arch_mach_hook PARAMS ((bfd *abfd, PTR filehdr)); +extern flagword _bfd_ecoff_styp_to_sec_flags PARAMS ((bfd *abfd, PTR hdr)); +extern boolean _bfd_ecoff_slurp_symbol_table PARAMS ((bfd *abfd)); diff --git a/gnu/usr.bin/gdb/bfd/libelf.h b/gnu/usr.bin/gdb/bfd/libelf.h index 187c51a29c0b..cc6d8b81d38e 100644 --- a/gnu/usr.bin/gdb/bfd/libelf.h +++ b/gnu/usr.bin/gdb/bfd/libelf.h @@ -24,6 +24,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "elf/common.h" #include "elf/internal.h" #include "elf/external.h" +#include "bfdlink.h" /* If size isn't specified as 64 or 32, NAME macro should fail. */ #ifndef NAME @@ -42,36 +43,331 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #define ElfNAME(X) NAME(Elf,X) #define elfNAME(X) NAME(elf,X) +/* Information held for an ELF symbol. The first field is the + corresponding asymbol. Every symbol is an ELF file is actually a + pointer to this structure, although it is often handled as a + pointer to an asymbol. */ + typedef struct { + /* The BFD symbol. */ asymbol symbol; + /* ELF symbol information. */ Elf_Internal_Sym internal_elf_sym; + /* Backend specific information. */ union { unsigned int hppa_arg_reloc; + PTR mips_extr; PTR any; } tc_data; } elf_symbol_type; + +/* ELF linker hash table entries. */ + +struct elf_link_hash_entry +{ + struct bfd_link_hash_entry root; + + /* Symbol index in output file. This is initialized to -1. It is + set to -2 if the symbol is used by a reloc. */ + long indx; + + /* Symbol size. */ + bfd_size_type size; + + /* Symbol alignment (common symbols only). */ + bfd_size_type align; + + /* Symbol index as a dynamic symbol. Initialized to -1, and remains + -1 if this is not a dynamic symbol. */ + long dynindx; + + /* String table index in .dynstr if this is a dynamic symbol. */ + unsigned long dynstr_index; + + /* If this is a weak defined symbol from a dynamic object, this + field points to a defined symbol with the same value, if there is + one. Otherwise it is NULL. */ + struct elf_link_hash_entry *weakdef; + + /* Symbol type (STT_NOTYPE, STT_OBJECT, etc.). */ + char type; + + /* Some flags; legal values follow. */ + unsigned char elf_link_hash_flags; + /* Symbol is referenced by a non-shared object. */ +#define ELF_LINK_HASH_REF_REGULAR 01 + /* Symbol is defined by a non-shared object. */ +#define ELF_LINK_HASH_DEF_REGULAR 02 + /* Symbol is referenced by a shared object. */ +#define ELF_LINK_HASH_REF_DYNAMIC 04 + /* Symbol is defined by a shared object. */ +#define ELF_LINK_HASH_DEF_DYNAMIC 010 + /* Symbol is referenced by two or more shared objects. */ +#define ELF_LINK_HASH_REF_DYNAMIC_MULTIPLE 020 + /* Symbol is defined by two or more shared objects. */ +#define ELF_LINK_HASH_DEF_DYNAMIC_MULTIPLE 040 + /* Dynamic symbol has been adjustd. */ +#define ELF_LINK_HASH_DYNAMIC_ADJUSTED 0100 + /* Symbol is defined as weak. */ +#define ELF_LINK_HASH_DEFINED_WEAK 0200 +}; + +/* ELF linker hash table. */ + +struct elf_link_hash_table +{ + struct bfd_link_hash_table root; + /* The first dynamic object found during a link. We create several + special input sections when linking against dynamic objects, and + we simply attach them to the first one found. */ + bfd *dynobj; + /* The number of symbols found in the link which must be put into + the .dynsym section. */ + size_t dynsymcount; + /* The string table of dynamic symbols, which becomes the .dynstr + section. */ + struct strtab *dynstr; + /* The number of buckets in the hash table in the .hash section. + This is based on the number of dynamic symbols. */ + size_t bucketcount; +}; + +/* Look up an entry in an ELF linker hash table. */ + +#define elf_link_hash_lookup(table, string, create, copy, follow) \ + ((struct elf_link_hash_entry *) \ + bfd_link_hash_lookup (&(table)->root, (string), (create), \ + (copy), (follow))) + +/* Traverse an ELF linker hash table. */ + +#define elf_link_hash_traverse(table, func, info) \ + (bfd_link_hash_traverse \ + (&(table)->root, \ + (boolean (*) PARAMS ((struct bfd_link_hash_entry *, PTR))) (func), \ + (info))) + +/* Get the ELF linker hash table from a link_info structure. */ + +#define elf_hash_table(p) ((struct elf_link_hash_table *) ((p)->hash)) + +/* Constant information held for an ELF backend. */ struct elf_backend_data { + /* Whether the backend uses REL or RELA relocations. FIXME: some + ELF backends use both. When we need to support one, this whole + approach will need to be changed. */ int use_rela_p; + + /* Whether this backend is 64 bits or not. FIXME: Who cares? */ int elf_64_p; + + /* The architecture for this backend. */ enum bfd_architecture arch; + + /* The ELF machine code (EM_xxxx) for this backend. */ + int elf_machine_code; + + /* The maximum page size for this backend. */ + bfd_vma maxpagesize; + + /* This is true if the linker should act like collect and gather + global constructors and destructors by name. This is true for + MIPS ELF because the Irix 5 tools can not handle the .init + section. */ + boolean collect; + + /* A function to translate an ELF RELA relocation to a BFD arelent + structure. */ void (*elf_info_to_howto) PARAMS ((bfd *, arelent *, Elf_Internal_Rela *)); + + /* A function to translate an ELF REL relocation to a BFD arelent + structure. */ void (*elf_info_to_howto_rel) PARAMS ((bfd *, arelent *, Elf_Internal_Rel *)); - bfd_vma maxpagesize; - void (*write_relocs) PARAMS ((bfd *, asection *, PTR)); + /* A function to determine whether a symbol is global when + partitioning the symbol table into local and global symbols. + This should be NULL for most targets, in which case the correct + thing will be done. MIPS ELF, at least on the Irix 5, has + special requirements. */ + boolean (*elf_backend_sym_is_global) PARAMS ((bfd *, asymbol *)); + + /* The remaining functions are hooks which are called only if they + are not NULL. */ + + /* A function to permit a backend specific check on whether a + particular BFD format is relevant for an object file, and to + permit the backend to set any global information it wishes. When + this is called elf_elfheader is set, but anything else should be + used with caution. If this returns false, the check_format + routine will return a bfd_error_wrong_format error. */ + boolean (*elf_backend_object_p) PARAMS ((bfd *)); + + /* A function to do additional symbol processing when reading the + ELF symbol table. This is where any processor-specific special + section indices are handled. */ void (*elf_backend_symbol_processing) PARAMS ((bfd *, asymbol *)); - boolean (*elf_backend_symbol_table_processing) PARAMS ((bfd *, elf_symbol_type *, int)); - boolean (*elf_backend_section_processing) PARAMS ((bfd *, Elf32_Internal_Shdr *)); - boolean (*elf_backend_section_from_shdr) PARAMS ((bfd *, Elf32_Internal_Shdr *, char *)); - boolean (*elf_backend_fake_sections) PARAMS ((bfd *, Elf32_Internal_Shdr *, asection *)); - boolean (*elf_backend_section_from_bfd_section) PARAMS ((bfd *, Elf32_Internal_Shdr *, asection *, int *)); + + /* A function to do additional symbol processing after reading the + entire ELF symbol table. */ + boolean (*elf_backend_symbol_table_processing) PARAMS ((bfd *, + elf_symbol_type *, + int)); + + /* A function to do additional processing on the ELF section header + just before writing it out. This is used to set the flags and + type fields for some sections, or to actually write out data for + unusual sections. */ + boolean (*elf_backend_section_processing) PARAMS ((bfd *, + Elf32_Internal_Shdr *)); + + /* A function to handle unusual section types when creating BFD + sections from ELF sections. */ + boolean (*elf_backend_section_from_shdr) PARAMS ((bfd *, + Elf32_Internal_Shdr *, + char *)); + + /* A function to set up the ELF section header for a BFD section in + preparation for writing it out. This is where the flags and type + fields are set for unusual sections. */ + boolean (*elf_backend_fake_sections) PARAMS ((bfd *, Elf32_Internal_Shdr *, + asection *)); + + /* A function to get the ELF section index for a BFD section. If + this returns true, the section was found. If it is a normal ELF + section, *RETVAL should be left unchanged. If it is not a normal + ELF section *RETVAL should be set to the SHN_xxxx index. */ + boolean (*elf_backend_section_from_bfd_section) + PARAMS ((bfd *, Elf32_Internal_Shdr *, asection *, int *retval)); + + /* If this field is not NULL, it is called by the add_symbols phase + of a link just before adding a symbol to the global linker hash + table. It may modify any of the fields as it wishes. If *NAME + is set to NULL, the symbol will be skipped rather than being + added to the hash table. This function is responsible for + handling all processor dependent symbol bindings and section + indices, and must set at least *FLAGS and *SEC for each processor + dependent case; failure to do so will cause a link error. */ + boolean (*elf_add_symbol_hook) + PARAMS ((bfd *abfd, struct bfd_link_info *info, + const Elf_Internal_Sym *, const char **name, + flagword *flags, asection **sec, bfd_vma *value)); + + /* If this field is not NULL, it is called by the elf_link_output_sym + phase of a link for each symbol which will appear in the object file. */ + boolean (*elf_backend_link_output_symbol_hook) + PARAMS ((bfd *, struct bfd_link_info *info, const char *, + Elf_Internal_Sym *, asection *)); + + /* The CREATE_DYNAMIC_SECTIONS function is called by the ELF backend + linker the first time it encounters a dynamic object in the link. + This function must create any sections required for dynamic + linking. The ABFD argument is a dynamic object. The .interp, + .dynamic, .dynsym, .dynstr, and .hash functions have already been + created, and this function may modify the section flags if + desired. This function will normally create the .got and .plt + sections, but different backends have different requirements. */ + boolean (*elf_backend_create_dynamic_sections) + PARAMS ((bfd *abfd, struct bfd_link_info *info)); + + /* The ADJUST_DYNAMIC_SYMBOL function is called by the ELF backend + linker for every symbol which is defined by a dynamic object and + referenced by a regular object. This is called after all the + input files have been seen, but before the SIZE_DYNAMIC_SECTIONS + function has been called. The hash table entry should be + bfd_link_hash_defined, and it should be defined in a section from + a dynamic object. Dynamic object sections are not included in + the final link, and this function is responsible for changing the + value to something which the rest of the link can deal with. + This will normally involve adding an entry to the .plt or .got or + some such section, and setting the symbol to point to that. */ + boolean (*elf_backend_adjust_dynamic_symbol) + PARAMS ((struct bfd_link_info *info, struct elf_link_hash_entry *h)); + + /* The SIZE_DYNAMIC_SECTIONS function is called by the ELF backend + linker after all the linker input files have been seen but before + the sections sizes have been set. This is called after + ADJUST_DYNAMIC_SYMBOL has been called on all appropriate symbols. + It is only called when linking against a dynamic object. It must + set the sizes of the dynamic sections, and may fill in their + contents as well. The generic ELF linker can handle the .dynsym, + .dynstr and .hash sections. This function must handle the + .interp section and any sections created by the + CREATE_DYNAMIC_SECTIONS entry point. */ + boolean (*elf_backend_size_dynamic_sections) + PARAMS ((bfd *output_bfd, struct bfd_link_info *info)); + + /* The RELOCATE_SECTION function is called by the ELF backend linker + to handle the relocations for a section. + + The relocs are always passed as Rela structures; if the section + actually uses Rel structures, the r_addend field will always be + zero. + + This function is responsible for adjust the section contents as + necessary, and (if using Rela relocs and generating a + relocateable output file) adjusting the reloc addend as + necessary. + + This function does not have to worry about setting the reloc + address or the reloc symbol index. + + LOCAL_SYMS is a pointer to the swapped in local symbols. + + LOCAL_SECTIONS is an array giving the section in the input file + corresponding to the st_shndx field of each local symbol. + + The global hash table entry for the global symbols can be found + via elf_sym_hashes (input_bfd). + + When generating relocateable output, this function must handle + STB_LOCAL/STT_SECTION symbols specially. The output symbol is + going to be the section symbol corresponding to the output + section, which means that the addend must be adjusted + accordingly. */ + boolean (*elf_backend_relocate_section) + PARAMS ((bfd *output_bfd, struct bfd_link_info *info, + bfd *input_bfd, asection *input_section, bfd_byte *contents, + Elf_Internal_Rela *relocs, Elf_Internal_Sym *local_syms, + asection **local_sections, char *output_names)); + + /* The FINISH_DYNAMIC_SYMBOL function is called by the ELF backend + linker just before it writes a symbol out to the .dynsym section. + The processor backend may make any required adjustment to the + symbol. It may also take the opportunity to set contents of the + dynamic sections. Note that FINISH_DYNAMIC_SYMBOL is called on + all .dynsym symbols, while ADJUST_DYNAMIC_SYMBOL is only called + on those symbols which are defined by a dynamic object. */ + boolean (*elf_backend_finish_dynamic_symbol) + PARAMS ((bfd *output_bfd, struct bfd_link_info *info, + struct elf_link_hash_entry *h, Elf_Internal_Sym *sym)); + + /* The FINISH_DYNAMIC_SECTIONS function is called by the ELF backend + linker just before it writes all the dynamic sections out to the + output file. The FINISH_DYNAMIC_SYMBOL will have been called on + all dynamic symbols. */ + boolean (*elf_backend_finish_dynamic_sections) + PARAMS ((bfd *output_bfd, struct bfd_link_info *info)); + + /* A function to do any beginning processing needed for the ELF file + before building the ELF headers and computing file positions. */ + void (*elf_backend_begin_write_processing) + PARAMS ((bfd *, struct bfd_link_info *)); + + /* A function to do any final processing needed for the ELF file + before writing it out. */ + void (*elf_backend_final_write_processing) + PARAMS ((bfd *, struct bfd_link_info *)); + + /* The swapping table to use when dealing with ECOFF information. + Used for the MIPS ELF .mdebug section. */ + const struct ecoff_debug_swap *elf_backend_ecoff_debug_swap; }; struct elf_sym_extra @@ -81,21 +377,29 @@ struct elf_sym_extra typedef struct elf_sym_extra Elf_Sym_Extra; -struct bfd_elf_arch_map { - enum bfd_architecture bfd_arch; - int elf_arch; -}; - -extern const struct bfd_elf_arch_map bfd_elf_arch_map[]; -extern const int bfd_elf_arch_map_size; +/* Information stored for each BFD section in an ELF file. This + structure is allocated by elf_new_section_hook. */ struct bfd_elf_section_data { + /* The ELF header for this section. */ Elf_Internal_Shdr this_hdr; + /* The ELF header for the reloc section associated with this + section, if any. */ Elf_Internal_Shdr rel_hdr; - int this_idx, rel_idx; + /* The ELF section number of this section. Only used for an output + file. */ + int this_idx; + /* The ELF section number of the reloc section associated with this + section, if any. Only used for an output file. */ + int rel_idx; + /* Used by the backend linker to store the symbol hash table entries + associated with relocs against global symbols. */ + struct elf_link_hash_entry **rel_hashes; + /* A pointer to the unswapped external relocs; this may be NULL. */ + PTR relocs; }; + #define elf_section_data(sec) ((struct bfd_elf_section_data*)sec->used_by_bfd) -#define shdr_name(abfd,shdr) (elf_shstrtab (abfd)->tab + (shdr)->sh_name) #define get_elf_backend_data(abfd) \ ((struct elf_backend_data *) (abfd)->xvec->backend_data) @@ -118,20 +422,38 @@ struct elf_obj_tdata struct strtab *strtab_ptr; int num_locals; int num_globals; - Elf_Internal_Sym *internal_syms; - elf_symbol_type *symbols; /* elf_symbol_type */ Elf_Sym_Extra *sym_extra; asymbol **section_syms; /* STT_SECTION symbols for each section */ int num_section_syms; /* number of section_syms allocated */ Elf_Internal_Shdr symtab_hdr; Elf_Internal_Shdr shstrtab_hdr; Elf_Internal_Shdr strtab_hdr; - int symtab_section, shstrtab_section, strtab_section; + Elf_Internal_Shdr dynsymtab_hdr; + Elf_Internal_Shdr dynstrtab_hdr; + int symtab_section, shstrtab_section, strtab_section, dynsymtab_section; file_ptr next_file_pos; void *prstatus; /* The raw /proc prstatus structure */ void *prpsinfo; /* The raw /proc prpsinfo structure */ bfd_vma gp; /* The gp value (MIPS only, for now) */ int gp_size; /* The gp size (MIPS only, for now) */ + + /* A mapping from external symbols to entries in the linker hash + table, used when linking. This is indexed by the symbol index + minus the sh_info field of the symbol table header. */ + struct elf_link_hash_entry **sym_hashes; + + /* The linker ELF emulation code needs to let the backend ELF linker + know what filename should be used for a dynamic object if the + dynamic object is found using a search. This field is used to + hold that information. */ + const char *dt_needed_name; + + /* Irix 5 often screws up the symbol table, sorting local symbols + after global symbols. This flag is set if the symbol table in + this BFD appears to be screwed up. If it is, we ignore the + sh_info field in the symbol table header, and always read all the + symbols. */ + boolean bad_symtab; }; #define elf_tdata(bfd) ((bfd) -> tdata.elf_obj_data) @@ -139,6 +461,7 @@ struct elf_obj_tdata #define elf_elfsections(bfd) (elf_tdata(bfd) -> elf_sect_ptr) #define elf_shstrtab(bfd) (elf_tdata(bfd) -> strtab_ptr) #define elf_onesymtab(bfd) (elf_tdata(bfd) -> symtab_section) +#define elf_dynsymtab(bfd) (elf_tdata(bfd) -> dynsymtab_section) #define elf_num_locals(bfd) (elf_tdata(bfd) -> num_locals) #define elf_num_globals(bfd) (elf_tdata(bfd) -> num_globals) #define elf_sym_extra(bfd) (elf_tdata(bfd) -> sym_extra) @@ -146,11 +469,12 @@ struct elf_obj_tdata #define elf_num_section_syms(bfd) (elf_tdata(bfd) -> num_section_syms) #define core_prpsinfo(bfd) (elf_tdata(bfd) -> prpsinfo) #define core_prstatus(bfd) (elf_tdata(bfd) -> prstatus) -#define obj_symbols(bfd) (elf_tdata(bfd) -> symbols) -#define obj_internal_syms(bfd) (elf_tdata(bfd) -> internal_syms) #define elf_gp(bfd) (elf_tdata(bfd) -> gp) #define elf_gp_size(bfd) (elf_tdata(bfd) -> gp_size) - +#define elf_sym_hashes(bfd) (elf_tdata(bfd) -> sym_hashes) +#define elf_dt_needed_name(bfd) (elf_tdata(bfd) -> dt_needed_name) +#define elf_bad_symtab(bfd) (elf_tdata(bfd) -> bad_symtab) + extern char * elf_string_from_elf_section PARAMS ((bfd *, unsigned, unsigned)); extern char * elf_get_str_section PARAMS ((bfd *, unsigned)); @@ -165,15 +489,27 @@ extern bfd_reloc_status_type bfd_elf_generic_reloc PARAMS ((bfd *, asymbol *, PTR, asection *, - bfd *)); + bfd *, + char **)); extern boolean bfd_elf_mkobject PARAMS ((bfd *)); extern Elf_Internal_Shdr *bfd_elf_find_section PARAMS ((bfd *, char *)); +extern boolean _bfd_elf_make_section_from_shdr + PARAMS ((bfd *abfd, Elf_Internal_Shdr *hdr, const char *name)); +extern struct bfd_hash_entry *_bfd_elf_link_hash_newfunc + PARAMS ((struct bfd_hash_entry *, struct bfd_hash_table *, const char *)); +extern struct bfd_link_hash_table *_bfd_elf_link_hash_table_create + PARAMS ((bfd *)); +extern boolean _bfd_elf_link_hash_table_init + PARAMS ((struct elf_link_hash_table *, bfd *, + struct bfd_hash_entry *(*) (struct bfd_hash_entry *, + struct bfd_hash_table *, + const char *))); extern boolean bfd_elf32_write_object_contents PARAMS ((bfd *)); extern boolean bfd_elf64_write_object_contents PARAMS ((bfd *)); -extern bfd_target *bfd_elf32_object_p PARAMS ((bfd *)); -extern bfd_target *bfd_elf32_core_file_p PARAMS ((bfd *)); +extern const bfd_target *bfd_elf32_object_p PARAMS ((bfd *)); +extern const bfd_target *bfd_elf32_core_file_p PARAMS ((bfd *)); extern char *bfd_elf32_core_file_failing_command PARAMS ((bfd *)); extern int bfd_elf32_core_file_failing_signal PARAMS ((bfd *)); extern boolean bfd_elf32_core_file_matches_executable_p PARAMS ((bfd *, @@ -182,12 +518,13 @@ extern boolean bfd_elf32_set_section_contents PARAMS ((bfd *, sec_ptr, PTR, file_ptr, bfd_size_type)); -extern unsigned int bfd_elf32_get_symtab_upper_bound PARAMS ((bfd *)); -extern unsigned int bfd_elf32_get_symtab PARAMS ((bfd *, asymbol **)); -extern unsigned int bfd_elf32_get_reloc_upper_bound PARAMS ((bfd *, sec_ptr)); -extern unsigned int bfd_elf32_canonicalize_reloc PARAMS ((bfd *, sec_ptr, - arelent **, - asymbol **)); +extern long bfd_elf32_get_symtab_upper_bound PARAMS ((bfd *)); +extern long bfd_elf32_get_symtab PARAMS ((bfd *, asymbol **)); +extern long bfd_elf32_get_dynamic_symtab_upper_bound PARAMS ((bfd *)); +extern long bfd_elf32_canonicalize_dynamic_symtab PARAMS ((bfd *, asymbol **)); +extern long bfd_elf32_get_reloc_upper_bound PARAMS ((bfd *, sec_ptr)); +extern long bfd_elf32_canonicalize_reloc PARAMS ((bfd *, sec_ptr, + arelent **, asymbol **)); extern asymbol *bfd_elf32_make_empty_symbol PARAMS ((bfd *)); extern void bfd_elf32_print_symbol PARAMS ((bfd *, PTR, asymbol *, bfd_print_symbol_type)); @@ -204,13 +541,36 @@ extern boolean bfd_elf32_find_nearest_line PARAMS ((bfd *, asection *, extern int bfd_elf32_sizeof_headers PARAMS ((bfd *, boolean)); extern void bfd_elf32__write_relocs PARAMS ((bfd *, asection *, PTR)); extern boolean bfd_elf32_new_section_hook PARAMS ((bfd *, asection *)); +extern boolean bfd_elf32_bfd_link_add_symbols + PARAMS ((bfd *, struct bfd_link_info *)); +extern boolean bfd_elf32_bfd_final_link + PARAMS ((bfd *, struct bfd_link_info *)); + +extern void bfd_elf32_swap_symbol_in + PARAMS ((bfd *, Elf32_External_Sym *, Elf_Internal_Sym *)); +extern void bfd_elf32_swap_symbol_out + PARAMS ((bfd *, Elf_Internal_Sym *, Elf32_External_Sym *)); +extern void bfd_elf32_swap_reloc_in + PARAMS ((bfd *, Elf32_External_Rel *, Elf_Internal_Rel *)); +extern void bfd_elf32_swap_reloc_out + PARAMS ((bfd *, Elf_Internal_Rel *, Elf32_External_Rel *)); +extern void bfd_elf32_swap_reloca_in + PARAMS ((bfd *, Elf32_External_Rela *, Elf_Internal_Rela *)); +extern void bfd_elf32_swap_reloca_out + PARAMS ((bfd *, Elf_Internal_Rela *, Elf32_External_Rela *)); +extern void bfd_elf32_swap_dyn_in + PARAMS ((bfd *, const Elf32_External_Dyn *, Elf_Internal_Dyn *)); +extern void bfd_elf32_swap_dyn_out + PARAMS ((bfd *, const Elf_Internal_Dyn *, Elf32_External_Dyn *)); +extern boolean bfd_elf32_add_dynamic_entry + PARAMS ((struct bfd_link_info *, bfd_vma, bfd_vma)); /* If the target doesn't have reloc handling written yet: */ extern void bfd_elf32_no_info_to_howto PARAMS ((bfd *, arelent *, Elf32_Internal_Rela *)); -extern bfd_target *bfd_elf64_object_p PARAMS ((bfd *)); -extern bfd_target *bfd_elf64_core_file_p PARAMS ((bfd *)); +extern const bfd_target *bfd_elf64_object_p PARAMS ((bfd *)); +extern const bfd_target *bfd_elf64_core_file_p PARAMS ((bfd *)); extern char *bfd_elf64_core_file_failing_command PARAMS ((bfd *)); extern int bfd_elf64_core_file_failing_signal PARAMS ((bfd *)); extern boolean bfd_elf64_core_file_matches_executable_p PARAMS ((bfd *, @@ -219,12 +579,13 @@ extern boolean bfd_elf64_set_section_contents PARAMS ((bfd *, sec_ptr, PTR, file_ptr, bfd_size_type)); -extern unsigned int bfd_elf64_get_symtab_upper_bound PARAMS ((bfd *)); -extern unsigned int bfd_elf64_get_symtab PARAMS ((bfd *, asymbol **)); -extern unsigned int bfd_elf64_get_reloc_upper_bound PARAMS ((bfd *, sec_ptr)); -extern unsigned int bfd_elf64_canonicalize_reloc PARAMS ((bfd *, sec_ptr, - arelent **, - asymbol **)); +extern long bfd_elf64_get_symtab_upper_bound PARAMS ((bfd *)); +extern long bfd_elf64_get_symtab PARAMS ((bfd *, asymbol **)); +extern long bfd_elf64_get_dynamic_symtab_upper_bound PARAMS ((bfd *)); +extern long bfd_elf64_canonicalize_dynamic_symtab PARAMS ((bfd *, asymbol **)); +extern long bfd_elf64_get_reloc_upper_bound PARAMS ((bfd *, sec_ptr)); +extern long bfd_elf64_canonicalize_reloc PARAMS ((bfd *, sec_ptr, + arelent **, asymbol **)); extern asymbol *bfd_elf64_make_empty_symbol PARAMS ((bfd *)); extern void bfd_elf64_print_symbol PARAMS ((bfd *, PTR, asymbol *, bfd_print_symbol_type)); @@ -241,6 +602,29 @@ extern boolean bfd_elf64_find_nearest_line PARAMS ((bfd *, asection *, extern int bfd_elf64_sizeof_headers PARAMS ((bfd *, boolean)); extern void bfd_elf64__write_relocs PARAMS ((bfd *, asection *, PTR)); extern boolean bfd_elf64_new_section_hook PARAMS ((bfd *, asection *)); +extern boolean bfd_elf64_bfd_link_add_symbols + PARAMS ((bfd *, struct bfd_link_info *)); +extern boolean bfd_elf64_bfd_final_link + PARAMS ((bfd *, struct bfd_link_info *)); + +extern void bfd_elf64_swap_symbol_in + PARAMS ((bfd *, Elf64_External_Sym *, Elf_Internal_Sym *)); +extern void bfd_elf64_swap_symbol_out + PARAMS ((bfd *, Elf_Internal_Sym *, Elf64_External_Sym *)); +extern void bfd_elf64_swap_reloc_in + PARAMS ((bfd *, Elf64_External_Rel *, Elf_Internal_Rel *)); +extern void bfd_elf64_swap_reloc_out + PARAMS ((bfd *, Elf_Internal_Rel *, Elf64_External_Rel *)); +extern void bfd_elf64_swap_reloca_in + PARAMS ((bfd *, Elf64_External_Rela *, Elf_Internal_Rela *)); +extern void bfd_elf64_swap_reloca_out + PARAMS ((bfd *, Elf_Internal_Rela *, Elf64_External_Rela *)); +extern void bfd_elf64_swap_dyn_in + PARAMS ((bfd *, const Elf64_External_Dyn *, Elf_Internal_Dyn *)); +extern void bfd_elf64_swap_dyn_out + PARAMS ((bfd *, const Elf_Internal_Dyn *, Elf64_External_Dyn *)); +extern boolean bfd_elf64_add_dynamic_entry + PARAMS ((struct bfd_link_info *, bfd_vma, bfd_vma)); /* If the target doesn't have reloc handling written yet: */ extern void bfd_elf64_no_info_to_howto PARAMS ((bfd *, arelent *, diff --git a/gnu/usr.bin/gdb/bfd/opncls.c b/gnu/usr.bin/gdb/bfd/opncls.c index 42858c25919e..fb93153d29af 100644 --- a/gnu/usr.bin/gdb/bfd/opncls.c +++ b/gnu/usr.bin/gdb/bfd/opncls.c @@ -1,5 +1,5 @@ /* opncls.c -- open and close a BFD. - Copyright (C) 1990-1991 Free Software Foundation, Inc. + Copyright (C) 1990 91, 92, 93, 94 Free Software Foundation, Inc. Written by Cygnus Support. This file is part of BFD, the Binary File Descriptor library. @@ -22,29 +22,34 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "sysdep.h" #include "libbfd.h" #include "obstack.h" -extern void bfd_cache_init PARAMS ((bfd *)); -FILE *bfd_open_file PARAMS ((bfd *)); /* fdopen is a loser -- we should use stdio exclusively. Unfortunately if we do that we can't use fcntl. */ -#define obstack_chunk_alloc bfd_xmalloc_by_size_t +#define obstack_chunk_alloc malloc #define obstack_chunk_free free /* Return a new BFD. All BFD's are allocated through this routine. */ bfd * -new_bfd PARAMS ((void)) +_bfd_new_bfd () { bfd *nbfd; - nbfd = (bfd *)zalloc (sizeof (bfd)); + nbfd = (bfd *)bfd_zmalloc (sizeof (bfd)); if (!nbfd) - return 0; + { + bfd_set_error (bfd_error_no_memory); + return 0; + } bfd_check_init(); - obstack_begin((PTR)&nbfd->memory, 128); + if (!obstack_begin(&nbfd->memory, 128)) + { + bfd_set_error (bfd_error_no_memory); + return 0; + } nbfd->arch_info = &bfd_default_arch_struct; @@ -69,12 +74,12 @@ new_bfd PARAMS ((void)) /* Allocate a new BFD as a member of archive OBFD. */ bfd * -new_bfd_contained_in (obfd) +_bfd_new_bfd_contained_in (obfd) bfd *obfd; { bfd *nbfd; - nbfd = new_bfd(); + nbfd = _bfd_new_bfd(); nbfd->xvec = obfd->xvec; nbfd->my_archive = obfd; nbfd->direction = read_direction; @@ -84,7 +89,7 @@ new_bfd_contained_in (obfd) /* SECTION - Opening and Closing BFDs + Opening and closing BFDs */ @@ -93,33 +98,36 @@ FUNCTION bfd_openr SYNOPSIS - bfd *bfd_openr(CONST char *filename, CONST char*target); + bfd *bfd_openr(CONST char *filename, CONST char *target); DESCRIPTION - This function opens the file supplied (using <<fopen>>) with the target - supplied, it returns a pointer to the created BFD. + Open the file @var{filename} (using <<fopen>>) with the target + @var{target}. Return 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. + Calls <<bfd_find_target>>, so @var{target} is interpreted as by + that function. + + If <<NULL>> is returned then an error has occured. Possible errors + are <<bfd_error_no_memory>>, <<bfd_error_invalid_target>> or <<system_call>> error. */ bfd * -DEFUN(bfd_openr, (filename, target), - CONST char *filename AND - CONST char *target) +bfd_openr (filename, target) + CONST char *filename; + CONST char *target; { bfd *nbfd; - bfd_target *target_vec; + const bfd_target *target_vec; - nbfd = new_bfd(); + nbfd = _bfd_new_bfd(); if (nbfd == NULL) { - bfd_error = no_memory; + bfd_set_error (bfd_error_no_memory); return NULL; } target_vec = bfd_find_target (target, nbfd); if (target_vec == NULL) { - bfd_error = invalid_target; + bfd_set_error (bfd_error_invalid_target); return NULL; } @@ -127,7 +135,7 @@ DEFUN(bfd_openr, (filename, target), nbfd->direction = read_direction; if (bfd_open_file (nbfd) == NULL) { - bfd_error = system_call_error; /* File didn't exist, or some such */ + bfd_set_error (bfd_error_system_call); /* File didn't exist, or some such */ bfd_release(nbfd,0); return NULL; } @@ -151,36 +159,35 @@ SYNOPSIS bfd *bfd_fdopenr(CONST char *filename, CONST char *target, int fd); DESCRIPTION - bfd_fdopenr is to bfd_fopenr much like fdopen is to fopen. + <<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. - When the file is later bfd_closed, the file descriptor will be closed. + When the file is later <<bfd_close>>d, the file descriptor will be closed. If the caller desires that this file descriptor be cached by BFD (opened as needed, closed as needed to free descriptors for other opens), with the supplied @var{fd} used as an initial - file descriptor (but subject to closure at any time), set - bfd->cacheable nonzero in the returned BFD. The default is to + file descriptor (but subject to closure at any time), call + bfd_set_cacheable(bfd, 1) on the returned BFD. The default is to assume no cacheing; the file descriptor will remain open until - bfd_close, and will not be affected by BFD operations on other + <<bfd_close>>, and will not be affected by BFD operations on other files. - Possible errors are no_memory, invalid_target and system_call - error. + Possible errors are <<bfd_error_no_memory>>, <<bfd_error_invalid_target>> and <<bfd_error_system_call>>. */ bfd * -DEFUN(bfd_fdopenr,(filename, target, fd), - CONST char *filename AND - CONST char *target AND - int fd) +bfd_fdopenr (filename, target, fd) + CONST char *filename; + CONST char *target; + int fd; { bfd *nbfd; - bfd_target *target_vec; + const bfd_target *target_vec; int fdflags; - bfd_error = system_call_error; + bfd_set_error (bfd_error_system_call); #ifdef NO_FCNTL fdflags = O_RDWR; /* Assume full access */ @@ -189,16 +196,16 @@ DEFUN(bfd_fdopenr,(filename, target, fd), #endif if (fdflags == -1) return NULL; - nbfd = new_bfd(); + nbfd = _bfd_new_bfd(); if (nbfd == NULL) { - bfd_error = no_memory; + bfd_set_error (bfd_error_no_memory); return NULL; } target_vec = bfd_find_target (target, nbfd); if (target_vec == NULL) { - bfd_error = invalid_target; + bfd_set_error (bfd_error_invalid_target); return NULL; } #if defined(VMS) || defined(__GO32__) @@ -232,7 +239,8 @@ DEFUN(bfd_fdopenr,(filename, target, fd), default: abort (); } - bfd_cache_init (nbfd); + if (! bfd_cache_init (nbfd)) + return NULL; return nbfd; } @@ -250,29 +258,29 @@ SYNOPSIS bfd *bfd_openw(CONST char *filename, CONST char *target); DESCRIPTION - Creates a BFD, associated with file @var{filename}, using the - file format @var{target}, and returns a pointer to it. + Create a BFD, associated with file @var{filename}, using the + file format @var{target}, and return a pointer to it. - Possible errors are system_call_error, no_memory, - invalid_target. + Possible errors are <<bfd_error_system_call>>, <<bfd_error_no_memory>>, + <<bfd_error_invalid_target>>. */ bfd * -DEFUN(bfd_openw,(filename, target), - CONST char *filename AND - CONST char *target) +bfd_openw (filename, target) + CONST char *filename; + CONST char *target; { bfd *nbfd; - bfd_target *target_vec; + const bfd_target *target_vec; - bfd_error = system_call_error; + bfd_set_error (bfd_error_system_call); /* nbfd has to point to head of malloc'ed block so that bfd_close may reclaim it correctly. */ - nbfd = new_bfd(); + nbfd = _bfd_new_bfd(); if (nbfd == NULL) { - bfd_error = no_memory; + bfd_set_error (bfd_error_no_memory); return NULL; } @@ -283,7 +291,7 @@ DEFUN(bfd_openw,(filename, target), nbfd->direction = write_direction; if (bfd_open_file (nbfd) == NULL) { - bfd_error = system_call_error; /* File not writeable, etc */ + bfd_set_error (bfd_error_system_call); /* File not writeable, etc */ (void) obstack_free (&nbfd->memory, (PTR)0); return NULL; } @@ -296,11 +304,11 @@ FUNCTION bfd_close SYNOPSIS - boolean bfd_close(bfd *); + boolean bfd_close(bfd *abfd); DESCRIPTION - This function closes a BFD. If the BFD was open for writing, + Close 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 <<chmod>> is called to mark it as such. @@ -308,7 +316,7 @@ DESCRIPTION All memory attached to the BFD's obstacks is released. The file descriptor associated with the BFD is closed (even - if it was passed in to BFD by bfd_fdopenr). + if it was passed in to BFD by <<bfd_fdopenr>>). RETURNS <<true>> is returned if all is ok, otherwise <<false>>. @@ -316,8 +324,8 @@ RETURNS boolean -DEFUN(bfd_close,(abfd), - bfd *abfd) +bfd_close (abfd) + bfd *abfd; { boolean ret; @@ -361,7 +369,7 @@ SYNOPSIS boolean bfd_close_all_done(bfd *); DESCRIPTION - This function closes a BFD. It differs from <<bfd_close>> + Close a BFD. Differs from <<bfd_close>> since it does not complete any pending operations. This routine would be used if the application had just used BFD for swapping and didn't want to use any of the writing code. @@ -377,8 +385,8 @@ RETURNS */ boolean -DEFUN(bfd_close_all_done,(abfd), - bfd *abfd) +bfd_close_all_done (abfd) + bfd *abfd; { boolean ret; @@ -417,14 +425,13 @@ SYNOPSIS bfd_size_type bfd_alloc_size(bfd *abfd); DESCRIPTION - Return the number of bytes in the obstacks connected to the - supplied BFD. + Return the number of bytes in the obstacks connected to @var{abfd}. */ bfd_size_type -DEFUN(bfd_alloc_size,(abfd), - bfd *abfd) +bfd_alloc_size (abfd) + bfd *abfd; { struct _obstack_chunk *chunk = abfd->memory.chunk; size_t size = 0; @@ -445,7 +452,7 @@ SYNOPSIS bfd *bfd_create(CONST char *filename, bfd *templ); DESCRIPTION - This routine creates a new BFD in the manner of + Create 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 <<bfd_object>>. @@ -453,13 +460,13 @@ DESCRIPTION */ bfd * -DEFUN(bfd_create,(filename, templ), - CONST char *filename AND - bfd *templ) +bfd_create (filename, templ) + CONST char *filename; + bfd *templ; { - bfd *nbfd = new_bfd(); + bfd *nbfd = _bfd_new_bfd(); if (nbfd == (bfd *)NULL) { - bfd_error = no_memory; + bfd_set_error (bfd_error_no_memory); return (bfd *)NULL; } nbfd->filename = filename; @@ -479,56 +486,63 @@ SYNOPSIS PTR bfd_alloc_by_size_t(bfd *abfd, size_t wanted); DESCRIPTION - This function allocates a block of memory in the obstack - attatched to <<abfd>> and returns a pointer to it. + Allocate a block of @var{wanted} bytes of memory in the obstack + attatched to <<abfd>> and return a pointer to it. */ PTR -DEFUN(bfd_alloc_by_size_t,(abfd, size), - bfd *abfd AND - size_t size) +bfd_alloc_by_size_t (abfd, size) + bfd *abfd; + size_t size; { - PTR res = obstack_alloc(&(abfd->memory), size); - return res; + return obstack_alloc(&(abfd->memory), size); } -DEFUN(void bfd_alloc_grow,(abfd, ptr, size), - bfd *abfd AND - PTR ptr AND - size_t size) +void +bfd_alloc_grow (abfd, ptr, size) + bfd *abfd; + PTR ptr; + size_t size; { (void) obstack_grow(&(abfd->memory), ptr, size); } -DEFUN(PTR bfd_alloc_finish,(abfd), - bfd *abfd) + +PTR +bfd_alloc_finish (abfd) + bfd *abfd; { return obstack_finish(&(abfd->memory)); } -DEFUN(PTR bfd_alloc, (abfd, size), - bfd *abfd AND - size_t size) +PTR +bfd_alloc (abfd, size) + bfd *abfd; + size_t size; { return bfd_alloc_by_size_t(abfd, (size_t)size); } -DEFUN(PTR bfd_zalloc,(abfd, size), - bfd *abfd AND - size_t size) +PTR +bfd_zalloc (abfd, size) + bfd *abfd; + size_t size; { PTR res; res = bfd_alloc(abfd, size); - memset(res, 0, (size_t)size); + if (res) + memset(res, 0, (size_t)size); return res; } -DEFUN(PTR bfd_realloc,(abfd, old, size), - bfd *abfd AND - PTR old AND - size_t size) +PTR +bfd_realloc (abfd, old, size) + bfd *abfd; + PTR old; + size_t size; { PTR res = bfd_alloc(abfd, size); - memcpy(res, old, (size_t)size); + if (res) + memcpy(res, old, (size_t)size); return res; } diff --git a/gnu/usr.bin/gdb/bfd/reloc.c b/gnu/usr.bin/gdb/bfd/reloc.c index f2dd5201d44b..9c65be945d5b 100644 --- a/gnu/usr.bin/gdb/bfd/reloc.c +++ b/gnu/usr.bin/gdb/bfd/reloc.c @@ -22,18 +22,18 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ SECTION Relocations - BFD maintains relocations in much the same was as it maintains - symbols; they are left alone until required, then read in - en-mass and traslated into an internal form. There is a common - routine <<bfd_perform_relocation>> which acts upon the - canonical form to do the actual fixup. + BFD maintains relocations in much the same way it maintains + symbols: they are left alone until required, then read in + en-mass and translated into an internal form. A common + routine <<bfd_perform_relocation>> acts upon the + canonical form to do the fixup. - Note that relocations are maintained on a per section basis, - whilst symbols are maintained on a per BFD basis. + Relocations are maintained on a per section basis, + while symbols are maintained on a per BFD basis. - All a back end has to do to fit the BFD interface is to create - as many <<struct reloc_cache_entry>> as there are relocations - in a particular section, and fill in the right bits: + All that a back end has to do to fit the BFD interface is to create + a <<struct reloc_cache_entry>> for each relocation + in a particular section, and fill in the right bits of the structures. @menu @* typedef arelent:: @@ -43,8 +43,8 @@ SECTION */ #include "bfd.h" #include "sysdep.h" +#include "bfdlink.h" #include "libbfd.h" -#include "seclet.h" /* DOCDD INODE @@ -57,7 +57,7 @@ SUBSECTION CODE_FRAGMENT . -.typedef enum bfd_reloc_status +.typedef enum bfd_reloc_status .{ . {* No errors detected *} . bfd_reloc_ok, @@ -71,10 +71,10 @@ CODE_FRAGMENT . {* Used by special functions *} . bfd_reloc_continue, . -. {* Unused *} +. {* Unsupported relocation size requested. *} . bfd_reloc_notsupported, . -. {* Unsupported relocation size requested. *} +. {* Unused *} . bfd_reloc_other, . . {* The symbol to relocate against was undefined. *} @@ -82,13 +82,14 @@ CODE_FRAGMENT . . {* The relocation was performed, but may not be ok - presently . generated only when linking i960 coff files with i960 b.out -. symbols. *} +. symbols. If this type is returned, the error_message argument +. to bfd_perform_relocation will be set. *} . bfd_reloc_dangerous . } . bfd_reloc_status_type; . . -.typedef struct reloc_cache_entry +.typedef struct reloc_cache_entry .{ . {* A pointer into the canonical table of pointers *} . struct symbol_cache_entry **sym_ptr_ptr; @@ -97,10 +98,10 @@ CODE_FRAGMENT . bfd_size_type address; . . {* addend for relocation value *} -. bfd_vma addend; +. bfd_vma addend; . . {* Pointer to how to perform the required relocation *} -. CONST struct reloc_howto_struct *howto; +. const struct reloc_howto_struct *howto; . .} arelent; @@ -109,14 +110,14 @@ CODE_FRAGMENT /* DESCRIPTION - Here is a description of each of the fields within a relent: + Here is a description of each of the fields within an <<arelent>>: - o sym_ptr_ptr + o <<sym_ptr_ptr>> The symbol table pointer points to a pointer to the symbol - associated with the relocation request. This would naturally - be the pointer into the table returned by the back end's - get_symtab action. @xref{Symbols}. The symbol is referenced + associated with the relocation request. It is + the pointer into the table returned by the back end's + <<get_symtab>> action. @xref{Symbols}. The symbol is referenced through a pointer to a pointer so that tools like the linker can fix up all the symbols of the same name by modifying only one pointer. The relocation routine looks in the symbol and @@ -124,19 +125,19 @@ DESCRIPTION value of the symbol as the initial relocation offset. If the symbol pointer is zero, then the section provided is looked up. - o address + o <<address>> - The address field gives the offset in bytes from the base of + The <<address>> field gives the offset in bytes from the base of the section data which owns the relocation record to the first byte of relocatable information. The actual data relocated - will be relative to this point - for example, a relocation + will be relative to this point; for example, a relocation type which modifies the bottom two bytes of a four byte word would not touch the first byte pointed to in a big endian world. - o addend + o <<addend>> - The addend is a value provided by the back end to be added (!) + The <<addend>> is a value provided by the back end to be added (!) to the relocation offset. Its interpretation is dependent upon the howto. For example, on the 68k the code: @@ -156,12 +157,12 @@ DESCRIPTION | rts - This could create a reloc pointing to foo, but leave the - offset in the data (something like) + This could create a reloc pointing to <<foo>>, but leave the + offset in the data, something like: |RELOCATION RECORDS FOR [.text]: -|offset type value +|offset type value |00000006 32 _foo | |00000000 4e56 fffc ; linkw fp,#-4 @@ -181,32 +182,32 @@ DESCRIPTION | jmp r1 - This should create two relocs, both pointing to _foo, and with + This should create two relocs, both pointing to <<_foo>>, and with 0x12340000 in their addend field. The data would consist of: |RELOCATION RECORDS FOR [.text]: -|offset type value +|offset type value |00000002 HVRT16 _foo+0x12340000 |00000006 LVRT16 _foo+0x12340000 - +| |00000000 5da05678 ; or.u r13,r0,0x5678 |00000004 1c4d5678 ; ld.b r2,r13,0x5678 |00000008 f400c001 ; jmp r1 The relocation routine digs out the value from the data, adds - it to the addend to get the original offset and then adds the - value of _foo. Note that all 32 bits have to be kept around + it to the addend to get the original offset, and then adds the + value of <<_foo>>. Note that all 32 bits have to be kept around somewhere, to cope with carry from bit 15 to bit 16. One further example is the sparc and the a.out format. The sparc has a similar problem to the 88k, in that some instructions don't have room for an entire offset, but on the - sparc the parts are created odd sized lumps. The designers of - the a.out format chose not to use the data within the section + sparc the parts are created in odd sized lumps. The designers of + the a.out format chose to not use the data within the section for storing part of the offset; all the offset is kept within - the reloc. Any thing in the data should be ignored. + the reloc. Anything in the data should be ignored. | save %sp,-112,%sp | sethi %hi(_foo+0x12345678),%g2 @@ -214,15 +215,15 @@ DESCRIPTION | ret | restore - Both relocs contains a pointer to foo, and the offsets would + Both relocs contain a pointer to <<foo>>, and the offsets contain junk. |RELOCATION RECORDS FOR [.text]: -|offset type value +|offset type value |00000004 HI22 _foo+0x12345678 |00000008 LO10 _foo+0x12345678 - +| |00000000 9de3bf90 ; save %sp,-112,%sp |00000004 05000000 ; sethi %hi(_foo+0),%g2 |00000008 f048a000 ; ldsb [%g2+%lo(_foo+0)],%i0 @@ -230,16 +231,16 @@ DESCRIPTION |00000010 81e80000 ; restore - o howto + o <<howto>> - The howto field can be imagined as a - relocation instruction. It is a pointer to a struct which - contains information on what to do with all the other + The <<howto>> field can be imagined as a + relocation instruction. It is a pointer to a structure which + contains information on what to do with all of the other information in the reloc record and data section. A back end would normally have a relocation instruction set and turn relocations into pointers to the correct structure on input - but it would be possible to create each howto field on demand. - + */ /* @@ -272,22 +273,25 @@ CODE_FRAGMENT */ /* -SUBSUBSECTION +SUBSUBSECTION <<reloc_howto_type>> The <<reloc_howto_type>> is a structure which contains all the - information that BFD needs to know to tie up a back end's data. + information that libbfd needs to know to tie up a back end's data. CODE_FRAGMENT .struct symbol_cache_entry; {* Forward declaration *} . -.typedef CONST struct reloc_howto_struct -.{ +.typedef unsigned char bfd_byte; +.typedef struct reloc_howto_struct reloc_howto_type; +. +.struct reloc_howto_struct +.{ . {* The type field has mainly a documetary use - the back end can -. to what it wants with it, though the normally the back end's -. external idea of what a reloc number would be would be stored -. in this field. For example, the a PC relative word relocation -. in a coff environment would have the type 023 - because that's +. do what it wants with it, though normally the back end's +. external idea of what a reloc number is stored +. in this field. For example, a PC relative word relocation +. in a coff environment has the type 023 - because that's . what the outside world calls a R_PCRWORD reloc. *} . unsigned int type; . @@ -296,16 +300,8 @@ CODE_FRAGMENT . unsigned int rightshift; . . {* The size of the item to be relocated. This is *not* a -. power-of-two measure. -. 0 : one byte -. 1 : two bytes -. 2 : four bytes -. 3 : nothing done (unless special_function is nonzero) -. 4 : eight bytes -. -2 : two bytes, result should be subtracted from the -. data instead of added -. There is currently no trivial way to extract a "number of -. bytes" from a howto pointer. *} +. power-of-two measure. To get the number of bytes operated +. on by a type of relocation, use bfd_get_reloc_size. *} . int size; . . {* The number of bits in the item to be relocated. This is used @@ -330,13 +326,14 @@ CODE_FRAGMENT . called rather than the normal function. This allows really . strange relocation methods to be accomodated (e.g., i960 callj . instructions). *} -. bfd_reloc_status_type (*special_function) +. bfd_reloc_status_type (*special_function) . PARAMS ((bfd *abfd, . arelent *reloc_entry, . struct symbol_cache_entry *symbol, . PTR data, -. asection *input_section, -. bfd *output_bfd)); +. asection *input_section, +. bfd *output_bfd, +. char **error_message)); . . {* The textual name of the relocation type. *} . char *name; @@ -345,7 +342,7 @@ CODE_FRAGMENT . relocations rather than the data - this flag signals this.*} . boolean partial_inplace; . -. {* The src_mask is used to select what parts of the read in data +. {* The src_mask selects which parts of the read in data . are to be used in the relocation sum. E.g., if this was an 8 bit . bit of data which we read and relocated, this would be . 0x000000ff. When we have relocs which have an addend, such as @@ -354,27 +351,27 @@ CODE_FRAGMENT . the mask would be 0x00000000. *} . bfd_vma src_mask; . -. {* The dst_mask is what parts of the instruction are replaced +. {* The dst_mask selects which parts of the instruction are replaced . into the instruction. In most cases src_mask == dst_mask, . except in the above special case, where dst_mask would be . 0x000000ff, and src_mask would be 0x00000000. *} -. bfd_vma dst_mask; +. bfd_vma dst_mask; . . {* When some formats create PC relative instructions, they leave . the value of the pc of the place being relocated in the offset . slot of the instruction, so that a PC relative relocation can . be made just by adding in an ordinary offset (e.g., sun3 a.out). . Some formats leave the displacement part of an instruction -. empty (e.g., m88k bcs), this flag signals the fact.*} +. empty (e.g., m88k bcs); this flag signals the fact.*} . boolean pcrel_offset; . -.} reloc_howto_type; +.}; */ /* FUNCTION - the HOWTO macro + The HOWTO Macro DESCRIPTION The HOWTO define is horrible and will go away. @@ -385,7 +382,7 @@ DESCRIPTION DESCRIPTION And will be replaced with the totally magic way. But for the - moment, we are compatible, so do it this way.. + moment, we are compatible, so do it this way. .#define NEWHOWTO( FUNCTION, NAME,SIZE,REL,IN) HOWTO(0,0,SIZE,0,REL,0,complain_overflow_dont,FUNCTION, NAME,false,0,0,IN) @@ -403,20 +400,46 @@ DESCRIPTION . relocation = symbol->value; \ . } \ . } \ -.} +.} */ /* +FUNCTION + bfd_get_reloc_size + +SYNOPSIS + int bfd_get_reloc_size (const reloc_howto_type *); + +DESCRIPTION + For a reloc_howto_type that operates on a fixed number of bytes, + this returns the number of bytes operated on. + */ + +int +bfd_get_reloc_size (howto) + const reloc_howto_type *howto; +{ + switch (howto->size) + { + case 0: return 1; + case 1: return 2; + case 2: return 4; + case 3: return 0; + case 4: return 8; + case -2: return 4; + default: abort (); + } +} + +/* TYPEDEF - reloc_chain + arelent_chain DESCRIPTION - How relocs are tied together + How relocs are tied together in an <<asection>>: -.typedef unsigned char bfd_byte; -. .typedef struct relent_chain { . arelent relent; . struct relent_chain *next; @@ -427,59 +450,59 @@ DESCRIPTION /* -FUNCTION +FUNCTION bfd_perform_relocation SYNOPSIS bfd_reloc_status_type bfd_perform_relocation - (bfd * abfd, - arelent *reloc_entry, - PTR data, - asection *input_section, - bfd *output_bfd); + (bfd *abfd, + arelent *reloc_entry, + PTR data, + asection *input_section, + bfd *output_bfd, + char **error_message); DESCRIPTION - 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 (e.g., 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. + If @var{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 (e.g., 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. + The @var{error_message} argument is set to an error message if + this return @code{bfd_reloc_dangerous}. */ bfd_reloc_status_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_perform_relocation (abfd, reloc_entry, data, input_section, output_bfd, + error_message) + bfd *abfd; + arelent *reloc_entry; + PTR data; + asection *input_section; + bfd *output_bfd; + char **error_message; { bfd_vma relocation; bfd_reloc_status_type flag = bfd_reloc_ok; - bfd_size_type addr = reloc_entry->address ; + bfd_size_type addr = reloc_entry->address; bfd_vma output_base = 0; - reloc_howto_type *howto = reloc_entry->howto; - asection *reloc_target_output_section ; - + const reloc_howto_type *howto = reloc_entry->howto; + asection *reloc_target_output_section; asymbol *symbol; - symbol = *( reloc_entry->sym_ptr_ptr); - if ((symbol->section == &bfd_abs_section) - && output_bfd != (bfd *)NULL) + symbol = *(reloc_entry->sym_ptr_ptr); + if (bfd_is_abs_section (symbol->section) + && output_bfd != (bfd *) NULL) { reloc_entry->address += input_section->output_offset; return bfd_reloc_ok; @@ -488,7 +511,7 @@ DEFUN(bfd_perform_relocation,(abfd, /* If we are not producing relocateable output, return an error if the symbol is not defined. An undefined weak symbol is considered to have a value of zero (SVR4 ABI, p. 4-27). */ - if (symbol->section == &bfd_und_section + if (bfd_is_und_section (symbol->section) && (symbol->flags & BSF_WEAK) == 0 && output_bfd == (bfd *) NULL) flag = bfd_reloc_undefined; @@ -500,7 +523,8 @@ DEFUN(bfd_perform_relocation,(abfd, { bfd_reloc_status_type cont; cont = howto->special_function (abfd, reloc_entry, symbol, data, - input_section, output_bfd); + input_section, output_bfd, + error_message); if (cont != bfd_reloc_continue) return cont; } @@ -522,7 +546,7 @@ DEFUN(bfd_perform_relocation,(abfd, reloc_target_output_section = symbol->section->output_section; /* Convert input-section-relative symbol value to absolute. */ - if (output_bfd && howto->partial_inplace==false) + if (output_bfd && howto->partial_inplace == false) output_base = 0; else output_base = reloc_target_output_section->vma; @@ -565,28 +589,28 @@ DEFUN(bfd_perform_relocation,(abfd, actually does. I don't want to change it, because it seems far too likely that something will break. */ - relocation -= + relocation -= input_section->output_section->vma + input_section->output_offset; if (howto->pcrel_offset == true) relocation -= reloc_entry->address; } - if (output_bfd!= (bfd *)NULL) + if (output_bfd != (bfd *) NULL) { - if ( howto->partial_inplace == false) + 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->address += input_section->output_offset; + 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 record a bit. If we've relocated with a symbol with a section, change into a ref to the section belonging to the symbol. */ @@ -594,9 +618,83 @@ DEFUN(bfd_perform_relocation,(abfd, reloc_entry->address += input_section->output_offset; /* WTF?? */ - if (abfd->xvec->flavour == bfd_target_coff_flavour) + if (abfd->xvec->flavour == bfd_target_coff_flavour + && strcmp (abfd->xvec->name, "aixcoff-rs6000") != 0 + && strcmp (abfd->xvec->name, "coff-Intel-little") != 0 + && strcmp (abfd->xvec->name, "coff-Intel-big") != 0) { +#if 1 + /* For m68k-coff, the addend was being subtracted twice during + relocation with -r. Removing the line below this comment + fixes that problem; see PR 2953. + +However, Ian wrote the following, regarding removing the line below, +which explains why it is still enabled: --djm + +If you put a patch like that into BFD you need to check all the COFF +linkers. I am fairly certain that patch will break coff-i386 (e.g., +SCO); see coff_i386_reloc in coff-i386.c where I worked around the +problem in a different way. There may very well be a reason that the +code works as it does. + +Hmmm. The first obvious point is that bfd_perform_relocation should +not have any tests that depend upon the flavour. It's seem like +entirely the wrong place for such a thing. The second obvious point +is that the current code ignores the reloc addend when producing +relocateable output for COFF. That's peculiar. In fact, I really +have no idea what the point of the line you want to remove is. + +A typical COFF reloc subtracts the old value of the symbol and adds in +the new value to the location in the object file (if it's a pc +relative reloc it adds the difference between the symbol value and the +location). When relocating we need to preserve that property. + +BFD handles this by setting the addend to the negative of the old +value of the symbol. Unfortunately it handles common symbols in a +non-standard way (it doesn't subtract the old value) but that's a +different story (we can't change it without losing backward +compatibility with old object files) (coff-i386 does subtract the old +value, to be compatible with existing coff-i386 targets, like SCO). + +So everything works fine when not producing relocateable output. When +we are producing relocateable output, logically we should do exactly +what we do when not producing relocateable output. Therefore, your +patch is correct. In fact, it should probably always just set +reloc_entry->addend to 0 for all cases, since it is, in fact, going to +add the value into the object file. This won't hurt the COFF code, +which doesn't use the addend; I'm not sure what it will do to other +formats (the thing to check for would be whether any formats both use +the addend and set partial_inplace). + +When I wanted to make coff-i386 produce relocateable output, I ran +into the problem that you are running into: I wanted to remove that +line. Rather than risk it, I made the coff-i386 relocs use a special +function; it's coff_i386_reloc in coff-i386.c. The function +specifically adds the addend field into the object file, knowing that +bfd_perform_relocation is not going to. If you remove that line, then +coff-i386.c will wind up adding the addend field in twice. It's +trivial to fix; it just needs to be done. + +The problem with removing the line is just that it may break some +working code. With BFD it's hard to be sure of anything. The right +way to deal with this is simply to build and test at least all the +supported COFF targets. It should be straightforward if time and disk +space consuming. For each target: + 1) build the linker + 2) generate some executable, and link it using -r (I would + probably use paranoia.o and link against newlib/libc.a, which + for all the supported targets would be available in + /usr/cygnus/progressive/H-host/target/lib/libc.a). + 3) make the change to reloc.c + 4) rebuild the linker + 5) repeat step 2 + 6) if the resulting object files are the same, you have at least + made it no worse + 7) if they are different you have to figure out which version is + right +*/ relocation -= reloc_entry->addend; +#endif reloc_entry->addend = 0; } else @@ -605,7 +703,7 @@ DEFUN(bfd_perform_relocation,(abfd, } } } - else + else { reloc_entry->addend = 0; } @@ -633,14 +731,14 @@ DEFUN(bfd_perform_relocation,(abfd, { /* Assumes two's complement. */ bfd_signed_vma reloc_signed_max = (1 << (howto->bitsize - 1)) - 1; - bfd_signed_vma reloc_signed_min = ~ reloc_signed_max; + bfd_signed_vma reloc_signed_min = ~reloc_signed_max; /* The above right shift is incorrect for a signed value. Fix it up by forcing on the upper bits. */ if (howto->rightshift > howto->bitpos && (bfd_signed_vma) relocation < 0) - check |= ((bfd_vma) -1 - &~ ((bfd_vma) -1 + check |= ((bfd_vma) - 1 + & ~((bfd_vma) - 1 >> (howto->rightshift - howto->bitpos))); if ((bfd_signed_vma) check > reloc_signed_max || (bfd_signed_vma) check < reloc_signed_min) @@ -653,7 +751,7 @@ DEFUN(bfd_perform_relocation,(abfd, overflow if howto->bitsize is the number of bits in bfd_vma. */ bfd_vma reloc_unsigned_max = - (((1 << (howto->bitsize - 1)) - 1) << 1) | 1; + (((1 << (howto->bitsize - 1)) - 1) << 1) | 1; if ((bfd_vma) check > reloc_unsigned_max) flag = bfd_reloc_overflow; @@ -666,8 +764,8 @@ DEFUN(bfd_perform_relocation,(abfd, bfd_vma. */ bfd_vma reloc_bits = (((1 << (howto->bitsize - 1)) - 1) << 1) | 1; - if (((bfd_vma) check &~ reloc_bits) != 0 - && ((bfd_vma) check &~ reloc_bits) != (-1 &~ reloc_bits)) + if (((bfd_vma) check & ~reloc_bits) != 0 + && ((bfd_vma) check & ~reloc_bits) != (-1 & ~reloc_bits)) { /* The above right shift is incorrect for a signed value. See if turning on the upper bits fixes the @@ -675,10 +773,10 @@ DEFUN(bfd_perform_relocation,(abfd, if (howto->rightshift > howto->bitpos && (bfd_signed_vma) relocation < 0) { - check |= ((bfd_vma) -1 - &~ ((bfd_vma) -1 + check |= ((bfd_vma) - 1 + & ~((bfd_vma) - 1 >> (howto->rightshift - howto->bitpos))); - if (((bfd_vma) check &~ reloc_bits) != (-1 &~ reloc_bits)) + if (((bfd_vma) check & ~reloc_bits) != (-1 & ~reloc_bits)) flag = bfd_reloc_overflow; } else @@ -690,17 +788,41 @@ DEFUN(bfd_perform_relocation,(abfd, abort (); } } - - /* + + /* 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; + + /* The cast to bfd_vma avoids a bug in the Alpha OSF/1 C compiler + (OSF version 1.3, compiler version 3.11). It miscompiles the + following program: + + struct str + { + unsigned int i0; + } s = { 0 }; + + int + main () + { + unsigned long x; + + x = 0x100000000; + x <<= (unsigned long) s.i0; + if (x == 0) + printf ("failed\n"); + else + printf ("succeeded (%lx)\n", x); + } + */ + + relocation >>= (bfd_vma) howto->rightshift; /* Shift everything up to where it's going to be used */ - - relocation <<= howto->bitpos; + + relocation <<= (bfd_vma) howto->bitpos; /* Wait for the day when all have the mask in them */ @@ -714,23 +836,23 @@ DEFUN(bfd_perform_relocation,(abfd, 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 + 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 + + 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> */ @@ -738,65 +860,319 @@ DEFUN(bfd_perform_relocation,(abfd, #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: - if (relocation) - { - short x = bfd_get_16(abfd, (bfd_byte *)data + addr); - DOIT(x); - bfd_put_16(abfd, x, (unsigned char *)data + addr); - } - break; - case 2: - if (relocation) - { - long x = bfd_get_32 (abfd, (bfd_byte *) data + addr); - DOIT (x); - bfd_put_32 (abfd, x, (bfd_byte *)data + addr); - } - break; - case -2: - { - long x = bfd_get_32(abfd, (bfd_byte *) data + addr); - relocation = -relocation; - DOIT(x); - bfd_put_32(abfd,x, (bfd_byte *)data + addr); - } - break; - - case 3: - /* Do nothing */ - break; - - case 4: + 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: + if (relocation) + { + short x = bfd_get_16 (abfd, (bfd_byte *) data + addr); + DOIT (x); + bfd_put_16 (abfd, x, (unsigned char *) data + addr); + } + break; + case 2: + if (relocation) + { + long x = bfd_get_32 (abfd, (bfd_byte *) data + addr); + DOIT (x); + bfd_put_32 (abfd, x, (bfd_byte *) data + addr); + } + break; + case -2: + { + long x = bfd_get_32 (abfd, (bfd_byte *) data + addr); + relocation = -relocation; + DOIT (x); + bfd_put_32 (abfd, x, (bfd_byte *) data + addr); + } + break; + + case 3: + /* Do nothing */ + break; + + case 4: #ifdef BFD64 - if (relocation) - { - bfd_vma x = bfd_get_64 (abfd, (bfd_byte *) data + addr); - DOIT (x); - bfd_put_64 (abfd, x, (bfd_byte *) data + addr); - } + if (relocation) + { + bfd_vma x = bfd_get_64 (abfd, (bfd_byte *) data + addr); + DOIT (x); + bfd_put_64 (abfd, x, (bfd_byte *) data + addr); + } #else - abort (); + abort (); #endif - break; - default: - return bfd_reloc_other; - } + break; + default: + return bfd_reloc_other; + } return flag; } +/* This relocation routine is used by some of the backend linkers. + They do not construct asymbol or arelent structures, so there is no + reason for them to use bfd_perform_relocation. Also, + bfd_perform_relocation is so hacked up it is easier to write a new + function than to try to deal with it. + + This routine does a final relocation. It should not be used when + generating relocateable output. + + FIXME: This routine ignores any special_function in the HOWTO, + since the existing special_function values have been written for + bfd_perform_relocation. + + HOWTO is the reloc howto information. + INPUT_BFD is the BFD which the reloc applies to. + INPUT_SECTION is the section which the reloc applies to. + CONTENTS is the contents of the section. + ADDRESS is the address of the reloc within INPUT_SECTION. + VALUE is the value of the symbol the reloc refers to. + ADDEND is the addend of the reloc. */ + +bfd_reloc_status_type +_bfd_final_link_relocate (howto, input_bfd, input_section, contents, address, + value, addend) + const reloc_howto_type *howto; + bfd *input_bfd; + asection *input_section; + bfd_byte *contents; + bfd_vma address; + bfd_vma value; + bfd_vma addend; +{ + bfd_vma relocation; + + /* Sanity check the address. */ + if (address > input_section->_cooked_size) + return bfd_reloc_outofrange; + /* This function assumes that we are dealing with a basic relocation + against a symbol. We want to compute the value of the symbol to + relocate to. This is just VALUE, the value of the symbol, plus + ADDEND, any addend associated with the reloc. */ + relocation = value + addend; + + /* If the relocation is PC relative, we want to set RELOCATION to + the distance between the symbol (currently in RELOCATION) and the + location we are relocating. Some targets (e.g., i386-aout) + arrange for the contents of the section to be the negative of the + offset of the location within the section; for such targets + pcrel_offset is false. Other targets (e.g., m88kbcs or ELF) + simply leave the contents of the section as zero; for such + targets pcrel_offset is true. If pcrel_offset is false we do not + need to subtract out the offset of the location within the + section (which is just ADDRESS). */ + if (howto->pc_relative) + { + relocation -= (input_section->output_section->vma + + input_section->output_offset); + if (howto->pcrel_offset) + relocation -= address; + } + + return _bfd_relocate_contents (howto, input_bfd, relocation, + contents + address); +} + +/* Relocate a given location using a given value and howto. */ + +bfd_reloc_status_type +_bfd_relocate_contents (howto, input_bfd, relocation, location) + const reloc_howto_type *howto; + bfd *input_bfd; + bfd_vma relocation; + bfd_byte *location; +{ + int size; + bfd_vma x; + boolean overflow; + + /* If the size is negative, negate RELOCATION. This isn't very + general. */ + if (howto->size < 0) + relocation = -relocation; + + /* Get the value we are going to relocate. */ + size = bfd_get_reloc_size (howto); + switch (size) + { + default: + case 0: + abort (); + case 1: + x = bfd_get_8 (input_bfd, location); + break; + case 2: + x = bfd_get_16 (input_bfd, location); + break; + case 4: + x = bfd_get_32 (input_bfd, location); + break; + case 8: +#ifdef BFD64 + x = bfd_get_64 (input_bfd, location); +#else + abort (); +#endif + break; + } + + /* Check for overflow. FIXME: We may drop bits during the addition + which we don't check for. We must either check at every single + operation, which would be tedious, or we must do the computations + in a type larger than bfd_vma, which would be inefficient. */ + overflow = false; + if (howto->complain_on_overflow != complain_overflow_dont) + { + bfd_vma check; + bfd_signed_vma signed_check; + bfd_vma add; + bfd_signed_vma signed_add; + + if (howto->rightshift == 0) + { + check = relocation; + signed_check = (bfd_signed_vma) relocation; + } + else + { + /* Drop unwanted bits from the value we are relocating to. */ + check = relocation >> howto->rightshift; + + /* If this is a signed value, the rightshift just dropped + leading 1 bits (assuming twos complement). */ + if ((bfd_signed_vma) relocation >= 0) + signed_check = check; + else + signed_check = (check + | ((bfd_vma) - 1 + & ~((bfd_vma) - 1 >> howto->rightshift))); + } + + /* Get the value from the object file. */ + add = x & howto->src_mask; + + /* Get the value from the object file with an appropriate sign. + The expression involving howto->src_mask isolates the upper + bit of src_mask. If that bit is set in the value we are + adding, it is negative, and we subtract out that number times + two. If src_mask includes the highest possible bit, then we + can not get the upper bit, but that does not matter since + signed_add needs no adjustment to become negative in that + case. */ + signed_add = add; + if ((add & (((~howto->src_mask) >> 1) & howto->src_mask)) != 0) + signed_add -= (((~howto->src_mask) >> 1) & howto->src_mask) << 1; + + /* Add the value from the object file, shifted so that it is a + straight number. */ + if (howto->bitpos == 0) + { + check += add; + signed_check += signed_add; + } + else + { + check += add >> howto->bitpos; + + /* For the signed case we use ADD, rather than SIGNED_ADD, + to avoid warnings from SVR4 cc. This is OK since we + explictly handle the sign bits. */ + if (signed_add >= 0) + signed_check += add >> howto->bitpos; + else + signed_check += ((add >> howto->bitpos) + | ((bfd_vma) - 1 + & ~((bfd_vma) - 1 >> howto->bitpos))); + } + + switch (howto->complain_on_overflow) + { + case complain_overflow_signed: + { + /* Assumes two's complement. */ + bfd_signed_vma reloc_signed_max = (1 << (howto->bitsize - 1)) - 1; + bfd_signed_vma reloc_signed_min = ~reloc_signed_max; + + if (signed_check > reloc_signed_max + || signed_check < reloc_signed_min) + overflow = true; + } + break; + case complain_overflow_unsigned: + { + /* Assumes two's complement. This expression avoids + overflow if howto->bitsize is the number of bits in + bfd_vma. */ + bfd_vma reloc_unsigned_max = + (((1 << (howto->bitsize - 1)) - 1) << 1) | 1; + + if (check > reloc_unsigned_max) + overflow = true; + } + break; + case complain_overflow_bitfield: + { + /* Assumes two's complement. This expression avoids + overflow if howto->bitsize is the number of bits in + bfd_vma. */ + bfd_vma reloc_bits = (((1 << (howto->bitsize - 1)) - 1) << 1) | 1; + + if ((check & ~reloc_bits) != 0 + && (((bfd_vma) signed_check & ~reloc_bits) + != (-1 & ~reloc_bits))) + overflow = true; + } + break; + default: + abort (); + } + } + + /* Put RELOCATION in the right bits. */ + relocation >>= (bfd_vma) howto->rightshift; + relocation <<= (bfd_vma) howto->bitpos; + + /* Add RELOCATION to the right bits of X. */ + x = ((x & ~howto->dst_mask) + | (((x & howto->src_mask) + relocation) & howto->dst_mask)); + + /* Put the relocated value back in the object file. */ + switch (size) + { + default: + case 0: + abort (); + case 1: + bfd_put_8 (input_bfd, x, location); + break; + case 2: + bfd_put_16 (input_bfd, x, location); + break; + case 4: + bfd_put_32 (input_bfd, x, location); + break; + case 8: +#ifdef BFD64 + bfd_put_64 (input_bfd, x, location); +#else + abort (); +#endif + break; + } + + return overflow ? bfd_reloc_overflow : bfd_reloc_ok; +} /* DOCDD @@ -804,7 +1180,7 @@ INODE howto manager, , typedef arelent, Relocations SECTION - The howto manager + The howto manager When an application wants to create a relocation, but doesn't know what the target machine might call it, it can find out by @@ -828,12 +1204,14 @@ DESCRIPTION CODE_FRAGMENT . -.typedef enum bfd_reloc_code_real +.typedef enum bfd_reloc_code_real .{ . {* Basic absolute relocations *} . BFD_RELOC_64, . BFD_RELOC_32, -. BFD_RELOC_16, +. BFD_RELOC_26, +. BFD_RELOC_16, +. BFD_RELOC_14, . BFD_RELOC_8, . . {* PC-relative relocations *} @@ -858,6 +1236,10 @@ CODE_FRAGMENT . {* 32-bit pc-relative, shifted right 2 bits (i.e., 30-bit . word displacement, e.g. for SPARC) *} . BFD_RELOC_32_PCREL_S2, +. {* signed 16-bit pc-relative, shifted right 2 bits (e.g. for MIPS) *} +. BFD_RELOC_16_PCREL_S2, +. {* this is used on the Alpha *} +. BFD_RELOC_23_PCREL_S2, . . {* High 22 bits of 32-bit value, placed into lower 22 bits of . target word; simple reloc. *} @@ -865,6 +1247,13 @@ CODE_FRAGMENT . {* Low 10 bits. *} . BFD_RELOC_LO10, . +. {* For systems that allocate a Global Pointer register, these are +. displacements off that register. These relocation types are +. handled specially, because the value the register will have is +. decided relatively late. *} +. BFD_RELOC_GPREL16, +. BFD_RELOC_GPREL32, +. . {* Reloc types used for i960/b.out. *} . BFD_RELOC_I960_CALLJ, . @@ -889,14 +1278,67 @@ CODE_FRAGMENT . BFD_RELOC_SPARC_BASE13, . BFD_RELOC_SPARC_BASE22, . +. {* some relocations we're using for sparc v9 +. -- subject to change *} +. BFD_RELOC_SPARC_10, +. BFD_RELOC_SPARC_11, +.#define BFD_RELOC_SPARC_64 BFD_RELOC_64 +. BFD_RELOC_SPARC_OLO10, +. BFD_RELOC_SPARC_HH22, +. BFD_RELOC_SPARC_HM10, +. BFD_RELOC_SPARC_LM22, +. BFD_RELOC_SPARC_PC_HH22, +. BFD_RELOC_SPARC_PC_HM10, +. BFD_RELOC_SPARC_PC_LM22, +. BFD_RELOC_SPARC_WDISP16, +. BFD_RELOC_SPARC_WDISP19, +. BFD_RELOC_SPARC_GLOB_JMP, +. BFD_RELOC_SPARC_LO7, +. +. {* Alpha ECOFF relocations. Some of these treat the symbol or "addend" +. in some special way. *} +. {* For GPDISP_HI16 ("gpdisp") relocations, the symbol is ignored when +. writing; when reading, it will be the absolute section symbol. The +. addend is the displacement in bytes of the "lda" instruction from +. the "ldah" instruction (which is at the address of this reloc). *} +. BFD_RELOC_ALPHA_GPDISP_HI16, +. {* For GPDISP_LO16 ("ignore") relocations, the symbol is handled as +. with GPDISP_HI16 relocs. The addend is ignored when writing the +. relocations out, and is filled in with the file's GP value on +. reading, for convenience. *} +. BFD_RELOC_ALPHA_GPDISP_LO16, +. +. {* The Alpha LITERAL/LITUSE relocs are produced by a symbol reference; +. the assembler turns it into a LDQ instruction to load the address of +. the symbol, and then fills in a register in the real instruction. +. +. The LITERAL reloc, at the LDQ instruction, refers to the .lita +. section symbol. The addend is ignored when writing, but is filled +. in with the file's GP value on reading, for convenience, as with the +. GPDISP_LO16 reloc. +. +. The LITUSE reloc, on the instruction using the loaded address, gives +. information to the linker that it might be able to use to optimize +. away some literal section references. The symbol is ignored (read +. as the absolute section symbol), and the "addend" indicates the type +. of instruction using the register: +. 1 - "memory" fmt insn +. 2 - byte-manipulation (byte offset reg) +. 3 - jsr (target of branch) +. +. The GNU linker currently doesn't do any of this optimizing. *} +. BFD_RELOC_ALPHA_LITERAL, +. BFD_RELOC_ALPHA_LITUSE, +. +. {* The HINT relocation indicates a value that should be filled into the +. "hint" field of a jmp/jsr/ret instruction, for possible branch- +. prediction logic which may be provided on some processors. *} +. BFD_RELOC_ALPHA_HINT, . . {* Bits 27..2 of the relocation address shifted right 2 bits; . simple reloc otherwise. *} . BFD_RELOC_MIPS_JMP, . -. {* signed 16-bit pc-relative, shifted right 2 bits (e.g. for MIPS) *} -. BFD_RELOC_16_PCREL_S2, -. . {* High 16 bits of 32-bit value; simple reloc. *} . BFD_RELOC_HI16, . {* High 16 bits of 32-bit value but the low 16 bits will be sign @@ -906,106 +1348,21 @@ CODE_FRAGMENT . BFD_RELOC_HI16_S, . {* Low 16 bits. *} . BFD_RELOC_LO16, +. {* Like BFD_RELOC_HI16_S, but PC relative. *} +. BFD_RELOC_PCREL_HI16_S, +. {* Like BFD_RELOC_LO16, but PC relative. *} +. BFD_RELOC_PCREL_LO16, . -. {* 16 bit relocation relative to the global pointer. *} -. BFD_RELOC_MIPS_GPREL, -. -. {* These are, so far, specific to HPPA processors. I'm not sure that some -. don't duplicate other reloc types, such as BFD_RELOC_32 and _32_PCREL. -. Also, many more were in the list I got that don't fit in well in the -. model BFD uses, so I've omitted them for now. If we do make this reloc -. type get used for code that really does implement the funky reloc types, -. they'll have to be added to this list. *} -. BFD_RELOC_HPPA_32, -. BFD_RELOC_HPPA_11, -. BFD_RELOC_HPPA_14, -. BFD_RELOC_HPPA_17, -. -. BFD_RELOC_HPPA_L21, -. BFD_RELOC_HPPA_R11, -. BFD_RELOC_HPPA_R14, -. BFD_RELOC_HPPA_R17, -. BFD_RELOC_HPPA_LS21, -. BFD_RELOC_HPPA_RS11, -. BFD_RELOC_HPPA_RS14, -. BFD_RELOC_HPPA_RS17, -. BFD_RELOC_HPPA_LD21, -. BFD_RELOC_HPPA_RD11, -. BFD_RELOC_HPPA_RD14, -. BFD_RELOC_HPPA_RD17, -. BFD_RELOC_HPPA_LR21, -. BFD_RELOC_HPPA_RR14, -. BFD_RELOC_HPPA_RR17, -. -. BFD_RELOC_HPPA_GOTOFF_11, -. BFD_RELOC_HPPA_GOTOFF_14, -. BFD_RELOC_HPPA_GOTOFF_L21, -. BFD_RELOC_HPPA_GOTOFF_R11, -. BFD_RELOC_HPPA_GOTOFF_R14, -. BFD_RELOC_HPPA_GOTOFF_LS21, -. BFD_RELOC_HPPA_GOTOFF_RS11, -. BFD_RELOC_HPPA_GOTOFF_RS14, -. BFD_RELOC_HPPA_GOTOFF_LD21, -. BFD_RELOC_HPPA_GOTOFF_RD11, -. BFD_RELOC_HPPA_GOTOFF_RD14, -. BFD_RELOC_HPPA_GOTOFF_LR21, -. BFD_RELOC_HPPA_GOTOFF_RR14, -. -. BFD_RELOC_HPPA_DLT_32, -. BFD_RELOC_HPPA_DLT_11, -. BFD_RELOC_HPPA_DLT_14, -. BFD_RELOC_HPPA_DLT_L21, -. BFD_RELOC_HPPA_DLT_R11, -. BFD_RELOC_HPPA_DLT_R14, -. -. BFD_RELOC_HPPA_ABS_CALL_11, -. BFD_RELOC_HPPA_ABS_CALL_14, -. BFD_RELOC_HPPA_ABS_CALL_17, -. BFD_RELOC_HPPA_ABS_CALL_L21, -. BFD_RELOC_HPPA_ABS_CALL_R11, -. BFD_RELOC_HPPA_ABS_CALL_R14, -. BFD_RELOC_HPPA_ABS_CALL_R17, -. BFD_RELOC_HPPA_ABS_CALL_LS21, -. BFD_RELOC_HPPA_ABS_CALL_RS11, -. BFD_RELOC_HPPA_ABS_CALL_RS14, -. BFD_RELOC_HPPA_ABS_CALL_RS17, -. BFD_RELOC_HPPA_ABS_CALL_LD21, -. BFD_RELOC_HPPA_ABS_CALL_RD11, -. BFD_RELOC_HPPA_ABS_CALL_RD14, -. BFD_RELOC_HPPA_ABS_CALL_RD17, -. BFD_RELOC_HPPA_ABS_CALL_LR21, -. BFD_RELOC_HPPA_ABS_CALL_RR14, -. BFD_RELOC_HPPA_ABS_CALL_RR17, +. {* relocation relative to the global pointer. *} +.#define BFD_RELOC_MIPS_GPREL BFD_RELOC_GPREL16 . -. BFD_RELOC_HPPA_PCREL_CALL_11, -. BFD_RELOC_HPPA_PCREL_CALL_12, -. BFD_RELOC_HPPA_PCREL_CALL_14, -. BFD_RELOC_HPPA_PCREL_CALL_17, -. BFD_RELOC_HPPA_PCREL_CALL_L21, -. BFD_RELOC_HPPA_PCREL_CALL_R11, -. BFD_RELOC_HPPA_PCREL_CALL_R14, -. BFD_RELOC_HPPA_PCREL_CALL_R17, -. BFD_RELOC_HPPA_PCREL_CALL_LS21, -. BFD_RELOC_HPPA_PCREL_CALL_RS11, -. BFD_RELOC_HPPA_PCREL_CALL_RS14, -. BFD_RELOC_HPPA_PCREL_CALL_RS17, -. BFD_RELOC_HPPA_PCREL_CALL_LD21, -. BFD_RELOC_HPPA_PCREL_CALL_RD11, -. BFD_RELOC_HPPA_PCREL_CALL_RD14, -. BFD_RELOC_HPPA_PCREL_CALL_RD17, -. BFD_RELOC_HPPA_PCREL_CALL_LR21, -. BFD_RELOC_HPPA_PCREL_CALL_RR14, -. BFD_RELOC_HPPA_PCREL_CALL_RR17, +. {* Relocation against a MIPS literal section. *} +. BFD_RELOC_MIPS_LITERAL, . -. BFD_RELOC_HPPA_PLABEL_32, -. BFD_RELOC_HPPA_PLABEL_11, -. BFD_RELOC_HPPA_PLABEL_14, -. BFD_RELOC_HPPA_PLABEL_L21, -. BFD_RELOC_HPPA_PLABEL_R11, -. BFD_RELOC_HPPA_PLABEL_R14, -. -. BFD_RELOC_HPPA_UNWIND_ENTRY, -. BFD_RELOC_HPPA_UNWIND_ENTRIES, +. {* MIPS ELF relocations. *} +. BFD_RELOC_MIPS_GOT16, +. BFD_RELOC_MIPS_CALL16, +.#define BFD_RELOC_MIPS_GPREL32 BFD_RELOC_GPREL32 . . {* i386/elf relocations *} . BFD_RELOC_386_GOT32, @@ -1017,6 +1374,29 @@ CODE_FRAGMENT . BFD_RELOC_386_GOTOFF, . BFD_RELOC_386_GOTPC, . +. {* ns32k relocations *} +. BFD_RELOC_NS32K_IMM_8, +. BFD_RELOC_NS32K_IMM_16, +. BFD_RELOC_NS32K_IMM_32, +. BFD_RELOC_NS32K_IMM_8_PCREL, +. BFD_RELOC_NS32K_IMM_16_PCREL, +. BFD_RELOC_NS32K_IMM_32_PCREL, +. BFD_RELOC_NS32K_DISP_8, +. BFD_RELOC_NS32K_DISP_16, +. BFD_RELOC_NS32K_DISP_32, +. BFD_RELOC_NS32K_DISP_8_PCREL, +. BFD_RELOC_NS32K_DISP_16_PCREL, +. BFD_RELOC_NS32K_DISP_32_PCREL, +. +. {* PowerPC/POWER (RS/6000) relocs. *} +. {* 26 bit relative branch. Low two bits must be zero. High 24 +. bits installed in bits 6 through 29 of instruction. *} +. BFD_RELOC_PPC_B26, +. {* 26 bit absolute branch, like BFD_RELOC_PPC_B26 but absolute. *} +. BFD_RELOC_PPC_BA26, +. {* 16 bit TOC relative reference. *} +. BFD_RELOC_PPC_TOC16, +. . {* this must be the highest numeric value *} . BFD_RELOC_UNUSED . } bfd_reloc_code_real_type; @@ -1024,31 +1404,31 @@ CODE_FRAGMENT /* -SECTION +FUNCTION bfd_reloc_type_lookup SYNOPSIS - CONST struct reloc_howto_struct * + const struct reloc_howto_struct * bfd_reloc_type_lookup (bfd *abfd, bfd_reloc_code_real_type code); DESCRIPTION - This routine returns a pointer to a howto struct which when - invoked, will perform the supplied relocation on data from the + Return a pointer to a howto structure which, when + invoked, will perform the relocation @var{code} on data from the architecture noted. */ -CONST struct reloc_howto_struct * -DEFUN(bfd_reloc_type_lookup,(abfd, code), - bfd *abfd AND - bfd_reloc_code_real_type code) +const struct reloc_howto_struct * +bfd_reloc_type_lookup (abfd, code) + bfd *abfd; + bfd_reloc_code_real_type code; { return BFD_SEND (abfd, reloc_type_lookup, (abfd, code)); } static reloc_howto_type bfd_howto_32 = - HOWTO(0, 00,2,32,false,0,complain_overflow_bitfield,0,"VRT32", false,0xffffffff,0xffffffff,true); +HOWTO (0, 00, 2, 32, false, 0, complain_overflow_bitfield, 0, "VRT32", false, 0xffffffff, 0xffffffff, true); /* @@ -1056,9 +1436,8 @@ INTERNAL_FUNCTION bfd_default_reloc_type_lookup SYNOPSIS - CONST struct reloc_howto_struct *bfd_default_reloc_type_lookup - (bfd *abfd AND - bfd_reloc_code_real_type code); + const struct reloc_howto_struct *bfd_default_reloc_type_lookup + (bfd *abfd, bfd_reloc_code_real_type code); DESCRIPTION Provides a default relocation lookup routine for any architecture. @@ -1066,30 +1445,31 @@ DESCRIPTION */ -CONST struct reloc_howto_struct * -DEFUN(bfd_default_reloc_type_lookup, (abfd, code), - bfd *abfd AND - bfd_reloc_code_real_type code) +const struct reloc_howto_struct * +bfd_default_reloc_type_lookup (abfd, code) + bfd *abfd; + bfd_reloc_code_real_type code; { - switch (code) + switch (code) { case BFD_RELOC_CTOR: /* The type of reloc used in a ctor, which will be as wide as the address - so either a 64, 32, or 16 bitter. */ - switch (bfd_get_arch_info (abfd)->bits_per_address) { - case 64: - BFD_FAIL(); - case 32: - return &bfd_howto_32; - case 16: - BFD_FAIL(); - default: - BFD_FAIL(); - } + switch (bfd_get_arch_info (abfd)->bits_per_address) + { + case 64: + BFD_FAIL (); + case 32: + return &bfd_howto_32; + case 16: + BFD_FAIL (); + default: + BFD_FAIL (); + } default: - BFD_FAIL(); + BFD_FAIL (); } - return (CONST struct reloc_howto_struct *)NULL; + return (const struct reloc_howto_struct *) NULL; } @@ -1101,25 +1481,26 @@ SYNOPSIS boolean bfd_generic_relax_section (bfd *abfd, asection *section, - asymbol **symbols); + struct bfd_link_info *, + boolean *); DESCRIPTION Provides default handling for relaxing for back ends which don't do relaxing -- i.e., does nothing. */ +/*ARGSUSED*/ boolean -DEFUN(bfd_generic_relax_section,(abfd, section, symbols), - bfd *abfd AND - asection *section AND - asymbol **symbols) +bfd_generic_relax_section (abfd, section, link_info, again) + bfd *abfd; + asection *section; + struct bfd_link_info *link_info; + boolean *again; { - - return false; - + *again = false; + return true; } - /* INTERNAL_FUNCTION bfd_generic_get_relocated_section_contents @@ -1127,9 +1508,11 @@ INTERNAL_FUNCTION SYNOPSIS bfd_byte * bfd_generic_get_relocated_section_contents (bfd *abfd, - struct bfd_seclet *seclet, + struct bfd_link_info *link_info, + struct bfd_link_order *link_order, bfd_byte *data, - boolean relocateable); + boolean relocateable, + asymbol **symbols); DESCRIPTION Provides default handling of relocation effort for back ends @@ -1138,88 +1521,115 @@ DESCRIPTION */ bfd_byte * -DEFUN(bfd_generic_get_relocated_section_contents,(abfd, - seclet, - data, - relocateable), - bfd *abfd AND - struct bfd_seclet *seclet AND - bfd_byte *data AND - boolean relocateable) +bfd_generic_get_relocated_section_contents (abfd, link_info, link_order, data, + relocateable, symbols) + bfd *abfd; + struct bfd_link_info *link_info; + struct bfd_link_order *link_order; + bfd_byte *data; + boolean relocateable; + asymbol **symbols; { - extern bfd_error_vector_type bfd_error_vector; - /* Get enough memory to hold the stuff */ - bfd *input_bfd = seclet->u.indirect.section->owner; - asection *input_section = seclet->u.indirect.section; + bfd *input_bfd = link_order->u.indirect.section->owner; + asection *input_section = link_order->u.indirect.section; + + long reloc_size = bfd_get_reloc_upper_bound (input_bfd, input_section); + arelent **reloc_vector = NULL; + long reloc_count; + if (reloc_size < 0) + goto error_return; + reloc_vector = (arelent **) malloc (reloc_size); + if (reloc_vector == NULL && reloc_size != 0) + { + bfd_set_error (bfd_error_no_memory); + goto error_return; + } - size_t reloc_size = bfd_get_reloc_upper_bound(input_bfd, input_section); - arelent **reloc_vector = (arelent **) alloca(reloc_size); - /* read in the section */ - bfd_get_section_contents(input_bfd, - input_section, - data, - 0, - input_section->_raw_size); - -/* We're not relaxing the section, so just copy the size info */ + if (!bfd_get_section_contents (input_bfd, + input_section, + (PTR) data, + 0, + input_section->_raw_size)) + goto error_return; + + /* We're not relaxing the section, so just copy the size info */ input_section->_cooked_size = input_section->_raw_size; input_section->reloc_done = true; - - - if (bfd_canonicalize_reloc(input_bfd, - input_section, - reloc_vector, - seclet->u.indirect.symbols) ) - { - arelent **parent; - for (parent = reloc_vector; * parent != (arelent *)NULL; - parent++) - { - bfd_reloc_status_type r= - bfd_perform_relocation(input_bfd, - *parent, - data, - input_section, - relocateable ? abfd : (bfd *) NULL); - - if (relocateable) - { - asection *os = input_section->output_section; - /* A partial link, so keep the relocs */ - os->orelocation[os->reloc_count] = *parent; - os->reloc_count++; - } + reloc_count = bfd_canonicalize_reloc (input_bfd, + input_section, + reloc_vector, + symbols); + if (reloc_count < 0) + goto error_return; - if (r != bfd_reloc_ok) - { - switch (r) + if (reloc_count > 0) + { + arelent **parent; + for (parent = reloc_vector; *parent != (arelent *) NULL; + parent++) { - case bfd_reloc_undefined: - bfd_error_vector.undefined_symbol(*parent, seclet); - break; - case bfd_reloc_dangerous: - bfd_error_vector.reloc_dangerous(*parent, seclet); - break; - case bfd_reloc_outofrange: - case bfd_reloc_overflow: - bfd_error_vector.reloc_value_truncated(*parent, seclet); - break; - default: - abort(); - break; - } + char *error_message = (char *) NULL; + bfd_reloc_status_type r = + bfd_perform_relocation (input_bfd, + *parent, + (PTR) data, + input_section, + relocateable ? abfd : (bfd *) NULL, + &error_message); + + if (relocateable) + { + asection *os = input_section->output_section; - } - } - } + /* A partial link, so keep the relocs */ + os->orelocation[os->reloc_count] = *parent; + os->reloc_count++; + } + if (r != bfd_reloc_ok) + { + switch (r) + { + case bfd_reloc_undefined: + if (!((*link_info->callbacks->undefined_symbol) + (link_info, bfd_asymbol_name (*(*parent)->sym_ptr_ptr), + input_bfd, input_section, (*parent)->address))) + goto error_return; + break; + case bfd_reloc_dangerous: + BFD_ASSERT (error_message != (char *) NULL); + if (!((*link_info->callbacks->reloc_dangerous) + (link_info, error_message, input_bfd, input_section, + (*parent)->address))) + goto error_return; + break; + case bfd_reloc_overflow: + if (!((*link_info->callbacks->reloc_overflow) + (link_info, bfd_asymbol_name (*(*parent)->sym_ptr_ptr), + (*parent)->howto->name, (*parent)->addend, + input_bfd, input_section, (*parent)->address))) + goto error_return; + break; + case bfd_reloc_outofrange: + default: + abort (); + break; + } + } + } + } + if (reloc_vector != NULL) + free (reloc_vector); return data; - +error_return: + if (reloc_vector != NULL) + free (reloc_vector); + return NULL; } diff --git a/gnu/usr.bin/gdb/bfd/section.c b/gnu/usr.bin/gdb/bfd/section.c index 547c69e2cb84..bfee4b90743e 100644 --- a/gnu/usr.bin/gdb/bfd/section.c +++ b/gnu/usr.bin/gdb/bfd/section.c @@ -22,13 +22,13 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ SECTION Sections - Sections are supported in BFD in <<section.c>>. - The raw data contained within a BFD is maintained through the section abstraction. A single BFD may have any number of - sections, and keeps hold of them by pointing to the first, + sections. It keeps hold of them by pointing to the first; each one points to the next in the list. + Sections are supported in BFD in <<section.c>>. + @menu @* Section Input:: @* Section Output:: @@ -39,31 +39,31 @@ SECTION INODE Section Input, Section Output, Sections, Sections SUBSECTION - Section Input + Section input When a BFD is opened for reading, the section structures are created and attached to the BFD. Each section has a name which describes the section in the - outside world - for example, <<a.out>> would contain at least - three sections, called <<.text>>, <<.data>> and <<.bss>>. + outside world---for example, <<a.out>> would contain at least + three sections, called <<.text>>, <<.data>> and <<.bss>>. Names need not be unique; for example a COFF file may have several - sections named .data. + sections named <<.data>>. - Sometimes a BFD will contain more than the 'natural' number of + Sometimes a BFD will contain more than the ``natural'' number of sections. A back end may attach other sections containing constructor data, or an application may add a section (using - bfd_make_section) to the sections attached to an already open - BFD. For example, the linker creates a supernumary section + <<bfd_make_section>>) to the sections attached to an already open + BFD. For example, the linker creates an extra section <<COMMON>> for each input file's BFD to hold information about common storage. - The raw data is not necessarily read in at the same time as + The raw data is not necessarily read in when the section descriptor is created. Some targets may leave the data in place until a <<bfd_get_section_contents>> call is - made. Other back ends may read in all the data at once - For - example; an S-record file has to be read once to determine the + made. Other back ends may read in all the data at once. For + example, an S-record file has to be read once to determine the size of the data. An IEEE-695 file doesn't contain raw data in sections, but data and relocation expressions intermixed, so the data area has to be parsed to get out the data and @@ -73,31 +73,32 @@ INODE Section Output, typedef asection, Section Input, Sections SUBSECTION - Section Output + Section output To write a new object style BFD, the various sections to be written have to be created. They are attached to the BFD in - the same way as input sections, data is written to the - sections using <<bfd_set_section_contents>>. + the same way as input sections; data is written to the + sections using <<bfd_set_section_contents>>. Any program that creates or combines sections (e.g., the assembler - and linker) must use the fields <<output_section>> and + and linker) must use the <<asection>> fields <<output_section>> and <<output_offset>> to indicate the file sections to which each section must be written. (If the section is being created from scratch, <<output_section>> should probably point to the section - itself, and <<output_offset>> should probably be zero.) + itself and <<output_offset>> should probably be zero.) - The data to be written comes from input sections attached to + The data to be written comes from input sections attached + (via <<output_section>> pointers) to the output sections. The output section structure can be - considered a filter for the input section, the output section + considered a filter for the input section: the output section determines the vma of the output data and the name, but the input section determines the offset into the output section of the data to be written. E.g., to create a section "O", starting at 0x100, 0x123 long, - containing two subsections, "A" at offset 0x0 (ie at vma - 0x100) and "B" at offset 0x20 (ie at vma 0x120) the structures - would look like: + containing two subsections, "A" at offset 0x0 (i.e., at vma + 0x100) and "B" at offset 0x20 (i.e., at vma 0x120) the <<asection>> + structures would look like: | section name "A" | output_offset 0x00 @@ -111,23 +112,23 @@ SUBSECTION SUBSECTION - Seglets + Link orders - The data within a section is stored in a <<seglet>>. These - are much like the fixups in <<gas>>. The seglet abstraction - allows the a section to grow and shrink within itself. + The data within a section is stored in a @dfn{link_order}. + These are much like the fixups in <<gas>>. The link_order + abstraction allows a section to grow and shrink within itself. - A seglet knows how big it is, and which is the next seglet and - where the raw data for it is, and also points to a list of - relocations which apply to it. + A link_order knows how big it is, and which is the next + link_order and where the raw data for it is; it also points to + a list of relocations which apply to it. - The seglet is used by the linker to perform relaxing on final - code. The application creates code which is as big as + The link_order is used by the linker to perform relaxing on + final code. The compiler creates code which is as big as necessary to make it work without relaxing, and the user can select whether to relax. Sometimes relaxing takes a lot of time. The linker runs around the relocations to see if any are attached to data which can be shrunk, if so it does it on - a seglet by seglet basis. + a link_order by link_order basis. */ @@ -144,44 +145,44 @@ typedef asection, section prototypes, Section Output, Sections SUBSECTION typedef asection - The shape of a section struct: + Here is the section structure: CODE_FRAGMENT . -.typedef struct sec +.typedef struct sec .{ -. {* The name of the section, the name isn't a copy, the pointer is +. {* The name of the section; the name isn't a copy, the pointer is . the same as that passed to bfd_make_section. *} . . CONST char *name; . -. {* Which section is it 0.nth *} +. {* Which section is it; 0..nth. *} . -. int index; +. int index; . . {* The next section in the list belonging to the BFD, or NULL. *} . . struct sec *next; . -. {* The field flags contains attributes of the section. Some of +. {* The field flags contains attributes of the section. Some . flags are read in from the object file, and some are -. synthesized from other information. *} +. synthesized from other information. *} . . flagword flags; . .#define SEC_NO_FLAGS 0x000 . -. {* Tells the OS to allocate space for this section when loaded. -. This would clear for a section containing debug information +. {* Tells the OS to allocate space for this section when loading. +. This is clear for a section containing debug information . only. *} .#define SEC_ALLOC 0x001 -. +. . {* Tells the OS to load the section from the file when loading. -. This would be clear for a .bss section *} +. This is clear for a .bss section. *} .#define SEC_LOAD 0x002 . -. {* The section contains data still to be relocated, so there will -. be some relocation information too. *} +. {* The section contains data still to be relocated, so there is +. some relocation information too. *} .#define SEC_RELOC 0x004 . .#if 0 {* Obsolete ? *} @@ -205,10 +206,10 @@ CODE_FRAGMENT . type is used by the linker to create lists of constructors and . destructors used by <<g++>>. When a back end sees a symbol . which should be used in a constructor list, it creates a new -. section for the type of name (eg <<__CTOR_LIST__>>), attaches -. the symbol to it and builds a relocation. To build the lists +. section for the type of name (e.g., <<__CTOR_LIST__>>), attaches +. the symbol to it, and builds a relocation. To build the lists . of constructors, all the linker has to do is catenate all the -. sections called <<__CTOR_LIST__>> and relocte the data +. sections called <<__CTOR_LIST__>> and relocate the data . contained within - exactly the operations it would peform on . standard data. *} .#define SEC_CONSTRUCTOR 0x100 @@ -220,25 +221,30 @@ CODE_FRAGMENT .#define SEC_CONSTRUCTOR_BSS 0x3100 . . {* The section has contents - a data section could be -. <<SEC_ALLOC>> | <<SEC_HAS_CONTENTS>>, a debug section could be +. <<SEC_ALLOC>> | <<SEC_HAS_CONTENTS>>; a debug section could be . <<SEC_HAS_CONTENTS>> *} .#define SEC_HAS_CONTENTS 0x200 . -. {* An instruction to the linker not to output sections -. containing this flag even if they have information which -. would normally be written. *} +. {* An instruction to the linker to not output the section +. even if it has information which would normally be written. *} .#define SEC_NEVER_LOAD 0x400 . -. {* The section is a shared library section. The linker must leave -. these completely alone, as the vma and size are used when -. the executable is loaded. *} -.#define SEC_SHARED_LIBRARY 0x800 +. {* The section is a COFF shared library section. This flag is +. only for the linker. If this type of section appears in +. the input file, the linker must copy it to the output file +. without changing the vma or size. FIXME: Although this +. was originally intended to be general, it really is COFF +. specific (and the flag was renamed to indicate this). It +. might be cleaner to have some more general mechanism to +. allow the back end to control what the linker does with +. sections. *} +.#define SEC_COFF_SHARED_LIBRARY 0x800 . . {* The section is a common section (symbols may be defined . multiple times, the value of a symbol is the amount of . space it requires, and the largest symbol value is the one . used). Most targets have exactly one of these (which we -. translate to bfd_com_section), but ECOFF has two. *} +. translate to bfd_com_section_ptr), but ECOFF has two. *} .#define SEC_IS_COMMON 0x8000 . . {* The section contains only debugging information. For @@ -247,6 +253,12 @@ CODE_FRAGMENT . discarded. *} .#define SEC_DEBUGGING 0x10000 . +. {* The contents of this section are held in memory pointed to +. by the contents field. This is checked by +. bfd_get_section_contents, and the data is retrieved from +. memory if appropriate. *} +.#define SEC_IN_MEMORY 0x20000 +. . {* End of section flags. *} . . {* The virtual memory address of the section - where it will be @@ -260,26 +272,26 @@ CODE_FRAGMENT . boolean user_set_vma; . . {* The load address of the section - where it would be in a -. rom image, really only used for writing section header +. rom image; really only used for writing section header . information. *} . . bfd_vma lma; . . {* The size of the section in bytes, as it will be output. -. contains a value even if the section has no contents (eg, the +. contains a value even if the section has no contents (e.g., the . size of <<.bss>>). This will be filled in after relocation *} . -. bfd_size_type _cooked_size; +. bfd_size_type _cooked_size; . -. {* The size on disk of the section in bytes originally. Normally this +. {* The original size on disk of the section, in bytes. Normally this . value is the same as the size, but if some relaxing has . been done, then this value will be bigger. *} . -. bfd_size_type _raw_size; +. bfd_size_type _raw_size; . . {* If this section is going to be output, then this value is the . offset into the output section of the first byte in the input -. section. Eg, if this was going to start at the 100th byte in +. section. E.g., if this was going to start at the 100th byte in . the output section, this value would be 100. *} . . bfd_vma output_offset; @@ -288,8 +300,8 @@ CODE_FRAGMENT . . struct sec *output_section; . -. {* The alignment requirement of the section, as an exponent - eg -. 3 aligns to 2^3 (or 8) *} +. {* The alignment requirement of the section, as an exponent of 2 - +. e.g., 3 aligns to 2^3 (or 8). *} . . unsigned int alignment_power; . @@ -312,8 +324,8 @@ CODE_FRAGMENT . . {* File position of section data *} . -. file_ptr filepos; -. +. file_ptr filepos; +. . {* File position of relocation info *} . . file_ptr rel_filepos; @@ -326,12 +338,14 @@ CODE_FRAGMENT . . PTR userdata; . -. struct lang_output_section *otheruserdata; +. {* If the SEC_IN_MEMORY flag is set, this points to the actual +. contents. *} +. unsigned char *contents; . . {* Attached line number information *} . . alent *lineno; -. +. . {* Number of line number records *} . . unsigned int lineno_count; @@ -341,7 +355,7 @@ CODE_FRAGMENT . . file_ptr moving_line_filepos; . -. {* what the section number is in the target world *} +. {* What the section number is in the target world *} . . int target_index; . @@ -358,35 +372,43 @@ CODE_FRAGMENT . . boolean reloc_done; . {* A symbol which points at this section only *} -. struct symbol_cache_entry *symbol; +. struct symbol_cache_entry *symbol; . struct symbol_cache_entry **symbol_ptr_ptr; . -. struct bfd_seclet *seclets_head; -. struct bfd_seclet *seclets_tail; +. struct bfd_link_order *link_order_head; +. struct bfd_link_order *link_order_tail; .} asection ; . -. . {* These sections are global, and are managed by BFD. The application . and target back end are not permitted to change the values in -. these sections. *} +. these sections. New code should use the section_ptr macros rather +. than referring directly to the const sections. The const sections +. may eventually vanish. *} .#define BFD_ABS_SECTION_NAME "*ABS*" .#define BFD_UND_SECTION_NAME "*UND*" .#define BFD_COM_SECTION_NAME "*COM*" .#define BFD_IND_SECTION_NAME "*IND*" . . {* the absolute section *} -.extern asection bfd_abs_section; +.extern const asection bfd_abs_section; +.#define bfd_abs_section_ptr ((asection *) &bfd_abs_section) +.#define bfd_is_abs_section(sec) ((sec) == bfd_abs_section_ptr) . {* Pointer to the undefined section *} -.extern asection bfd_und_section; +.extern const asection bfd_und_section; +.#define bfd_und_section_ptr ((asection *) &bfd_und_section) +.#define bfd_is_und_section(sec) ((sec) == bfd_und_section_ptr) . {* Pointer to the common section *} -.extern asection bfd_com_section; +.extern const asection bfd_com_section; +.#define bfd_com_section_ptr ((asection *) &bfd_com_section) . {* Pointer to the indirect section *} -.extern asection bfd_ind_section; -. -.extern struct symbol_cache_entry *bfd_abs_symbol; -.extern struct symbol_cache_entry *bfd_com_symbol; -.extern struct symbol_cache_entry *bfd_und_symbol; -.extern struct symbol_cache_entry *bfd_ind_symbol; +.extern const asection bfd_ind_section; +.#define bfd_ind_section_ptr ((asection *) &bfd_ind_section) +.#define bfd_is_ind_section(sec) ((sec) == bfd_ind_section_ptr) +. +.extern const struct symbol_cache_entry * const bfd_abs_symbol; +.extern const struct symbol_cache_entry * const bfd_com_symbol; +.extern const struct symbol_cache_entry * const bfd_und_symbol; +.extern const struct symbol_cache_entry * const bfd_ind_symbol; .#define bfd_get_section_size_before_reloc(section) \ . (section->reloc_done ? (abort(),1): (section)->_raw_size) .#define bfd_get_section_size_after_reloc(section) \ @@ -395,21 +417,24 @@ CODE_FRAGMENT /* These symbols are global, not specific to any BFD. Therefore, anything that tries to change them is broken, and should be repaired. */ -static CONST asymbol global_syms[] = { - /* the_bfd, name, value, attr, section [, udata] */ - { 0, BFD_COM_SECTION_NAME, 0, BSF_SECTION_SYM, &bfd_com_section }, - { 0, BFD_UND_SECTION_NAME, 0, BSF_SECTION_SYM, &bfd_und_section }, - { 0, BFD_ABS_SECTION_NAME, 0, BSF_SECTION_SYM, &bfd_abs_section }, - { 0, BFD_IND_SECTION_NAME, 0, BSF_SECTION_SYM, &bfd_ind_section }, +static const asymbol global_syms[] = +{ + /* the_bfd, name, value, attr, section [, udata] */ + {0, BFD_COM_SECTION_NAME, 0, BSF_SECTION_SYM, (asection *) &bfd_com_section}, + {0, BFD_UND_SECTION_NAME, 0, BSF_SECTION_SYM, (asection *) &bfd_und_section}, + {0, BFD_ABS_SECTION_NAME, 0, BSF_SECTION_SYM, (asection *) &bfd_abs_section}, + {0, BFD_IND_SECTION_NAME, 0, BSF_SECTION_SYM, (asection *) &bfd_ind_section}, }; #define STD_SECTION(SEC, FLAGS, SYM, NAME, IDX) \ - asymbol *SYM = (asymbol *) &global_syms[IDX]; \ - asection SEC = { NAME, 0, 0, FLAGS, 0, 0, (boolean) 0, 0, 0, 0, &SEC,\ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, (boolean) 0, \ - (asymbol *) &global_syms[IDX], &SYM, } - -STD_SECTION (bfd_com_section, SEC_IS_COMMON, bfd_com_symbol, BFD_COM_SECTION_NAME, 0); + const asymbol * const SYM = (asymbol *) &global_syms[IDX]; \ + const asection SEC = \ + { NAME, 0, 0, FLAGS, 0, false, 0, 0, 0, 0, (asection *) &SEC, \ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, (boolean) 0, \ + (asymbol *) &global_syms[IDX], (asymbol **) &SYM, } + +STD_SECTION (bfd_com_section, SEC_IS_COMMON, bfd_com_symbol, + BFD_COM_SECTION_NAME, 0); STD_SECTION (bfd_und_section, 0, bfd_und_symbol, BFD_UND_SECTION_NAME, 1); STD_SECTION (bfd_abs_section, 0, bfd_abs_symbol, BFD_ABS_SECTION_NAME, 2); STD_SECTION (bfd_ind_section, 0, bfd_ind_symbol, BFD_IND_SECTION_NAME, 3); @@ -420,39 +445,39 @@ DOCDD INODE section prototypes, , typedef asection, Sections SUBSECTION - section prototypes + Section prototypes -These are the functions exported by the section handling part of -<<libbfd>. +These are the functions exported by the section handling part of BFD. */ /* -FUNCTION +FUNCTION bfd_get_section_by_name SYNOPSIS asection *bfd_get_section_by_name(bfd *abfd, CONST char *name); DESCRIPTION - Runs through the provided @var{abfd} and returns the one of the - <<asection>>s who's name matches that provided, otherwise NULL. + Run through @var{abfd} and return the one of the + <<asection>>s whose name matches @var{name}, otherwise <<NULL>>. @xref{Sections}, for more information. This should only be used in special cases; the normal way to process - all sections of a given name is to use bfd_map_over_sections and - strcmp on the name (or better yet, base it on the section flags + all sections of a given name is to use <<bfd_map_over_sections>> and + <<strcmp>> on the name (or better yet, base it on the section flags or something else) for each section. */ asection * -DEFUN(bfd_get_section_by_name,(abfd, name), - bfd *abfd AND - CONST char *name) +bfd_get_section_by_name (abfd, name) + bfd *abfd; + CONST char *name; { asection *sect; for (sect = abfd->sections; sect != NULL; sect = sect->next) - if (!strcmp (sect->name, name)) return sect; + if (!strcmp (sect->name, name)) + return sect; return NULL; } @@ -462,36 +487,36 @@ FUNCTION bfd_make_section_old_way SYNOPSIS - asection *bfd_make_section_old_way(bfd *, CONST char *name); + asection *bfd_make_section_old_way(bfd *abfd, CONST char *name); DESCRIPTION - This function creates a new empty section called @var{name} - and attaches it to the end of the chain of sections for the - BFD supplied. An attempt to create a section with a name which - is already in use, returns its pointer without changing the + Create a new empty section called @var{name} + and attach it to the end of the chain of sections for the + BFD @var{abfd}. An attempt to create a section with a name which + is already in use returns its pointer without changing the section chain. It has the funny name since this is the way it used to be - before is was rewritten... + before it was rewritten.... Possible errors are: - o invalid_operation - + o <<bfd_error_invalid_operation>> - If output has already started for this BFD. - o no_memory - + o <<bfd_error_no_memory>> - If obstack alloc fails. */ asection * -DEFUN(bfd_make_section_old_way,(abfd, name), - bfd *abfd AND - CONST char * name) +bfd_make_section_old_way (abfd, name) + bfd *abfd; + CONST char *name; { - asection *sec = bfd_get_section_by_name(abfd, name); - if (sec == (asection *)NULL) + asection *sec = bfd_get_section_by_name (abfd, name); + if (sec == (asection *) NULL) { - sec = bfd_make_section(abfd, name); + sec = bfd_make_section (abfd, name); } return sec; } @@ -501,16 +526,16 @@ FUNCTION bfd_make_section_anyway SYNOPSIS - asection *bfd_make_section_anyway(bfd *, CONST char *name); + asection *bfd_make_section_anyway(bfd *abfd, CONST char *name); DESCRIPTION Create a new empty section called @var{name} and attach it to the end of the chain of sections for @var{abfd}. Create a new section even if there - is already a section with that name. + is already a section with that name. - Returns NULL and sets bfd_error on error; possible errors are: - o invalid_operation - If output has already started for @var{abfd}. - o no_memory - If obstack alloc fails. + Return <<NULL>> and set <<bfd_error>> on error; possible errors are: + o <<bfd_error_invalid_operation>> - If output has already started for @var{abfd}. + o <<bfd_error_no_memory>> - If obstack alloc fails. */ sec_ptr @@ -520,40 +545,45 @@ bfd_make_section_anyway (abfd, name) { asection *newsect; asection **prev = &abfd->sections; - asection * sect = abfd->sections; + asection *sect = abfd->sections; if (abfd->output_has_begun) { - bfd_error = invalid_operation; + bfd_set_error (bfd_error_invalid_operation); return NULL; } - while (sect) { - prev = §->next; - sect = sect->next; - } + while (sect) + { + prev = §->next; + sect = sect->next; + } - newsect = (asection *) bfd_zalloc(abfd, sizeof (asection)); - if (newsect == NULL) { - bfd_error = no_memory; - return NULL; - } + newsect = (asection *) bfd_zalloc (abfd, sizeof (asection)); + if (newsect == NULL) + { + bfd_set_error (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->userdata = NULL; + newsect->contents = NULL; + newsect->next = (asection *) NULL; + newsect->relocation = (arelent *) NULL; newsect->reloc_count = 0; - newsect->line_filepos =0; + newsect->line_filepos = 0; newsect->owner = abfd; /* Create a symbol whos only job is to point to this section. This is useful for things like relocs which are relative to the base of a section. */ - newsect->symbol = bfd_make_empty_symbol(abfd); + newsect->symbol = bfd_make_empty_symbol (abfd); + if (!newsect) + return NULL; newsect->symbol->name = name; newsect->symbol->value = 0; newsect->symbol->section = newsect; @@ -561,10 +591,11 @@ bfd_make_section_anyway (abfd, name) newsect->symbol_ptr_ptr = &newsect->symbol; - if (BFD_SEND (abfd, _new_section_hook, (abfd, newsect)) != true) { - free (newsect); - return NULL; - } + if (BFD_SEND (abfd, _new_section_hook, (abfd, newsect)) != true) + { + free (newsect); + return NULL; + } *prev = newsect; return newsect; @@ -578,41 +609,43 @@ SYNOPSIS asection *bfd_make_section(bfd *, CONST char *name); DESCRIPTION - Like bfd_make_section_anyway, but return NULL (without setting - bfd_error) without changing the section chain if there is already a - section named @var{name}. If there is an error, return NULL and set - bfd_error. + Like <<bfd_make_section_anyway>>, but return <<NULL>> (without calling + bfd_set_error ()) without changing the section chain if there is already a + section named @var{name}. If there is an error, return <<NULL>> and set + <<bfd_error>>. */ -sec_ptr -DEFUN(bfd_make_section,(abfd, name), - bfd *abfd AND - CONST char * name) +asection * +bfd_make_section (abfd, name) + bfd *abfd; + CONST char *name; { - asection * sect = abfd->sections; - - if (strcmp(name, BFD_ABS_SECTION_NAME) == 0) - { - return &bfd_abs_section; - } - if (strcmp(name, BFD_COM_SECTION_NAME) == 0) - { - return &bfd_com_section; - } - if (strcmp(name, BFD_UND_SECTION_NAME) == 0) - { - return &bfd_und_section; - } - - if (strcmp(name, BFD_IND_SECTION_NAME) == 0) - { - return &bfd_ind_section; - } - - while (sect) { - if (!strcmp(sect->name, name)) return NULL; - sect = sect->next; - } + asection *sect = abfd->sections; + + if (strcmp (name, BFD_ABS_SECTION_NAME) == 0) + { + return bfd_abs_section_ptr; + } + if (strcmp (name, BFD_COM_SECTION_NAME) == 0) + { + return bfd_com_section_ptr; + } + if (strcmp (name, BFD_UND_SECTION_NAME) == 0) + { + return bfd_und_section_ptr; + } + + if (strcmp (name, BFD_IND_SECTION_NAME) == 0) + { + return bfd_ind_section_ptr; + } + + while (sect) + { + if (!strcmp (sect->name, name)) + return NULL; + sect = sect->next; + } /* The name is not already used; go ahead and make a new section. */ return bfd_make_section_anyway (abfd, name); @@ -624,25 +657,26 @@ FUNCTION bfd_set_section_flags SYNOPSIS - boolean bfd_set_section_flags(bfd *, asection *, flagword); + boolean bfd_set_section_flags(bfd *abfd, asection *sec, flagword flags); DESCRIPTION - Attempts to set the attributes of the section named in the BFD - supplied to the value. Returns true on success, false on - error. Possible error returns are: + Set the attributes of the section @var{sec} in the BFD + @var{abfd} to the value @var{flags}. Return <<true>> on success, + <<false>> on error. Possible error returns are: - o invalid operation - + o <<bfd_error_invalid_operation>> - The section cannot have one or more of the attributes requested. For example, a .bss section in <<a.out>> may not have the <<SEC_HAS_CONTENTS>> field set. */ +/*ARGSUSED*/ boolean -DEFUN(bfd_set_section_flags,(abfd, section, flags), - bfd *abfd AND - sec_ptr section AND - flagword flags) +bfd_set_section_flags (abfd, section, flags) + bfd *abfd; + sec_ptr section; + flagword flags; { #if 0 /* If you try to copy a text section from an input file (where it @@ -650,10 +684,11 @@ DEFUN(bfd_set_section_flags,(abfd, section, flags), the bfd_applicable_section_flags (abfd) doesn't have the SEC_CODE set - which it doesn't, at least not for a.out. FIXME */ - if ((flags & bfd_applicable_section_flags (abfd)) != flags) { - bfd_error = invalid_operation; - return false; - } + if ((flags & bfd_applicable_section_flags (abfd)) != flags) + { + bfd_set_error (bfd_error_invalid_operation); + return false; + } #endif section->flags = flags; @@ -673,13 +708,13 @@ SYNOPSIS PTR obj); DESCRIPTION - Calls the provided function @var{func} for each section + Call the provided function @var{func} for each section attached to the BFD @var{abfd}, passing @var{obj} as an - argument. The function will be called as if by + argument. The function will be called as if by | func(abfd, the_section, obj); - This is the prefered method for iterating over sections, an + This is the prefered method for iterating over sections; an alternative would be to use a loop: | section *p; @@ -691,19 +726,19 @@ DESCRIPTION /*VARARGS2*/ void -DEFUN(bfd_map_over_sections,(abfd, operation, user_storage), - bfd *abfd AND - void (*operation) PARAMS ((bfd *abfd, asection *sect, PTR obj)) AND - PTR user_storage) +bfd_map_over_sections (abfd, operation, user_storage) + bfd *abfd; + void (*operation) PARAMS ((bfd * abfd, asection * sect, PTR obj)); + 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(); + if (i != abfd->section_count) /* Debugging */ + abort (); } @@ -712,35 +747,36 @@ FUNCTION bfd_set_section_size SYNOPSIS - boolean bfd_set_section_size(bfd *, asection *, bfd_size_type val); + boolean bfd_set_section_size(bfd *abfd, asection *sec, bfd_size_type val); DESCRIPTION - Sets @var{section} to the size @var{val}. If the operation is - ok, then <<true>> is returned, else <<false>>. + Set @var{sec} to the size @var{val}. If the operation is + ok, then <<true>> is returned, else <<false>>. Possible error returns: - o invalid_operation - - Writing has started to the BFD, so setting the size is invalid + o <<bfd_error_invalid_operation>> - + Writing has started to the BFD, so setting the size is invalid. */ boolean -DEFUN(bfd_set_section_size,(abfd, ptr, val), - bfd *abfd AND - sec_ptr ptr AND - bfd_size_type val) +bfd_set_section_size (abfd, ptr, val) + bfd *abfd; + sec_ptr ptr; + bfd_size_type 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; - } + if (abfd->output_has_begun) + { + bfd_set_error (bfd_error_invalid_operation); + return false; + } ptr->_cooked_size = val; ptr->_raw_size = val; - + return true; } @@ -750,7 +786,7 @@ FUNCTION SYNOPSIS boolean bfd_set_section_contents - (bfd *abfd, + (bfd *abfd, asection *section, PTR data, file_ptr offset, @@ -761,13 +797,13 @@ DESCRIPTION Sets the contents of the section @var{section} in BFD @var{abfd} to the data starting in memory at @var{data}. The data is written to the output section starting at offset - @var{offset} for @var{count} bytes. + @var{offset} for @var{count} bytes. Normally <<true>> is returned, else <<false>>. Possible error returns are: - o no_contents - + o <<bfd_error_no_contents>> - The output section does not have the <<SEC_HAS_CONTENTS>> attribute, so nothing can be written to it. o and some more too @@ -784,25 +820,25 @@ DESCRIPTION : bfd_get_section_size_before_reloc (sec)) 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) +bfd_set_section_contents (abfd, section, location, offset, count) + bfd *abfd; + sec_ptr section; + PTR location; + file_ptr offset; + bfd_size_type count; { bfd_size_type sz; - if (!bfd_get_section_flags(abfd, section) & SEC_HAS_CONTENTS) - { - bfd_error = no_contents; - return(false); - } + if (!(bfd_get_section_flags (abfd, section) & SEC_HAS_CONTENTS)) + { + bfd_set_error (bfd_error_no_contents); + return (false); + } if (offset < 0) { bad_val: - bfd_error = bad_value; + bfd_set_error (bfd_error_bad_value); return false; } sz = bfd_get_section_size_now (abfd, section); @@ -813,28 +849,28 @@ DEFUN(bfd_set_section_contents,(abfd, section, location, offset, count), switch (abfd->direction) { - case read_direction: - case no_direction: - bfd_error = invalid_operation; - return false; + case read_direction: + case no_direction: + bfd_set_error (bfd_error_invalid_operation); + return false; - case write_direction: - break; + case write_direction: + break; - case both_direction: - /* File is opened for update. `output_has_begun' some time ago when + case both_direction: + /* File is opened for update. `output_has_begun' some time ago when the file was created. Do not recompute sections sizes or alignments in _bfd_set_section_content. */ - abfd->output_has_begun = true; - break; + abfd->output_has_begun = true; + break; } if (BFD_SEND (abfd, _bfd_set_section_contents, - (abfd, section, location, offset, count))) - { - abfd->output_has_begun = true; - return true; - } + (abfd, section, location, offset, count))) + { + abfd->output_has_begun = true; + return true; + } return false; } @@ -844,56 +880,90 @@ FUNCTION bfd_get_section_contents SYNOPSIS - boolean bfd_get_section_contents + boolean bfd_get_section_contents (bfd *abfd, asection *section, PTR location, file_ptr offset, bfd_size_type count); DESCRIPTION - This function reads data from @var{section} in BFD @var{abfd} + Read data from @var{section} in BFD @var{abfd} into memory starting at @var{location}. The data is read at an offset of @var{offset} from the start of the input section, and is read for @var{count} bytes. - If the contents of a constuctor with the <<SEC_CONSTUCTOR>> - flag set are requested, then the @var{location} is filled with - zeroes. If no errors occur, <<true>> is returned, else + If the contents of a constructor with the <<SEC_CONSTRUCTOR>> + flag set are requested or if the section does not have the + <<SEC_HAS_CONTENTS>> flag set, then the @var{location} is filled + with zeroes. If no errors occur, <<true>> is returned, else <<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) +bfd_get_section_contents (abfd, section, location, offset, count) + bfd *abfd; + sec_ptr section; + PTR location; + file_ptr offset; + bfd_size_type count; { bfd_size_type sz; - if (section->flags & SEC_CONSTRUCTOR) + if (section->flags & SEC_CONSTRUCTOR) { - memset(location, 0, (unsigned)count); + memset (location, 0, (unsigned) count); return true; } if (offset < 0) { bad_val: - bfd_error = bad_value; + bfd_set_error (bfd_error_bad_value); return false; } - sz = bfd_get_section_size_now (abfd, section); - if (offset > sz - || count > sz - || offset + count > sz) + /* Even if reloc_done is true, this function reads unrelocated + contents, so we want the raw size. */ + sz = section->_raw_size; + if (offset > sz || count > sz || offset + count > sz) goto bad_val; if (count == 0) /* Don't bother. */ return true; + if ((section->flags & SEC_HAS_CONTENTS) == 0) + { + memset (location, 0, (unsigned) count); + return true; + } + + if ((section->flags & SEC_IN_MEMORY) != 0) + { + memcpy (location, section->contents + offset, count); + return true; + } + return BFD_SEND (abfd, _bfd_get_section_contents, (abfd, section, location, offset, count)); } + +/* +FUNCTION + bfd_copy_private_section_data + +SYNOPSIS + boolean bfd_copy_private_section_data(bfd *ibfd, asection *isec, bfd *obfd, asection *osec); + +DESCRIPTION + Copy private section information from @var{isec} in the BFD + @var{ibfd} to the section @var{osec} in the BFD @var{obfd}. + Return <<true>> on success, <<false>> on error. Possible error + returns are: + + o <<bfd_error_no_memory>> - + Not enough memory exists to create private data for @var{osec}. + +.#define bfd_copy_private_section_data(ibfd, isection, obfd, osection) \ +. BFD_SEND (ibfd, _bfd_copy_private_section_data, \ +. (ibfd, isection, obfd, osection)) +*/ diff --git a/gnu/usr.bin/gdb/bfd/srec.c b/gnu/usr.bin/gdb/bfd/srec.c index 88ba9570e34e..a52e9b280ae1 100644 --- a/gnu/usr.bin/gdb/bfd/srec.c +++ b/gnu/usr.bin/gdb/bfd/srec.c @@ -1,5 +1,5 @@ /* BFD back-end for s-record objects. - Copyright 1990, 1991, 1992, 1993 Free Software Foundation, Inc. + Copyright 1990, 1991, 1992, 1993, 1994 Free Software Foundation, Inc. Written by Steve Chamberlain of Cygnus Support <sac@cygnus.com>. This file is part of BFD, the Binary File Descriptor library. @@ -26,12 +26,12 @@ DESCRIPTION Ordinary S-Records cannot hold anything but addresses and data, so that's all that we implement. - + The only interesting thing is that S-Records may come out of order and there is no header, so an initial scan is required to discover the minimum and maximum addresses used to create the vma and size of the only section we create. We - arbitrarily call this section ".text". + arbitrarily call this section ".text". When bfd_get_section_contents is called the file is read again, and this time the data is placed into a bfd_alloc'd @@ -95,7 +95,7 @@ EXAMPLE _etext $8036 _edata $8036 _end $8036 - $$ + $$ DESCRIPTION We allow symbols to be anywhere in the data stream - the module names @@ -107,11 +107,19 @@ DESCRIPTION #include "sysdep.h" #include "libbfd.h" -/* Macros for converting between hex and binary */ +static boolean srec_write_record PARAMS ((bfd *, int, bfd_vma, + const unsigned char *, + const unsigned char *)); +static boolean srec_write_header PARAMS ((bfd *)); +static boolean srec_write_symbols PARAMS ((bfd *)); + +/* Macros for converting between hex and binary. */ static CONST char digs[] = "0123456789ABCDEF"; -static char hex_value[1 + (unsigned char)~0]; +/* Table that gets filled in with numbers corresponding to hex chars. */ + +static char hex_value[256]; #define NOT_HEX 20 #define NIBBLE(x) hex_value[(unsigned char)(x)] @@ -122,40 +130,37 @@ static char hex_value[1 + (unsigned char)~0]; ch += ((x) & 0xff); #define ISHEX(x) (hex_value[(unsigned char)(x)] != NOT_HEX) - +/* Initialize by filling in the hex conversion array. */ static void -DEFUN_VOID(srec_init) +srec_init () { - unsigned int i; - static boolean inited = false; - - if (inited == false) + unsigned int i; + static boolean inited = false; + + if (inited == false) { - - inited = true; - - for (i = 0; i < sizeof (hex_value); i++) + inited = true; + + for (i = 0; i < sizeof (hex_value); i++) { - hex_value[i] = NOT_HEX; + hex_value[i] = NOT_HEX; } - - for (i = 0; i < 10; i++) + for (i = 0; i < 10; i++) { - hex_value[i + '0'] = i; - + hex_value[i + '0'] = i; } - for (i = 0; i < 6; i++) + for (i = 0; i < 6; i++) { - hex_value[i + 'a'] = i+10; - hex_value[i + 'A'] = i+10; + hex_value[i + 'a'] = i + 10; + hex_value[i + 'A'] = i + 10; } - } + } } /* The maximum number of bytes on a line is FF */ -#define MAXCHUNK 0xff +#define MAXCHUNK 0xff /* The number of bytes we fit onto a line on output */ #define CHUNK 21 @@ -164,21 +169,21 @@ DEFUN_VOID(srec_init) struct srec_data_list_struct { - unsigned char *data; - bfd_vma where; - bfd_size_type size; - struct srec_data_list_struct *next; + unsigned char *data; + bfd_vma where; + bfd_size_type size; + struct srec_data_list_struct *next; + - -} ; +}; typedef struct srec_data_list_struct srec_data_list_type; -typedef struct srec_data_struct -{ - srec_data_list_type *head; +typedef struct srec_data_struct + { + srec_data_list_type *head; unsigned int type; - + int done_symbol_read; int count; asymbol *symbols; @@ -186,67 +191,78 @@ typedef struct srec_data_struct int symbol_idx; int string_size; int string_idx; -} tdata_type; + } +tdata_type; +static boolean srec_write_section PARAMS ((bfd *, tdata_type *, + srec_data_list_type *)); +static boolean srec_write_terminator PARAMS ((bfd *, tdata_type *)); -/* +/* called once per input S-Record, used to work out vma and size of data. */ -static bfd_vma low,high; +static bfd_vma low, high; +/*ARGSUSED*/ static void -size_symbols(abfd, buf, len, val) -bfd *abfd; -char *buf; -int len; -int val; -{ - abfd->symcount ++; - abfd->tdata.srec_data->string_size += len + 1; +size_symbols (abfd, buf, len, val) + bfd *abfd; + char *buf; + int len; + int val; +{ + abfd->symcount++; + abfd->tdata.srec_data->string_size += len + 1; } static void -fillup_symbols(abfd, buf, len, val) -bfd *abfd; -char *buf; -int len; -int val; +fillup_symbols (abfd, buf, len, val) + bfd *abfd; + char *buf; + int len; + int val; { if (!abfd->tdata.srec_data->done_symbol_read) - { - asymbol *p; - if (abfd->tdata.srec_data->symbols == 0) { - abfd->tdata.srec_data->symbols = (asymbol *)bfd_alloc(abfd, abfd->symcount * sizeof(asymbol)); - abfd->tdata.srec_data->strings = (char*)bfd_alloc(abfd, abfd->tdata.srec_data->string_size); - abfd->tdata.srec_data->symbol_idx = 0; - abfd->tdata.srec_data->string_idx = 0; - } + asymbol *p; + if (abfd->tdata.srec_data->symbols == 0) + { + abfd->tdata.srec_data->symbols = (asymbol *) bfd_alloc (abfd, abfd->symcount * sizeof (asymbol)); + abfd->tdata.srec_data->strings = (char *) bfd_alloc (abfd, abfd->tdata.srec_data->string_size); + if (!abfd->tdata.srec_data->symbols || !abfd->tdata.srec_data->strings) + { + bfd_set_error (bfd_error_no_memory); + abort (); /* FIXME */ + } + abfd->tdata.srec_data->symbol_idx = 0; + abfd->tdata.srec_data->string_idx = 0; + } - p = abfd->tdata.srec_data->symbols + abfd->tdata.srec_data->symbol_idx++; - p->the_bfd = abfd; - p->name = abfd->tdata.srec_data->strings + abfd->tdata.srec_data->string_idx; - memcpy((char *)(p->name), buf, len+1); - abfd->tdata.srec_data->string_idx += len + 1; - p->value = val; - p->flags = BSF_EXPORT | BSF_GLOBAL; - p->section = &bfd_abs_section; - p->udata = 0; - } + p = abfd->tdata.srec_data->symbols + abfd->tdata.srec_data->symbol_idx++; + p->the_bfd = abfd; + p->name = abfd->tdata.srec_data->strings + abfd->tdata.srec_data->string_idx; + memcpy ((char *) (p->name), buf, len + 1); + abfd->tdata.srec_data->string_idx += len + 1; + p->value = val; + p->flags = BSF_EXPORT | BSF_GLOBAL; + p->section = bfd_abs_section_ptr; + p->udata = 0; + } } +/*ARGSUSED*/ static void -DEFUN(size_srec,(abfd, section, address, raw, length), - bfd *abfd AND - asection *section AND - bfd_vma address AND - bfd_byte *raw AND - unsigned int length) +size_srec (abfd, section, address, raw, length) + bfd *abfd; + asection *section; + bfd_vma address; + bfd_byte *raw; + unsigned int length; { if (address < low) low = address; - if (address + length > high) - high = address + length -1; + if (address + length > high) + high = address + length - 1; } @@ -254,280 +270,302 @@ DEFUN(size_srec,(abfd, section, address, raw, length), called once per input S-Record, copies data from input into bfd_alloc'd area */ +/*ARGSUSED*/ static void -DEFUN(fillup,(abfd, section, address, raw, length), -bfd *abfd AND -asection *section AND -bfd_vma address AND -bfd_byte *raw AND -unsigned int length) -{ - unsigned int i; - bfd_byte *dst = - (bfd_byte *)(section->used_by_bfd) + address - section->vma; - /* length -1 because we don't read in the checksum */ - for (i = 0; i < length -1 ; i++) { - *dst = HEX(raw); - dst++; - raw+=2; - } +fillup (abfd, section, address, raw, length) + bfd *abfd; + asection *section; + bfd_vma address; + bfd_byte *raw; + unsigned int length; +{ + unsigned int i; + bfd_byte *dst = + (bfd_byte *) (section->used_by_bfd) + address - section->vma; + /* length -1 because we don't read in the checksum */ + for (i = 0; i < length - 1; i++) + { + *dst = HEX (raw); + dst++; + raw += 2; + } } /* Pass over an S-Record file, calling one of the above functions on each record. */ -static int white(x) -char x; +static int +white (x) + char x; { -return (x== ' ' || x == '\t' || x == '\n' || x == '\r'); + return (x == ' ' || x == '\t' || x == '\n' || x == '\r'); } static int -skipwhite(src,abfd) -char *src; -bfd *abfd; +skipwhite (src, abfd) + char *src; + bfd *abfd; { int eof = 0; - while (white(*src) && !eof) - { - eof = (boolean)(bfd_read(src, 1, 1, abfd) != 1); - } + while (white (*src) && !eof) + { + eof = (boolean) (bfd_read (src, 1, 1, abfd) != 1); + } return eof; } static boolean -DEFUN(srec_mkobject, (abfd), - bfd *abfd) +srec_mkobject (abfd) + bfd *abfd; { - if (abfd->tdata.srec_data == 0) - { - tdata_type *tdata = (tdata_type *)bfd_alloc(abfd, sizeof(tdata_type)); - abfd->tdata.srec_data = tdata; - tdata->type = 1; - tdata->head = (srec_data_list_type *)NULL; - } + if (abfd->tdata.srec_data == 0) + { + tdata_type *tdata = (tdata_type *) bfd_alloc (abfd, sizeof (tdata_type)); + if (!tdata) + { + bfd_set_error (bfd_error_no_memory); + return false; + } + abfd->tdata.srec_data = tdata; + tdata->type = 1; + tdata->head = (srec_data_list_type *) NULL; + } return true; - + } static void -DEFUN(pass_over,(abfd, func, symbolfunc, section), - bfd *abfd AND - void (*func)() AND - void (*symbolfunc)() AND - asection *section) +pass_over (abfd, func, symbolfunc, section) + bfd *abfd; + void (*func) (); + void (*symbolfunc) (); + asection *section; { unsigned int bytes_on_line; boolean eof = false; - srec_mkobject(abfd); + srec_mkobject (abfd); /* To the front of the file */ - bfd_seek(abfd, (file_ptr)0, SEEK_SET); + if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0) + abort (); while (eof == false) - { - char buffer[MAXCHUNK]; - char *src = buffer; - char type; - bfd_vma address = 0; - - /* Find first 'S' or $ */ - eof = (boolean)(bfd_read(src, 1, 1, abfd) != 1); - switch (*src) { - default: - eof = (boolean)(bfd_read(src, 1, 1, abfd) != 1); - if (eof) return; - break; - - case '$': - /* Inside a symbol definition - just ignore the module name */ - while (*src != '\n' && !eof) - { - eof = (boolean)(bfd_read(src, 1, 1, abfd) != 1); - } - break; - - case ' ': - /* spaces - maybe just before a symbol */ - while (*src != '\n' && white(*src)) { - eof = skipwhite(src, abfd); - -{ - int val = 0; - int slen = 0; - char symbol[MAXCHUNK]; - - /* get the symbol part */ - while (!eof && !white(*src) && slen < MAXCHUNK) - { - symbol[slen++] = *src; - eof = (boolean)(bfd_read(src, 1, 1, abfd) != 1); - } - symbol[slen] = 0; - eof = skipwhite(src, abfd); - /* skip the $ for the hex value */ - if (*src == '$') - { - eof = (boolean)(bfd_read(src, 1, 1, abfd) != 1); - } - - /* Scan off the hex number */ - while (isxdigit(*src )) + char buffer[MAXCHUNK]; + char *src = buffer; + char type; + bfd_vma address = 0; + + /* Find first 'S' or $ */ + eof = (boolean) (bfd_read (src, 1, 1, abfd) != 1); + switch (*src) { - val *= 16; - if (isdigit(*src)) - val += *src - '0'; - else if (isupper(*src)) { - val += *src - 'A' + 10; - } - else { - val += *src - 'a' + 10; - } - eof = (boolean)(bfd_read(src, 1, 1, abfd) != 1); + default: + if (eof) + return; + break; + + case '$': + /* Inside a symbol definition - just ignore the module name */ + while (*src != '\n' && !eof) + { + eof = (boolean) (bfd_read (src, 1, 1, abfd) != 1); + } + break; + + case ' ': + /* spaces - maybe just before a symbol */ + while (*src != '\n' && *src != '\r' && white (*src)) + { + eof = skipwhite (src, abfd); + + { + int val = 0; + int slen = 0; + char symbol[MAXCHUNK]; + + /* get the symbol part */ + while (!eof && !white (*src) && slen < MAXCHUNK) + { + symbol[slen++] = *src; + eof = (boolean) (bfd_read (src, 1, 1, abfd) != 1); + } + symbol[slen] = 0; + eof = skipwhite (src, abfd); + /* skip the $ for the hex value */ + if (*src == '$') + { + eof = (boolean) (bfd_read (src, 1, 1, abfd) != 1); + } + + /* Scan off the hex number */ + while (isxdigit (*src)) + { + val *= 16; + if (isdigit (*src)) + val += *src - '0'; + else if (isupper (*src)) + { + val += *src - 'A' + 10; + } + else + { + val += *src - 'a' + 10; + } + eof = (boolean) (bfd_read (src, 1, 1, abfd) != 1); + } + symbolfunc (abfd, symbol, slen, val); + } + } + break; + case 'S': + src++; + + /* Fetch the type and the length */ + if (bfd_read (src, 1, 3, abfd) != 3) + abort (); /* FIXME */ + + type = *src++; + + if (!ISHEX (src[0]) || !ISHEX (src[1])) + break; + + bytes_on_line = HEX (src); + + if (bytes_on_line > MAXCHUNK / 2) + break; + src += 2; + + if (bfd_read (src, 1, bytes_on_line * 2, abfd) != bytes_on_line * 2) + abort (); /* FIXME */ + + switch (type) + { + case '0': + case '5': + /* Prologue - ignore */ + break; + case '3': + address = HEX (src); + src += 2; + bytes_on_line--; + + case '2': + address = HEX (src) | (address << 8); + src += 2; + bytes_on_line--; + case '1': + address = HEX (src) | (address << 8); + src += 2; + address = HEX (src) | (address << 8); + src += 2; + bytes_on_line -= 2; + func (abfd, section, address, src, bytes_on_line); + break; + default: + return; + } } - symbolfunc(abfd, symbol, slen, val); - } -} - break; - case 'S': - src++; - - /* Fetch the type and the length */ - bfd_read(src, 1, 3, abfd); - - type = *src++; - - if (!ISHEX (src[0]) || !ISHEX (src[1])) - break; - - bytes_on_line = HEX(src); - - if (bytes_on_line > MAXCHUNK/2) - break; - src+=2 ; - - bfd_read(src, 1 , bytes_on_line * 2, abfd); - - switch (type) { - case '0': - case '5': - /* Prologue - ignore */ - break; - case '3': - address = HEX(src); - src+=2; - bytes_on_line--; - - case '2': - address = HEX(src) | (address<<8) ; - src+=2; - bytes_on_line--; - case '1': - address = HEX(src) | (address<<8) ; - src+=2; - address = HEX(src) | (address<<8) ; - src+=2; - bytes_on_line-=2; - func(abfd,section, address, src, bytes_on_line); - break; - default: - return; - } } - } } -static bfd_target * -object_p(abfd) -bfd *abfd; +static const bfd_target * +object_p (abfd) + bfd *abfd; { asection *section; - /* We create one section called .text for all the contents, + /* We create one section called .text for all the contents, and allocate enough room for the entire file. */ - - section = bfd_make_section(abfd, ".text"); + + section = bfd_make_section (abfd, ".text"); section->_raw_size = 0; section->vma = 0xffffffff; low = 0xffffffff; high = 0; - pass_over(abfd, size_srec, size_symbols, section); + pass_over (abfd, size_srec, size_symbols, section); section->_raw_size = high - low; section->vma = low; section->flags = SEC_HAS_CONTENTS | SEC_LOAD | SEC_ALLOC; if (abfd->symcount) - abfd->flags |= HAS_SYMS; + abfd->flags |= HAS_SYMS; return abfd->xvec; } -static bfd_target * -DEFUN(srec_object_p, (abfd), - bfd *abfd) +static const bfd_target * +srec_object_p (abfd) + bfd *abfd; { char b[4]; - srec_init(); - - bfd_seek(abfd, (file_ptr)0, SEEK_SET); - bfd_read(b, 1, 4, abfd); + srec_init (); + + if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0 + || bfd_read (b, 1, 4, abfd) != 4) + return NULL; - if (b[0] != 'S' || !ISHEX(b[1]) || !ISHEX(b[2]) || !ISHEX(b[3])) - return (bfd_target*) NULL; - - /* We create one section called .text for all the contents, + if (b[0] != 'S' || !ISHEX (b[1]) || !ISHEX (b[2]) || !ISHEX (b[3])) + return (const bfd_target *) NULL; + + /* We create one section called .text for all the contents, and allocate enough room for the entire file. */ - return object_p(abfd); + return object_p (abfd); } -static bfd_target * -DEFUN(symbolsrec_object_p, (abfd), - bfd *abfd) +static const bfd_target * +symbolsrec_object_p (abfd) + bfd *abfd; { char b[4]; - srec_init(); - - bfd_seek(abfd, (file_ptr)0, SEEK_SET); - bfd_read(b, 1, 4, abfd); + srec_init (); + + if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0 + || bfd_read (b, 1, 4, abfd) != 4) + return NULL; if (b[0] != '$' || b[1] != '$') - return (bfd_target*) NULL; + return (const bfd_target *) NULL; - return object_p(abfd); + return object_p (abfd); } static boolean -DEFUN(srec_get_section_contents,(abfd, section, location, offset, count), - bfd *abfd AND - asection *section AND - PTR location AND - file_ptr offset AND - bfd_size_type count) -{ - if (section->used_by_bfd == (PTR)NULL) +srec_get_section_contents (abfd, section, location, offset, count) + bfd *abfd; + asection *section; + PTR location; + file_ptr offset; + bfd_size_type count; +{ + if (section->used_by_bfd == (PTR) NULL) { - section->used_by_bfd = (PTR)bfd_alloc (abfd, section->_raw_size); - - pass_over(abfd, fillup, fillup_symbols, section); + section->used_by_bfd = (PTR) bfd_alloc (abfd, section->_raw_size); + if (!section->used_by_bfd) + { + bfd_set_error (bfd_error_no_memory); + return false; + } + + pass_over (abfd, fillup, fillup_symbols, section); } - (void) memcpy((PTR)location, - (PTR)((char *)(section->used_by_bfd) + offset), - count); - return true; + memcpy ((PTR) location, + (PTR) ((char *) (section->used_by_bfd) + offset), + count); + return true; } - + boolean -DEFUN(srec_set_arch_mach,(abfd, arch, machine), - bfd *abfd AND - enum bfd_architecture arch AND - unsigned long machine) +srec_set_arch_mach (abfd, arch, machine) + bfd *abfd; + enum bfd_architecture arch; + unsigned long machine; { - return bfd_default_set_arch_mach(abfd, arch, machine); + return bfd_default_set_arch_mach (abfd, arch, machine); } @@ -535,33 +573,44 @@ DEFUN(srec_set_arch_mach,(abfd, arch, machine), also remember */ static boolean -DEFUN(srec_set_section_contents,(abfd, section, location, offset, bytes_to_do), - bfd *abfd AND - sec_ptr section AND - PTR location AND - file_ptr offset AND - bfd_size_type bytes_to_do) -{ - tdata_type *tdata = abfd->tdata.srec_data; +srec_set_section_contents (abfd, section, location, offset, bytes_to_do) + bfd *abfd; + sec_ptr section; + PTR location; + file_ptr offset; + bfd_size_type bytes_to_do; +{ + tdata_type *tdata = abfd->tdata.srec_data; srec_data_list_type *entry = (srec_data_list_type *) - bfd_alloc(abfd, sizeof(srec_data_list_type)); + bfd_alloc (abfd, sizeof (srec_data_list_type)); + + if (!entry) + { + bfd_set_error (bfd_error_no_memory); + return false; + } if ((section->flags & SEC_ALLOC) - && (section->flags & SEC_LOAD)) + && (section->flags & SEC_LOAD)) { - unsigned char *data = (unsigned char *) bfd_alloc(abfd, bytes_to_do); - memcpy(data, location, bytes_to_do); + unsigned char *data = (unsigned char *) bfd_alloc (abfd, bytes_to_do); + if (!data) + { + bfd_set_error (bfd_error_no_memory); + return false; + } + memcpy ((PTR) data, location, bytes_to_do); - if ((section->lma + offset + bytes_to_do) <= 0xffff) + if ((section->lma + offset + bytes_to_do) <= 0xffff) { } - else if ((section->lma + offset + bytes_to_do) <= 0xffffff - && tdata->type < 2) + else if ((section->lma + offset + bytes_to_do) <= 0xffffff + && tdata->type < 2) { tdata->type = 2; } - else + else { tdata->type = 3; } @@ -572,430 +621,453 @@ DEFUN(srec_set_section_contents,(abfd, section, location, offset, bytes_to_do), entry->next = tdata->head; tdata->head = entry; } - return true; + return true; } /* Write a record of type, of the supplied number of bytes. The supplied bytes and length don't have a checksum. That's worked out here */ -static -void DEFUN(srec_write_record,(abfd, type, address, data, end), - bfd *abfd AND - char type AND - bfd_vma address AND - CONST unsigned char *data AND - CONST unsigned char *end) - -{ - char buffer[MAXCHUNK]; - - unsigned int check_sum = 0; - unsigned CONST char *src = data; - char *dst =buffer; - char *length; - - - *dst++ = 'S'; - *dst++ = '0' + type; - - length = dst; - dst+=2; /* leave room for dst*/ - - switch (type) +static boolean +srec_write_record (abfd, type, address, data, end) + bfd *abfd; + int type; + bfd_vma address; + const unsigned char *data; + const unsigned char *end; +{ + char buffer[MAXCHUNK]; + + unsigned int check_sum = 0; + CONST unsigned char *src = data; + char *dst = buffer; + char *length; + + + *dst++ = 'S'; + *dst++ = '0' + type; + + length = dst; + dst += 2; /* leave room for dst*/ + + switch (type) { - case 3: - case 7: - TOHEX(dst, (address >> 24), check_sum); - dst+=2; - case 8: - case 2: - TOHEX(dst, (address >> 16), check_sum); - dst+=2; - case 9: - case 1: - case 0: - TOHEX(dst, (address >> 8), check_sum); - dst+=2; - TOHEX(dst, (address), check_sum); - dst+=2; - break; + case 3: + case 7: + TOHEX (dst, (address >> 24), check_sum); + dst += 2; + case 8: + case 2: + TOHEX (dst, (address >> 16), check_sum); + dst += 2; + case 9: + case 1: + case 0: + TOHEX (dst, (address >> 8), check_sum); + dst += 2; + TOHEX (dst, (address), check_sum); + dst += 2; + break; } - for (src = data; src < end; src++) + for (src = data; src < end; src++) { - TOHEX(dst, *src, check_sum); - dst+=2; + TOHEX (dst, *src, check_sum); + dst += 2; } - /* Fill in the length */ - TOHEX(length, (dst - length)/2, check_sum); - check_sum &= 0xff; - check_sum = 255 - check_sum; - TOHEX(dst, check_sum, check_sum); - dst+=2; - - *dst ++ = '\r'; - *dst ++ = '\n'; - bfd_write((PTR)buffer, 1, dst - buffer , abfd); + /* Fill in the length */ + TOHEX (length, (dst - length) / 2, check_sum); + check_sum &= 0xff; + check_sum = 255 - check_sum; + TOHEX (dst, check_sum, check_sum); + dst += 2; + + *dst++ = '\r'; + *dst++ = '\n'; + if (bfd_write ((PTR) buffer, 1, dst - buffer, abfd) != dst - buffer) + return false; + return true; } -static void -DEFUN(srec_write_header,(abfd), - bfd *abfd) +static boolean +srec_write_header (abfd) + bfd *abfd; { - unsigned char buffer[MAXCHUNK]; - unsigned char *dst = buffer; - unsigned int i; + unsigned char buffer[MAXCHUNK]; + unsigned char *dst = buffer; + unsigned int i; - /* I'll put an arbitary 40 char limit on header size */ - for (i = 0; i < 40 && abfd->filename[i]; i++) + /* I'll put an arbitary 40 char limit on header size */ + for (i = 0; i < 40 && abfd->filename[i]; i++) { - *dst++ = abfd->filename[i]; + *dst++ = abfd->filename[i]; } - srec_write_record(abfd,0, 0, buffer, dst); + return srec_write_record (abfd, 0, 0, buffer, dst); } -static void -DEFUN(srec_write_section,(abfd, tdata, list), - bfd *abfd AND - tdata_type *tdata AND - srec_data_list_type *list) +static boolean +srec_write_section (abfd, tdata, list) + bfd *abfd; + tdata_type *tdata; + srec_data_list_type *list; { - unsigned int bytes_written = 0; - unsigned char *location = list->data; + unsigned int bytes_written = 0; + unsigned char *location = list->data; - while (bytes_written < list->size) + while (bytes_written < list->size) { - bfd_vma address; - - unsigned int bytes_this_chunk = list->size - bytes_written; + bfd_vma address; + + unsigned int bytes_this_chunk = list->size - bytes_written; - if (bytes_this_chunk > CHUNK) + if (bytes_this_chunk > CHUNK) { - bytes_this_chunk = CHUNK; + bytes_this_chunk = CHUNK; } - address = list->where + bytes_written; + address = list->where + bytes_written; - srec_write_record(abfd, - tdata->type, - address, - location, - location + bytes_this_chunk); + if (! srec_write_record (abfd, + tdata->type, + address, + location, + location + bytes_this_chunk)) + return false; - bytes_written += bytes_this_chunk; - location += bytes_this_chunk; + bytes_written += bytes_this_chunk; + location += bytes_this_chunk; } + return true; } -static void -DEFUN(srec_write_terminator,(abfd, tdata), - bfd *abfd AND - tdata_type *tdata) -{ - unsigned char buffer[2]; - - srec_write_record(abfd, 10 - tdata->type, - abfd->start_address, buffer, buffer); +static boolean +srec_write_terminator (abfd, tdata) + bfd *abfd; + tdata_type *tdata; +{ + unsigned char buffer[2]; + + return srec_write_record (abfd, 10 - tdata->type, + abfd->start_address, buffer, buffer); } - -static void -srec_write_symbols(abfd) + +static boolean +srec_write_symbols (abfd) bfd *abfd; { char buffer[MAXCHUNK]; /* Dump out the symbols of a bfd */ int i; - int len = bfd_get_symcount(abfd); + int count = bfd_get_symcount (abfd); - if (len) - { - asymbol **table = bfd_get_outsymbols(abfd); - sprintf(buffer, "$$ %s\r\n", abfd->filename); + if (count) + { + size_t len; + asymbol **table = bfd_get_outsymbols (abfd); + sprintf (buffer, "$$ %s\r\n", abfd->filename); - bfd_write(buffer, strlen(buffer), 1, abfd); + len = strlen (buffer); + if (bfd_write (buffer, len, 1, abfd) != len) + return false; - for (i = 0; i < len; i++) - { - asymbol *s = table[i]; + for (i = 0; i < count; i++) + { + asymbol *s = table[i]; #if 0 - int len = strlen(s->name); + int len = strlen (s->name); - /* If this symbol has a .[ocs] in it, it's probably a file name + /* If this symbol has a .[ocs] in it, it's probably a file name and we'll output that as the module name */ - if (len > 3 && s->name[len-2] == '.') - { - int l; - sprintf(buffer, "$$ %s\r\n", s->name); - l = strlen(buffer); - bfd_write(buffer, l, 1, abfd); - } - else + if (len > 3 && s->name[len - 2] == '.') + { + int l; + sprintf (buffer, "$$ %s\r\n", s->name); + l = strlen (buffer); + if (bfd_write (buffer, l, 1, abfd) != l) + return false; + } + else #endif - if (s->flags & (BSF_GLOBAL | BSF_LOCAL) - && (s->flags & BSF_DEBUGGING) == 0 - && s->name[0] != '.' - && s->name[0] != 't') - { - /* Just dump out non debug symbols */ - - int l; - char buf2[40], *p; - - sprintf_vma (buf2, s->value + s->section->lma); - p = buf2; - while (p[0] == '0' && p[1] != 0) - p++; - sprintf (buffer, " %s $%s\r\n", s->name, p); - l = strlen(buffer); - bfd_write(buffer, l, 1,abfd); - } + if (s->flags & (BSF_GLOBAL | BSF_LOCAL) + && (s->flags & BSF_DEBUGGING) == 0 + && s->name[0] != '.' + && s->name[0] != 't') + { + /* Just dump out non debug symbols */ + + int l; + char buf2[40], *p; + + sprintf_vma (buf2, + s->value + s->section->output_section->lma + + s->section->output_offset); + p = buf2; + while (p[0] == '0' && p[1] != 0) + p++; + sprintf (buffer, " %s $%s\r\n", s->name, p); + l = strlen (buffer); + if (bfd_write (buffer, l, 1, abfd) != l) + return false; + } + } + sprintf (buffer, "$$ \r\n"); + len = strlen (buffer); + if (bfd_write (buffer, len, 1, abfd) != len) + return false; } - sprintf(buffer, "$$ \r\n"); - bfd_write(buffer, strlen(buffer), 1, abfd); - } + + return true; } static boolean -internal_srec_write_object_contents(abfd, symbols) +internal_srec_write_object_contents (abfd, symbols) bfd *abfd; int symbols; { - int bytes_written; - tdata_type *tdata = abfd->tdata.srec_data; - srec_data_list_type *list; + tdata_type *tdata = abfd->tdata.srec_data; + srec_data_list_type *list; - bytes_written = 0; - - - if (symbols) - srec_write_symbols(abfd); + if (symbols) + { + if (! srec_write_symbols (abfd)) + return false; + } - srec_write_header(abfd); + if (! srec_write_header (abfd)) + return false; - /* Now wander though all the sections provided and output them */ - list = tdata->head; + /* Now wander though all the sections provided and output them */ + list = tdata->head; - while (list != (srec_data_list_type*)NULL) + while (list != (srec_data_list_type *) NULL) { - srec_write_section(abfd, tdata, list); - list = list->next; + if (! srec_write_section (abfd, tdata, list)) + return false; + list = list->next; } - srec_write_terminator(abfd, tdata); - return true; + return srec_write_terminator (abfd, tdata); } static boolean -srec_write_object_contents(abfd) +srec_write_object_contents (abfd) bfd *abfd; { - return internal_srec_write_object_contents(abfd, 0); + return internal_srec_write_object_contents (abfd, 0); } static boolean -symbolsrec_write_object_contents(abfd) +symbolsrec_write_object_contents (abfd) bfd *abfd; { - return internal_srec_write_object_contents(abfd, 1); + return internal_srec_write_object_contents (abfd, 1); } -static int -DEFUN(srec_sizeof_headers,(abfd, exec), - bfd *abfd AND - boolean exec) +/*ARGSUSED*/ +static int +srec_sizeof_headers (abfd, exec) + bfd *abfd; + boolean exec; { -return 0; + return 0; } static asymbol * -DEFUN(srec_make_empty_symbol, (abfd), - bfd*abfd) +srec_make_empty_symbol (abfd) + bfd *abfd; { - asymbol *new= (asymbol *)bfd_zalloc (abfd, sizeof (asymbol)); - new->the_bfd = abfd; + asymbol *new = (asymbol *) bfd_zalloc (abfd, sizeof (asymbol)); + if (new) + new->the_bfd = abfd; return new; } -static unsigned int -srec_get_symtab_upper_bound(abfd) -bfd *abfd; +static long +srec_get_symtab_upper_bound (abfd) + bfd *abfd; { /* Read in all the info */ - srec_get_section_contents(abfd,abfd->sections,0,0,0); - return (bfd_get_symcount(abfd) + 1) * (sizeof(asymbol *)); + if (! srec_get_section_contents (abfd, abfd->sections, 0, 0, 0)) + return -1; + return (bfd_get_symcount (abfd) + 1) * (sizeof (asymbol *)); } -static unsigned int -DEFUN(srec_get_symtab, (abfd, alocation), - bfd *abfd AND - asymbol **alocation) +static long +srec_get_symtab (abfd, alocation) + bfd *abfd; + asymbol **alocation; { int lim = abfd->symcount; int i; - for (i = 0; i < lim; i++) { - alocation[i] = abfd->tdata.srec_data->symbols + i; - } + for (i = 0; i < lim; i++) + { + alocation[i] = abfd->tdata.srec_data->symbols + i; + } alocation[i] = 0; return lim; } -void -DEFUN(srec_get_symbol_info,(ignore_abfd, symbol, ret), - bfd *ignore_abfd AND - asymbol *symbol AND - symbol_info *ret) +/*ARGSUSED*/ +void +srec_get_symbol_info (ignore_abfd, symbol, ret) + bfd *ignore_abfd; + asymbol *symbol; + symbol_info *ret; { bfd_symbol_info (symbol, ret); } -void -DEFUN(srec_print_symbol,(ignore_abfd, afile, symbol, how), - bfd *ignore_abfd AND - PTR afile AND - asymbol *symbol AND - bfd_print_symbol_type how) +/*ARGSUSED*/ +void +srec_print_symbol (ignore_abfd, afile, symbol, how) + bfd *ignore_abfd; + PTR afile; + asymbol *symbol; + bfd_print_symbol_type how; { - FILE *file = (FILE *)afile; - switch (how) - { - case bfd_print_symbol_name: - fprintf (file, "%s", symbol->name); - break; - default: - bfd_print_symbol_vandf ((PTR) file, symbol); - fprintf (file, " %-5s %s", - symbol->section->name, - symbol->name); + FILE *file = (FILE *) afile; + switch (how) + { + case bfd_print_symbol_name: + fprintf (file, "%s", symbol->name); + break; + default: + bfd_print_symbol_vandf ((PTR) file, symbol); + fprintf (file, " %-5s %s", + symbol->section->name, + symbol->name); - } + } } -#define FOO PROTO -#define srec_new_section_hook (FOO(boolean, (*), (bfd *, asection *)))bfd_true - -#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_close_and_cleanup _bfd_generic_close_and_cleanup +#define srec_bfd_free_cached_info _bfd_generic_bfd_free_cached_info +#define srec_new_section_hook _bfd_generic_new_section_hook +#define srec_bfd_is_local_label bfd_generic_is_local_label +#define srec_get_lineno _bfd_nosymbols_get_lineno +#define srec_find_nearest_line _bfd_nosymbols_find_nearest_line +#define srec_bfd_make_debug_symbol _bfd_nosymbols_bfd_make_debug_symbol -#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 (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 (FOO( boolean, (*),(bfd *, unsigned int, struct orl *, unsigned 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 -#define srec_bfd_get_relocated_section_contents bfd_generic_get_relocated_section_contents +#define srec_bfd_get_relocated_section_contents \ + bfd_generic_get_relocated_section_contents #define srec_bfd_relax_section bfd_generic_relax_section -#define srec_bfd_seclet_link bfd_generic_seclet_link -#define srec_bfd_reloc_type_lookup \ - ((CONST struct reloc_howto_struct *(*) PARAMS ((bfd *, bfd_reloc_code_real_type))) bfd_nullvoidptr) -#define srec_bfd_make_debug_symbol \ - ((asymbol *(*) PARAMS ((bfd *, void *, unsigned long))) bfd_nullvoidptr) - -bfd_target srec_vec = -{ - "srec", /* name */ - bfd_target_srec_flavour, - 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_CODE|SEC_DATA|SEC_ROM|SEC_HAS_CONTENTS - |SEC_ALLOC | SEC_LOAD | SEC_RELOC), /* section flags */ - 0, /* leading underscore */ - ' ', /* ar_pad_char */ - 16, /* ar_max_namelen */ - 1, /* minimum alignment */ - bfd_getb64, bfd_getb_signed_64, bfd_putb64, - bfd_getb32, bfd_getb_signed_32, bfd_putb32, - bfd_getb16, bfd_getb_signed_16, bfd_putb16, /* data */ - bfd_getb64, bfd_getb_signed_64, bfd_putb64, - bfd_getb32, bfd_getb_signed_32, bfd_putb32, - bfd_getb16, bfd_getb_signed_16, bfd_putb16, /* hdrs */ +#define srec_bfd_link_hash_table_create _bfd_generic_link_hash_table_create +#define srec_bfd_link_add_symbols _bfd_generic_link_add_symbols +#define srec_bfd_final_link _bfd_generic_final_link + +const bfd_target srec_vec = +{ + "srec", /* name */ + bfd_target_srec_flavour, + true, /* target byte order */ + true, /* target headers byte order */ + (HAS_RELOC | EXEC_P | /* object flags */ + HAS_LINENO | HAS_DEBUG | + HAS_SYMS | HAS_LOCALS | WP_TEXT | D_PAGED), + (SEC_CODE | SEC_DATA | SEC_ROM | SEC_HAS_CONTENTS + | SEC_ALLOC | SEC_LOAD | SEC_RELOC), /* section flags */ + 0, /* leading underscore */ + ' ', /* ar_pad_char */ + 16, /* ar_max_namelen */ + 1, /* minimum alignment */ + bfd_getb64, bfd_getb_signed_64, bfd_putb64, + bfd_getb32, bfd_getb_signed_32, bfd_putb32, + bfd_getb16, bfd_getb_signed_16, bfd_putb16, /* data */ + bfd_getb64, bfd_getb_signed_64, bfd_putb64, + bfd_getb32, bfd_getb_signed_32, bfd_putb32, + bfd_getb16, bfd_getb_signed_16, bfd_putb16, /* hdrs */ { - _bfd_dummy_target, - srec_object_p, /* bfd_check_format */ - (struct bfd_target *(*)()) bfd_nullvoidptr, - (struct bfd_target *(*)()) bfd_nullvoidptr, + _bfd_dummy_target, + srec_object_p, /* bfd_check_format */ + _bfd_dummy_target, + _bfd_dummy_target, }, { - bfd_false, - srec_mkobject, - _bfd_generic_mkarchive, - bfd_false, + bfd_false, + srec_mkobject, + _bfd_generic_mkarchive, + bfd_false, }, { /* bfd_write_contents */ - bfd_false, - srec_write_object_contents, - _bfd_write_archive_contents, - bfd_false, + bfd_false, + srec_write_object_contents, + _bfd_write_archive_contents, + bfd_false, }, - JUMP_TABLE(srec) - }; - - - -bfd_target symbolsrec_vec = -{ - "symbolsrec", /* name */ - bfd_target_srec_flavour, - 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_CODE|SEC_DATA|SEC_ROM|SEC_HAS_CONTENTS - |SEC_ALLOC | SEC_LOAD | SEC_RELOC), /* section flags */ - 0, /* leading underscore */ - ' ', /* ar_pad_char */ - 16, /* ar_max_namelen */ - 1, /* minimum alignment */ - bfd_getb64, bfd_getb_signed_64, bfd_putb64, - bfd_getb32, bfd_getb_signed_32, bfd_putb32, - bfd_getb16, bfd_getb_signed_16, bfd_putb16, /* data */ - bfd_getb64, bfd_getb_signed_64, bfd_putb64, - bfd_getb32, bfd_getb_signed_32, bfd_putb32, - bfd_getb16, bfd_getb_signed_16, bfd_putb16, /* hdrs */ + + BFD_JUMP_TABLE_GENERIC (srec), + BFD_JUMP_TABLE_COPY (_bfd_generic), + BFD_JUMP_TABLE_CORE (_bfd_nocore), + BFD_JUMP_TABLE_ARCHIVE (_bfd_noarchive), + BFD_JUMP_TABLE_SYMBOLS (srec), + BFD_JUMP_TABLE_RELOCS (_bfd_norelocs), + BFD_JUMP_TABLE_WRITE (srec), + BFD_JUMP_TABLE_LINK (srec), + BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic), + + (PTR) 0 +}; + + + +const bfd_target symbolsrec_vec = +{ + "symbolsrec", /* name */ + bfd_target_srec_flavour, + true, /* target byte order */ + true, /* target headers byte order */ + (HAS_RELOC | EXEC_P | /* object flags */ + HAS_LINENO | HAS_DEBUG | + HAS_SYMS | HAS_LOCALS | WP_TEXT | D_PAGED), + (SEC_CODE | SEC_DATA | SEC_ROM | SEC_HAS_CONTENTS + | SEC_ALLOC | SEC_LOAD | SEC_RELOC), /* section flags */ + 0, /* leading underscore */ + ' ', /* ar_pad_char */ + 16, /* ar_max_namelen */ + 1, /* minimum alignment */ + bfd_getb64, bfd_getb_signed_64, bfd_putb64, + bfd_getb32, bfd_getb_signed_32, bfd_putb32, + bfd_getb16, bfd_getb_signed_16, bfd_putb16, /* data */ + bfd_getb64, bfd_getb_signed_64, bfd_putb64, + bfd_getb32, bfd_getb_signed_32, bfd_putb32, + bfd_getb16, bfd_getb_signed_16, bfd_putb16, /* hdrs */ { - _bfd_dummy_target, - symbolsrec_object_p, /* bfd_check_format */ - (struct bfd_target *(*)()) bfd_nullvoidptr, - (struct bfd_target *(*)()) bfd_nullvoidptr, + _bfd_dummy_target, + symbolsrec_object_p, /* bfd_check_format */ + _bfd_dummy_target, + _bfd_dummy_target, }, { - bfd_false, - srec_mkobject, - _bfd_generic_mkarchive, - bfd_false, + bfd_false, + srec_mkobject, + _bfd_generic_mkarchive, + bfd_false, }, { /* bfd_write_contents */ - bfd_false, - symbolsrec_write_object_contents, - _bfd_write_archive_contents, - bfd_false, + bfd_false, + symbolsrec_write_object_contents, + _bfd_write_archive_contents, + bfd_false, }, - JUMP_TABLE(srec), - (PTR) 0 - }; + BFD_JUMP_TABLE_GENERIC (srec), + BFD_JUMP_TABLE_COPY (_bfd_generic), + BFD_JUMP_TABLE_CORE (_bfd_nocore), + BFD_JUMP_TABLE_ARCHIVE (_bfd_noarchive), + BFD_JUMP_TABLE_SYMBOLS (srec), + BFD_JUMP_TABLE_RELOCS (_bfd_norelocs), + BFD_JUMP_TABLE_WRITE (srec), + BFD_JUMP_TABLE_LINK (srec), + BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic), + + (PTR) 0 +}; diff --git a/gnu/usr.bin/gdb/bfd/stab-syms.c b/gnu/usr.bin/gdb/bfd/stab-syms.c index 88cf8506e47d..4cc9332784a2 100644 --- a/gnu/usr.bin/gdb/bfd/stab-syms.c +++ b/gnu/usr.bin/gdb/bfd/stab-syms.c @@ -1,5 +1,5 @@ /* Table of stab names for the BFD library. - Copyright (C) 1990-1991 Free Software Foundation, Inc. + Copyright (C) 1990, 91, 92, 93, 94 Free Software Foundation, Inc. Written by Cygnus Support. This file is part of BFD, the Binary File Descriptor library. @@ -20,7 +20,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "bfd.h" -#define ARCH_SIZE 32 /* Value doesn't matter. */ +#define ARCH_SIZE 32 /* Value doesn't matter. */ #include "libaout.h" #include "aout/aout64.h" @@ -28,30 +28,35 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #define __define_name(CODE, STRING) {(int)CODE, STRING}, #define __define_stab(NAME, CODE, STRING) __define_name(CODE, STRING) -CONST struct {short code; char string[10];} aout_stab_names[] - = { +CONST struct + { + short code; + char string[10]; + } +aout_stab_names[] = +{ #include "aout/stab.def" /* These are not really stab symbols, but it is convenient to have them here for the sake of nm. For completeness, we could also add N_TEXT etc, but those are never needed, since nm treats those specially. */ -__define_name (N_SETA, "SETA") /* Absolute set element symbol */ -__define_name (N_SETT, "SETT") /* Text set element symbol */ -__define_name (N_SETD, "SETD") /* Data set element symbol */ -__define_name (N_SETB, "SETB") /* Bss set element symbol */ -__define_name (N_SETV, "SETV") /* Pointer to set vector in data area. */ -__define_name (N_INDR, "INDR") -__define_name (N_WARNING, "WARNING") - }; + __define_name (N_SETA, "SETA")/* Absolute set element symbol */ + __define_name (N_SETT, "SETT")/* Text set element symbol */ + __define_name (N_SETD, "SETD")/* Data set element symbol */ + __define_name (N_SETB, "SETB")/* Bss set element symbol */ + __define_name (N_SETV, "SETV")/* Pointer to set vector in data area. */ + __define_name (N_INDR, "INDR") + __define_name (N_WARNING, "WARNING") +}; #undef __define_stab #undef GNU_EXTRA_STABS CONST char * -DEFUN(aout_stab_name,(code), -int code) +aout_stab_name (code) + int code; { - register int i = sizeof(aout_stab_names) / sizeof(aout_stab_names[0]); + register int i = sizeof (aout_stab_names) / sizeof (aout_stab_names[0]); while (--i >= 0) if (aout_stab_names[i].code == code) return aout_stab_names[i].string; diff --git a/gnu/usr.bin/gdb/bfd/syms.c b/gnu/usr.bin/gdb/bfd/syms.c index 89ac00124e3c..23a70f5e3ea9 100644 --- a/gnu/usr.bin/gdb/bfd/syms.c +++ b/gnu/usr.bin/gdb/bfd/syms.c @@ -22,20 +22,20 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ SECTION Symbols - BFD trys to maintain as much symbol information as it can when + BFD tries to maintain as much symbol information as it can when it moves information from file to file. BFD passes information to applications though the <<asymbol>> structure. When the application requests the symbol table, BFD reads the table in the native form and translates parts of it into the internal - format. To maintain more than the infomation passed to - applications some targets keep some information `behind the - scenes', in a structure only the particular back end knows + format. To maintain more than the information passed to + applications, some targets keep some information ``behind the + scenes'' in a structure only the particular back end knows about. For example, the coff back end keeps the original symbol table structure as well as the canonical structure when a BFD is read in. On output, the coff back end can reconstruct the output symbol table so that no information is lost, even information unique to coff which BFD doesn't know or - understand. If a coff symbol table was read, but was written + understand. If a coff symbol table were read, but were written through an a.out back end, all the coff specific information would be lost. The symbol table of a BFD is not necessarily read in until a canonicalize request is @@ -43,8 +43,8 @@ SECTION application with pointers to the canonical information. To output symbols, the application provides BFD with a table of pointers to pointers to <<asymbol>>s. This allows applications - like the linker to output a symbol as read, since the `behind - the scenes' information will be still available. + like the linker to output a symbol as it was read, since the ``behind + the scenes'' information will be still available. @menu @* Reading Symbols:: @* Writing Symbols:: @@ -55,57 +55,63 @@ SECTION INODE Reading Symbols, Writing Symbols, Symbols, Symbols SUBSECTION - Reading Symbols + Reading symbols - There are two stages to reading a symbol table from a BFD; + There are two stages to reading a symbol table from a BFD: allocating storage, and the actual reading process. This is an - excerpt from an appliction which reads the symbol table: + excerpt from an application which reads the symbol table: -| unsigned int storage_needed; +| long storage_needed; | asymbol **symbol_table; -| unsigned int number_of_symbols; -| unsigned int i; -| -| storage_needed = get_symtab_upper_bound (abfd); -| +| long number_of_symbols; +| long i; +| +| storage_needed = bfd_get_symtab_upper_bound (abfd); +| +| if (storage_needed < 0) +| FAIL +| | if (storage_needed == 0) { | return ; | } -| symbol_table = (asymbol **) bfd_xmalloc (storage_needed); +| symbol_table = (asymbol **) xmalloc (storage_needed); | ... -| number_of_symbols = -| bfd_canonicalize_symtab (abfd, symbol_table); -| +| number_of_symbols = +| bfd_canonicalize_symtab (abfd, symbol_table); +| +| if (number_of_symbols < 0) +| FAIL +| | for (i = 0; i < number_of_symbols; i++) { | process_symbol (symbol_table[i]); | } All storage for the symbols themselves is in an obstack - connected to the BFD, and is freed when the BFD is closed. + connected to the BFD; it is freed when the BFD is closed. INODE Writing Symbols, typedef asymbol, Reading Symbols, Symbols SUBSECTION - Writing Symbols + Writing symbols Writing of a symbol table is automatic when a BFD open for writing is closed. The application attaches a vector of pointers to pointers to symbols to the BFD being written, and fills in the symbol count. The close and cleanup code reads through the table provided and performs all the necessary - operations. The outputing code must always be provided with an - 'owned' symbol; one which has come from another BFD, or one - which has been created using <<bfd_make_empty_symbol>>. An + operations. The BFD output code must always be provided with an + ``owned'' symbol: one which has come from another BFD, or one + which has been created using <<bfd_make_empty_symbol>>. Here is an example showing the creation of a symbol table with only one element: | #include "bfd.h" -| main() +| main() | { | bfd *abfd; | asymbol *ptrs[2]; | asymbol *new; -| +| | abfd = bfd_openw("foo","a.out-sunos-big"); | bfd_set_format(abfd, bfd_object); | new = bfd_make_empty_symbol(abfd); @@ -113,23 +119,23 @@ SUBSECTION | new->section = bfd_make_section_old_way(abfd, ".text"); | new->flags = BSF_GLOBAL; | new->value = 0x12345; -| +| | ptrs[0] = new; | ptrs[1] = (asymbol *)0; -| +| | bfd_set_symtab(abfd, ptrs, 1); | bfd_close(abfd); | } -| -| ./makesym +| +| ./makesym | nm foo | 00012345 A dummy_symbol Many formats cannot represent arbitary symbol information; for - instance the <<a.out>> object format does not allow an + instance, the <<a.out>> object format does not allow an arbitary number of sections. A symbol pointing to a section which is not one of <<.text>>, <<.data>> or <<.bss>> cannot - be described. + be described. */ @@ -153,7 +159,7 @@ SUBSECTION CODE_FRAGMENT . -.typedef struct symbol_cache_entry +.typedef struct symbol_cache_entry .{ . {* A pointer to the BFD which owns the symbol. This information . is necessary so that a back end can work out what additional @@ -167,7 +173,7 @@ CODE_FRAGMENT . . struct _bfd *the_bfd; {* Use bfd_asymbol_bfd(sym) to access this field. *} . -. {* The text of the symbol. The name is left alone, and not copied - the +. {* The text of the symbol. The name is left alone, and not copied; the . application may not alter it. *} . CONST char *name; . @@ -188,7 +194,7 @@ CODE_FRAGMENT . value is the offset into the section of the data. *} .#define BSF_GLOBAL 0x02 . -. {* The symbol has global scope, and is exported. The value is +. {* The symbol has global scope and is exported. The value is . the offset into the section of the data. *} .#define BSF_EXPORT BSF_GLOBAL {* no real difference *} . @@ -249,9 +255,12 @@ CODE_FRAGMENT . for ELF STT_FILE symbols. *} .#define BSF_FILE 0x4000 . +. {* Symbol is from dynamic linking information. *} +.#define BSF_DYNAMIC 0x8000 +. . flagword flags; . -. {* A pointer to the section to which this symbol is +. {* A pointer to the section to which this symbol is . relative. This will always be non NULL, there are special . sections for undefined and absolute symbols *} . struct sec *section; @@ -268,39 +277,53 @@ CODE_FRAGMENT #include "libbfd.h" #include "aout/stab_gnu.h" - + /* DOCDD INODE symbol handling functions, , typedef asymbol, Symbols SUBSECTION - Symbol Handling Functions + Symbol handling functions */ /* FUNCTION - get_symtab_upper_bound + bfd_get_symtab_upper_bound DESCRIPTION - Returns the number of bytes required in a vector of pointers - to <<asymbols>> for all the symbols in the supplied BFD, + Return the number of bytes required to store a vector of pointers + to <<asymbols>> for all the symbols in the BFD @var{abfd}, including a terminal NULL pointer. If there are no symbols in - the BFD, then 0 is returned. + the BFD, then return 0. If an error occurs, return -1. -.#define get_symtab_upper_bound(abfd) \ -. BFD_SEND (abfd, _get_symtab_upper_bound, (abfd)) +.#define bfd_get_symtab_upper_bound(abfd) \ +. BFD_SEND (abfd, _bfd_get_symtab_upper_bound, (abfd)) */ /* FUNCTION + bfd_is_local_label + +SYNOPSIS + boolean bfd_is_local_label(bfd *abfd, asymbol *sym); + +DESCRIPTION + Return true if the given symbol @var{sym} in the BFD @var{abfd} is + a compiler generated local label, else return false. +.#define bfd_is_local_label(abfd, sym) \ +. BFD_SEND (abfd, _bfd_is_local_label,(abfd, sym)) +*/ + +/* +FUNCTION bfd_canonicalize_symtab DESCRIPTION - Supplied a BFD and a pointer to an uninitialized vector of - pointers. This reads in the symbols from the BFD, and fills in - the table with pointers to the symbols, and a trailing NULL. - The routine returns the actual number of symbol pointers not + Read the symbols from the BFD @var{abfd}, and fills in + the vector @var{location} with pointers to the symbols and + a trailing NULL. + Return the actual number of symbol pointers, not including the NULL. @@ -315,12 +338,13 @@ DESCRIPTION FUNCTION bfd_set_symtab -DESCRIPTION - Provided a table of pointers to symbols and a count, writes to - the output BFD the symbols when closed. - SYNOPSIS - boolean bfd_set_symtab (bfd *, asymbol **, unsigned int ); + boolean bfd_set_symtab (bfd *abfd, asymbol **location, unsigned int count); + +DESCRIPTION + Arrange that when the output BFD @var{abfd} is closed, + the table @var{location} of @var{count} pointers to symbols + will be written. */ boolean @@ -329,10 +353,11 @@ bfd_set_symtab (abfd, location, symcount) asymbol **location; unsigned int symcount; { - if ((abfd->format != bfd_object) || (bfd_read_p (abfd))) { - bfd_error = invalid_operation; - return false; - } + if ((abfd->format != bfd_object) || (bfd_read_p (abfd))) + { + bfd_set_error (bfd_error_invalid_operation); + return false; + } bfd_get_outsymbols (abfd) = location; bfd_get_symcount (abfd) = symcount; @@ -343,35 +368,40 @@ bfd_set_symtab (abfd, location, symcount) FUNCTION bfd_print_symbol_vandf -DESCRIPTION - Prints the value and flags of the symbol supplied to the stream file. - SYNOPSIS void bfd_print_symbol_vandf(PTR file, asymbol *symbol); + +DESCRIPTION + Print the value and flags of the @var{symbol} supplied to the + stream @var{file}. */ void -DEFUN(bfd_print_symbol_vandf,(file, symbol), -PTR file AND -asymbol *symbol) +bfd_print_symbol_vandf (arg, symbol) + PTR arg; + asymbol *symbol; { + FILE *file = (FILE *) arg; 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_WEAK) ? 'w' : ' ', - (type & BSF_CONSTRUCTOR) ? 'C' : ' ', - (type & BSF_WARNING) ? 'W' : ' ', - (type & BSF_INDIRECT) ? 'I' : ' ', - (type & BSF_DEBUGGING) ? 'd' :' '); - + if (symbol->section != (asection *) NULL) + { + fprintf_vma (file, symbol->value + symbol->section->vma); + } + else + { + fprintf_vma (file, symbol->value); + } + + /* This presumes that a symbol can not be both BSF_DEBUGGING and + BSF_DYNAMIC. */ + fprintf (file, " %c%c%c%c%c%c%c", + (type & BSF_LOCAL) ? 'l' : ' ', + (type & BSF_GLOBAL) ? 'g' : ' ', + (type & BSF_WEAK) ? 'w' : ' ', + (type & BSF_CONSTRUCTOR) ? 'C' : ' ', + (type & BSF_WARNING) ? 'W' : ' ', + (type & BSF_INDIRECT) ? 'I' : ' ', + (type & BSF_DEBUGGING) ? 'd' + : (type & BSF_DYNAMIC) ? 'D' : ' '); } @@ -380,10 +410,10 @@ FUNCTION bfd_make_empty_symbol DESCRIPTION - This function creates a new <<asymbol>> structure for the BFD, - and returns a pointer to it. + Create a new <<asymbol>> structure for the BFD @var{abfd} + and return a pointer to it. - This routine is necessary, since each back end has private + This routine is necessary because each back end has private information surrounding the <<asymbol>>. Building your own <<asymbol>> and pointing to it will not create the private information, and will cause problems later on. @@ -397,7 +427,7 @@ FUNCTION bfd_make_debug_symbol DESCRIPTION - This function creates a new <<asymbol>> structure for the BFD, + Create a new <<asymbol>> structure for the BFD @var{abfd}, to be used as a debugging symbol. Further details of its use have yet to be worked out. @@ -411,10 +441,11 @@ struct section_to_type char type; }; -/* Map COFF section names to POSIX/BSD single-character symbol types. +/* Map section names to POSIX/BSD single-character symbol types. This table is probably incomplete. It is sorted for convenience of adding entries. Since it is so short, a linear search is used. */ -static CONST struct section_to_type stt[] = { +static CONST struct section_to_type stt[] = +{ {"*DEBUG*", 'N'}, {".bss", 'b'}, {".data", 'd'}, @@ -426,7 +457,7 @@ static CONST struct section_to_type stt[] = { }; /* Return the single-character symbol type corresponding to - COFF section S, or '?' for an unknown COFF section. */ + section S, or '?' for an unknown COFF section. */ static char coff_section_type (s) @@ -453,27 +484,27 @@ FUNCTION DESCRIPTION Return a character corresponding to the symbol - class of symbol, or '?' for an unknown class. + class of @var{symbol}, or '?' for an unknown class. SYNOPSIS int bfd_decode_symclass(asymbol *symbol); */ int -DEFUN(bfd_decode_symclass,(symbol), -asymbol *symbol) +bfd_decode_symclass (symbol) + asymbol *symbol; { char c; if (bfd_is_com_section (symbol->section)) return 'C'; - if (symbol->section == &bfd_und_section) + if (bfd_is_und_section (symbol->section)) return 'U'; - if (symbol->section == &bfd_ind_section) + if (bfd_is_ind_section (symbol->section)) return 'I'; - if (!(symbol->flags & (BSF_GLOBAL|BSF_LOCAL))) + if (!(symbol->flags & (BSF_GLOBAL | BSF_LOCAL))) return '?'; - if (symbol->section == &bfd_abs_section) + if (bfd_is_abs_section (symbol->section)) c = 'a'; else if (symbol->section) c = coff_section_type (symbol->section->name); @@ -484,8 +515,8 @@ asymbol *symbol) return c; /* We don't have to handle these cases just yet, but we will soon: - N_SETV: 'v'; - N_SETA: 'l'; + N_SETV: 'v'; + N_SETA: 'l'; N_SETT: 'x'; N_SETD: 'z'; N_SETB: 's'; @@ -507,21 +538,20 @@ SYNOPSIS */ void -DEFUN(bfd_symbol_info,(symbol, ret), - asymbol *symbol AND - symbol_info *ret) +bfd_symbol_info (symbol, ret) + asymbol *symbol; + symbol_info *ret; { ret->type = bfd_decode_symclass (symbol); if (ret->type != 'U') - ret->value = symbol->value+symbol->section->vma; + ret->value = symbol->value + symbol->section->vma; else ret->value = 0; ret->name = symbol->name; } void -bfd_symbol_is_absolute() +bfd_symbol_is_absolute () { - abort(); + abort (); } - diff --git a/gnu/usr.bin/gdb/bfd/sysdep.h b/gnu/usr.bin/gdb/bfd/sysdep.h index dd7328b1d0f0..68b107d7b67b 100644 --- a/gnu/usr.bin/gdb/bfd/sysdep.h +++ b/gnu/usr.bin/gdb/bfd/sysdep.h @@ -30,13 +30,12 @@ #ifdef __bsdi__ /* This seems to be the right thing for BSDI. */ #define HOST_STACK_END_ADDR USRSTACK +#define HOST_DATA_START_ADDR ((bfd_vma)u.u_kproc.kp_eproc.e_vm.vm_daddr) #else /* This seems to be the right thing for 386BSD release 0.1. */ #define HOST_STACK_END_ADDR (USRSTACK - MAXSSIZ) #endif -#define HOST_DATA_START_ADDR ((bfd_vma)u.u_kproc.kp_eproc.e_vm.vm_daddr) - #define TRAD_UNIX_CORE_FILE_FAILING_SIGNAL(core_bfd) \ ((core_bfd)->tdata.trad_core_data->u.u_sig) #define u_comm u_kproc.kp_proc.p_comm diff --git a/gnu/usr.bin/gdb/bfd/targets.c b/gnu/usr.bin/gdb/bfd/targets.c index d6a966588c45..15a1e45f25df 100644 --- a/gnu/usr.bin/gdb/bfd/targets.c +++ b/gnu/usr.bin/gdb/bfd/targets.c @@ -1,5 +1,5 @@ /* Generic target-file-type support for the BFD library. - Copyright 1990, 1991, 1992, 1993 Free Software Foundation, Inc. + Copyright 1990, 91, 92, 93, 1994 Free Software Foundation, Inc. Written by Cygnus Support. This file is part of BFD, the Binary File Descriptor library. @@ -38,25 +38,25 @@ DESCRIPTION target are unknown. BFD uses various mechanisms to determine how to interpret the file. The operations performed are: - o First a BFD is created by calling the internal routine - <<new_bfd>>, then <<bfd_find_target>> is called with the + o Create a BFD by calling the internal routine + <<_bfd_new_bfd>>, then call <<bfd_find_target>> with the target string supplied to <<bfd_openr>> and the new BFD pointer. o If a null target string was provided to <<bfd_find_target>>, - it looks up the environment variable <<GNUTARGET>> and uses + look up the environment variable <<GNUTARGET>> and use that as the target string. - o If the target string is still NULL, or the target string is - <<default>>, then the first item in the target vector is used - as the target type, and <<target_defaulted>> is set to + o If the target string is still <<NULL>>, or the target string is + <<default>>, then use the first item in the target vector + as the target type, and set <<target_defaulted>> in the BFD to cause <<bfd_check_format>> to loop through all the targets. @xref{bfd_target}. @xref{Formats}. - o Otherwise, the elements in the target vector are inspected + o Otherwise, inspect the elements in the target vector one by one, until a match on target name is found. When found, - that is used. + use it. - o Otherwise the error <<invalid_target>> is returned to + o Otherwise return the error <<bfd_error_invalid_target>> to <<bfd_openr>>. o <<bfd_openr>> attempts to open the file using @@ -66,8 +66,8 @@ DESCRIPTION format may be determined. This is done by calling <<bfd_check_format>> on the BFD with a suggested format. If <<target_defaulted>> has been set, each possible target - type is tried to see if it recognizes the specified format. The - routine returns <<true>> when the application guesses right. + type is tried to see if it recognizes the specified format. + <<bfd_check_format>> returns <<true>> when the caller guesses right. @menu @* bfd_target:: @end menu @@ -84,16 +84,16 @@ SUBSECTION DESCRIPTION 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. + target. It includes things like its byte order, name, and which + routines to call to do various operations. Every BFD points to a target structure with its <<xvec>> member. - These macros are used to dispatch to functions through the - bfd_target vector. They are used in a number of macros further + The macros below are used to dispatch to functions through the + <<bfd_target>> vector. They are used in a number of macros further down in @file{bfd.h}, and are also used when calling various - routines by hand inside the BFD implementation. The "arglist" + routines by hand inside the BFD implementation. The @var{arglist} argument must be parenthesized; it contains all the arguments to the called function. @@ -102,13 +102,29 @@ DESCRIPTION .#define BFD_SEND(bfd, message, arglist) \ . ((*((bfd)->xvec->message)) arglist) +. +.#ifdef DEBUG_BFD_SEND +.#undef BFD_SEND +.#define BFD_SEND(bfd, message, arglist) \ +. (((bfd) && (bfd)->xvec && (bfd)->xvec->message) ? \ +. ((*((bfd)->xvec->message)) arglist) : \ +. (bfd_assert (__FILE__,__LINE__), NULL)) +.#endif - For operations which index on the BFD format + For operations which index on the BFD format: .#define BFD_SEND_FMT(bfd, message, arglist) \ . (((bfd)->xvec->message[(int)((bfd)->format)]) arglist) +. +.#ifdef DEBUG_BFD_SEND +.#undef BFD_SEND_FMT +.#define BFD_SEND_FMT(bfd, message, arglist) \ +. (((bfd) && (bfd)->xvec && (bfd)->xvec->message) ? \ +. (((bfd)->xvec->message[(int)((bfd)->format)]) arglist) : \ +. (bfd_assert (__FILE__,__LINE__), NULL)) +.#endif - This is the struct which defines the type of BFD this is. The + This is the structure 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. @@ -118,28 +134,34 @@ DESCRIPTION the entry points which call them. Too bad we can't have one macro to define them both! +.enum bfd_flavour { +. bfd_target_unknown_flavour, +. bfd_target_aout_flavour, +. bfd_target_coff_flavour, +. bfd_target_ecoff_flavour, +. bfd_target_elf_flavour, +. bfd_target_ieee_flavour, +. bfd_target_nlm_flavour, +. bfd_target_oasys_flavour, +. bfd_target_tekhex_flavour, +. bfd_target_srec_flavour, +. bfd_target_som_flavour, +. bfd_target_os9k_flavour}; +. +.{* Forward declaration. *} +.typedef struct bfd_link_info _bfd_link_info; +. .typedef struct bfd_target .{ -Identifies the kind of target, eg SunOS4, Ultrix, etc. +Identifies the kind of target, e.g., SunOS4, Ultrix, etc. . char *name; The "flavour" of a back end is a general indication about the contents of a file. -. enum target_flavour { -. bfd_target_unknown_flavour, -. bfd_target_aout_flavour, -. bfd_target_coff_flavour, -. bfd_target_ecoff_flavour, -. bfd_target_elf_flavour, -. bfd_target_ieee_flavour, -. bfd_target_nlm_flavour, -. bfd_target_oasys_flavour, -. bfd_target_tekhex_flavour, -. bfd_target_srec_flavour, -. bfd_target_hppa_flavour} flavour; +. enum bfd_flavour flavour; The order of bytes within the data area of a file. @@ -149,22 +171,22 @@ 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 - +A mask of all the flags which an executable may have set - from the set <<NO_FLAGS>>, <<HAS_RELOC>>, ...<<D_PAGED>>. . flagword object_flags; -This is a mask of all the flags which a section may have set - from +A mask of all the flags which a section may have set - from the set <<SEC_NO_FLAGS>>, <<SEC_ALLOC>>, ...<<SET_NEVER_LOAD>>. . flagword section_flags; The character normally found at the front of a symbol -(if any), perhaps _. +(if any), perhaps `_'. . char symbol_leading_char; -The pad character for filenames within an archive header. +The pad character for file names within an archive header. . char ar_pad_char; @@ -176,60 +198,95 @@ 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. +Entries for byte swapping for data. These are different from the other +entry points, since they don't take a BFD asthe first argument. +Certain other handlers could do the same. -. bfd_vma (*bfd_getx64) PARAMS ((bfd_byte *)); -. bfd_signed_vma (*bfd_getx_signed_64) PARAMS ((bfd_byte *)); +. bfd_vma (*bfd_getx64) PARAMS ((const bfd_byte *)); +. bfd_signed_vma (*bfd_getx_signed_64) PARAMS ((const bfd_byte *)); . void (*bfd_putx64) PARAMS ((bfd_vma, bfd_byte *)); -. bfd_vma (*bfd_getx32) PARAMS ((bfd_byte *)); -. bfd_signed_vma (*bfd_getx_signed_32) PARAMS ((bfd_byte *)); +. bfd_vma (*bfd_getx32) PARAMS ((const bfd_byte *)); +. bfd_signed_vma (*bfd_getx_signed_32) PARAMS ((const bfd_byte *)); . void (*bfd_putx32) PARAMS ((bfd_vma, bfd_byte *)); -. bfd_vma (*bfd_getx16) PARAMS ((bfd_byte *)); -. bfd_signed_vma (*bfd_getx_signed_16) PARAMS ((bfd_byte *)); +. bfd_vma (*bfd_getx16) PARAMS ((const bfd_byte *)); +. bfd_signed_vma (*bfd_getx_signed_16) PARAMS ((const bfd_byte *)); . void (*bfd_putx16) PARAMS ((bfd_vma, bfd_byte *)); Byte swapping for the headers -. bfd_vma (*bfd_h_getx64) PARAMS ((bfd_byte *)); -. bfd_signed_vma (*bfd_h_getx_signed_64) PARAMS ((bfd_byte *)); +. bfd_vma (*bfd_h_getx64) PARAMS ((const bfd_byte *)); +. bfd_signed_vma (*bfd_h_getx_signed_64) PARAMS ((const bfd_byte *)); . void (*bfd_h_putx64) PARAMS ((bfd_vma, bfd_byte *)); -. bfd_vma (*bfd_h_getx32) PARAMS ((bfd_byte *)); -. bfd_signed_vma (*bfd_h_getx_signed_32) PARAMS ((bfd_byte *)); +. bfd_vma (*bfd_h_getx32) PARAMS ((const bfd_byte *)); +. bfd_signed_vma (*bfd_h_getx_signed_32) PARAMS ((const bfd_byte *)); . void (*bfd_h_putx32) PARAMS ((bfd_vma, bfd_byte *)); -. bfd_vma (*bfd_h_getx16) PARAMS ((bfd_byte *)); -. bfd_signed_vma (*bfd_h_getx_signed_16) PARAMS ((bfd_byte *)); +. bfd_vma (*bfd_h_getx16) PARAMS ((const bfd_byte *)); +. bfd_signed_vma (*bfd_h_getx_signed_16) PARAMS ((const bfd_byte *)); . void (*bfd_h_putx16) PARAMS ((bfd_vma, bfd_byte *)); Format dependent routines: these are 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. +Check the format of a file being read. Return a <<bfd_target *>> or zero. -. struct bfd_target * (*_bfd_check_format[bfd_type_end]) PARAMS ((bfd *)); +. const struct bfd_target *(*_bfd_check_format[bfd_type_end]) PARAMS ((bfd *)); Set the format of a file being written. . boolean (*_bfd_set_format[bfd_type_end]) PARAMS ((bfd *)); -Write cached information into a file being written, at bfd_close. +Write cached information into a file being written, at <<bfd_close>>. . boolean (*_bfd_write_contents[bfd_type_end]) PARAMS ((bfd *)); -The following functions are defined in <<JUMP_TABLE>>. The idea is -that the back end writer of <<foo>> names all the routines -<<foo_>>@var{entry_point}, <<JUMP_TABLE>> will built the entries -in this structure in the right order. - -Core file entry points +The general target vector. +. +. {* Generic entry points. *} +.#define BFD_JUMP_TABLE_GENERIC(NAME)\ +.CAT(NAME,_close_and_cleanup),\ +.CAT(NAME,_bfd_free_cached_info),\ +.CAT(NAME,_new_section_hook),\ +.CAT(NAME,_get_section_contents) +. {* Called when the BFD is being closed to do any necessary cleanup. *} +. boolean (*_close_and_cleanup) PARAMS ((bfd *)); +. {* Ask the BFD to free all cached information. *} +. boolean (*_bfd_free_cached_info) PARAMS ((bfd *)); +. {* Called when a new section is created. *} +. boolean (*_new_section_hook) PARAMS ((bfd *, sec_ptr)); +. {* Read the contents of a section. *} +. boolean (*_bfd_get_section_contents) PARAMS ((bfd *, sec_ptr, PTR, +. file_ptr, bfd_size_type)); +. +. {* Entry points to copy private data. *} +.#define BFD_JUMP_TABLE_COPY(NAME)\ +.CAT(NAME,_bfd_copy_private_bfd_data),\ +.CAT(NAME,_bfd_copy_private_section_data) +. {* Called to copy BFD general private data from one object file +. to another. *} +. boolean (*_bfd_copy_private_bfd_data) PARAMS ((bfd *, bfd *)); +. {* Called to copy BFD private section data from one object file +. to another. *} +. boolean (*_bfd_copy_private_section_data) PARAMS ((bfd *, sec_ptr, +. bfd *, sec_ptr)); +. +. {* Core file entry points. *} +.#define BFD_JUMP_TABLE_CORE(NAME)\ +.CAT(NAME,_core_file_failing_command),\ +.CAT(NAME,_core_file_failing_signal),\ +.CAT(NAME,_core_file_matches_executable_p) . char * (*_core_file_failing_command) PARAMS ((bfd *)); . int (*_core_file_failing_signal) PARAMS ((bfd *)); . boolean (*_core_file_matches_executable_p) PARAMS ((bfd *, bfd *)); - -Archive entry points - +. +. {* Archive entry points. *} +.#define BFD_JUMP_TABLE_ARCHIVE(NAME)\ +.CAT(NAME,_slurp_armap),\ +.CAT(NAME,_slurp_extended_name_table),\ +.CAT(NAME,_truncate_arname),\ +.CAT(NAME,_write_armap),\ +.CAT(NAME,_openr_next_archived_file),\ +.CAT(NAME,_generic_stat_arch_elt) . boolean (*_bfd_slurp_armap) PARAMS ((bfd *)); . boolean (*_bfd_slurp_extended_name_table) PARAMS ((bfd *)); . void (*_bfd_truncate_arname) PARAMS ((bfd *, CONST char *, char *)); @@ -238,24 +295,23 @@ Archive entry points . struct orl *map, . unsigned int orl_count, . int stridx)); - -Standard stuff. - -. boolean (*_close_and_cleanup) PARAMS ((bfd *)); -. boolean (*_bfd_set_section_contents) PARAMS ((bfd *, sec_ptr, PTR, -. file_ptr, bfd_size_type)); -. boolean (*_bfd_get_section_contents) PARAMS ((bfd *, sec_ptr, PTR, -. file_ptr, bfd_size_type)); -. boolean (*_new_section_hook) PARAMS ((bfd *, sec_ptr)); - -Symbols and relocations - -. unsigned int (*_get_symtab_upper_bound) PARAMS ((bfd *)); -. unsigned int (*_bfd_canonicalize_symtab) PARAMS ((bfd *, -. struct symbol_cache_entry **)); -. unsigned int (*_get_reloc_upper_bound) PARAMS ((bfd *, sec_ptr)); -. unsigned int (*_bfd_canonicalize_reloc) PARAMS ((bfd *, sec_ptr, arelent **, -. struct symbol_cache_entry **)); +. bfd * (*openr_next_archived_file) PARAMS ((bfd *arch, bfd *prev)); +. int (*_bfd_stat_arch_elt) PARAMS ((bfd *, struct stat *)); +. +. {* Entry points used for symbols. *} +.#define BFD_JUMP_TABLE_SYMBOLS(NAME)\ +.CAT(NAME,_get_symtab_upper_bound),\ +.CAT(NAME,_get_symtab),\ +.CAT(NAME,_make_empty_symbol),\ +.CAT(NAME,_print_symbol),\ +.CAT(NAME,_get_symbol_info),\ +.CAT(NAME,_bfd_is_local_label),\ +.CAT(NAME,_get_lineno),\ +.CAT(NAME,_find_nearest_line),\ +.CAT(NAME,_bfd_make_debug_symbol) +. long (*_bfd_get_symtab_upper_bound) PARAMS ((bfd *)); +. long (*_bfd_canonicalize_symtab) PARAMS ((bfd *, +. struct symbol_cache_entry **)); . struct symbol_cache_entry * . (*_bfd_make_empty_symbol) PARAMS ((bfd *)); . void (*_bfd_print_symbol) PARAMS ((bfd *, PTR, @@ -266,49 +322,88 @@ Symbols and relocations . struct symbol_cache_entry *, . symbol_info *)); .#define bfd_get_symbol_info(b,p,e) BFD_SEND(b, _bfd_get_symbol_info, (b,p,e)) - -. alent * (*_get_lineno) PARAMS ((bfd *, struct symbol_cache_entry *)); +. boolean (*_bfd_is_local_label) PARAMS ((bfd *, asymbol *)); . -. boolean (*_bfd_set_arch_mach) PARAMS ((bfd *, enum bfd_architecture, -. unsigned long)); -. -. bfd * (*openr_next_archived_file) PARAMS ((bfd *arch, bfd *prev)); -. +. alent * (*_get_lineno) PARAMS ((bfd *, struct symbol_cache_entry *)); . boolean (*_bfd_find_nearest_line) PARAMS ((bfd *abfd, . struct sec *section, struct symbol_cache_entry **symbols, . bfd_vma offset, CONST char **file, CONST char **func, . unsigned int *line)); -. -. int (*_bfd_stat_arch_elt) PARAMS ((bfd *, struct stat *)); +. {* Back-door to allow format-aware applications to create debug symbols +. while using BFD for everything else. Currently used by the assembler +. when creating COFF files. *} +. asymbol * (*_bfd_make_debug_symbol) PARAMS (( +. bfd *abfd, +. void *ptr, +. unsigned long size)); . -. int (*_bfd_sizeof_headers) PARAMS ((bfd *, boolean)); +. {* Routines for relocs. *} +.#define BFD_JUMP_TABLE_RELOCS(NAME)\ +.CAT(NAME,_get_reloc_upper_bound),\ +.CAT(NAME,_canonicalize_reloc),\ +.CAT(NAME,_bfd_reloc_type_lookup) +. long (*_get_reloc_upper_bound) PARAMS ((bfd *, sec_ptr)); +. long (*_bfd_canonicalize_reloc) PARAMS ((bfd *, sec_ptr, arelent **, +. struct symbol_cache_entry **)); +. {* See documentation on reloc types. *} +. CONST struct reloc_howto_struct * +. (*reloc_type_lookup) PARAMS ((bfd *abfd, +. bfd_reloc_code_real_type code)); . -. void (*_bfd_debug_info_start) PARAMS ((bfd *)); -. void (*_bfd_debug_info_end) PARAMS ((bfd *)); -. void (*_bfd_debug_info_accumulate) PARAMS ((bfd *, struct sec *)); +. {* Routines used when writing an object file. *} +.#define BFD_JUMP_TABLE_WRITE(NAME)\ +.CAT(NAME,_set_arch_mach),\ +.CAT(NAME,_set_section_contents) +. boolean (*_bfd_set_arch_mach) PARAMS ((bfd *, enum bfd_architecture, +. unsigned long)); +. boolean (*_bfd_set_section_contents) PARAMS ((bfd *, sec_ptr, PTR, +. file_ptr, bfd_size_type)); . +. {* Routines used by the linker. *} +.#define BFD_JUMP_TABLE_LINK(NAME)\ +.CAT(NAME,_sizeof_headers),\ +.CAT(NAME,_bfd_get_relocated_section_contents),\ +.CAT(NAME,_bfd_relax_section),\ +.CAT(NAME,_bfd_link_hash_table_create),\ +.CAT(NAME,_bfd_link_add_symbols),\ +.CAT(NAME,_bfd_final_link) +. int (*_bfd_sizeof_headers) PARAMS ((bfd *, boolean)); . bfd_byte * (*_bfd_get_relocated_section_contents) PARAMS ((bfd *, -. struct bfd_seclet *, bfd_byte *data, -. boolean relocateable)); +. struct bfd_link_info *, struct bfd_link_order *, +. bfd_byte *data, boolean relocateable, +. struct symbol_cache_entry **)); . . boolean (*_bfd_relax_section) PARAMS ((bfd *, struct sec *, -. struct symbol_cache_entry **)); +. struct bfd_link_info *, boolean *again)); . -. boolean (*_bfd_seclet_link) PARAMS ((bfd *, PTR data, -. boolean relocateable)); - -. {* See documentation on reloc types. *} -. CONST struct reloc_howto_struct * -. (*reloc_type_lookup) PARAMS ((bfd *abfd, -. bfd_reloc_code_real_type code)); +. {* Create a hash table for the linker. Different backends store +. different information in this table. *} +. struct bfd_link_hash_table *(*_bfd_link_hash_table_create) PARAMS ((bfd *)); +. +. {* Add symbols from this object file into the hash table. *} +. boolean (*_bfd_link_add_symbols) PARAMS ((bfd *, struct bfd_link_info *)); +. +. {* Do a link based on the link_order structures attached to each +. section of the BFD. *} +. boolean (*_bfd_final_link) PARAMS ((bfd *, struct bfd_link_info *)); +. +. {* Routines to handle dynamic symbols and relocs. *} +.#define BFD_JUMP_TABLE_DYNAMIC(NAME)\ +.CAT(NAME,_get_dynamic_symtab_upper_bound),\ +.CAT(NAME,_canonicalize_dynamic_symtab),\ +.CAT(NAME,_get_dynamic_reloc_upper_bound),\ +.CAT(NAME,_canonicalize_dynamic_reloc) +. {* Get the amount of memory required to hold the dynamic symbols. *} +. long (*_bfd_get_dynamic_symtab_upper_bound) PARAMS ((bfd *)); +. {* Read in the dynamic symbols. *} +. long (*_bfd_canonicalize_dynamic_symtab) +. PARAMS ((bfd *, struct symbol_cache_entry **)); +. {* Get the amount of memory required to hold the dynamic relocs. *} +. long (*_bfd_get_dynamic_reloc_upper_bound) PARAMS ((bfd *)); +. {* Read in the dynamic relocs. *} +. long (*_bfd_canonicalize_dynamic_reloc) +. PARAMS ((bfd *, arelent **, struct symbol_cache_entry **)); . -. {* Back-door to allow format-aware applications to create debug symbols -. while using BFD for everything else. Currently used by the assembler -. when creating COFF files. *} -. asymbol * (*_bfd_make_debug_symbol) PARAMS (( -. bfd *abfd, -. void *ptr, -. unsigned long size)); Data for use by back-end routines, which isn't generic enough to belong in this structure. @@ -322,77 +417,93 @@ in this structure. Alphabetized for easy reference. They are listed a second time below, since we can't intermix extern's and initializers. */ -extern bfd_target a29kcoff_big_vec; -extern bfd_target a_out_adobe_vec; -extern bfd_target aout_mips_big_vec; -extern bfd_target aout_mips_little_vec; -extern bfd_target apollocoff_vec; -extern bfd_target b_out_vec_big_host; -extern bfd_target b_out_vec_little_host; -extern bfd_target bfd_elf32_big_generic_vec; -extern bfd_target bfd_elf32_bigmips_vec; -extern bfd_target bfd_elf32_hppa_vec; -extern bfd_target bfd_elf32_i386_vec; -extern bfd_target bfd_elf32_i860_vec; -extern bfd_target bfd_elf32_little_generic_vec; -extern bfd_target bfd_elf32_littlemips_vec; -extern bfd_target bfd_elf32_m68k_vec; -extern bfd_target bfd_elf32_m88k_vec; -extern bfd_target bfd_elf32_sparc_vec; -extern bfd_target bfd_elf64_big_generic_vec; -extern bfd_target bfd_elf64_little_generic_vec; -extern bfd_target demo_64_vec; -extern bfd_target ecoff_big_vec; -extern bfd_target ecoff_little_vec; -extern bfd_target ecoffalpha_little_vec; -extern bfd_target h8300coff_vec; -extern bfd_target h8500coff_vec; -extern bfd_target host_aout_vec; -extern bfd_target hp300bsd_vec; -extern bfd_target hp300hpux_vec; -extern bfd_target hppa_vec; -extern bfd_target i386aout_vec; -extern bfd_target i386bsd_vec; -extern bfd_target netbsd386_vec; -extern bfd_target freebsd386_vec; -extern bfd_target i386coff_vec; -extern bfd_target i386linux_vec; -extern bfd_target i386lynx_aout_vec; -extern bfd_target i386lynx_coff_vec; -extern bfd_target icoff_big_vec; -extern bfd_target icoff_little_vec; -extern bfd_target ieee_vec; -extern bfd_target m68kcoff_vec; -extern bfd_target m68kcoffun_vec; -extern bfd_target m68klynx_aout_vec; -extern bfd_target m68klynx_coff_vec; -extern bfd_target m88kbcs_vec; -extern bfd_target newsos3_vec; -extern bfd_target nlm32_big_generic_vec; -extern bfd_target nlm32_i386_vec; -extern bfd_target nlm32_little_generic_vec; -extern bfd_target nlm64_big_generic_vec; -extern bfd_target nlm64_little_generic_vec; -extern bfd_target oasys_vec; -extern bfd_target rs6000coff_vec; -extern bfd_target shcoff_vec; -extern bfd_target sunos_big_vec; -extern bfd_target tekhex_vec; -extern bfd_target we32kcoff_vec; -extern bfd_target z8kcoff_vec; +extern const bfd_target a29kcoff_big_vec; +extern const bfd_target a_out_adobe_vec; +extern const bfd_target aout_mips_big_vec; +extern const bfd_target aout_mips_little_vec; +extern const bfd_target aout0_big_vec; +extern const bfd_target apollocoff_vec; +extern const bfd_target b_out_vec_big_host; +extern const bfd_target b_out_vec_little_host; +extern const bfd_target bfd_elf32_big_generic_vec; +extern const bfd_target bfd_elf32_bigmips_vec; +extern const bfd_target bfd_elf32_hppa_vec; +extern const bfd_target bfd_elf32_i386_vec; +extern const bfd_target bfd_elf32_i860_vec; +extern const bfd_target bfd_elf32_little_generic_vec; +extern const bfd_target bfd_elf32_littlemips_vec; +extern const bfd_target bfd_elf32_m68k_vec; +extern const bfd_target bfd_elf32_m88k_vec; +extern const bfd_target bfd_elf32_powerpc_vec; +extern const bfd_target bfd_elf32_sparc_vec; +extern const bfd_target bfd_elf64_big_generic_vec; +extern const bfd_target bfd_elf64_little_generic_vec; +extern const bfd_target bfd_elf64_sparc_vec; +extern const bfd_target demo_64_vec; +extern const bfd_target ecoff_big_vec; +extern const bfd_target ecoff_little_vec; +extern const bfd_target ecoffalpha_little_vec; +extern const bfd_target h8300coff_vec; +extern const bfd_target h8500coff_vec; +extern const bfd_target host_aout_vec; +extern const bfd_target hp300bsd_vec; +extern const bfd_target hp300hpux_vec; +extern const bfd_target som_vec; +extern const bfd_target i386aout_vec; +extern const bfd_target i386bsd_vec; +extern const bfd_target i386dynix_vec; +extern const bfd_target i386os9k_vec; +extern const bfd_target netbsd386_vec; +extern const bfd_target freebsd386_vec; +extern const bfd_target i386coff_vec; +extern const bfd_target go32coff_vec; +extern const bfd_target i386linux_vec; +extern const bfd_target i386lynx_aout_vec; +extern const bfd_target i386lynx_coff_vec; +extern const bfd_target i386mach3_vec; +extern const bfd_target icoff_big_vec; +extern const bfd_target icoff_little_vec; +extern const bfd_target ieee_vec; +extern const bfd_target m68kcoff_vec; +extern const bfd_target m68kcoffun_vec; +extern const bfd_target m68klynx_aout_vec; +extern const bfd_target m68klynx_coff_vec; +extern const bfd_target m88kbcs_vec; +extern const bfd_target m88kmach3_vec; +extern const bfd_target netbsd532_vec; +extern const bfd_target newsos3_vec; +extern const bfd_target nlm32_i386_vec; +extern const bfd_target nlm32_sparc_vec; +extern const bfd_target nlm32_alpha_vec; +extern const bfd_target nlm32_powerpc_vec; +extern const bfd_target oasys_vec; +extern const bfd_target pc532mach_vec; +extern const bfd_target rs6000coff_vec; +extern const bfd_target shcoff_vec; +extern const bfd_target sparclynx_aout_vec; +extern const bfd_target sparclynx_coff_vec; +extern const bfd_target sparccoff_vec; +extern const bfd_target sunos_big_vec; +extern const bfd_target tekhex_vec; +extern const bfd_target we32kcoff_vec; +extern const bfd_target z8kcoff_vec; /* srec is always included. */ -extern bfd_target srec_vec; -extern bfd_target symbolsrec_vec; +extern const bfd_target srec_vec; +extern const bfd_target symbolsrec_vec; /* All of the xvecs for core files. */ -extern bfd_target aix386_core_vec; -extern bfd_target hpux_core_vec; -extern bfd_target osf_core_vec; -extern bfd_target sco_core_vec; -extern bfd_target trad_core_vec; - -bfd_target *target_vector[] = { +extern const bfd_target aix386_core_vec; +extern const bfd_target cisco_core_vec; +extern const bfd_target hpux_core_vec; +extern const bfd_target hppabsd_core_vec; +extern const bfd_target irix_core_vec; +extern const bfd_target osf_core_vec; +extern const bfd_target sco_core_vec; +extern const bfd_target trad_core_vec; +extern const bfd_target ptrace_core_vec; + +const bfd_target * const bfd_target_vector[] = { #ifdef SELECT_VECS @@ -417,26 +528,32 @@ bfd_target *target_vector[] = { &aout_mips_little_vec, &b_out_vec_big_host, &b_out_vec_little_host, -#if 0 /* No one seems to use this. */ + + /* This, and other vectors, may not be used in any *.mt configuration. + But that does not mean they are unnecessary. If configured with + --enable-targets=all, objdump or gdb should be able to examine + the file even if we don't recognize the machine type. */ &bfd_elf32_big_generic_vec, &bfd_elf32_bigmips_vec, -#endif -#if 0 &bfd_elf32_hppa_vec, -#endif &bfd_elf32_i386_vec, &bfd_elf32_i860_vec, -#if 0 /* No one seems to use this. */ &bfd_elf32_little_generic_vec, &bfd_elf32_littlemips_vec, -#endif &bfd_elf32_m68k_vec, &bfd_elf32_m88k_vec, &bfd_elf32_sparc_vec, + &bfd_elf32_powerpc_vec, #ifdef BFD64 /* No one seems to use this. */ &bfd_elf64_big_generic_vec, &bfd_elf64_little_generic_vec, #endif +#if 0 + &bfd_elf64_sparc_vec, +#endif + /* We don't include cisco_core_vec. Although it has a magic number, + the magic number isn't at the beginning of the file, and thus + might spuriously match other kinds of files. */ #ifdef BFD64 &demo_64_vec, /* Only compiled if host has long-long support */ #endif @@ -448,25 +565,33 @@ bfd_target *target_vector[] = { &h8300coff_vec, &h8500coff_vec, #if 0 + /* Since a.out files lack decent magic numbers, no way to recognize + which kind of a.out file it is. */ &host_aout_vec, #endif #if 0 /* Clashes with sunos_big_vec magic no. */ &hp300bsd_vec, #endif &hp300hpux_vec, -#if defined (HOST_HPPAHPUX) || defined (HOST_HPPABSD) - &hppa_vec, +#if defined (HOST_HPPAHPUX) || defined (HOST_HPPABSD) || defined (HOST_HPPAOSF) + &som_vec, #endif &i386aout_vec, &i386bsd_vec, - &netbsd386_vec, - &freebsd386_vec, &i386coff_vec, + &go32coff_vec, #if 0 + /* Since a.out files lack decent magic numbers, no way to recognize + which kind of a.out file it is. */ &i386linux_vec, #endif &i386lynx_aout_vec, &i386lynx_coff_vec, +#if 0 + /* No distinguishing features for Mach 3 executables. */ + &i386mach3_vec, +#endif + &i386os9k_vec, &icoff_big_vec, &icoff_little_vec, &ieee_vec, @@ -475,17 +600,14 @@ bfd_target *target_vector[] = { &m68klynx_aout_vec, &m68klynx_coff_vec, &m88kbcs_vec, + &m88kmach3_vec, &newsos3_vec, -#if 0 /* No one seems to use this. */ - &nlm32_big_generic_vec, -#endif + &netbsd386_vec, + &netbsd532_vec, &nlm32_i386_vec, -#if 0 /* No one seems to use this. */ - &nlm32_little_generic_vec, -#endif + &nlm32_sparc_vec, #ifdef BFD64 - &nlm64_big_generic_vec, - &nlm64_little_generic_vec, + &nlm32_alpha_vec, #endif #if 0 /* We have no oasys tools anymore, so we can't test any of this @@ -495,9 +617,13 @@ bfd_target *target_vector[] = { can be annoying target mis-matches. */ &oasys_vec, #endif + &pc532machaout_vec, &rs6000coff_vec, &shcoff_vec, + &sparclynx_aout_vec, + &sparclynx_coff_vec, &sunos_big_vec, + &aout0_big_vec, #if 0 &tekhex_vec, #endif @@ -518,57 +644,66 @@ bfd_target *target_vector[] = { #ifdef HPUX_CORE &hpux_core_vec, #endif +#ifdef HPPABSD_CORE + &hppabsd_core_vec, +#endif +#ifdef IRIX_CORE + &irix_core_vec, +#endif #ifdef OSF_CORE &osf_core_vec, #endif -#ifdef SCO_CORE - &sco_core_vec, -#endif #ifdef TRAD_CORE &trad_core_vec, #endif +#ifdef PTRACE_CORE + &ptrace_core_vec, +#endif + NULL /* end of list marker */ }; -/* default_vector[0] contains either the address of the default vector, +/* bfd_default_vector[0] contains either the address of the default vector, if there is one, or zero if there isn't. */ -bfd_target *default_vector[] = { +const bfd_target * const bfd_default_vector[] = { #ifdef DEFAULT_VECTOR &DEFAULT_VECTOR, #endif NULL }; - - +/* When there is an ambiguous match, bfd_check_format_matches puts the + names of the matching targets in an array. This variable is the maximum + number of entries that the array could possibly need. */ +const size_t _bfd_target_vector_entries = sizeof(bfd_target_vector)/sizeof(*bfd_target_vector); /* FUNCTION bfd_find_target +SYNOPSIS + const bfd_target *bfd_find_target(CONST char *target_name, bfd *abfd); + DESCRIPTION - 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 thenthe first entry in the target list is chosen. + Return a pointer to the transfer vector for the object target + named @var{target_name}. If @var{target_name} is <<NULL>>, choose the + one in the environment variable <<GNUTARGET>>; if that is null or not + defined, then choose the first entry in the target list. 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. - -SYNOPSIS - bfd_target *bfd_find_target(CONST char *, bfd *); */ -bfd_target * -DEFUN(bfd_find_target,(target_name, abfd), - CONST char *target_name AND - bfd *abfd) +const bfd_target * +bfd_find_target (target_name, abfd) + CONST char *target_name; + bfd *abfd; { - bfd_target **target; + const bfd_target * const *target; extern char *getenv (); CONST char *targname = (target_name ? target_name : (CONST char *) getenv ("GNUTARGET")); @@ -576,17 +711,17 @@ DEFUN(bfd_find_target,(target_name, abfd), /* This is safe; the vector cannot be null */ if (targname == NULL || !strcmp (targname, "default")) { abfd->target_defaulted = true; - return abfd->xvec = target_vector[0]; + return abfd->xvec = bfd_target_vector[0]; } abfd->target_defaulted = false; - for (target = &target_vector[0]; *target != NULL; target++) { + for (target = &bfd_target_vector[0]; *target != NULL; target++) { if (!strcmp (targname, (*target)->name)) return abfd->xvec = *target; } - bfd_error = invalid_target; + bfd_set_error (bfd_error_invalid_target); return NULL; } @@ -595,18 +730,18 @@ DEFUN(bfd_find_target,(target_name, abfd), FUNCTION bfd_target_list +SYNOPSIS + const char **bfd_target_list(void); + DESCRIPTION - This function returns a freshly malloced NULL-terminated + Return a freshly malloced NULL-terminated vector of the names of all the valid BFD targets. Do not - modify the names - -SYNOPSIS - CONST char **bfd_target_list(void); + modify the names. */ -CONST char ** -DEFUN_VOID(bfd_target_list) +const char ** +bfd_target_list () { int vec_length= 0; #ifdef NATIVE_HPPAHPUX_COMPILER @@ -614,21 +749,21 @@ DEFUN_VOID(bfd_target_list) to loop endlessly when compiling this file. This avoids it. */ volatile #endif - bfd_target **target; + const bfd_target * const *target; CONST char **name_list, **name_ptr; - for (target = &target_vector[0]; *target != NULL; target++) + for (target = &bfd_target_vector[0]; *target != NULL; target++) vec_length++; - name_ptr = - name_list = (CONST char **) zalloc ((vec_length + 1) * sizeof (char **)); + name_ptr = name_list = (CONST char **) + bfd_zmalloc ((vec_length + 1) * sizeof (char **)); if (name_list == NULL) { - bfd_error = no_memory; + bfd_set_error (bfd_error_no_memory); return NULL; } - for (target = &target_vector[0]; *target != NULL; target++) + for (target = &bfd_target_vector[0]; *target != NULL; target++) *(name_ptr++) = (*target)->name; return name_list; diff --git a/gnu/usr.bin/gdb/bfd/trad-core.c b/gnu/usr.bin/gdb/bfd/trad-core.c index 203c80e6a832..48b5f8e0ad81 100644 --- a/gnu/usr.bin/gdb/bfd/trad-core.c +++ b/gnu/usr.bin/gdb/bfd/trad-core.c @@ -1,5 +1,5 @@ /* BFD back end for traditional Unix core files (U-area and raw sections) - Copyright 1988, 1989, 1991, 1992, 1993 Free Software Foundation, Inc. + Copyright 1988, 1989, 1991, 1992, 1993, 1994 Free Software Foundation, Inc. Written by John Gilmore of Cygnus Support. This file is part of BFD, the Binary File Descriptor library. @@ -63,7 +63,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ /* forward declarations */ -bfd_target * trad_unix_core_file_p PARAMS ((bfd *abfd)); +const bfd_target *trad_unix_core_file_p PARAMS ((bfd *abfd)); char * trad_unix_core_file_failing_command PARAMS ((bfd *abfd)); int trad_unix_core_file_failing_signal PARAMS ((bfd *abfd)); boolean trad_unix_core_file_matches_executable_p @@ -72,7 +72,7 @@ boolean trad_unix_core_file_matches_executable_p /* Handle 4.2-style (and perhaps also sysV-style) core dump file. */ /* ARGSUSED */ -bfd_target * +const bfd_target * trad_unix_core_file_p (abfd) bfd *abfd; @@ -82,7 +82,7 @@ trad_unix_core_file_p (abfd) #ifdef TRAD_CORE_USER_OFFSET /* If defined, this macro is the file position of the user struct. */ - if (bfd_seek (abfd, TRAD_CORE_USER_OFFSET, SEEK_SET) == 0) + if (bfd_seek (abfd, TRAD_CORE_USER_OFFSET, SEEK_SET) != 0) return 0; #endif @@ -90,19 +90,19 @@ trad_unix_core_file_p (abfd) if (val != sizeof u) { /* Too small to be a core file */ - bfd_error = wrong_format; + bfd_set_error (bfd_error_wrong_format); return 0; } /* Sanity check perhaps??? */ if (u.u_dsize > 0x1000000) /* Remember, it's in pages... */ { - bfd_error = wrong_format; + bfd_set_error (bfd_error_wrong_format); return 0; } if (u.u_ssize > 0x1000000) { - bfd_error = wrong_format; + bfd_set_error (bfd_error_wrong_format); return 0; } @@ -114,14 +114,19 @@ trad_unix_core_file_p (abfd) return 0; if (fstat (fileno (stream), &statbuf) < 0) { - bfd_error = system_call_error; + bfd_set_error (bfd_error_system_call); return 0; } - if (NBPG * (UPAGES + u.u_dsize + u.u_ssize) > statbuf.st_size) + if (NBPG * (UPAGES + u.u_dsize +#ifdef TRAD_CORE_DSIZE_INCLUDES_TSIZE + - u.u_tsize +#endif + + u.u_ssize) > statbuf.st_size) { - bfd_error = file_truncated; + bfd_set_error (bfd_error_file_truncated); return 0; } +#ifndef TRAD_CORE_ALLOW_ANY_EXTRA_SIZE if (NBPG * (UPAGES + u.u_dsize + u.u_ssize) #ifdef TRAD_CORE_EXTRA_SIZE_ALLOWED /* Some systems write the file too big. */ @@ -131,9 +136,10 @@ trad_unix_core_file_p (abfd) { /* The file is too big. Maybe it's not a core file or we otherwise have bad values for u_dsize and u_ssize). */ - bfd_error = wrong_format; + bfd_set_error (bfd_error_wrong_format); return 0; } +#endif } /* OK, we believe you. You're a core file (sure, sure). */ @@ -141,9 +147,9 @@ trad_unix_core_file_p (abfd) /* Allocate both the upage and the struct core_data at once, so a single free() will free them both. */ rawptr = (struct trad_core_struct *) - bfd_zalloc (abfd, sizeof (struct trad_core_struct)); + bfd_zmalloc (sizeof (struct trad_core_struct)); if (rawptr == NULL) { - bfd_error = no_memory; + bfd_set_error (bfd_error_no_memory); return 0; } @@ -154,20 +160,20 @@ trad_unix_core_file_p (abfd) /* Create the sections. This is raunchy, but bfd_close wants to free them separately. */ - core_stacksec(abfd) = (asection *) zalloc (sizeof (asection)); + core_stacksec(abfd) = (asection *) bfd_zmalloc (sizeof (asection)); if (core_stacksec (abfd) == NULL) { loser: - bfd_error = no_memory; + bfd_set_error (bfd_error_no_memory); free ((void *)rawptr); return 0; } - core_datasec (abfd) = (asection *) zalloc (sizeof (asection)); + core_datasec (abfd) = (asection *) bfd_zmalloc (sizeof (asection)); if (core_datasec (abfd) == NULL) { loser1: free ((void *)core_stacksec (abfd)); goto loser; } - core_regsec (abfd) = (asection *) zalloc (sizeof (asection)); + core_regsec (abfd) = (asection *) bfd_zmalloc (sizeof (asection)); if (core_regsec (abfd) == NULL) { free ((void *)core_datasec (abfd)); goto loser1; @@ -179,9 +185,13 @@ trad_unix_core_file_p (abfd) core_stacksec (abfd)->flags = SEC_ALLOC + SEC_LOAD + SEC_HAS_CONTENTS; core_datasec (abfd)->flags = SEC_ALLOC + SEC_LOAD + SEC_HAS_CONTENTS; - core_regsec (abfd)->flags = SEC_ALLOC + SEC_HAS_CONTENTS; + core_regsec (abfd)->flags = SEC_HAS_CONTENTS; - core_datasec (abfd)->_raw_size = NBPG * u.u_dsize; + core_datasec (abfd)->_raw_size = NBPG * u.u_dsize +#ifdef TRAD_CORE_DSIZE_INCLUDES_TSIZE + - NBPG * u.u_tsize +#endif + ; core_stacksec (abfd)->_raw_size = NBPG * u.u_ssize; core_regsec (abfd)->_raw_size = NBPG * UPAGES; /* Larger than sizeof struct u */ @@ -192,14 +202,7 @@ trad_unix_core_file_p (abfd) #else core_datasec (abfd)->vma = HOST_TEXT_START_ADDR + (NBPG * u.u_tsize); #endif -/* a hack, but it works for FreeBSD !! */ -#include <vm/vm_param.h> -/* this should really be in <vm/vm_param.h>, but somebody forgot it */ -#ifndef vm_page_size -#define vm_page_size 4096 -#endif -#define HOST_STACK_START_ADDR trunc_page(u.u_kproc.kp_eproc.e_vm.vm_maxsaddr \ -+ MAXSSIZ - ctob(u.u_ssize)) + #ifdef HOST_STACK_START_ADDR core_stacksec (abfd)->vma = HOST_STACK_START_ADDR; #else @@ -223,11 +226,11 @@ trad_unix_core_file_p (abfd) core_regsec (abfd)->vma = 0 - (int) u.u_ar0; core_datasec (abfd)->filepos = NBPG * UPAGES; -#ifdef TRAD_CORE_STACK_FILEPOS - core_stacksec (abfd)->filepos = TRAD_CORE_STACK_FILEPOS; -#else - core_stacksec (abfd)->filepos = (NBPG * UPAGES) + NBPG * u.u_dsize; + core_stacksec (abfd)->filepos = (NBPG * UPAGES) + NBPG * u.u_dsize +#ifdef TRAD_CORE_DSIZE_INCLUDES_TSIZE + - NBPG * u.u_tsize #endif + ; core_regsec (abfd)->filepos = 0; /* Register segment is the upage */ /* Align to word at least */ @@ -276,74 +279,18 @@ trad_unix_core_file_matches_executable_p (core_bfd, exec_bfd) return true; /* FIXME, We have no way of telling at this point */ } -/* No archive file support via this BFD */ -#define trad_unix_openr_next_archived_file bfd_generic_openr_next_archived_file -#define trad_unix_generic_stat_arch_elt bfd_generic_stat_arch_elt -#define trad_unix_slurp_armap bfd_false -#define trad_unix_slurp_extended_name_table bfd_true -#define trad_unix_write_armap (boolean (*) PARAMS \ - ((bfd *arch, unsigned int elength, struct orl *map, \ - unsigned int orl_count, int stridx))) bfd_false -#define trad_unix_truncate_arname bfd_dont_truncate_arname -#define aout_32_openr_next_archived_file bfd_generic_openr_next_archived_file - -#define trad_unix_close_and_cleanup bfd_generic_close_and_cleanup -#define trad_unix_set_section_contents (boolean (*) PARAMS \ - ((bfd *abfd, asection *section, PTR data, file_ptr offset, \ - bfd_size_type count))) bfd_false -#define trad_unix_get_section_contents bfd_generic_get_section_contents -#define trad_unix_new_section_hook (boolean (*) PARAMS \ - ((bfd *, sec_ptr))) bfd_true -#define trad_unix_get_symtab_upper_bound bfd_0u -#define trad_unix_get_symtab (unsigned int (*) PARAMS \ - ((bfd *, struct symbol_cache_entry **))) bfd_0u -#define trad_unix_get_reloc_upper_bound (unsigned int (*) PARAMS \ - ((bfd *, sec_ptr))) bfd_0u -#define trad_unix_canonicalize_reloc (unsigned int (*) PARAMS \ - ((bfd *, sec_ptr, arelent **, struct symbol_cache_entry**))) bfd_0u -#define trad_unix_make_empty_symbol (struct symbol_cache_entry * \ - (*) PARAMS ((bfd *))) bfd_false -#define trad_unix_print_symbol (void (*) PARAMS \ - ((bfd *, PTR, struct symbol_cache_entry *, \ - bfd_print_symbol_type))) bfd_false -#define trad_unix_get_symbol_info (void (*) PARAMS \ - ((bfd *, struct symbol_cache_entry *, \ - symbol_info *))) bfd_false -#define trad_unix_get_lineno (alent * (*) PARAMS \ - ((bfd *, struct symbol_cache_entry *))) bfd_nullvoidptr -#define trad_unix_set_arch_mach (boolean (*) PARAMS \ - ((bfd *, enum bfd_architecture, unsigned long))) bfd_false -#define trad_unix_find_nearest_line (boolean (*) PARAMS \ - ((bfd *abfd, struct sec *section, \ - struct symbol_cache_entry **symbols,bfd_vma offset, \ - CONST char **file, CONST char **func, unsigned int *line))) bfd_false -#define trad_unix_sizeof_headers (int (*) PARAMS \ - ((bfd *, boolean))) bfd_0 - -#define trad_unix_bfd_debug_info_start bfd_void -#define trad_unix_bfd_debug_info_end bfd_void -#define trad_unix_bfd_debug_info_accumulate (void (*) PARAMS \ - ((bfd *, struct sec *))) bfd_void -#define trad_unix_bfd_get_relocated_section_contents bfd_generic_get_relocated_section_contents -#define trad_unix_bfd_relax_section bfd_generic_relax_section -#define trad_unix_bfd_seclet_link \ - ((boolean (*) PARAMS ((bfd *, PTR, boolean))) bfd_false) -#define trad_unix_bfd_reloc_type_lookup \ - ((CONST struct reloc_howto_struct *(*) PARAMS ((bfd *, bfd_reloc_code_real_type))) bfd_nullvoidptr) -#define trad_unix_bfd_make_debug_symbol \ - ((asymbol *(*) PARAMS ((bfd *, void *, unsigned long))) bfd_nullvoidptr) - /* If somebody calls any byte-swapping routines, shoot them. */ void swap_abort() { abort(); /* This way doesn't require any declaration for ANSI to fuck up */ } -#define NO_GET ((bfd_vma (*) PARAMS (( bfd_byte *))) swap_abort ) +#define NO_GET ((bfd_vma (*) PARAMS (( const bfd_byte *))) swap_abort ) #define NO_PUT ((void (*) PARAMS ((bfd_vma, bfd_byte *))) swap_abort ) -#define NO_SIGNED_GET ((bfd_signed_vma (*) PARAMS ((bfd_byte *))) swap_abort ) +#define NO_SIGNED_GET \ + ((bfd_signed_vma (*) PARAMS ((const bfd_byte *))) swap_abort ) -bfd_target trad_core_vec = +const bfd_target trad_core_vec = { "trad-core", bfd_target_unknown_flavour, @@ -351,7 +298,7 @@ bfd_target trad_core_vec = true, /* target headers byte order */ (HAS_RELOC | EXEC_P | /* object flags */ HAS_LINENO | HAS_DEBUG | - HAS_SYMS | HAS_LOCALS | DYNAMIC | WP_TEXT | D_PAGED), + HAS_SYMS | HAS_LOCALS | WP_TEXT | D_PAGED), (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC), /* section flags */ 0, /* symbol prefix */ ' ', /* ar_pad_char */ @@ -379,6 +326,15 @@ bfd_target trad_core_vec = bfd_false, bfd_false }, - JUMP_TABLE(trad_unix), + BFD_JUMP_TABLE_GENERIC (_bfd_generic), + BFD_JUMP_TABLE_COPY (_bfd_generic), + BFD_JUMP_TABLE_CORE (trad_unix), + BFD_JUMP_TABLE_ARCHIVE (_bfd_noarchive), + BFD_JUMP_TABLE_SYMBOLS (_bfd_nosymbols), + BFD_JUMP_TABLE_RELOCS (_bfd_norelocs), + BFD_JUMP_TABLE_WRITE (_bfd_generic), + BFD_JUMP_TABLE_LINK (_bfd_nolink), + BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic), + (PTR) 0 /* backend_data */ }; |