X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=bfd%2Fecoff.c;h=4bda9dc4cf048d00cc7599201bb82ebba15a11dc;hb=454c9bb956abd5451b6a46c96327c5ec0884eaed;hp=8b40eb5c56b16977cf658df8a8777b2043231a92;hpb=aca736871c2567ee38bd285afdff62d6339790e4;p=deliverable%2Fbinutils-gdb.git diff --git a/bfd/ecoff.c b/bfd/ecoff.c index 8b40eb5c56..4bda9dc4cf 100644 --- a/bfd/ecoff.c +++ b/bfd/ecoff.c @@ -1,30 +1,30 @@ /* Generic ECOFF (Extended-COFF) routines. - Copyright 1990, 1991, 1992, 1993, 1994, 1995 Free Software Foundation, Inc. + Copyright (C) 1990-2017 Free Software Foundation, Inc. Original version by Per Bothner. Full support added by Ian Lance Taylor, ian@cygnus.com. -This file is part of BFD, the Binary File Descriptor library. + This file is part of BFD, the Binary File Descriptor library. -This program is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2 of the License, or -(at your option) any later version. + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. -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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + 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., 51 Franklin Street - Fifth Floor, Boston, + MA 02110-1301, USA. */ -#include "bfd.h" #include "sysdep.h" +#include "bfd.h" #include "bfdlink.h" #include "libbfd.h" #include "aout/ar.h" -#include "aout/ranlib.h" #include "aout/stab_gnu.h" /* FIXME: We need the definitions of N_SET[ADTB], but aout64.h defines @@ -42,75 +42,75 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "coff/ecoff.h" #include "libcoff.h" #include "libecoff.h" - -/* Prototypes for static functions. */ - -static int ecoff_get_magic PARAMS ((bfd *abfd)); -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)); -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, FDR *fdr, - unsigned int indx)); -static boolean ecoff_slurp_reloc_table PARAMS ((bfd *abfd, asection *section, - asymbol **symbols)); -static int ecoff_sort_hdrs PARAMS ((const PTR, const PTR)); -static boolean 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, - unsigned int hlog)); +#include "libiberty.h" + +#define streq(a, b) (strcmp ((a), (b)) == 0) +#define strneq(a, b, n) (strncmp ((a), (b), (n)) == 0) + /* This stuff is somewhat copied from coffcode.h. */ - -static asection bfd_debug_section = { "*DEBUG*" }; +static asection bfd_debug_section = +{ + /* name, id, index, next, prev, flags, user_set_vma, */ + "*DEBUG*", 0, 0, NULL, NULL, 0, 0, + /* linker_mark, linker_has_input, gc_mark, compress_status, */ + 0, 0, 1, 0, + /* segment_mark, sec_info_type, use_rela_p, */ + 0, 0, 0, + /* sec_flg0, sec_flg1, sec_flg2, sec_flg3, sec_flg4, sec_flg5, */ + 0, 0, 0, 0, 0, 0, + /* vma, lma, size, rawsize, compressed_size, relax, relax_count, */ + 0, 0, 0, 0, 0, 0, 0, + /* output_offset, output_section, alignment_power, */ + 0, NULL, 0, + /* relocation, orelocation, reloc_count, filepos, rel_filepos, */ + NULL, NULL, 0, 0, 0, + /* line_filepos, userdata, contents, lineno, lineno_count, */ + 0, NULL, NULL, NULL, 0, + /* entsize, kept_section, moving_line_filepos, */ + 0, NULL, 0, + /* target_index, used_by_bfd, constructor_chain, owner, */ + 0, NULL, NULL, NULL, + /* symbol, */ + NULL, + /* symbol_ptr_ptr, */ + NULL, + /* map_head, map_tail */ + { NULL }, { NULL } +}; /* Create an ECOFF object. */ -boolean -_bfd_ecoff_mkobject (abfd) - bfd *abfd; +bfd_boolean +_bfd_ecoff_mkobject (bfd *abfd) { - abfd->tdata.ecoff_obj_data = ((struct ecoff_tdata *) - bfd_zalloc (abfd, sizeof (ecoff_data_type))); + bfd_size_type amt = sizeof (ecoff_data_type); + + abfd->tdata.ecoff_obj_data = (struct ecoff_tdata *) bfd_zalloc (abfd, amt); if (abfd->tdata.ecoff_obj_data == NULL) - { - bfd_set_error (bfd_error_no_memory); - return false; - } + return FALSE; - return true; + return TRUE; } /* This is a hook called by coff_real_object_p to create any backend specific information. */ -PTR -_bfd_ecoff_mkobject_hook (abfd, filehdr, aouthdr) - bfd *abfd; - PTR filehdr; - PTR aouthdr; +void * +_bfd_ecoff_mkobject_hook (bfd *abfd, void * filehdr, void * aouthdr) { struct internal_filehdr *internal_f = (struct internal_filehdr *) filehdr; struct internal_aouthdr *internal_a = (struct internal_aouthdr *) aouthdr; ecoff_data_type *ecoff; - if (_bfd_ecoff_mkobject (abfd) == false) + if (! _bfd_ecoff_mkobject (abfd)) return NULL; ecoff = ecoff_data (abfd); ecoff->gp_size = 8; ecoff->sym_filepos = internal_f->f_symptr; - if (internal_a != (struct internal_aouthdr *) NULL) + if (internal_a != NULL) { int i; @@ -133,52 +133,53 @@ _bfd_ecoff_mkobject_hook (abfd, filehdr, aouthdr) fprmask) and let the swapping routines ensure that only relevant information is written out. */ - return (PTR) ecoff; + return (void *) ecoff; } /* Initialize a new section. */ -boolean -_bfd_ecoff_new_section_hook (abfd, section) - bfd *abfd; - asection *section; +bfd_boolean +_bfd_ecoff_new_section_hook (bfd *abfd, asection *section) { - /* For the .pdata section, which has a special meaning on the Alpha, - we set the alignment power to 3. 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. For every other - section we use an alignment power of 4; this could be made target - dependent by adding a field to ecoff_backend_data, but 4 appears - to be correct for both the MIPS and the Alpha. */ - if (strcmp (section->name, _PDATA) == 0) - section->alignment_power = 3; - else - section->alignment_power = 4; - - if (strcmp (section->name, _TEXT) == 0) - section->flags |= SEC_CODE | SEC_LOAD | SEC_ALLOC; - else if (strcmp (section->name, _DATA) == 0 - || strcmp (section->name, _SDATA) == 0) - section->flags |= SEC_DATA | SEC_LOAD | SEC_ALLOC; - else if (strcmp (section->name, _RDATA) == 0 - || strcmp (section->name, _LIT8) == 0 - || strcmp (section->name, _LIT4) == 0) - section->flags |= SEC_DATA | SEC_LOAD | SEC_ALLOC | SEC_READONLY; - else if (strcmp (section->name, _BSS) == 0 - || strcmp (section->name, _SBSS) == 0) - section->flags |= SEC_ALLOC; - else if (strcmp (section->name, _LIB) == 0) - { - /* An Irix 4 shared libary. */ - section->flags |= SEC_COFF_SHARED_LIBRARY; - } + unsigned int i; + static struct + { + const char * name; + flagword flags; + } + section_flags [] = + { + { _TEXT, SEC_ALLOC | SEC_CODE | SEC_LOAD }, + { _INIT, SEC_ALLOC | SEC_CODE | SEC_LOAD }, + { _FINI, SEC_ALLOC | SEC_CODE | SEC_LOAD }, + { _DATA, SEC_ALLOC | SEC_DATA | SEC_LOAD }, + { _SDATA, SEC_ALLOC | SEC_DATA | SEC_LOAD }, + { _RDATA, SEC_ALLOC | SEC_DATA | SEC_LOAD | SEC_READONLY}, + { _LIT8, SEC_ALLOC | SEC_DATA | SEC_LOAD | SEC_READONLY}, + { _LIT4, SEC_ALLOC | SEC_DATA | SEC_LOAD | SEC_READONLY}, + { _RCONST, SEC_ALLOC | SEC_DATA | SEC_LOAD | SEC_READONLY}, + { _PDATA, SEC_ALLOC | SEC_DATA | SEC_LOAD | SEC_READONLY}, + { _BSS, SEC_ALLOC}, + { _SBSS, SEC_ALLOC}, + /* An Irix 4 shared libary. */ + { _LIB, SEC_COFF_SHARED_LIBRARY} + }; + + section->alignment_power = 4; + + for (i = 0; i < ARRAY_SIZE (section_flags); i++) + if (streq (section->name, section_flags[i].name)) + { + section->flags |= section_flags[i].flags; + break; + } + /* Probably any other section name is SEC_NEVER_LOAD, but I'm uncertain about .init on some systems and I don't know how shared libraries work. */ - return true; + return _bfd_generic_new_section_hook (abfd, section); } /* Determine the machine architecture and type. This is called from @@ -186,10 +187,8 @@ _bfd_ecoff_new_section_hook (abfd, section) below. This could be an ECOFF backend routine, with one version for each target, but there aren't all that many ECOFF targets. */ -boolean -_bfd_ecoff_set_arch_mach_hook (abfd, filehdr) - bfd *abfd; - PTR filehdr; +bfd_boolean +_bfd_ecoff_set_arch_mach_hook (bfd *abfd, void * filehdr) { struct internal_filehdr *internal_f = (struct internal_filehdr *) filehdr; enum bfd_architecture arch; @@ -201,21 +200,21 @@ _bfd_ecoff_set_arch_mach_hook (abfd, filehdr) case MIPS_MAGIC_LITTLE: case MIPS_MAGIC_BIG: arch = bfd_arch_mips; - mach = 3000; + mach = bfd_mach_mips3000; break; case MIPS_MAGIC_LITTLE2: case MIPS_MAGIC_BIG2: - /* MIPS ISA level 2: the r6000 */ + /* MIPS ISA level 2: the r6000. */ arch = bfd_arch_mips; - mach = 6000; + mach = bfd_mach_mips6000; break; case MIPS_MAGIC_LITTLE3: case MIPS_MAGIC_BIG3: - /* MIPS ISA level 3: the r4000 */ + /* MIPS ISA level 3: the r4000. */ arch = bfd_arch_mips; - mach = 4000; + mach = bfd_mach_mips4000; break; case ALPHA_MAGIC: @@ -232,12 +231,19 @@ _bfd_ecoff_set_arch_mach_hook (abfd, filehdr) return bfd_default_set_arch_mach (abfd, arch, mach); } +bfd_boolean +_bfd_ecoff_no_long_sections (bfd *abfd, int enable) +{ + (void) abfd; + (void) enable; + return FALSE; +} + /* Get the magic number to use based on the architecture and machine. This is the inverse of _bfd_ecoff_set_arch_mach_hook, above. */ static int -ecoff_get_magic (abfd) - bfd *abfd; +ecoff_get_magic (bfd *abfd) { int big, little; @@ -248,23 +254,23 @@ ecoff_get_magic (abfd) { default: case 0: - case 3000: + case bfd_mach_mips3000: big = MIPS_MAGIC_BIG; little = MIPS_MAGIC_LITTLE; break; - case 6000: + case bfd_mach_mips6000: big = MIPS_MAGIC_BIG2; little = MIPS_MAGIC_LITTLE2; break; - case 4000: + case bfd_mach_mips4000: big = MIPS_MAGIC_BIG3; little = MIPS_MAGIC_LITTLE3; break; } - return abfd->xvec->byteorder_big_p ? big : little; + return bfd_big_endian (abfd) ? big : little; case bfd_arch_alpha: return ALPHA_MAGIC; @@ -278,73 +284,67 @@ ecoff_get_magic (abfd) /* Get the section s_flags to use for a section. */ static long -ecoff_sec_to_styp_flags (name, flags) - const char *name; - flagword flags; +ecoff_sec_to_styp_flags (const char *name, flagword flags) { - long styp; - - styp = 0; - - if (strcmp (name, _TEXT) == 0) - styp = STYP_TEXT; - else if (strcmp (name, _DATA) == 0) - styp = STYP_DATA; - else if (strcmp (name, _SDATA) == 0) - 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) - styp = STYP_LIT4; - else if (strcmp (name, _BSS) == 0) - styp = STYP_BSS; - else if (strcmp (name, _SBSS) == 0) - styp = STYP_SBSS; - else if (strcmp (name, _INIT) == 0) - 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 (strcmp (name, _GOT) == 0) - styp = STYP_GOT; - else if (strcmp (name, _HASH) == 0) - styp = STYP_HASH; - else if (strcmp (name, _DYNAMIC) == 0) - styp = STYP_DYNAMIC; - else if (strcmp (name, _LIBLIST) == 0) - styp = STYP_LIBLIST; - else if (strcmp (name, _RELDYN) == 0) - styp = STYP_RELDYN; - else if (strcmp (name, _CONFLIC) == 0) - styp = STYP_CONFLIC; - else if (strcmp (name, _DYNSTR) == 0) - styp = STYP_DYNSTR; - else if (strcmp (name, _DYNSYM) == 0) - styp = STYP_DYNSYM; - else if (strcmp (name, _COMMENT) == 0) + unsigned int i; + static struct + { + const char * name; + long flags; + } + styp_flags [] = + { + { _TEXT, STYP_TEXT }, + { _DATA, STYP_DATA }, + { _SDATA, STYP_SDATA }, + { _RDATA, STYP_RDATA }, + { _LITA, STYP_LITA }, + { _LIT8, STYP_LIT8 }, + { _LIT4, STYP_LIT4 }, + { _BSS, STYP_BSS }, + { _SBSS, STYP_SBSS }, + { _INIT, STYP_ECOFF_INIT }, + { _FINI, STYP_ECOFF_FINI }, + { _PDATA, STYP_PDATA }, + { _XDATA, STYP_XDATA }, + { _LIB, STYP_ECOFF_LIB }, + { _GOT, STYP_GOT }, + { _HASH, STYP_HASH }, + { _DYNAMIC, STYP_DYNAMIC }, + { _LIBLIST, STYP_LIBLIST }, + { _RELDYN, STYP_RELDYN }, + { _CONFLIC, STYP_CONFLIC }, + { _DYNSTR, STYP_DYNSTR }, + { _DYNSYM, STYP_DYNSYM }, + { _RCONST, STYP_RCONST } + }; + long styp = 0; + + for (i = 0; i < ARRAY_SIZE (styp_flags); i++) + if (streq (name, styp_flags[i].name)) + { + styp = styp_flags[i].flags; + break; + } + + if (styp == 0) { - styp = STYP_COMMENT; - flags &=~ SEC_NEVER_LOAD; + if (streq (name, _COMMENT)) + { + styp = STYP_COMMENT; + flags &=~ SEC_NEVER_LOAD; + } + else if (flags & SEC_CODE) + styp = STYP_TEXT; + else if (flags & SEC_DATA) + styp = STYP_DATA; + else if (flags & SEC_READONLY) + styp = STYP_RDATA; + else if (flags & SEC_LOAD) + styp = STYP_REG; + else + styp = STYP_BSS; } - else if (flags & SEC_CODE) - styp = STYP_TEXT; - else if (flags & SEC_DATA) - styp = STYP_DATA; - else if (flags & SEC_READONLY) - styp = STYP_RDATA; - else if (flags & SEC_LOAD) - styp = STYP_REG; - else - styp = STYP_BSS; if (flags & SEC_NEVER_LOAD) styp |= STYP_NOLOAD; @@ -354,16 +354,16 @@ ecoff_sec_to_styp_flags (name, flags) /* Get the BFD flags to use for a section. */ -/*ARGSUSED*/ -flagword -_bfd_ecoff_styp_to_sec_flags (abfd, hdr, name) - bfd *abfd; - PTR hdr; - const char *name; +bfd_boolean +_bfd_ecoff_styp_to_sec_flags (bfd *abfd ATTRIBUTE_UNUSED, + void * hdr, + const char *name ATTRIBUTE_UNUSED, + asection *section ATTRIBUTE_UNUSED, + flagword * flags_ptr) { struct internal_scnhdr *internal_s = (struct internal_scnhdr *) hdr; long styp_flags = internal_s->s_flags; - flagword sec_flags=0; + flagword sec_flags = 0; if (styp_flags & STYP_NOLOAD) sec_flags |= SEC_NEVER_LOAD; @@ -391,64 +391,56 @@ _bfd_ecoff_styp_to_sec_flags (abfd, hdr, name) || (styp_flags & STYP_SDATA) || styp_flags == STYP_PDATA || styp_flags == STYP_XDATA - || (styp_flags & STYP_GOT)) + || (styp_flags & STYP_GOT) + || styp_flags == STYP_RCONST) { if (sec_flags & SEC_NEVER_LOAD) sec_flags |= SEC_DATA | SEC_COFF_SHARED_LIBRARY; else sec_flags |= SEC_DATA | SEC_LOAD | SEC_ALLOC; if ((styp_flags & STYP_RDATA) - || styp_flags == STYP_PDATA) + || styp_flags == STYP_PDATA + || styp_flags == STYP_RCONST) sec_flags |= SEC_READONLY; } else if ((styp_flags & STYP_BSS) || (styp_flags & STYP_SBSS)) - { - sec_flags |= SEC_ALLOC; - } + sec_flags |= SEC_ALLOC; else if ((styp_flags & STYP_INFO) || styp_flags == STYP_COMMENT) - { - sec_flags |= SEC_NEVER_LOAD; - } + sec_flags |= SEC_NEVER_LOAD; else if ((styp_flags & STYP_LITA) || (styp_flags & STYP_LIT8) || (styp_flags & STYP_LIT4)) - { - sec_flags |= SEC_DATA | SEC_LOAD | SEC_ALLOC | SEC_READONLY; - } + sec_flags |= SEC_DATA | SEC_LOAD | SEC_ALLOC | SEC_READONLY; else if (styp_flags & STYP_ECOFF_LIB) - { - sec_flags |= SEC_COFF_SHARED_LIBRARY; - } + sec_flags |= SEC_COFF_SHARED_LIBRARY; else - { - sec_flags |= SEC_ALLOC | SEC_LOAD; - } + sec_flags |= SEC_ALLOC | SEC_LOAD; - return sec_flags; + * flags_ptr = sec_flags; + return TRUE; } /* Read in the symbolic header for an ECOFF object file. */ -static boolean -ecoff_slurp_symbolic_header (abfd) - bfd *abfd; +static bfd_boolean +ecoff_slurp_symbolic_header (bfd *abfd) { const struct ecoff_backend_data * const backend = ecoff_backend (abfd); bfd_size_type external_hdr_size; - PTR raw = NULL; + void * raw = NULL; HDRR *internal_symhdr; /* See if we've already read it in. */ - if (ecoff_data (abfd)->debug_info.symbolic_header.magic == + if (ecoff_data (abfd)->debug_info.symbolic_header.magic == backend->debug_swap.sym_magic) - return true; + return TRUE; /* See whether there is a symbolic header. */ if (ecoff_data (abfd)->sym_filepos == 0) { bfd_get_symcount (abfd) = 0; - return true; + return TRUE; } /* At this point bfd_get_symcount (abfd) holds the number of symbols @@ -459,20 +451,16 @@ ecoff_slurp_symbolic_header (abfd) if (bfd_get_symcount (abfd) != external_hdr_size) { bfd_set_error (bfd_error_bad_value); - return false; + return FALSE; } /* Read the symbolic information header. */ - raw = (PTR) malloc ((size_t) external_hdr_size); + raw = bfd_malloc (external_hdr_size); if (raw == NULL) - { - bfd_set_error (bfd_error_no_memory); - goto error_return; - } + 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)) + if (bfd_seek (abfd, ecoff_data (abfd)->sym_filepos, SEEK_SET) != 0 + || bfd_bread (raw, external_hdr_size, abfd) != external_hdr_size) goto error_return; internal_symhdr = &ecoff_data (abfd)->debug_info.symbolic_header; (*backend->debug_swap.swap_hdr_in) (abfd, raw, internal_symhdr); @@ -489,50 +477,49 @@ ecoff_slurp_symbolic_header (abfd) if (raw != NULL) free (raw); - return true; + return TRUE; error_return: if (raw != NULL) free (raw); - return false; + 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; +bfd_boolean +_bfd_ecoff_slurp_symbolic_info (bfd *abfd, + asection *ignore ATTRIBUTE_UNUSED, + 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; + void * 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; + file_ptr pos; 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)->raw_syments != NULL) + return TRUE; if (ecoff_data (abfd)->sym_filepos == 0) { bfd_get_symcount (abfd) = 0; - return true; + return TRUE; } if (! ecoff_slurp_symbolic_header (abfd)) - return false; + return FALSE; internal_symhdr = &debug->symbolic_header; @@ -545,7 +532,6 @@ _bfd_ecoff_slurp_symbolic_info (abfd, ignore, debug) documented section. And the ordering of the sections varies between statically and dynamically linked executables. If bfd supports SEEK_END someday, this code could be simplified. */ - raw_end = 0; #define UPDATE_RAW_END(start, count, size) \ @@ -557,7 +543,9 @@ _bfd_ecoff_slurp_symbolic_info (abfd, ignore, debug) 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); + /* eraxxon@alumni.rice.edu: ioptMax refers to the size of the + optimization symtab, not the number of entries. */ + UPDATE_RAW_END (cbOptOffset, ioptMax, sizeof (char)); UPDATE_RAW_END (cbAuxOffset, iauxMax, sizeof (union aux_ext)); UPDATE_RAW_END (cbSsOffset, issMax, sizeof (char)); UPDATE_RAW_END (cbSsExtOffset, issExtMax, sizeof (char)); @@ -571,45 +559,43 @@ _bfd_ecoff_slurp_symbolic_info (abfd, ignore, debug) if (raw_size == 0) { ecoff_data (abfd)->sym_filepos = 0; - return true; + return TRUE; } - raw = (PTR) bfd_alloc (abfd, raw_size); + raw = bfd_alloc (abfd, raw_size); if (raw == NULL) - { - bfd_set_error (bfd_error_no_memory); - return false; - } - 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) + return FALSE; + + pos = ecoff_data (abfd)->sym_filepos; + pos += backend->debug_swap.external_hdr_size; + if (bfd_seek (abfd, pos, SEEK_SET) != 0 + || bfd_bread (raw, raw_size, abfd) != raw_size) { bfd_release (abfd, raw); - return false; + return FALSE; } 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) \ - debug->off2 = (type) NULL; \ - else \ - debug->off2 = (type) ((char *) raw \ - + (internal_symhdr->off1 \ +#define FIX(off1, off2, type) \ + if (internal_symhdr->off1 == 0) \ + debug->off2 = NULL; \ + else \ + 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); - FIX (cbSymOffset, external_sym, PTR); - FIX (cbOptOffset, external_opt, PTR); + FIX (cbDnOffset, external_dnr, void *); + FIX (cbPdOffset, external_pdr, void *); + FIX (cbSymOffset, external_sym, void *); + FIX (cbOptOffset, external_opt, void *); FIX (cbAuxOffset, external_aux, union aux_ext *); FIX (cbSsOffset, ss, char *); FIX (cbSsExtOffset, ssext, char *); - FIX (cbFdOffset, external_fdr, PTR); - FIX (cbRfdOffset, external_rfd, PTR); - FIX (cbExtOffset, external_ext, PTR); + FIX (cbFdOffset, external_fdr, void *); + FIX (cbRfdOffset, external_rfd, void *); + FIX (cbExtOffset, external_ext, void *); #undef FIX /* I don't want to always swap all the data, because it will just @@ -620,22 +606,21 @@ _bfd_ecoff_slurp_symbolic_info (abfd, ignore, debug) We need to look at the fdr to deal with a lot of information in the symbols, so we swap them here. */ - debug->fdr = (struct fdr *) bfd_alloc (abfd, - (internal_symhdr->ifdMax * - sizeof (struct fdr))); + debug->fdr = (FDR *) bfd_alloc2 (abfd, internal_symhdr->ifdMax, + sizeof (struct fdr)); if (debug->fdr == NULL) - { - bfd_set_error (bfd_error_no_memory); - return false; - } + return FALSE; external_fdr_size = backend->debug_swap.external_fdr_size; fdr_ptr = debug->fdr; fraw_src = (char *) debug->external_fdr; + /* PR 17512: file: 3372-1243-0.004. */ + if (fraw_src == NULL && internal_symhdr->ifdMax > 0) + return FALSE; fraw_end = fraw_src + internal_symhdr->ifdMax * external_fdr_size; for (; fraw_src < fraw_end; fraw_src += external_fdr_size, fdr_ptr++) - (*backend->debug_swap.swap_fdr_in) (abfd, (PTR) fraw_src, fdr_ptr); + (*backend->debug_swap.swap_fdr_in) (abfd, (void *) fraw_src, fdr_ptr); - return true; + return TRUE; } /* ECOFF symbol table routines. The ECOFF symbol table is described @@ -653,34 +638,30 @@ static asymbol *ecoff_scom_symbol_ptr; /* Create an empty symbol. */ asymbol * -_bfd_ecoff_make_empty_symbol (abfd) - bfd *abfd; +_bfd_ecoff_make_empty_symbol (bfd *abfd) { - ecoff_symbol_type *new; + ecoff_symbol_type *new_symbol; + bfd_size_type amt = sizeof (ecoff_symbol_type); - new = (ecoff_symbol_type *) bfd_alloc (abfd, sizeof (ecoff_symbol_type)); - if (new == (ecoff_symbol_type *) NULL) - { - bfd_set_error (bfd_error_no_memory); - return (asymbol *) NULL; - } - memset ((PTR) new, 0, sizeof *new); - new->symbol.section = (asection *) NULL; - new->fdr = (FDR *) NULL; - new->local = false; - new->native = NULL; - new->symbol.the_bfd = abfd; - return &new->symbol; + new_symbol = (ecoff_symbol_type *) bfd_zalloc (abfd, amt); + if (new_symbol == NULL) + return NULL; + new_symbol->symbol.section = NULL; + new_symbol->fdr = NULL; + new_symbol->local = FALSE; + new_symbol->native = NULL; + new_symbol->symbol.the_bfd = abfd; + return &new_symbol->symbol; } /* Set the BFD flags and section for an ECOFF symbol. */ -static boolean -ecoff_set_symbol_info (abfd, ecoff_sym, asym, ext) - bfd *abfd; - SYMR *ecoff_sym; - asymbol *asym; - int ext; +static bfd_boolean +ecoff_set_symbol_info (bfd *abfd, + SYMR *ecoff_sym, + asymbol *asym, + int ext, + int weak) { asym->the_bfd = abfd; asym->value = ecoff_sym->value; @@ -700,15 +681,17 @@ ecoff_set_symbol_info (abfd, ecoff_sym, asym, ext) if (ECOFF_IS_STAB (ecoff_sym)) { asym->flags = BSF_DEBUGGING; - return true; + return TRUE; } break; default: asym->flags = BSF_DEBUGGING; - return true; + return TRUE; } - if (ext) + if (weak) + asym->flags = BSF_EXPORT | BSF_WEAK; + else if (ext) asym->flags = BSF_EXPORT | BSF_GLOBAL; else { @@ -724,6 +707,10 @@ ecoff_set_symbol_info (abfd, ecoff_sym, asym, ext) || ECOFF_IS_STAB (ecoff_sym)) asym->flags |= BSF_DEBUGGING; } + + if (ecoff_sym->st == stProc || ecoff_sym->st == stStaticProc) + asym->flags |= BSF_FUNCTION; + switch (ecoff_sym->sc) { case scNil: @@ -734,15 +721,15 @@ ecoff_set_symbol_info (abfd, ecoff_sym, asym, ext) asym->flags = BSF_LOCAL; break; case scText: - asym->section = bfd_make_section_old_way (abfd, ".text"); + asym->section = bfd_make_section_old_way (abfd, _TEXT); asym->value -= asym->section->vma; break; case scData: - asym->section = bfd_make_section_old_way (abfd, ".data"); + asym->section = bfd_make_section_old_way (abfd, _DATA); asym->value -= asym->section->vma; break; case scBss: - asym->section = bfd_make_section_old_way (abfd, ".bss"); + asym->section = bfd_make_section_old_way (abfd, _BSS); asym->value -= asym->section->vma; break; case scRegister: @@ -826,6 +813,10 @@ ecoff_set_symbol_info (abfd, ecoff_sym, asym, ext) asym->section = bfd_make_section_old_way (abfd, ".fini"); asym->value -= asym->section->vma; break; + case scRConst: + asym->section = bfd_make_section_old_way (abfd, ".rconst"); + asym->value -= asym->section->vma; + break; default: break; } @@ -844,97 +835,28 @@ ecoff_set_symbol_info (abfd, ecoff_sym, asym, ext) case N_SETT: case N_SETD: case N_SETB: - { - const char *name; - asection *section; - arelent_chain *reloc_chain; - unsigned int bitsize; - - /* Get a section with the same name as the symbol (usually - __CTOR_LIST__ or __DTOR_LIST__). FIXME: gcc uses the - name ___CTOR_LIST (three underscores). We need - __CTOR_LIST (two underscores), since ECOFF doesn't use - a leading underscore. This should be handled by gcc, - but instead we do it here. Actually, this should all - be done differently anyhow. */ - name = bfd_asymbol_name (asym); - if (name[0] == '_' && name[1] == '_' && name[2] == '_') - { - ++name; - asym->name = name; - } - section = bfd_get_section_by_name (abfd, name); - if (section == (asection *) NULL) - { - 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); - } - - /* 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; - reloc_chain->relent.addend = asym->value; - reloc_chain->relent.howto = - ecoff_backend (abfd)->constructor_reloc; - - /* Set up the constructor section to hold the reloc. */ - section->flags = SEC_CONSTRUCTOR; - ++section->reloc_count; - - /* Constructor sections must be rounded to a boundary - based on the bitsize. These are not real sections-- - they are handled specially by the linker--so the ECOFF - 16 byte alignment restriction does not apply. */ - bitsize = ecoff_backend (abfd)->constructor_bitsize; - section->alignment_power = 1; - while ((1 << section->alignment_power) < bitsize / 8) - ++section->alignment_power; - - reloc_chain->next = section->constructor_chain; - section->constructor_chain = reloc_chain; - section->_raw_size += bitsize / 8; - - /* Mark the symbol as a constructor. */ - asym->flags |= BSF_CONSTRUCTOR; - } + /* Mark the symbol as a constructor. */ + asym->flags |= BSF_CONSTRUCTOR; break; } } - return true; + return TRUE; } /* Read an ECOFF symbol table. */ -boolean -_bfd_ecoff_slurp_symbol_table (abfd) - bfd *abfd; +bfd_boolean +_bfd_ecoff_slurp_symbol_table (bfd *abfd) { const struct ecoff_backend_data * const backend = ecoff_backend (abfd); 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 *)) + void (* const swap_ext_in) (bfd *, void *, EXTR *) = backend->debug_swap.swap_ext_in; - void (* const swap_sym_in) PARAMS ((bfd *, PTR, SYMR *)) + void (* const swap_sym_in) (bfd *, void *, SYMR *) = backend->debug_swap.swap_sym_in; - bfd_size_type internal_size; ecoff_symbol_type *internal; ecoff_symbol_type *internal_ptr; char *eraw_src; @@ -944,22 +866,19 @@ _bfd_ecoff_slurp_symbol_table (abfd) /* If we've already read in the symbol table, do nothing. */ if (ecoff_data (abfd)->canonical_symbols != NULL) - return true; + return TRUE; /* Get the symbolic information. */ - if (! _bfd_ecoff_slurp_symbolic_info (abfd, (asection *) NULL, + if (! _bfd_ecoff_slurp_symbolic_info (abfd, NULL, &ecoff_data (abfd)->debug_info)) - return false; + return FALSE; if (bfd_get_symcount (abfd) == 0) - return true; + return TRUE; - internal_size = bfd_get_symcount (abfd) * sizeof (ecoff_symbol_type); - internal = (ecoff_symbol_type *) bfd_alloc (abfd, internal_size); + internal = (ecoff_symbol_type *) bfd_alloc2 (abfd, bfd_get_symcount (abfd), + sizeof (ecoff_symbol_type)); if (internal == NULL) - { - bfd_set_error (bfd_error_no_memory); - return false; - } + return FALSE; internal_ptr = internal; eraw_src = (char *) ecoff_data (abfd)->debug_info.external_ext; @@ -970,20 +889,35 @@ _bfd_ecoff_slurp_symbol_table (abfd) { EXTR internal_esym; - (*swap_ext_in) (abfd, (PTR) eraw_src, &internal_esym); + (*swap_ext_in) (abfd, (void *) eraw_src, &internal_esym); + + /* PR 17512: file: 3372-1000-0.004. */ + if (internal_esym.asym.iss >= ecoff_data (abfd)->debug_info.symbolic_header.issExtMax + || internal_esym.asym.iss < 0) + return FALSE; + internal_ptr->symbol.name = (ecoff_data (abfd)->debug_info.ssext + internal_esym.asym.iss); + if (!ecoff_set_symbol_info (abfd, &internal_esym.asym, - &internal_ptr->symbol, 1)) - return false; + &internal_ptr->symbol, 1, + internal_esym.weakext)) + return FALSE; + /* The alpha uses a negative ifd field for section symbols. */ if (internal_esym.ifd >= 0) - internal_ptr->fdr = (ecoff_data (abfd)->debug_info.fdr - + internal_esym.ifd); + { + /* PR 17512: file: 3372-1983-0.004. */ + if (internal_esym.ifd >= ecoff_data (abfd)->debug_info.symbolic_header.ifdMax) + internal_ptr->fdr = NULL; + else + internal_ptr->fdr = (ecoff_data (abfd)->debug_info.fdr + + internal_esym.ifd); + } else internal_ptr->fdr = NULL; - internal_ptr->local = false; - internal_ptr->native = (PTR) eraw_src; + internal_ptr->local = FALSE; + internal_ptr->native = (void *) eraw_src; } /* The local symbols must be accessed via the fdr's, because the @@ -1004,31 +938,45 @@ _bfd_ecoff_slurp_symbol_table (abfd) { SYMR internal_sym; - (*swap_sym_in) (abfd, (PTR) lraw_src, &internal_sym); + (*swap_sym_in) (abfd, (void *) lraw_src, &internal_sym); internal_ptr->symbol.name = (ecoff_data (abfd)->debug_info.ss + fdr_ptr->issBase + internal_sym.iss); if (!ecoff_set_symbol_info (abfd, &internal_sym, - &internal_ptr->symbol, 0)) - return false; + &internal_ptr->symbol, 0, 0)) + return FALSE; internal_ptr->fdr = fdr_ptr; - internal_ptr->local = true; - internal_ptr->native = (PTR) lraw_src; + internal_ptr->local = TRUE; + internal_ptr->native = (void *) lraw_src; } } + /* PR 17512: file: 3372-3080-0.004. + A discrepancy between ecoff_data (abfd)->debug_info.symbolic_header.isymMax + and ecoff_data (abfd)->debug_info.symbolic_header.ifdMax can mean that + we have fewer symbols than we were expecting. Allow for this by updating + the symbol count and warning the user. */ + if (internal_ptr - internal < (ptrdiff_t) bfd_get_symcount (abfd)) + { + bfd_get_symcount (abfd) = internal_ptr - internal; + _bfd_error_handler + /* xgettext:c-format */ + (_("%B: warning: isymMax (%ld) is greater than ifdMax (%ld)"), + abfd, ecoff_data (abfd)->debug_info.symbolic_header.isymMax, + ecoff_data (abfd)->debug_info.symbolic_header.ifdMax); + } + ecoff_data (abfd)->canonical_symbols = internal; - return true; + return TRUE; } /* Return the amount of space needed for the canonical symbols. */ long -_bfd_ecoff_get_symtab_upper_bound (abfd) - bfd *abfd; +_bfd_ecoff_get_symtab_upper_bound (bfd *abfd) { - if (! _bfd_ecoff_slurp_symbolic_info (abfd, (asection *) NULL, + if (! _bfd_ecoff_slurp_symbolic_info (abfd, NULL, &ecoff_data (abfd)->debug_info)) return -1; @@ -1041,15 +989,13 @@ _bfd_ecoff_get_symtab_upper_bound (abfd) /* Get the canonical symbols. */ long -_bfd_ecoff_get_symtab (abfd, alocation) - bfd *abfd; - asymbol **alocation; +_bfd_ecoff_canonicalize_symtab (bfd *abfd, asymbol **alocation) { unsigned int counter = 0; ecoff_symbol_type *symbase; ecoff_symbol_type **location = (ecoff_symbol_type **) alocation; - if (_bfd_ecoff_slurp_symbol_table (abfd) == false) + if (! _bfd_ecoff_slurp_symbol_table (abfd)) return -1; if (bfd_get_symcount (abfd) == 0) return 0; @@ -1060,7 +1006,7 @@ _bfd_ecoff_get_symtab (abfd, alocation) *(location++) = symbase++; counter++; } - *location++ = (ecoff_symbol_type *) NULL; + *location++ = NULL; return bfd_get_symcount (abfd); } @@ -1071,13 +1017,12 @@ _bfd_ecoff_get_symtab (abfd, alocation) /* Write aggregate information to a string. */ static void -ecoff_emit_aggregate (abfd, fdr, string, rndx, isym, which) - bfd *abfd; - FDR *fdr; - char *string; - RNDXR *rndx; - long isym; - const char *which; +ecoff_emit_aggregate (bfd *abfd, + FDR *fdr, + char *string, + RNDXR *rndx, + long isym, + const char *which) { const struct ecoff_debug_swap * const debug_swap = &ecoff_backend (abfd)->debug_swap; @@ -1085,7 +1030,7 @@ ecoff_emit_aggregate (abfd, fdr, string, rndx, isym, which) unsigned int ifd = rndx->rfd; unsigned int indx = rndx->index; const char *name; - + if (ifd == 0xfff) ifd = isym; @@ -1127,22 +1072,20 @@ ecoff_emit_aggregate (abfd, fdr, string, rndx, isym, which) sprintf (string, "%s %s { ifd = %u, index = %lu }", which, name, ifd, - ((long) indx + ((unsigned long) indx + debug_info->symbolic_header.iextMax)); } /* Convert the type information to string format. */ static char * -ecoff_type_to_string (abfd, fdr, indx) - bfd *abfd; - FDR *fdr; - unsigned int indx; +ecoff_type_to_string (bfd *abfd, FDR *fdr, unsigned int indx) { union aux_ext *aux_ptr; int bigendian; AUXU u; - struct qual { + struct qual + { unsigned int type; int low_bound; int high_bound; @@ -1179,56 +1122,54 @@ ecoff_type_to_string (abfd, fdr, indx) qualifiers[5].type = u.ti.tq5; qualifiers[6].type = tqNil; - /* - * Go get the basic type. - */ + /* Go get the basic type. */ switch (basic_type) { - case btNil: /* undefined */ + case btNil: /* Undefined. */ strcpy (p1, "nil"); break; - case btAdr: /* address - integer same size as pointer */ + case btAdr: /* Address - integer same size as pointer. */ strcpy (p1, "address"); break; - case btChar: /* character */ + case btChar: /* Character. */ strcpy (p1, "char"); break; - case btUChar: /* unsigned character */ + case btUChar: /* Unsigned character. */ strcpy (p1, "unsigned char"); break; - case btShort: /* short */ + case btShort: /* Short. */ strcpy (p1, "short"); break; - case btUShort: /* unsigned short */ + case btUShort: /* Unsigned short. */ strcpy (p1, "unsigned short"); break; - case btInt: /* int */ + case btInt: /* Int. */ strcpy (p1, "int"); break; - case btUInt: /* unsigned int */ + case btUInt: /* Unsigned int. */ strcpy (p1, "unsigned int"); break; - case btLong: /* long */ + case btLong: /* Long. */ strcpy (p1, "long"); break; - case btULong: /* unsigned long */ + case btULong: /* Unsigned long. */ strcpy (p1, "unsigned long"); break; - case btFloat: /* float (real) */ + case btFloat: /* Float (real). */ strcpy (p1, "float"); break; - case btDouble: /* Double (real) */ + case btDouble: /* Double (real). */ strcpy (p1, "double"); break; @@ -1236,96 +1177,94 @@ ecoff_type_to_string (abfd, fdr, indx) 1st word is [ST_RFDESCAPE, offset] pointer to struct def; 2nd word is file index if 1st word rfd is ST_RFDESCAPE. */ - case btStruct: /* Structure (Record) */ + case btStruct: /* Structure (Record). */ _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 */ + indx++; /* Skip aux words. */ break; /* Unions add 1-2 aux words: 1st word is [ST_RFDESCAPE, offset] pointer to union def; 2nd word is file index if 1st word rfd is ST_RFDESCAPE. */ - case btUnion: /* Union */ + case btUnion: /* Union. */ _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 */ + indx++; /* Skip aux words. */ break; /* Enumerations add 1-2 aux words: 1st word is [ST_RFDESCAPE, offset] pointer to enum def; 2nd word is file index if 1st word rfd is ST_RFDESCAPE. */ - case btEnum: /* Enumeration */ + case btEnum: /* Enumeration. */ _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 */ + indx++; /* Skip aux words. */ break; - case btTypedef: /* defined via a typedef, isymRef points */ + case btTypedef: /* Defined via a typedef, isymRef points. */ strcpy (p1, "typedef"); break; - case btRange: /* subrange of int */ + case btRange: /* Subrange of int. */ strcpy (p1, "subrange"); break; - case btSet: /* pascal sets */ + case btSet: /* Pascal sets. */ strcpy (p1, "set"); break; - case btComplex: /* fortran complex */ + case btComplex: /* Fortran complex. */ strcpy (p1, "complex"); break; - case btDComplex: /* fortran double complex */ + case btDComplex: /* Fortran double complex. */ strcpy (p1, "double complex"); break; - case btIndirect: /* forward or unnamed typedef */ + case btIndirect: /* Forward or unnamed typedef. */ strcpy (p1, "forward/unamed typedef"); break; - case btFixedDec: /* Fixed Decimal */ + case btFixedDec: /* Fixed Decimal. */ strcpy (p1, "fixed decimal"); break; - case btFloatDec: /* Float Decimal */ + case btFloatDec: /* Float Decimal. */ strcpy (p1, "float decimal"); break; - case btString: /* Varying Length Character String */ + case btString: /* Varying Length Character String. */ strcpy (p1, "string"); break; - case btBit: /* Aligned Bit String */ + case btBit: /* Aligned Bit String. */ strcpy (p1, "bit"); break; - case btPicture: /* Picture */ + case btPicture: /* Picture. */ strcpy (p1, "picture"); break; - case btVoid: /* Void */ + case btVoid: /* Void. */ strcpy (p1, "void"); break; default: - sprintf (p1, "Unknown basic type %d", (int) basic_type); + sprintf (p1, _("Unknown basic type %d"), (int) basic_type); break; } p1 += strlen (buffer1); - /* - * If this is a bitfield, get the bitsize. - */ + /* If this is a bitfield, get the bitsize. */ if (u.ti.fBitfield) { int bitsize; @@ -1335,21 +1274,16 @@ ecoff_type_to_string (abfd, fdr, indx) p1 += strlen (buffer1); } - - /* - * Deal with any qualifiers. - */ + /* Deal with any qualifiers. */ if (qualifiers[0].type != tqNil) { - /* - * Snarf up any array bounds in the correct order. Arrays - * store 5 successive words in the aux. table: - * word 0 RNDXR to type of the bounds (ie, int) - * word 1 Current file descriptor index - * word 2 low bound - * word 3 high bound (or -1 if []) - * word 4 stride size in bits - */ + /* Snarf up any array bounds in the correct order. Arrays + store 5 successive words in the aux. table: + word 0 RNDXR to type of the bounds (ie, int) + word 1 Current file descriptor index + word 2 low bound + word 3 high bound (or -1 if []) + word 4 stride size in bits. */ for (i = 0; i < 7; i++) { if (qualifiers[i].type == tqArray) @@ -1364,9 +1298,7 @@ ecoff_type_to_string (abfd, fdr, indx) } } - /* - * Now print out the qualifiers. - */ + /* Now print out the qualifiers. */ for (i = 0; i < 6; i++) { switch (qualifiers[i].type) @@ -1401,8 +1333,7 @@ ecoff_type_to_string (abfd, fdr, indx) int j; /* Print array bounds reversed (ie, in the order the C - programmer writes them). C is such a fun language.... */ - + programmer writes them). C is such a fun language.... */ while (i < 5 && qualifiers[i+1].type == tqArray) i++; @@ -1442,35 +1373,30 @@ ecoff_type_to_string (abfd, fdr, indx) /* Return information about ECOFF symbol SYMBOL in RET. */ -/*ARGSUSED*/ void -_bfd_ecoff_get_symbol_info (abfd, symbol, ret) - bfd *abfd; /* Ignored. */ - asymbol *symbol; - symbol_info *ret; +_bfd_ecoff_get_symbol_info (bfd *abfd ATTRIBUTE_UNUSED, + asymbol *symbol, + symbol_info *ret) { bfd_symbol_info (symbol, ret); } /* Return whether this is a local label. */ -/*ARGSUSED*/ -boolean -_bfd_ecoff_bfd_is_local_label (abfd, symbol) - bfd *abfd; - asymbol *symbol; +bfd_boolean +_bfd_ecoff_bfd_is_local_label_name (bfd *abfd ATTRIBUTE_UNUSED, + const char *name) { - return symbol->name[0] == '$'; + return name[0] == '$'; } /* Print information about an ECOFF symbol. */ void -_bfd_ecoff_print_symbol (abfd, filep, symbol, how) - bfd *abfd; - PTR filep; - asymbol *symbol; - bfd_print_symbol_type how; +_bfd_ecoff_print_symbol (bfd *abfd, + void * filep, + asymbol *symbol, + bfd_print_symbol_type how) { const struct ecoff_debug_swap * const debug_swap = &ecoff_backend (abfd)->debug_swap; @@ -1485,7 +1411,7 @@ _bfd_ecoff_print_symbol (abfd, filep, symbol, how) if (ecoffsymbol (symbol)->local) { SYMR ecoff_sym; - + (*debug_swap->swap_sym_in) (abfd, ecoffsymbol (symbol)->native, &ecoff_sym); fprintf (file, "ecoff local "); @@ -1506,7 +1432,7 @@ _bfd_ecoff_print_symbol (abfd, filep, symbol, how) } break; case bfd_print_symbol_all: - /* Print out the symbols in a reasonable way */ + /* Print out the symbols in a reasonable way. */ { char type; int pos; @@ -1580,7 +1506,7 @@ _bfd_ecoff_print_symbol (abfd, filep, symbol, how) order is indicated by a bit in the fdr. */ bigendian = fdr->fBigendian; - /* This switch is basically from gcc/mips-tdump.c */ + /* This switch is basically from gcc/mips-tdump.c. */ switch (ecoff_ext.asym.st) { case stNil: @@ -1589,17 +1515,17 @@ _bfd_ecoff_print_symbol (abfd, filep, symbol, how) case stFile: case stBlock: - fprintf (file, "\n End+1 symbol: %ld", + fprintf (file, _("\n End+1 symbol: %ld"), (long) (indx + sym_base)); break; case stEnd: if (ecoff_ext.asym.sc == scText || ecoff_ext.asym.sc == scInfo) - fprintf (file, "\n First symbol: %ld", + fprintf (file, _("\n First symbol: %ld"), (long) (indx + sym_base)); else - fprintf (file, "\n First symbol: %ld", + fprintf (file, _("\n First symbol: %ld"), ((long) (AUX_GET_ISYM (bigendian, &aux_base[ecoff_ext.asym.index]) @@ -1611,14 +1537,15 @@ _bfd_ecoff_print_symbol (abfd, filep, symbol, how) if (ECOFF_IS_STAB (&ecoff_ext.asym)) ; else if (ecoffsymbol (symbol)->local) - fprintf (file, "\n End+1 symbol: %-7ld Type: %s", + /* xgettext:c-format */ + 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, fdr, indx + 1)); else - fprintf (file, "\n Local symbol: %ld", + fprintf (file, _("\n Local symbol: %ld"), ((long) indx + (long) sym_base + (ecoff_data (abfd) @@ -1626,23 +1553,23 @@ _bfd_ecoff_print_symbol (abfd, filep, symbol, how) break; case stStruct: - fprintf (file, "\n struct; End+1 symbol: %ld", + fprintf (file, _("\n struct; End+1 symbol: %ld"), (long) (indx + sym_base)); break; case stUnion: - fprintf (file, "\n union; End+1 symbol: %ld", + fprintf (file, _("\n union; End+1 symbol: %ld"), (long) (indx + sym_base)); break; case stEnum: - fprintf (file, "\n enum; End+1 symbol: %ld", + 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", + fprintf (file, _("\n Type: %s"), ecoff_type_to_string (abfd, fdr, indx)); break; } @@ -1654,45 +1581,40 @@ _bfd_ecoff_print_symbol (abfd, filep, symbol, how) /* Read in the relocs for a section. */ -static boolean -ecoff_slurp_reloc_table (abfd, section, symbols) - bfd *abfd; - asection *section; - asymbol **symbols; +static bfd_boolean +ecoff_slurp_reloc_table (bfd *abfd, + asection *section, + asymbol **symbols) { const struct ecoff_backend_data * const backend = ecoff_backend (abfd); arelent *internal_relocs; bfd_size_type external_reloc_size; - bfd_size_type external_relocs_size; + bfd_size_type amt; char *external_relocs; arelent *rptr; unsigned int i; - if (section->relocation != (arelent *) NULL + if (section->relocation != NULL || section->reloc_count == 0 || (section->flags & SEC_CONSTRUCTOR) != 0) - return true; - - if (_bfd_ecoff_slurp_symbol_table (abfd) == false) - return false; - - internal_relocs = (arelent *) bfd_alloc (abfd, - (sizeof (arelent) - * section->reloc_count)); + return TRUE; + + if (! _bfd_ecoff_slurp_symbol_table (abfd)) + return FALSE; + + amt = section->reloc_count; + amt *= sizeof (arelent); + internal_relocs = (arelent *) bfd_alloc (abfd, amt); + external_reloc_size = backend->external_reloc_size; - external_relocs_size = external_reloc_size * section->reloc_count; - external_relocs = (char *) bfd_alloc (abfd, external_relocs_size); - if (internal_relocs == (arelent *) NULL - || external_relocs == (char *) NULL) - { - bfd_set_error (bfd_error_no_memory); - return false; - } + amt = external_reloc_size * section->reloc_count; + external_relocs = (char *) bfd_alloc (abfd, amt); + if (internal_relocs == NULL || external_relocs == NULL) + 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) - return false; + return FALSE; + if (bfd_bread (external_relocs, amt, abfd) != amt) + return FALSE; for (i = 0, rptr = internal_relocs; i < section->reloc_count; i++, rptr++) { @@ -1720,30 +1642,31 @@ ecoff_slurp_reloc_table (abfd, section, symbols) } else { - CONST char *sec_name; + const char *sec_name; asection *sec; /* r_symndx is a section key. */ switch (intern.r_symndx) { - case RELOC_SECTION_TEXT: sec_name = ".text"; break; - case RELOC_SECTION_RDATA: sec_name = ".rdata"; break; - case RELOC_SECTION_DATA: sec_name = ".data"; break; - case RELOC_SECTION_SDATA: sec_name = ".sdata"; break; - case RELOC_SECTION_SBSS: sec_name = ".sbss"; break; - case RELOC_SECTION_BSS: sec_name = ".bss"; break; - case RELOC_SECTION_INIT: sec_name = ".init"; break; - case RELOC_SECTION_LIT8: sec_name = ".lit8"; break; - 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; + case RELOC_SECTION_TEXT: sec_name = _TEXT; break; + case RELOC_SECTION_RDATA: sec_name = _RDATA; break; + case RELOC_SECTION_DATA: sec_name = _DATA; break; + case RELOC_SECTION_SDATA: sec_name = _SDATA; break; + case RELOC_SECTION_SBSS: sec_name = _SBSS; break; + case RELOC_SECTION_BSS: sec_name = _BSS; break; + case RELOC_SECTION_INIT: sec_name = _INIT; break; + case RELOC_SECTION_LIT8: sec_name = _LIT8; break; + 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; + case RELOC_SECTION_RCONST: sec_name = _RCONST; break; default: abort (); } sec = bfd_get_section_by_name (abfd, sec_name); - if (sec == (asection *) NULL) + if (sec == NULL) abort (); rptr->sym_ptr_ptr = sec->symbol_ptr_ptr; @@ -1761,21 +1684,20 @@ ecoff_slurp_reloc_table (abfd, section, symbols) section->relocation = internal_relocs; - return true; + return TRUE; } /* Get a canonical list of relocs. */ long -_bfd_ecoff_canonicalize_reloc (abfd, section, relptr, symbols) - bfd *abfd; - asection *section; - arelent **relptr; - asymbol **symbols; +_bfd_ecoff_canonicalize_reloc (bfd *abfd, + asection *section, + arelent **relptr, + asymbol **symbols) { unsigned int count; - if (section->flags & SEC_CONSTRUCTOR) + if (section->flags & SEC_CONSTRUCTOR) { arelent_chain *chain; @@ -1788,10 +1710,10 @@ _bfd_ecoff_canonicalize_reloc (abfd, section, relptr, symbols) *relptr++ = &chain->relent; } else - { + { arelent *tblptr; - if (ecoff_slurp_reloc_table (abfd, section, symbols) == false) + if (! ecoff_slurp_reloc_table (abfd, section, symbols)) return -1; tblptr = section->relocation; @@ -1800,7 +1722,7 @@ _bfd_ecoff_canonicalize_reloc (abfd, section, relptr, symbols) *relptr++ = tblptr++; } - *relptr = (arelent *) NULL; + *relptr = NULL; return section->reloc_count; } @@ -1809,51 +1731,39 @@ _bfd_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 -_bfd_ecoff_find_nearest_line (abfd, section, ignore_symbols, offset, - filename_ptr, functionname_ptr, retline_ptr) - bfd *abfd; - asection *section; - asymbol **ignore_symbols; - bfd_vma offset; - CONST char **filename_ptr; - CONST char **functionname_ptr; - unsigned int *retline_ptr; +bfd_boolean +_bfd_ecoff_find_nearest_line (bfd *abfd, + asymbol **symbols ATTRIBUTE_UNUSED, + asection *section, + bfd_vma offset, + const char **filename_ptr, + const char **functionname_ptr, + unsigned int *retline_ptr, + unsigned int *discriminator_ptr) { 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; struct ecoff_find_line *line_info; - /* If we're not in the .text section, we don't have any line - numbers. */ - if (strcmp (section->name, _TEXT) != 0 - || offset < ecoff_data (abfd)->text_start - || offset >= ecoff_data (abfd)->text_end) - return false; - /* Make sure we have the FDR's. */ - if (! _bfd_ecoff_slurp_symbolic_info (abfd, (asection *) NULL, debug_info) + if (! _bfd_ecoff_slurp_symbolic_info (abfd, NULL, debug_info) || bfd_get_symcount (abfd) == 0) - return false; + return FALSE; if (ecoff_data (abfd)->find_line_info == NULL) { + bfd_size_type amt = sizeof (struct ecoff_find_line); + ecoff_data (abfd)->find_line_info = - ((struct ecoff_find_line *) - bfd_alloc (abfd, sizeof (struct ecoff_find_line))); + (struct ecoff_find_line *) bfd_zalloc (abfd, amt); if (ecoff_data (abfd)->find_line_info == NULL) - { - bfd_set_error (bfd_error_no_memory); - return false; - } - ecoff_data (abfd)->find_line_info->find_buffer = NULL; - ecoff_data (abfd)->find_line_info->fdrtab_len = 0; - ecoff_data (abfd)->find_line_info->fdrtab = NULL; + return FALSE; } - line_info = ecoff_data (abfd)->find_line_info; + if (discriminator_ptr) + *discriminator_ptr = 0; + line_info = ecoff_data (abfd)->find_line_info; return _bfd_ecoff_locate_line (abfd, section, offset, debug_info, debug_swap, line_info, filename_ptr, functionname_ptr, retline_ptr); @@ -1872,23 +1782,21 @@ _bfd_ecoff_find_nearest_line (abfd, section, ignore_symbols, offset, the symbol table, so this function only handles the other debugging information. */ -boolean -_bfd_ecoff_bfd_copy_private_bfd_data (ibfd, obfd) - bfd *ibfd; - bfd *obfd; +bfd_boolean +_bfd_ecoff_bfd_copy_private_bfd_data (bfd *ibfd, bfd *obfd) { struct ecoff_debug_info *iinfo = &ecoff_data (ibfd)->debug_info; struct ecoff_debug_info *oinfo = &ecoff_data (obfd)->debug_info; - register int i; + int i; asymbol **sym_ptr_ptr; size_t c; - boolean local; + bfd_boolean local; - /* This function is selected based on the input vector. We only - want to copy information over if the output BFD also uses ECOFF + /* We only want to copy information over if both BFD's use ECOFF format. */ - if (bfd_get_flavour (obfd) != bfd_target_ecoff_flavour) - return true; + if (bfd_get_flavour (ibfd) != bfd_target_ecoff_flavour + || bfd_get_flavour (obfd) != bfd_target_ecoff_flavour) + return TRUE; /* Copy the GP value and the register masks. */ ecoff_data (obfd)->gp = ecoff_data (ibfd)->gp; @@ -1903,16 +1811,16 @@ _bfd_ecoff_bfd_copy_private_bfd_data (ibfd, obfd) /* 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; + if (c == 0 || sym_ptr_ptr == NULL) + return TRUE; /* See if there are any local symbols. */ - local = false; + local = FALSE; for (; c > 0; c--, sym_ptr_ptr++) { if (ecoffsymbol (*sym_ptr_ptr)->local) { - local = true; + local = TRUE; break; } } @@ -1975,18 +1883,17 @@ _bfd_ecoff_bfd_copy_private_bfd_data (ibfd, obfd) } } - return true; + return TRUE; } /* Set the architecture. The supported architecture is stored in the backend pointer. We always set the architecture anyhow, since many callers ignore the return value. */ -boolean -_bfd_ecoff_set_arch_mach (abfd, arch, machine) - bfd *abfd; - enum bfd_architecture arch; - unsigned long machine; +bfd_boolean +_bfd_ecoff_set_arch_mach (bfd *abfd, + enum bfd_architecture arch, + unsigned long machine) { bfd_default_set_arch_mach (abfd, arch, machine); return arch == ecoff_backend (abfd)->arch; @@ -1994,11 +1901,9 @@ _bfd_ecoff_set_arch_mach (abfd, arch, machine) /* Get the size of the section headers. */ -/*ARGSUSED*/ int -_bfd_ecoff_sizeof_headers (abfd, reloc) - bfd *abfd; - boolean reloc; +_bfd_ecoff_sizeof_headers (bfd *abfd, + struct bfd_link_info *info ATTRIBUTE_UNUSED) { asection *current; int c; @@ -2006,25 +1911,24 @@ _bfd_ecoff_sizeof_headers (abfd, reloc) c = 0; for (current = abfd->sections; - current != (asection *)NULL; - current = current->next) + current != NULL; + current = current->next) ++c; ret = (bfd_coff_filhsz (abfd) + bfd_coff_aoutsz (abfd) + c * bfd_coff_scnhsz (abfd)); - return BFD_ALIGN (ret, 16); + return (int) BFD_ALIGN (ret, 16); } /* Get the contents of a section. */ -boolean -_bfd_ecoff_get_section_contents (abfd, section, location, offset, count) - bfd *abfd; - asection *section; - PTR location; - file_ptr offset; - bfd_size_type count; +bfd_boolean +_bfd_ecoff_get_section_contents (bfd *abfd, + asection *section, + void * location, + file_ptr offset, + bfd_size_type count) { return _bfd_generic_get_section_contents (abfd, section, location, offset, count); @@ -2034,9 +1938,7 @@ _bfd_ecoff_get_section_contents (abfd, section, location, offset, count) called via qsort. */ static int -ecoff_sort_hdrs (arg1, arg2) - const PTR arg1; - const PTR arg2; +ecoff_sort_hdrs (const void * arg1, const void * arg2) { const asection *hdr1 = *(const asection **) arg1; const asection *hdr2 = *(const asection **) arg2; @@ -2062,28 +1964,28 @@ ecoff_sort_hdrs (arg1, arg2) /* Calculate the file position for each section, and set reloc_filepos. */ -static boolean -ecoff_compute_section_file_positions (abfd) - bfd *abfd; +static bfd_boolean +ecoff_compute_section_file_positions (bfd *abfd) { - file_ptr sofar; + file_ptr sofar, file_sofar; asection **sorted_hdrs; asection *current; unsigned int i; file_ptr old_sofar; - boolean first_data, first_nonalloc; + bfd_boolean rdata_in_text; + bfd_boolean first_data, first_nonalloc; const bfd_vma round = ecoff_backend (abfd)->round; + bfd_size_type amt; - sofar = _bfd_ecoff_sizeof_headers (abfd, false); + sofar = _bfd_ecoff_sizeof_headers (abfd, NULL); + file_sofar = sofar; /* Sort the sections by VMA. */ - sorted_hdrs = (asection **) malloc (abfd->section_count - * sizeof (asection *)); + amt = abfd->section_count; + amt *= sizeof (asection *); + sorted_hdrs = (asection **) bfd_malloc (amt); if (sorted_hdrs == NULL) - { - bfd_set_error (bfd_error_no_memory); - return false; - } + return FALSE; for (current = abfd->sections, i = 0; current != NULL; current = current->next, i++) @@ -2093,29 +1995,43 @@ ecoff_compute_section_file_positions (abfd) qsort (sorted_hdrs, abfd->section_count, sizeof (asection *), ecoff_sort_hdrs); - first_data = true; - first_nonalloc = true; + /* Some versions of the OSF linker put the .rdata section in the + text segment, and some do not. */ + rdata_in_text = ecoff_backend (abfd)->rdata_in_text; + if (rdata_in_text) + { + for (i = 0; i < abfd->section_count; i++) + { + current = sorted_hdrs[i]; + if (streq (current->name, _RDATA)) + break; + if ((current->flags & SEC_CODE) == 0 + && ! streq (current->name, _PDATA) + && ! streq (current->name, _RCONST)) + { + rdata_in_text = FALSE; + break; + } + } + } + ecoff_data (abfd)->rdata_in_text = rdata_in_text; + + first_data = TRUE; + first_nonalloc = TRUE; for (i = 0; i < abfd->section_count; i++) { unsigned int alignment_power; current = sorted_hdrs[i]; - /* Only deal with sections which have contents */ - 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; - } + if (streq (current->name, _PDATA)) + current->line_filepos = current->size / 8; + + alignment_power = current->alignment_power; /* On Ultrix, the data sections in an executable file must be aligned to a page boundary within the file. This does not @@ -2125,22 +2041,25 @@ ecoff_compute_section_file_positions (abfd) the data. */ if ((abfd->flags & EXEC_P) != 0 && (abfd->flags & D_PAGED) != 0 - && first_data != false + && ! first_data && (current->flags & SEC_CODE) == 0 - && (! ecoff_backend (abfd)->rdata_in_text - || strcmp (current->name, _RDATA) != 0) - && strcmp (current->name, _PDATA) != 0) + && (! rdata_in_text + || ! streq (current->name, _RDATA)) + && ! streq (current->name, _PDATA) + && ! streq (current->name, _RCONST)) { sofar = (sofar + round - 1) &~ (round - 1); - first_data = false; + file_sofar = (file_sofar + round - 1) &~ (round - 1); + first_data = FALSE; } - else if (strcmp (current->name, _LIB) == 0) + else if (streq (current->name, _LIB)) { /* 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); + file_sofar = (file_sofar + round - 1) &~ (round - 1); } else if (first_nonalloc && (current->flags & SEC_ALLOC) == 0 @@ -2149,35 +2068,46 @@ ecoff_compute_section_file_positions (abfd) /* Skip up to the next page for an unallocated section, such as the .comment section on the Alpha. This leaves room for the .bss section. */ - first_nonalloc = false; + first_nonalloc = FALSE; sofar = (sofar + round - 1) &~ (round - 1); + file_sofar = (file_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 << alignment_power); + if ((current->flags & SEC_HAS_CONTENTS) != 0) + file_sofar = BFD_ALIGN (file_sofar, 1 << alignment_power); if ((abfd->flags & D_PAGED) != 0 && (current->flags & SEC_ALLOC) != 0) - sofar += (current->vma - sofar) % round; + { + sofar += (current->vma - sofar) % round; + if ((current->flags & SEC_HAS_CONTENTS) != 0) + file_sofar += (current->vma - file_sofar) % round; + } - current->filepos = sofar; + if ((current->flags & (SEC_HAS_CONTENTS | SEC_LOAD)) != 0) + current->filepos = file_sofar; - sofar += current->_raw_size; + sofar += current->size; + if ((current->flags & SEC_HAS_CONTENTS) != 0) + file_sofar += current->size; - /* make sure that this section is of the right size too */ + /* Make sure that this section is of the right size too. */ old_sofar = sofar; sofar = BFD_ALIGN (sofar, 1 << alignment_power); - current->_raw_size += sofar - old_sofar; + if ((current->flags & SEC_HAS_CONTENTS) != 0) + file_sofar = BFD_ALIGN (file_sofar, 1 << alignment_power); + current->size += sofar - old_sofar; } free (sorted_hdrs); sorted_hdrs = NULL; - ecoff_data (abfd)->reloc_filepos = sofar; + ecoff_data (abfd)->reloc_filepos = file_sofar; - return true; + return TRUE; } /* Determine the location of the relocs for all the sections in the @@ -2185,8 +2115,7 @@ ecoff_compute_section_file_positions (abfd) information. */ static bfd_size_type -ecoff_compute_reloc_file_positions (abfd) - bfd *abfd; +ecoff_compute_reloc_file_positions (bfd *abfd) { const bfd_size_type external_reloc_size = ecoff_backend (abfd)->external_reloc_size; @@ -2199,15 +2128,15 @@ ecoff_compute_reloc_file_positions (abfd) { if (! ecoff_compute_section_file_positions (abfd)) abort (); - abfd->output_has_begun = true; + 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) + current != NULL; + current = current->next) { if (current->reloc_count == 0) current->rel_filepos = 0; @@ -2239,44 +2168,54 @@ ecoff_compute_reloc_file_positions (abfd) /* Set the contents of a section. */ -boolean -_bfd_ecoff_set_section_contents (abfd, section, location, offset, count) - bfd *abfd; - asection *section; - PTR location; - file_ptr offset; - bfd_size_type count; +bfd_boolean +_bfd_ecoff_set_section_contents (bfd *abfd, + asection *section, + const void * location, + file_ptr offset, + bfd_size_type count) { + file_ptr pos; + /* 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) + going to set output_has_begun to TRUE. */ + if (! abfd->output_has_begun + && ! ecoff_compute_section_file_positions (abfd)) + return FALSE; + + /* Handle the .lib section specially so that Irix 4 shared libraries + work out. See coff_set_section_contents in coffcode.h. */ + if (streq (section->name, _LIB)) { - if (! ecoff_compute_section_file_positions (abfd)) - return false; - } + bfd_byte *rec, *recend; + + rec = (bfd_byte *) location; + recend = rec + count; + while (rec < recend) + { + ++section->lma; + rec += bfd_get_32 (abfd, rec) * 4; + } - /* 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 . */ - if (strcmp (section->name, _LIB) == 0) - ++section->vma; + BFD_ASSERT (rec == recend); + } if (count == 0) - return true; + return TRUE; - if (bfd_seek (abfd, (file_ptr) (section->filepos + offset), SEEK_SET) != 0 - || bfd_write (location, 1, count, abfd) != count) - return false; + pos = section->filepos + offset; + if (bfd_seek (abfd, pos, SEEK_SET) != 0 + || bfd_bwrite (location, count, abfd) != count) + return FALSE; - return true; + 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; +bfd_ecoff_get_gp_value (bfd *abfd) { if (bfd_get_flavour (abfd) != bfd_target_ecoff_flavour || bfd_get_format (abfd) != bfd_object) @@ -2284,39 +2223,36 @@ bfd_ecoff_get_gp_value (abfd) bfd_set_error (bfd_error_invalid_operation); return 0; } - + return ecoff_data (abfd)->gp; } /* Set the GP value for an ECOFF file. This is a hook used by the assembler. */ -boolean -bfd_ecoff_set_gp_value (abfd, gp_value) - bfd *abfd; - bfd_vma gp_value; +bfd_boolean +bfd_ecoff_set_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; + return FALSE; } 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; +bfd_boolean +bfd_ecoff_set_regmasks (bfd *abfd, + unsigned long gprmask, + unsigned long fprmask, + unsigned long *cprmask) { ecoff_data_type *tdata; @@ -2324,30 +2260,28 @@ bfd_ecoff_set_regmasks (abfd, gprmask, fprmask, cprmask) || bfd_get_format (abfd) != bfd_object) { bfd_set_error (bfd_error_invalid_operation); - return false; + return FALSE; } tdata = ecoff_data (abfd); tdata->gprmask = gprmask; tdata->fprmask = fprmask; - if (cprmask != (unsigned long *) NULL) + if (cprmask != NULL) { - register int i; + int i; for (i = 0; i < 3; i++) tdata->cprmask[i] = cprmask[i]; } - return true; + 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; +static bfd_boolean +ecoff_get_extr (asymbol *sym, EXTR *esym) { ecoff_symbol_type *ecoff_sym_ptr; bfd *input_bfd; @@ -2359,11 +2293,11 @@ ecoff_get_extr (sym, esym) if ((sym->flags & BSF_DEBUGGING) != 0 || (sym->flags & BSF_LOCAL) != 0 || (sym->flags & BSF_SECTION_SYM) != 0) - return false; + return FALSE; esym->jmptbl = 0; esym->cobol_main = 0; - esym->weakext = 0; + esym->weakext = (sym->flags & BSF_WEAK) != 0; esym->reserved = 0; esym->ifd = ifdNil; /* FIXME: we can do better than this for st and sc. */ @@ -2371,13 +2305,13 @@ ecoff_get_extr (sym, esym) esym->asym.sc = scAbs; esym->asym.reserved = 0; esym->asym.index = indexNil; - return true; + return TRUE; } ecoff_sym_ptr = ecoffsymbol (sym); if (ecoff_sym_ptr->local) - return false; + return FALSE; input_bfd = bfd_asymbol_bfd (sym); (*(ecoff_backend (input_bfd)->debug_swap.swap_ext_in)) @@ -2399,29 +2333,26 @@ ecoff_get_extr (sym, esym) input_debug = &ecoff_data (input_bfd)->debug_info; BFD_ASSERT (esym->ifd < input_debug->symbolic_header.ifdMax); - if (input_debug->ifdmap != (RFDT *) NULL) + if (input_debug->ifdmap != NULL) esym->ifd = input_debug->ifdmap[esym->ifd]; } - return true; + 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_index (asymbol *sym, bfd_size_type indx) { ecoff_set_sym_index (sym, indx); } /* Write out an ECOFF file. */ -boolean -_bfd_ecoff_write_object_contents (abfd) - bfd *abfd; +bfd_boolean +_bfd_ecoff_write_object_contents (bfd *abfd) { const struct ecoff_backend_data * const backend = ecoff_backend (abfd); const bfd_vma round = backend->round; @@ -2431,13 +2362,9 @@ _bfd_ecoff_write_object_contents (abfd) 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 *)) + void (* const adjust_reloc_out) (bfd *, const arelent *, struct internal_reloc *) = backend->adjust_reloc_out; - void (* const swap_reloc_out) PARAMS ((bfd *, - const struct internal_reloc *, - PTR)) + void (* const swap_reloc_out) (bfd *, const struct internal_reloc *, void *) = backend->swap_reloc_out; struct ecoff_debug_info * const debug = &ecoff_data (abfd)->debug_info; HDRR * const symhdr = &debug->symbolic_header; @@ -2446,13 +2373,13 @@ _bfd_ecoff_write_object_contents (abfd) bfd_size_type reloc_size; bfd_size_type text_size; bfd_vma text_start; - boolean set_text_start; + bfd_boolean set_text_start; bfd_size_type data_size; bfd_vma data_start; - boolean set_data_start; + bfd_boolean set_data_start; bfd_size_type bss_size; - PTR buff = NULL; - PTR reloc_buff = NULL; + void * buff = NULL; + void * reloc_buff = NULL; struct internal_filehdr internal_f; struct internal_aouthdr internal_a; int i; @@ -2463,22 +2390,22 @@ _bfd_ecoff_write_object_contents (abfd) count = 1; for (current = abfd->sections; - current != (asection *)NULL; - current = current->next) + current != NULL; + current = current->next) { current->target_index = count; ++count; } if ((abfd->flags & D_PAGED) != 0) - text_size = _bfd_ecoff_sizeof_headers (abfd, false); + text_size = _bfd_ecoff_sizeof_headers (abfd, NULL); else text_size = 0; text_start = 0; - set_text_start = false; + set_text_start = FALSE; data_size = 0; data_start = 0; - set_data_start = false; + set_data_start = FALSE; bss_size = 0; /* Write section headers to the file. */ @@ -2487,24 +2414,23 @@ _bfd_ecoff_write_object_contents (abfd) 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 ((size_t) siz); + buff = bfd_malloc (siz); if (buff == NULL) - { - bfd_set_error (bfd_error_no_memory); - goto error_return; - } + goto error_return; } internal_f.f_nscns = 0; if (bfd_seek (abfd, (file_ptr) (filhsz + aoutsz), SEEK_SET) != 0) goto error_return; + for (current = abfd->sections; - current != (asection *) NULL; + current != NULL; current = current->next) { struct internal_scnhdr section; @@ -2516,13 +2442,13 @@ _bfd_ecoff_write_object_contents (abfd) /* This seems to be correct for Irix 4 shared libraries. */ vma = bfd_get_section_vma (abfd, current); - if (strcmp (current->name, _LIB) == 0) + if (streq (current->name, _LIB)) section.s_vaddr = 0; else section.s_vaddr = vma; - section.s_paddr = vma; - section.s_size = bfd_get_section_size_before_reloc (current); + section.s_paddr = current->lma; + section.s_size = current->size; /* If this section is unloadable then the scnptr will be 0. */ if ((current->flags & (SEC_LOAD | SEC_HAS_CONTENTS)) == 0) @@ -2538,7 +2464,7 @@ _bfd_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. */ - if (strcmp (current->name, _PDATA) != 0) + if (! streq (current->name, _PDATA)) section.s_lnnoptr = 0; else { @@ -2554,13 +2480,13 @@ _bfd_ecoff_write_object_contents (abfd) section.s_flags = ecoff_sec_to_styp_flags (current->name, current->flags); - if (bfd_coff_swap_scnhdr_out (abfd, (PTR) §ion, buff) == 0 - || bfd_write (buff, 1, scnhsz, abfd) != scnhsz) + if (bfd_coff_swap_scnhdr_out (abfd, (void *) §ion, buff) == 0 + || bfd_bwrite (buff, scnhsz, abfd) != scnhsz) goto error_return; if ((section.s_flags & STYP_TEXT) != 0 || ((section.s_flags & STYP_RDATA) != 0 - && backend->rdata_in_text) + && ecoff_data (abfd)->rdata_in_text) || section.s_flags == STYP_PDATA || (section.s_flags & STYP_DYNAMIC) != 0 || (section.s_flags & STYP_LIBLIST) != 0 @@ -2570,13 +2496,14 @@ _bfd_ecoff_write_object_contents (abfd) || (section.s_flags & STYP_DYNSYM) != 0 || (section.s_flags & STYP_HASH) != 0 || (section.s_flags & STYP_ECOFF_INIT) != 0 - || (section.s_flags & STYP_ECOFF_FINI) != 0) + || (section.s_flags & STYP_ECOFF_FINI) != 0 + || section.s_flags == STYP_RCONST) { - text_size += bfd_get_section_size_before_reloc (current); + text_size += current->size; if (! set_text_start || text_start > vma) { text_start = vma; - set_text_start = true; + set_text_start = TRUE; } } else if ((section.s_flags & STYP_RDATA) != 0 @@ -2588,26 +2515,25 @@ _bfd_ecoff_write_object_contents (abfd) || section.s_flags == STYP_XDATA || (section.s_flags & STYP_GOT) != 0) { - data_size += bfd_get_section_size_before_reloc (current); + data_size += current->size; if (! set_data_start || data_start > vma) { data_start = vma; - set_data_start = true; + 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); + bss_size += current->size; else if (section.s_flags == 0 || (section.s_flags & STYP_ECOFF_LIB) != 0 || section.s_flags == STYP_COMMENT) - /* Do nothing */ ; + /* Do nothing. */ ; else abort (); - } + } /* Set up the file header. */ - internal_f.f_magic = ecoff_get_magic (abfd); /* We will NOT put a fucking timestamp in the header here. Every @@ -2640,7 +2566,7 @@ _bfd_ecoff_write_object_contents (abfd) if (abfd->flags & EXEC_P) internal_f.f_flags |= F_EXEC; - if (! abfd->xvec->byteorder_big_p) + if (bfd_little_endian (abfd)) internal_f.f_flags |= F_AR32WR; else internal_f.f_flags |= F_AR32W; @@ -2700,16 +2626,15 @@ _bfd_ecoff_write_object_contents (abfd) } /* Write out the file header and the optional header. */ - if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0) goto error_return; - bfd_coff_swap_filehdr_out (abfd, (PTR) &internal_f, buff); - if (bfd_write (buff, 1, filhsz, abfd) != filhsz) + bfd_coff_swap_filehdr_out (abfd, (void *) &internal_f, buff); + if (bfd_bwrite (buff, filhsz, abfd) != filhsz) goto error_return; - bfd_coff_swap_aouthdr_out (abfd, (PTR) &internal_a, buff); - if (bfd_write (buff, 1, aoutsz, abfd) != aoutsz) + bfd_coff_swap_aouthdr_out (abfd, (void *) &internal_a, buff); + if (bfd_bwrite (buff, aoutsz, abfd) != aoutsz) goto error_return; /* Build the external symbol information. This must be done before @@ -2722,36 +2647,33 @@ _bfd_ecoff_write_object_contents (abfd) 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) + if (! bfd_ecoff_debug_externals (abfd, debug, &backend->debug_swap, + (abfd->flags & EXEC_P) == 0, + ecoff_get_extr, ecoff_set_index)) goto error_return; /* Write out the relocs. */ for (current = abfd->sections; - current != (asection *) NULL; + current != NULL; current = current->next) { arelent **reloc_ptr_ptr; arelent **reloc_end; char *out_ptr; + bfd_size_type amt; if (current->reloc_count == 0) continue; - reloc_buff = - bfd_alloc (abfd, current->reloc_count * external_reloc_size); + amt = current->reloc_count * external_reloc_size; + reloc_buff = bfd_alloc (abfd, amt); if (reloc_buff == NULL) - { - bfd_set_error (bfd_error_no_memory); - goto error_return; - } + goto error_return; 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) @@ -2759,12 +2681,17 @@ _bfd_ecoff_write_object_contents (abfd) arelent *reloc; asymbol *sym; struct internal_reloc in; - - memset ((PTR) &in, 0, sizeof in); + + memset ((void *) &in, 0, sizeof in); reloc = *reloc_ptr_ptr; sym = *reloc->sym_ptr_ptr; + /* If the howto field has not been initialised then skip this reloc. + This assumes that an error message has been issued elsewhere. */ + if (reloc->howto == NULL) + continue; + in.r_vaddr = (reloc->address + bfd_get_section_vma (abfd, current)); in.r_type = reloc->howto->type; @@ -2776,52 +2703,55 @@ _bfd_ecoff_write_object_contents (abfd) } else { - CONST char *name; + const char *name; + unsigned int j; + static struct + { + const char * name; + long r_symndx; + } + section_symndx [] = + { + { _TEXT, RELOC_SECTION_TEXT }, + { _RDATA, RELOC_SECTION_RDATA }, + { _DATA, RELOC_SECTION_DATA }, + { _SDATA, RELOC_SECTION_SDATA }, + { _SBSS, RELOC_SECTION_SBSS }, + { _BSS, RELOC_SECTION_BSS }, + { _INIT, RELOC_SECTION_INIT }, + { _LIT8, RELOC_SECTION_LIT8 }, + { _LIT4, RELOC_SECTION_LIT4 }, + { _XDATA, RELOC_SECTION_XDATA }, + { _PDATA, RELOC_SECTION_PDATA }, + { _FINI, RELOC_SECTION_FINI }, + { _LITA, RELOC_SECTION_LITA }, + { "*ABS*", RELOC_SECTION_ABS }, + { _RCONST, RELOC_SECTION_RCONST } + }; 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 + + for (j = 0; j < ARRAY_SIZE (section_symndx); j++) + if (streq (name, section_symndx[j].name)) + { + in.r_symndx = section_symndx[j].r_symndx; + break; + } + + if (j == ARRAY_SIZE (section_symndx)) abort (); in.r_extern = 0; } (*adjust_reloc_out) (abfd, reloc, &in); - (*swap_reloc_out) (abfd, &in, (PTR) out_ptr); + (*swap_reloc_out) (abfd, &in, (void *) 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) + amt = current->reloc_count * external_reloc_size; + if (bfd_bwrite (reloc_buff, amt, abfd) != amt) goto error_return; bfd_release (abfd, reloc_buff); reloc_buff = NULL; @@ -2831,9 +2761,8 @@ _bfd_ecoff_write_object_contents (abfd) 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) + if (! bfd_ecoff_write_debug (abfd, debug, &backend->debug_swap, + ecoff_data (abfd)->sym_filepos)) goto error_return; } } @@ -2851,12 +2780,12 @@ _bfd_ecoff_write_object_contents (abfd) if (bfd_seek (abfd, (file_ptr) ecoff_data (abfd)->sym_filepos - 1, SEEK_SET) != 0) goto error_return; - if (bfd_read (&c, 1, 1, abfd) == 0) + if (bfd_bread (&c, (bfd_size_type) 1, abfd) == 0) c = 0; if (bfd_seek (abfd, (file_ptr) ecoff_data (abfd)->sym_filepos - 1, SEEK_SET) != 0) goto error_return; - if (bfd_write (&c, 1, 1, abfd) != 1) + if (bfd_bwrite (&c, (bfd_size_type) 1, abfd) != 1) goto error_return; } @@ -2864,13 +2793,13 @@ _bfd_ecoff_write_object_contents (abfd) bfd_release (abfd, reloc_buff); if (buff != NULL) free (buff); - return true; + return TRUE; error_return: if (reloc_buff != NULL) bfd_release (abfd, reloc_buff); if (buff != NULL) free (buff); - return false; + return FALSE; } /* Archive handling. ECOFF uses what appears to be a unique type of @@ -2903,19 +2832,19 @@ _bfd_ecoff_write_object_contents (abfd) The Alpha seems to use ________64E[BL]E[BL]_. */ -#define ARMAP_BIG_ENDIAN 'B' -#define ARMAP_LITTLE_ENDIAN 'L' -#define ARMAP_MARKER 'E' -#define ARMAP_START_LENGTH 10 -#define ARMAP_HEADER_MARKER_INDEX 10 -#define ARMAP_HEADER_ENDIAN_INDEX 11 -#define ARMAP_OBJECT_MARKER_INDEX 12 -#define ARMAP_OBJECT_ENDIAN_INDEX 13 -#define ARMAP_END_INDEX 14 -#define ARMAP_END "_ " +#define ARMAP_BIG_ENDIAN 'B' +#define ARMAP_LITTLE_ENDIAN 'L' +#define ARMAP_MARKER 'E' +#define ARMAP_START_LENGTH 10 +#define ARMAP_HEADER_MARKER_INDEX 10 +#define ARMAP_HEADER_ENDIAN_INDEX 11 +#define ARMAP_OBJECT_MARKER_INDEX 12 +#define ARMAP_OBJECT_ENDIAN_INDEX 13 +#define ARMAP_END_INDEX 14 +#define ARMAP_END "_ " /* This is a magic number used in the hashing algorithm. */ -#define ARMAP_HASH_MAGIC 0x9dd68ab5 +#define ARMAP_HASH_MAGIC 0x9dd68ab5 /* This returns the hash value to use for a string. It also sets *REHASH to the rehash adjustment if the first slot is taken. SIZE @@ -2923,14 +2852,15 @@ _bfd_ecoff_write_object_contents (abfd) base 2 of SIZE. */ static unsigned int -ecoff_armap_hash (s, rehash, size, hlog) - CONST char *s; - unsigned int *rehash; - unsigned int size; - unsigned int hlog; +ecoff_armap_hash (const char *s, + unsigned int *rehash, + unsigned int size, + unsigned int hlog) { unsigned int hash; + if (hlog == 0) + return 0; hash = *s++; while (*s != '\0') hash = ((hash >> 27) | (hash << 5)) + *s++; @@ -2941,9 +2871,8 @@ ecoff_armap_hash (s, rehash, size, hlog) /* Read in the armap. */ -boolean -_bfd_ecoff_slurp_armap (abfd) - bfd *abfd; +bfd_boolean +_bfd_ecoff_slurp_armap (bfd *abfd) { char nextname[17]; unsigned int i; @@ -2953,86 +2882,81 @@ _bfd_ecoff_slurp_armap (abfd) struct artdata *ardata; unsigned int count; char *raw_ptr; - struct symdef *symdef_ptr; + carsym *symdef_ptr; char *stringbase; - + bfd_size_type amt; + /* Get the name of the first element. */ - i = bfd_read ((PTR) nextname, 1, 16, abfd); + i = bfd_bread ((void *) nextname, (bfd_size_type) 16, abfd); if (i == 0) - return true; + return TRUE; if (i != 16) - return false; + return FALSE; if (bfd_seek (abfd, (file_ptr) -16, SEEK_CUR) != 0) - return false; + 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 bfd_slurp_armap, but that seems inappropriate since no other target uses this format. Instead, we check directly for a COFF armap. */ - if (strncmp (nextname, "/ ", 16) == 0) + if (CONST_STRNEQ (nextname, "/ ")) return bfd_slurp_armap (abfd); /* See if the first element is an armap. */ - if (strncmp (nextname, ecoff_backend (abfd)->armap_start, - ARMAP_START_LENGTH) != 0 + if (! strneq (nextname, ecoff_backend (abfd)->armap_start, ARMAP_START_LENGTH) || nextname[ARMAP_HEADER_MARKER_INDEX] != ARMAP_MARKER || (nextname[ARMAP_HEADER_ENDIAN_INDEX] != ARMAP_BIG_ENDIAN && nextname[ARMAP_HEADER_ENDIAN_INDEX] != ARMAP_LITTLE_ENDIAN) || nextname[ARMAP_OBJECT_MARKER_INDEX] != ARMAP_MARKER || (nextname[ARMAP_OBJECT_ENDIAN_INDEX] != ARMAP_BIG_ENDIAN && nextname[ARMAP_OBJECT_ENDIAN_INDEX] != ARMAP_LITTLE_ENDIAN) - || strncmp (nextname + ARMAP_END_INDEX, - ARMAP_END, sizeof ARMAP_END - 1) != 0) + || ! strneq (nextname + ARMAP_END_INDEX, ARMAP_END, sizeof ARMAP_END - 1)) { - bfd_has_map (abfd) = false; - return true; + bfd_has_map (abfd) = FALSE; + return TRUE; } /* Make sure we have the right byte ordering. */ if (((nextname[ARMAP_HEADER_ENDIAN_INDEX] == ARMAP_BIG_ENDIAN) - ^ (abfd->xvec->header_byteorder_big_p != false)) + ^ (bfd_header_big_endian (abfd))) || ((nextname[ARMAP_OBJECT_ENDIAN_INDEX] == ARMAP_BIG_ENDIAN) - ^ (abfd->xvec->byteorder_big_p != false))) + ^ (bfd_big_endian (abfd)))) { bfd_set_error (bfd_error_wrong_format); - return false; + return FALSE; } /* Read in the armap. */ ardata = bfd_ardata (abfd); - mapdata = _bfd_snarf_ar_hdr (abfd); - if (mapdata == (struct areltdata *) NULL) - return false; + mapdata = (struct areltdata *) _bfd_read_ar_hdr (abfd); + if (mapdata == NULL) + return FALSE; parsed_size = mapdata->parsed_size; - bfd_release (abfd, (PTR) mapdata); - + free (mapdata); + raw_armap = (char *) bfd_alloc (abfd, parsed_size); - if (raw_armap == (char *) NULL) - { - bfd_set_error (bfd_error_no_memory); - return false; - } - - if (bfd_read ((PTR) raw_armap, 1, parsed_size, abfd) != parsed_size) + if (raw_armap == NULL) + return FALSE; + + if (bfd_bread ((void *) raw_armap, parsed_size, abfd) != parsed_size) { if (bfd_get_error () != bfd_error_system_call) bfd_set_error (bfd_error_malformed_archive); - bfd_release (abfd, (PTR) raw_armap); - return false; + bfd_release (abfd, (void *) raw_armap); + return FALSE; } - - ardata->tdata = (PTR) raw_armap; - count = bfd_h_get_32 (abfd, (PTR) raw_armap); + ardata->tdata = (void *) raw_armap; + + count = H_GET_32 (abfd, raw_armap); ardata->symdef_count = 0; - ardata->cache = (struct ar_cache *) NULL; + ardata->cache = NULL; /* This code used to overlay the symdefs over the raw archive data, but that doesn't work on a 64 bit host. */ - stringbase = raw_armap + count * 8 + 8; #ifdef CHECK_ARMAP_HASH @@ -3051,9 +2975,9 @@ _bfd_ecoff_slurp_armap (abfd) { unsigned int name_offset, file_offset; unsigned int hash, rehash, srch; - - name_offset = bfd_h_get_32 (abfd, (PTR) raw_ptr); - file_offset = bfd_h_get_32 (abfd, (PTR) (raw_ptr + 4)); + + name_offset = H_GET_32 (abfd, raw_ptr); + file_offset = H_GET_32 (abfd, (raw_ptr + 4)); if (file_offset == 0) continue; hash = ecoff_armap_hash (stringbase + name_offset, &rehash, count, @@ -3065,8 +2989,7 @@ _bfd_ecoff_slurp_armap (abfd) for (srch = (hash + rehash) & (count - 1); srch != hash && srch != i; srch = (srch + rehash) & (count - 1)) - BFD_ASSERT (bfd_h_get_32 (abfd, (PTR) (raw_armap + 8 + srch * 8)) - != 0); + BFD_ASSERT (H_GET_32 (abfd, (raw_armap + 8 + srch * 8)) != 0); BFD_ASSERT (srch == i); } } @@ -3075,30 +2998,27 @@ _bfd_ecoff_slurp_armap (abfd) raw_ptr = raw_armap + 4; for (i = 0; i < count; i++, raw_ptr += 8) - if (bfd_h_get_32 (abfd, (PTR) (raw_ptr + 4)) != 0) + if (H_GET_32 (abfd, (raw_ptr + 4)) != 0) ++ardata->symdef_count; - symdef_ptr = ((struct symdef *) - bfd_alloc (abfd, - ardata->symdef_count * sizeof (struct symdef))); + amt = ardata->symdef_count; + amt *= sizeof (carsym); + symdef_ptr = (carsym *) bfd_alloc (abfd, amt); if (!symdef_ptr) - { - bfd_set_error (bfd_error_no_memory); - return false; - } + return FALSE; - ardata->symdefs = (carsym *) symdef_ptr; + ardata->symdefs = symdef_ptr; raw_ptr = raw_armap + 4; for (i = 0; i < count; i++, raw_ptr += 8) { unsigned int name_offset, file_offset; - file_offset = bfd_h_get_32 (abfd, (PTR) (raw_ptr + 4)); + file_offset = H_GET_32 (abfd, (raw_ptr + 4)); if (file_offset == 0) continue; - name_offset = bfd_h_get_32 (abfd, (PTR) raw_ptr); - symdef_ptr->s.name = stringbase + name_offset; + name_offset = H_GET_32 (abfd, raw_ptr); + symdef_ptr->name = stringbase + name_offset; symdef_ptr->file_offset = file_offset; ++symdef_ptr; } @@ -3107,23 +3027,22 @@ _bfd_ecoff_slurp_armap (abfd) /* Pad to an even boundary. */ ardata->first_file_filepos += ardata->first_file_filepos % 2; - bfd_has_map (abfd) = true; + bfd_has_map (abfd) = TRUE; - return true; + return TRUE; } /* Write out an armap. */ -boolean -_bfd_ecoff_write_armap (abfd, elength, map, orl_count, stridx) - bfd *abfd; - unsigned int elength; - struct orl *map; - unsigned int orl_count; - int stridx; +bfd_boolean +_bfd_ecoff_write_armap (bfd *abfd, + unsigned int elength, + struct orl *map, + unsigned int orl_count, + int stridx) { unsigned int hashsize, hashlog; - unsigned int symdefsize; + bfd_size_type symdefsize; int padit; unsigned int stringsize; unsigned int mapsize; @@ -3138,7 +3057,7 @@ _bfd_ecoff_write_armap (abfd, elength, map, orl_count, stridx) /* Ultrix appears to use as a hash table size the least power of two greater than twice the number of entries. */ - for (hashlog = 0; (1 << hashlog) <= 2 * orl_count; hashlog++) + for (hashlog = 0; ((unsigned int) 1 << hashlog) <= 2 * orl_count; hashlog++) ; hashsize = 1 << hashlog; @@ -3146,23 +3065,23 @@ _bfd_ecoff_write_armap (abfd, elength, map, orl_count, stridx) padit = stridx % 2; stringsize = stridx + padit; - /* Include 8 bytes to store symdefsize and stringsize in output. */ + /* Include 8 bytes to store symdefsize and stringsize in output. */ mapsize = symdefsize + stringsize + 8; firstreal = SARMAG + sizeof (struct ar_hdr) + mapsize + elength; - memset ((PTR) &hdr, 0, sizeof hdr); + memset ((void *) &hdr, 0, sizeof hdr); /* Work out the ECOFF armap name. */ strcpy (hdr.ar_name, ecoff_backend (abfd)->armap_start); hdr.ar_name[ARMAP_HEADER_MARKER_INDEX] = ARMAP_MARKER; hdr.ar_name[ARMAP_HEADER_ENDIAN_INDEX] = - (abfd->xvec->header_byteorder_big_p + (bfd_header_big_endian (abfd) ? ARMAP_BIG_ENDIAN : ARMAP_LITTLE_ENDIAN); hdr.ar_name[ARMAP_OBJECT_MARKER_INDEX] = ARMAP_MARKER; hdr.ar_name[ARMAP_OBJECT_ENDIAN_INDEX] = - abfd->xvec->byteorder_big_p ? ARMAP_BIG_ENDIAN : ARMAP_LITTLE_ENDIAN; + bfd_big_endian (abfd) ? ARMAP_BIG_ENDIAN : ARMAP_LITTLE_ENDIAN; memcpy (hdr.ar_name + ARMAP_END_INDEX, ARMAP_END, sizeof ARMAP_END - 1); /* Write the timestamp of the archive header to be just a little bit @@ -3171,62 +3090,63 @@ _bfd_ecoff_write_armap (abfd, elength, map, orl_count, stridx) linker just checks the archive name; the GNU linker may check the date. */ stat (abfd->filename, &statbuf); - sprintf (hdr.ar_date, "%ld", (long) (statbuf.st_mtime + 60)); + _bfd_ar_spacepad (hdr.ar_date, sizeof (hdr.ar_date), "%ld", + (long) (statbuf.st_mtime + 60)); /* The DECstation uses zeroes for the uid, gid and mode of the armap. */ hdr.ar_uid[0] = '0'; hdr.ar_gid[0] = '0'; - hdr.ar_mode[0] = '0'; + /* Building gcc ends up extracting the armap as a file - twice. */ + hdr.ar_mode[0] = '6'; + hdr.ar_mode[1] = '4'; + hdr.ar_mode[2] = '4'; - sprintf (hdr.ar_size, "%-10d", (int) mapsize); + _bfd_ar_spacepad (hdr.ar_size, sizeof (hdr.ar_size), "%-10ld", mapsize); hdr.ar_fmag[0] = '`'; hdr.ar_fmag[1] = '\012'; /* Turn all null bytes in the header into spaces. */ for (i = 0; i < sizeof (struct ar_hdr); i++) - if (((char *)(&hdr))[i] == '\0') - (((char *)(&hdr))[i]) = ' '; + if (((char *) (&hdr))[i] == '\0') + (((char *) (&hdr))[i]) = ' '; - if (bfd_write ((PTR) &hdr, 1, sizeof (struct ar_hdr), abfd) + if (bfd_bwrite ((void *) &hdr, (bfd_size_type) sizeof (struct ar_hdr), abfd) != sizeof (struct ar_hdr)) - return false; + return FALSE; + + H_PUT_32 (abfd, hashsize, temp); + if (bfd_bwrite ((void *) temp, (bfd_size_type) 4, abfd) != 4) + return FALSE; - 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; - } + return FALSE; current = abfd->archive_head; last_elt = current; for (i = 0; i < orl_count; i++) { - unsigned int hash, rehash; + unsigned int hash, rehash = 0; /* Advance firstreal to the file position of this archive element. */ - if (((bfd *) map[i].pos) != last_elt) + if (map[i].u.abfd != last_elt) { do { firstreal += arelt_size (current) + sizeof (struct ar_hdr); firstreal += firstreal % 2; - current = current->next; + current = current->archive_next; } - while (current != (bfd *) map[i].pos); + while (current != map[i].u.abfd); } last_elt = current; hash = ecoff_armap_hash (*map[i].name, &rehash, hashsize, hashlog); - if (bfd_h_get_32 (abfd, (PTR) (hashtable + (hash * 8) + 4)) != 0) + if (H_GET_32 (abfd, (hashtable + (hash * 8) + 4)) != 0) { unsigned int srch; @@ -3234,131 +3154,65 @@ _bfd_ecoff_write_armap (abfd, elength, map, orl_count, stridx) for (srch = (hash + rehash) & (hashsize - 1); srch != hash; srch = (srch + rehash) & (hashsize - 1)) - if (bfd_h_get_32 (abfd, (PTR) (hashtable + (srch * 8) + 4)) == 0) + if (H_GET_32 (abfd, (hashtable + (srch * 8) + 4)) == 0) break; BFD_ASSERT (srch != hash); hash = srch; } - - 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)); + + H_PUT_32 (abfd, map[i].namidx, (hashtable + hash * 8)); + H_PUT_32 (abfd, firstreal, (hashtable + hash * 8 + 4)); } - if (bfd_write ((PTR) hashtable, 1, symdefsize, abfd) != symdefsize) - return false; + if (bfd_bwrite ((void *) hashtable, symdefsize, abfd) != symdefsize) + return FALSE; bfd_release (abfd, hashtable); /* Now write the strings. */ - bfd_h_put_32 (abfd, (bfd_vma) stringsize, temp); - if (bfd_write ((PTR) temp, 1, 4, abfd) != 4) - return false; + H_PUT_32 (abfd, stringsize, temp); + if (bfd_bwrite ((void *) temp, (bfd_size_type) 4, abfd) != 4) + return FALSE; for (i = 0; i < orl_count; i++) { bfd_size_type len; len = strlen (*map[i].name) + 1; - if (bfd_write ((PTR) (*map[i].name), 1, len, abfd) != len) - return false; + if (bfd_bwrite ((void *) (*map[i].name), len, abfd) != len) + return FALSE; } /* The spec sez this should be a newline. But in order to be bug-compatible for DECstation ar we use a null. */ if (padit) { - if (bfd_write ("", 1, 1, abfd) != 1) - return false; - } - - return true; -} - -/* See whether this BFD is an archive. If it is, read in the armap - and the extended name table. */ - -const bfd_target * -_bfd_ecoff_archive_p (abfd) - bfd *abfd; -{ - char armag[SARMAG + 1]; - - if (bfd_read ((PTR) armag, 1, SARMAG, abfd) != SARMAG - || strncmp (armag, ARMAG, SARMAG) != 0) - { - 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 - 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)); - - if (bfd_ardata (abfd) == (struct artdata *) NULL) - { - bfd_set_error (bfd_error_no_memory); - return (const bfd_target *) NULL; + if (bfd_bwrite ("", (bfd_size_type) 1, abfd) != 1) + return FALSE; } - 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 (_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 (const bfd_target *) NULL; - } - - return abfd->xvec; + return TRUE; } /* 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; +ecoff_link_hash_newfunc (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) + if (ret == 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; - } + if (ret == NULL) + return NULL; /* Call the allocation method of the superclass. */ ret = ((struct ecoff_link_hash_entry *) @@ -3373,7 +3227,7 @@ ecoff_link_hash_newfunc (entry, table, string) ret->written = 0; ret->small = 0; } - memset ((PTR) &ret->esym, 0, sizeof ret->esym); + memset ((void *) &ret->esym, 0, sizeof ret->esym); return (struct bfd_hash_entry *) ret; } @@ -3381,23 +3235,20 @@ ecoff_link_hash_newfunc (entry, table, string) /* Create an ECOFF link hash table. */ struct bfd_link_hash_table * -_bfd_ecoff_bfd_link_hash_table_create (abfd) - bfd *abfd; +_bfd_ecoff_bfd_link_hash_table_create (bfd *abfd) { struct ecoff_link_hash_table *ret; + bfd_size_type amt = sizeof (struct ecoff_link_hash_table); - ret = ((struct ecoff_link_hash_table *) - bfd_alloc (abfd, sizeof (struct ecoff_link_hash_table))); + ret = (struct ecoff_link_hash_table *) bfd_malloc (amt); if (ret == NULL) - { - bfd_set_error (bfd_error_no_memory); - return NULL; - } - if (! _bfd_link_hash_table_init (&ret->root, abfd, - ecoff_link_hash_newfunc)) + return NULL; + if (!_bfd_link_hash_table_init (&ret->root, abfd, + ecoff_link_hash_newfunc, + sizeof (struct ecoff_link_hash_entry))) { free (ret); - return (struct bfd_link_hash_table *) NULL; + return NULL; } return &ret->root; } @@ -3408,431 +3259,48 @@ _bfd_ecoff_bfd_link_hash_table_create (abfd) ((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. */ +/* 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. */ -boolean -_bfd_ecoff_bfd_link_add_symbols (abfd, info) - bfd *abfd; - struct bfd_link_info *info; +static bfd_boolean +ecoff_link_add_externals (bfd *abfd, + struct bfd_link_info *info, + void * external_ext, + char *ssext) { - 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; - } -} + const struct ecoff_backend_data * const backend = ecoff_backend (abfd); + void (* const swap_ext_in) (bfd *, void *, EXTR *) + = backend->debug_swap.swap_ext_in; + bfd_size_type external_ext_size = backend->debug_swap.external_ext_size; + unsigned long ext_count; + struct bfd_link_hash_entry **sym_hash; + char *ext_ptr; + char *ext_end; + bfd_size_type amt; -/* 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. */ + ext_count = ecoff_data (abfd)->debug_info.symbolic_header.iextMax; -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; + amt = ext_count; + amt *= sizeof (struct bfd_link_hash_entry *); + sym_hash = (struct bfd_link_hash_entry **) bfd_alloc (abfd, amt); + if (!sym_hash) + return FALSE; + ecoff_data (abfd)->sym_hashes = (struct ecoff_link_hash_entry **) sym_hash; - if (! bfd_has_map (abfd)) - { - /* An empty archive is a special case. */ - if (bfd_openr_next_archived_file (abfd, (bfd *) NULL) == NULL) - return true; - bfd_set_error (bfd_error_no_armap); - 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) != - (bfd_size_type) 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) - != (bfd_size_type) 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++) + 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_boolean skip; bfd_vma value; asection *section; const char *name; @@ -3840,10 +3308,10 @@ ecoff_link_add_externals (abfd, info, external_ext, ssext) *sym_hash = NULL; - (*swap_ext_in) (abfd, (PTR) ext_ptr, &esym); + (*swap_ext_in) (abfd, (void *) ext_ptr, &esym); /* Skip debugging symbols. */ - skip = false; + skip = FALSE; switch (esym.asym.st) { case stGlobal: @@ -3853,7 +3321,7 @@ ecoff_link_add_externals (abfd, info, external_ext, ssext) case stStaticProc: break; default: - skip = true; + skip = TRUE; break; } @@ -3882,15 +3350,15 @@ ecoff_link_add_externals (abfd, info, external_ext, ssext) section = NULL; break; case scText: - section = bfd_make_section_old_way (abfd, ".text"); + section = bfd_make_section_old_way (abfd, _TEXT); value -= section->vma; break; case scData: - section = bfd_make_section_old_way (abfd, ".data"); + section = bfd_make_section_old_way (abfd, _DATA); value -= section->vma; break; case scBss: - section = bfd_make_section_old_way (abfd, ".bss"); + section = bfd_make_section_old_way (abfd, _BSS); value -= section->vma; break; case scAbs: @@ -3900,15 +3368,15 @@ ecoff_link_add_externals (abfd, info, external_ext, ssext) section = bfd_und_section_ptr; break; case scSData: - section = bfd_make_section_old_way (abfd, ".sdata"); + section = bfd_make_section_old_way (abfd, _SDATA); value -= section->vma; break; case scSBss: - section = bfd_make_section_old_way (abfd, ".sbss"); + section = bfd_make_section_old_way (abfd, _SBSS); value -= section->vma; break; case scRData: - section = bfd_make_section_old_way (abfd, ".rdata"); + section = bfd_make_section_old_way (abfd, _RDATA); value -= section->vma; break; case scCommon: @@ -3938,34 +3406,37 @@ ecoff_link_add_externals (abfd, info, external_ext, ssext) section = bfd_und_section_ptr; break; case scInit: - section = bfd_make_section_old_way (abfd, ".init"); + section = bfd_make_section_old_way (abfd, _INIT); value -= section->vma; break; case scFini: - section = bfd_make_section_old_way (abfd, ".fini"); + section = bfd_make_section_old_way (abfd, _FINI); + value -= section->vma; + break; + case scRConst: + section = bfd_make_section_old_way (abfd, _RCONST); value -= section->vma; break; } - if (section == (asection *) NULL) + if (section == 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; + (info, abfd, name, + (flagword) (esym.weakext ? BSF_WEAK : BSF_GLOBAL), + section, value, NULL, TRUE, TRUE, sym_hash))) + return FALSE; - *sym_hash = h; + h = (struct ecoff_link_hash_entry *) *sym_hash; /* If we are building an ECOFF hash table, save the external symbol information. */ - if (info->hash->creator->flavour == bfd_get_flavour (abfd)) + if (bfd_get_flavour (info->output_bfd) == bfd_get_flavour (abfd)) { - if (h->abfd == (bfd *) NULL + if (h->abfd == NULL || (! bfd_is_und_section (section) && (! bfd_is_com_section (section) || (h->root.type != bfd_link_hash_defined @@ -3986,7 +3457,7 @@ ecoff_link_add_externals (abfd, info, external_ext, ssext) 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.p->section->name, SCOMMON) != 0) + && streq (h->root.u.c.p->section->name, SCOMMON)) { h->root.u.c.p->section = bfd_make_section_old_way (abfd, SCOMMON); @@ -3997,261 +3468,309 @@ ecoff_link_add_externals (abfd, info, external_ext, ssext) } } - return true; + 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. */ +/* Add symbols from an ECOFF object file to the global linker hash + table. */ -boolean -_bfd_ecoff_bfd_final_link (abfd, info) - bfd *abfd; - struct bfd_link_info *info; +static bfd_boolean +ecoff_link_add_object_symbols (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; + bfd_size_type external_ext_size; + void * external_ext = NULL; + bfd_size_type esize; + char *ssext = NULL; + bfd_boolean result; - /* 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; + if (! ecoff_slurp_symbolic_header (abfd)) + return FALSE; - /* 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; + /* If there are no symbols, we don't want it. */ + if (bfd_get_symcount (abfd) == 0) + return TRUE; - handle = bfd_ecoff_debug_init (abfd, debug, &backend->debug_swap, info); - if (handle == (PTR) NULL) - return false; + symhdr = &ecoff_data (abfd)->debug_info.symbolic_header; - /* 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; + /* 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 = bfd_malloc (esize); + if (external_ext == NULL && esize != 0) + goto error_return; - 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; + if (bfd_seek (abfd, (file_ptr) symhdr->cbExtOffset, SEEK_SET) != 0 + || bfd_bread (external_ext, esize, abfd) != esize) + goto error_return; - /* 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]; - } + ssext = (char *) bfd_malloc ((bfd_size_type) symhdr->issExtMax); + if (ssext == NULL && symhdr->issExtMax != 0) + goto error_return; - /* Write out the external symbols. */ - ecoff_link_hash_traverse (ecoff_hash_table (info), - ecoff_link_write_external, - (PTR) abfd); + if (bfd_seek (abfd, (file_ptr) symhdr->cbSsExtOffset, SEEK_SET) != 0 + || (bfd_bread (ssext, (bfd_size_type) symhdr->issExtMax, abfd) + != (bfd_size_type) symhdr->issExtMax)) + goto error_return; - 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; - } - } + result = ecoff_link_add_externals (abfd, info, external_ext, ssext); - /* Compute the reloc and symbol file positions. */ - ecoff_compute_reloc_file_positions (abfd); + if (ssext != NULL) + free (ssext); + if (external_ext != NULL) + free (external_ext); + return result; - /* 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; + error_return: + if (ssext != NULL) + free (ssext); + if (external_ext != NULL) + free (external_ext); + return FALSE; +} - bfd_ecoff_debug_free (handle, abfd, debug, &backend->debug_swap, info); +/* This is called if we used _bfd_generic_link_add_archive_symbols + because we were not dealing with an ECOFF archive. */ + +static bfd_boolean +ecoff_link_check_archive_element (bfd *abfd, + struct bfd_link_info *info, + struct bfd_link_hash_entry *h, + const char *name, + bfd_boolean *pneeded) +{ + *pneeded = FALSE; + + /* Unlike the generic linker, we do not pull in elements because + of common symbols. */ + if (h->type != bfd_link_hash_undefined) + return TRUE; - if (info->relocateable) + /* Include this element? */ + if (!(*info->callbacks->add_archive_element) (info, abfd, name, &abfd)) + return TRUE; + *pneeded = TRUE; + + return ecoff_link_add_object_symbols (abfd, info); +} + +/* 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 bfd_boolean +ecoff_link_add_archive_symbols (bfd *abfd, struct bfd_link_info *info) +{ + const struct ecoff_backend_data * const backend = ecoff_backend (abfd); + 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)) { - /* 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; + /* An empty archive is a special case. */ + if (bfd_openr_next_archived_file (abfd, NULL) == NULL) + return TRUE; + bfd_set_error (bfd_error_no_armap); + return FALSE; } - /* Get a value for the GP register. */ - if (ecoff_data (abfd)->gp == 0) + /* 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 == NULL) + return (_bfd_generic_link_add_archive_symbols + (abfd, info, ecoff_link_check_archive_element)); + + armap_count = 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 != NULL) { struct bfd_link_hash_entry *h; + unsigned int hash, rehash = 0; + unsigned int file_offset; + const char *name; + bfd *element; - 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) + 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) { - bfd_vma lo; + /* 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)->u.undef.next; + else + pundef = &(*pundef)->u.undef.next; + continue; + } - /* 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; + /* 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)->u.undef.next; + continue; } - else + + /* Look for this symbol in the archive hash table. */ + hash = ecoff_armap_hash (h->root.string, &rehash, armap_count, + armap_log); + + file_offset = H_GET_32 (abfd, hashtable + (hash * 8) + 4); + if (file_offset == 0) { - /* 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. */ + /* Nothing in this slot. */ + pundef = &(*pundef)->u.undef.next; + continue; } - } - 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) + name = stringbase + H_GET_32 (abfd, hashtable + (hash * 8)); + if (name[0] != h->root.string[0] + || ! streq (name, h->root.string)) { - 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) + unsigned int srch; + bfd_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)) { - if (! ecoff_reloc_link_order (abfd, info, o, p)) - return false; + file_offset = H_GET_32 (abfd, hashtable + (srch * 8) + 4); + if (file_offset == 0) + break; + name = stringbase + H_GET_32 (abfd, hashtable + (srch * 8)); + if (name[0] == h->root.string[0] + && streq (name, h->root.string)) + { + found = TRUE; + break; + } } - else + + if (! found) { - if (! _bfd_default_link_order (abfd, info, o, p)) - return false; + pundef = &(*pundef)->u.undef.next; + continue; } + + hash = srch; } + + element = (*backend->get_elt_at_filepos) (abfd, (file_ptr) file_offset); + if (element == 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, &element)) + return FALSE; + if (! ecoff_link_add_object_symbols (element, info)) + return FALSE; + + pundef = &(*pundef)->u.undef.next; } - bfd_get_symcount (abfd) = symhdr->iextMax + symhdr->isymMax; + return TRUE; +} - ecoff_data (abfd)->linker = true; +/* Given an ECOFF BFD, add symbols to the global hash table as + appropriate. */ - return true; +bfd_boolean +_bfd_ecoff_bfd_link_add_symbols (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; + } } + +/* ECOFF final link routines. */ + +/* Structure used to pass information to ecoff_link_write_external. */ + +struct extsym_info +{ + bfd *abfd; + struct bfd_link_info *info; +}; + /* 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; +static bfd_boolean +ecoff_final_link_debug_accumulate (bfd *output_bfd, + bfd *input_bfd, + struct bfd_link_info *info, + void * 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_t) (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; \ - } \ + bfd_boolean ret; + +#define READ(ptr, offset, count, size, type) \ + if (symhdr->count == 0) \ + debug->ptr = NULL; \ + else \ + { \ + bfd_size_type amt = (bfd_size_type) size * symhdr->count; \ + debug->ptr = (type) bfd_malloc (amt); \ + if (debug->ptr == NULL) \ + { \ + ret = FALSE; \ + goto return_something; \ + } \ + if (bfd_seek (input_bfd, (file_ptr) symhdr->offset, SEEK_SET) != 0 \ + || bfd_bread (debug->ptr, amt, input_bfd) != amt) \ + { \ + ret = FALSE; \ + goto return_something; \ + } \ } /* If raw_syments is not NULL, then the data was already by read by @@ -4260,15 +3779,15 @@ ecoff_final_link_debug_accumulate (output_bfd, input_bfd, info, handle) { 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_dnr, cbDnOffset, idnMax, swap->external_dnr_size, void *); + READ (external_pdr, cbPdOffset, ipdMax, swap->external_pdr_size, void *); + READ (external_sym, cbSymOffset, isymMax, swap->external_sym_size, void *); + READ (external_opt, cbOptOffset, ioptMax, swap->external_opt_size, void *); 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); + READ (external_fdr, cbFdOffset, ifdMax, swap->external_fdr_size, void *); + READ (external_rfd, cbRfdOffset, crfd, swap->external_rfd_size, void *); } #undef READ @@ -4317,22 +3836,331 @@ ecoff_final_link_debug_accumulate (output_bfd, input_bfd, info, handle) return ret; } +/* Relocate and write an ECOFF section into an ECOFF output file. */ + +static bfd_boolean +ecoff_indirect_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; + bfd_byte *contents = NULL; + bfd_size_type external_reloc_size; + bfd_size_type external_relocs_size; + void * external_relocs = NULL; + + BFD_ASSERT ((output_section->flags & SEC_HAS_CONTENTS) != 0); + + input_section = link_order->u.indirect.section; + input_bfd = input_section->owner; + if (input_section->size == 0) + return TRUE; + + BFD_ASSERT (input_section->output_section == output_section); + BFD_ASSERT (input_section->output_offset == link_order->offset); + BFD_ASSERT (input_section->size == link_order->size); + + /* Get the section contents. */ + if (!bfd_malloc_and_get_section (input_bfd, input_section, &contents)) + 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; + + external_relocs = bfd_malloc (external_relocs_size); + if (external_relocs == NULL && external_relocs_size != 0) + goto error_return; + + if (bfd_seek (input_bfd, input_section->rel_filepos, SEEK_SET) != 0 + || (bfd_bread (external_relocs, 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, + contents, + input_section->output_offset, + input_section->size)) + goto error_return; + + /* If we are producing relocatable 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 (bfd_link_relocatable (info)) + { + file_ptr pos = (output_section->rel_filepos + + output_section->reloc_count * external_reloc_size); + if (bfd_seek (output_bfd, pos, SEEK_SET) != 0 + || (bfd_bwrite (external_relocs, 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) + free (external_relocs); + return TRUE; + + error_return: + if (contents != NULL) + free (contents); + if (external_relocs != 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 bfd_boolean +ecoff_reloc_link_order (bfd *output_bfd, + struct bfd_link_info *info, + asection *output_section, + struct bfd_link_order *link_order) +{ + enum bfd_link_order_type type; + asection *section; + bfd_vma addend; + arelent rel; + struct internal_reloc in; + bfd_size_type external_reloc_size; + bfd_byte *rbuf; + bfd_boolean ok; + file_ptr pos; + + type = link_order->type; + section = NULL; + addend = link_order->u.reloc.p->addend; + + /* 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 == 0) + { + bfd_set_error (bfd_error_bad_value); + return FALSE; + } + + if (type == bfd_section_reloc_link_order) + { + section = link_order->u.reloc.p->u.section; + rel.sym_ptr_ptr = section->symbol_ptr_ptr; + } + else + { + struct bfd_link_hash_entry *h; + + /* Treat a reloc against a defined symbol as though it were + actually against the section. */ + h = bfd_wrapped_link_hash_lookup (output_bfd, info, + link_order->u.reloc.p->u.name, + FALSE, FALSE, FALSE); + if (h != NULL + && (h->type == bfd_link_hash_defined + || h->type == bfd_link_hash_defweak)) + { + type = bfd_section_reloc_link_order; + section = h->u.def.section->output_section; + /* It seems that we ought to add the symbol value to the + addend here, but in practice it has already been added + because it was passed to constructor_callback. */ + addend += section->vma + h->u.def.section->output_offset; + } + else + { + /* We can't set up a reloc against a symbol correctly, + because we have no asymbol structure. Currently no + adjust_reloc_out routine cares. */ + rel.sym_ptr_ptr = NULL; + } + } + + /* All ECOFF relocs are in-place. Put the addend into the object + file. */ + + BFD_ASSERT (rel.howto->partial_inplace); + if (addend != 0) + { + bfd_size_type size; + bfd_reloc_status_type rstat; + bfd_byte *buf; + + size = bfd_get_reloc_size (rel.howto); + buf = (bfd_byte *) bfd_zmalloc (size); + if (buf == NULL && size != 0) + return FALSE; + rstat = _bfd_relocate_contents (rel.howto, output_bfd, + (bfd_vma) addend, buf); + switch (rstat) + { + case bfd_reloc_ok: + break; + default: + case bfd_reloc_outofrange: + abort (); + case bfd_reloc_overflow: + (*info->callbacks->reloc_overflow) + (info, NULL, + (link_order->type == bfd_section_reloc_link_order + ? bfd_section_name (output_bfd, section) + : link_order->u.reloc.p->u.name), + rel.howto->name, addend, NULL, NULL, (bfd_vma) 0); + break; + } + ok = bfd_set_section_contents (output_bfd, output_section, (void *) buf, + (file_ptr) link_order->offset, size); + free (buf); + if (! ok) + return FALSE; + } + + rel.addend = 0; + + /* Move the information into an internal_reloc structure. */ + in.r_vaddr = (rel.address + + bfd_get_section_vma (output_bfd, output_section)); + in.r_type = rel.howto->type; + + if (type == bfd_symbol_reloc_link_order) + { + struct ecoff_link_hash_entry *h; + + h = ((struct ecoff_link_hash_entry *) + bfd_wrapped_link_hash_lookup (output_bfd, info, + link_order->u.reloc.p->u.name, + FALSE, FALSE, TRUE)); + if (h != NULL + && h->indx != -1) + in.r_symndx = h->indx; + else + { + (*info->callbacks->unattached_reloc) + (info, link_order->u.reloc.p->u.name, NULL, NULL, (bfd_vma) 0); + in.r_symndx = 0; + } + in.r_extern = 1; + } + else + { + const char *name; + unsigned int i; + static struct + { + const char * name; + long r_symndx; + } + section_symndx [] = + { + { _TEXT, RELOC_SECTION_TEXT }, + { _RDATA, RELOC_SECTION_RDATA }, + { _DATA, RELOC_SECTION_DATA }, + { _SDATA, RELOC_SECTION_SDATA }, + { _SBSS, RELOC_SECTION_SBSS }, + { _BSS, RELOC_SECTION_BSS }, + { _INIT, RELOC_SECTION_INIT }, + { _LIT8, RELOC_SECTION_LIT8 }, + { _LIT4, RELOC_SECTION_LIT4 }, + { _XDATA, RELOC_SECTION_XDATA }, + { _PDATA, RELOC_SECTION_PDATA }, + { _FINI, RELOC_SECTION_FINI }, + { _LITA, RELOC_SECTION_LITA }, + { "*ABS*", RELOC_SECTION_ABS }, + { _RCONST, RELOC_SECTION_RCONST } + }; + + name = bfd_get_section_name (output_bfd, section); + + for (i = 0; i < ARRAY_SIZE (section_symndx); i++) + if (streq (name, section_symndx[i].name)) + { + in.r_symndx = section_symndx[i].r_symndx; + break; + } + + if (i == ARRAY_SIZE (section_symndx)) + 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 *) bfd_malloc (external_reloc_size); + if (rbuf == NULL) + return FALSE; + + (*ecoff_backend (output_bfd)->swap_reloc_out) (output_bfd, &in, (void *) rbuf); + + pos = (output_section->rel_filepos + + output_section->reloc_count * external_reloc_size); + ok = (bfd_seek (output_bfd, pos, SEEK_SET) == 0 + && (bfd_bwrite ((void *) rbuf, external_reloc_size, output_bfd) + == external_reloc_size)); + + if (ok) + ++output_section->reloc_count; + + free (rbuf); + + return ok; +} + /* 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; +static bfd_boolean +ecoff_link_write_external (struct bfd_hash_entry *bh, void * data) { - bfd *output_bfd = (bfd *) data; + struct ecoff_link_hash_entry *h = (struct ecoff_link_hash_entry *) bh; + struct extsym_info *einfo = (struct extsym_info *) data; + bfd *output_bfd = einfo->abfd; + bfd_boolean strip; - /* FIXME: We should check if this symbol is being stripped. */ + if (h->root.type == bfd_link_hash_warning) + { + h = (struct ecoff_link_hash_entry *) h->root.u.i.link; + if (h->root.type == bfd_link_hash_new) + return TRUE; + } - if (h->written) - return true; + /* We need to check if this symbol is being stripped. */ + if (h->root.type == bfd_link_hash_undefined + || h->root.type == bfd_link_hash_undefweak) + strip = FALSE; + else if (einfo->info->strip == strip_all + || (einfo->info->strip == strip_some + && bfd_hash_lookup (einfo->info->keep_hash, + h->root.root.string, + FALSE, FALSE) == NULL)) + strip = TRUE; + else + strip = FALSE; - if (h->abfd == (bfd *) NULL) + if (strip || h->written) + return TRUE; + + if (h->abfd == NULL) { h->esym.jmptbl = 0; h->esym.cobol_main = 0; @@ -4349,31 +4177,38 @@ ecoff_link_write_external (h, data) { asection *output_section; const char *name; + unsigned int i; + static struct + { + const char * name; + int sc; + } + section_storage_classes [] = + { + { _TEXT, scText }, + { _DATA, scData }, + { _SDATA, scSData }, + { _RDATA, scRData }, + { _BSS, scBss }, + { _SBSS, scSBss }, + { _INIT, scInit }, + { _FINI, scFini }, + { _PDATA, scPData }, + { _XDATA, scXData }, + { _RCONST, scRConst } + }; + + output_section = h->root.u.def.section->output_section; + name = bfd_section_name (output_section->owner, output_section); + + for (i = 0; i < ARRAY_SIZE (section_storage_classes); i++) + if (streq (name, section_storage_classes[i].name)) + { + h->esym.asym.sc = section_storage_classes[i].sc; + break; + } - 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 + if (i == ARRAY_SIZE (section_storage_classes)) h->esym.asym.sc = scAbs; } @@ -4395,6 +4230,7 @@ ecoff_link_write_external (h, data) switch (h->root.type) { default: + case bfd_link_hash_warning: case bfd_link_hash_new: abort (); case bfd_link_hash_undefined: @@ -4423,10 +4259,9 @@ ecoff_link_write_external (h, data) 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; + /* We ignore these symbols, since the indirected symbol is + already in the hash table. */ + return TRUE; } /* bfd_ecoff_debug_one_external uses iextMax to keep track of the @@ -4440,313 +4275,202 @@ ecoff_link_write_external (h, data) &h->esym)); } -/* Relocate and write an ECOFF section into an ECOFF output file. */ +/* 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. */ -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; +bfd_boolean +_bfd_ecoff_bfd_final_link (bfd *abfd, struct bfd_link_info *info) { - asection *input_section; + const struct ecoff_backend_data * const backend = ecoff_backend (abfd); + struct ecoff_debug_info * const debug = &ecoff_data (abfd)->debug_info; + HDRR *symhdr; + void * handle; 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; + asection *o; + struct bfd_link_order *p; + struct extsym_info einfo; - input_section = link_order->u.indirect.section; - input_bfd = input_section->owner; - section_tdata = ecoff_section_data (input_bfd, input_section); + /* 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; - raw_size = input_section->_raw_size; - cooked_size = input_section->_cooked_size; - if (cooked_size == 0) - cooked_size = raw_size; + /* 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; - 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 - ? (size_t) raw_size - : (size_t) cooked_size); - if (contents == NULL && raw_size != 0) - { - bfd_set_error (bfd_error_no_memory); - goto error_return; - } + handle = bfd_ecoff_debug_init (abfd, debug, &backend->debug_swap, info); + if (handle == NULL) + return FALSE; - /* 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, (size_t) raw_size); - else + /* Accumulate the debugging symbols from each input BFD. */ + for (input_bfd = info->input_bfds; + input_bfd != NULL; + input_bfd = input_bfd->link.next) { - 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; + bfd_boolean ret; - if (section_tdata != (struct ecoff_section_tdata *) NULL) - external_relocs = section_tdata->external_relocs; - else - { - external_relocs = (PTR) malloc ((size_t) external_relocs_size); - if (external_relocs == NULL && external_relocs_size != 0) + if (bfd_get_flavour (input_bfd) == bfd_target_ecoff_flavour) { - bfd_set_error (bfd_error_no_memory); - goto error_return; + /* Arbitrarily 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; - 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; + /* 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]; } - /* 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; + /* Write out the external symbols. */ + einfo.abfd = abfd; + einfo.info = info; + bfd_hash_traverse (&info->hash->table, ecoff_link_write_external, &einfo); - /* 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_link_relocatable (info)) { - 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; + /* 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 != NULL; o = o->next) + { + o->reloc_count = 0; + for (p = o->map_head.link_order; + p != 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; + } } - 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; + /* Compute the reloc and symbol file positions. */ + ecoff_compute_reloc_file_positions (abfd); - /* We set up an arelent to pass to the backend adjust_reloc_out - routine. */ - rel.address = link_order->offset; + /* 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; - rel.howto = bfd_reloc_type_lookup (output_bfd, link_order->u.reloc.p->reloc); - if (rel.howto == 0) - { - bfd_set_error (bfd_error_bad_value); - return false; - } + bfd_ecoff_debug_free (handle, abfd, debug, &backend->debug_swap, info); - if (link_order->type == bfd_section_reloc_link_order) - rel.sym_ptr_ptr = link_order->u.reloc.p->u.section->symbol_ptr_ptr; - else + if (bfd_link_relocatable (info)) { - /* 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; + /* 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 != NULL; o = o->next) + o->reloc_count = 0; } - /* 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) + /* Get a value for the GP register. */ + if (ecoff_data (abfd)->gp == 0) { - bfd_size_type size; - bfd_reloc_status_type rstat; - bfd_byte *buf; - boolean ok; + struct bfd_link_hash_entry *h; - 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) + h = bfd_link_hash_lookup (info->hash, "_gp", FALSE, FALSE, TRUE); + if (h != 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 (bfd_link_relocatable (info)) { - 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))) + bfd_vma lo; + + /* Make up a value. */ + lo = (bfd_vma) -1; + for (o = abfd->sections; o != NULL; o = o->next) { - free (buf); - return false; + if (o->vma < lo + && (streq (o->name, _SBSS) + || streq (o->name, _SDATA) + || streq (o->name, _LIT4) + || streq (o->name, _LIT8) + || streq (o->name, _LITA))) + lo = o->vma; } - break; + ecoff_data (abfd)->gp = lo + 0x8000; } - 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; + /* 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. */ } - 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 ((size_t) external_reloc_size); - if (rbuf == (bfd_byte *) NULL) + for (o = abfd->sections; o != NULL; o = o->next) { - bfd_set_error (bfd_error_no_memory); - return false; + for (p = o->map_head.link_order; + p != 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; + } + } } - (*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; + bfd_get_symcount (abfd) = symhdr->iextMax + symhdr->isymMax; - free (rbuf); + ecoff_data (abfd)->linker = TRUE; - return ok; + return TRUE; }