diff --git a/bfd/ChangeLog b/bfd/ChangeLog index 152a7f7420..3fe46ffbc6 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,18 @@ +Sun Dec 15 14:46:06 1996 Ian Lance Taylor + + * elfcode.h (elf_slurp_reloc_table): Add dynamic parameter. + * elf.c (_bfd_elf_canonicalize_reloc): Pass new argument to + slurp_reloc_table. + (_bfd_elf_get_dynamic_reloc_upper_bound): New function. + (_bfd_elf_canonicalize_dynamic_reloc): New function. + * elf-bfd.h (struct elf_size_info): Update declaration of + slurp_reloc_table. + (_bfd_elf_get_dynamic_reloc_upper_bound): Declare. + (_bfd_elf_canonicalize_dynamic_reloc): Declare. + * elfxx-target.h: Use new dynamic reloc routines by default. + * elf64-mips.c (mips_elf64_slurp_reloc_table): Add dynamic + parameter. + Fri Dec 13 13:18:49 1996 Dan Wilder * coffcode.h (coff_set_flags): Use MC68KBCSMAGIC for bfd_arch_m68k diff --git a/bfd/elf-bfd.h b/bfd/elf-bfd.h index 4592386ae6..ac27d1fe4e 100644 --- a/bfd/elf-bfd.h +++ b/bfd/elf-bfd.h @@ -110,6 +110,9 @@ struct elf_link_hash_entry /* Symbol type (STT_NOTYPE, STT_OBJECT, etc.). */ char type; + /* Symbol st_other value. */ + unsigned char other; + /* Some flags; legal values follow. */ unsigned char elf_link_hash_flags; /* Symbol is referenced by a non-shared object. */ @@ -193,7 +196,8 @@ struct elf_size_info { boolean (*write_shdrs_and_ehdr) PARAMS ((bfd *)); void (*write_relocs) PARAMS ((bfd *, asection *, PTR)); void (*swap_symbol_out) PARAMS ((bfd *, const Elf_Internal_Sym *, PTR)); - boolean (*slurp_reloc_table) PARAMS ((bfd *, asection *, asymbol **)); + boolean (*slurp_reloc_table) + PARAMS ((bfd *, asection *, asymbol **, boolean)); long (*slurp_symbol_table) PARAMS ((bfd *, asymbol **, boolean)); void (*swap_dyn_in) PARAMS ((bfd *, const PTR, Elf_Internal_Dyn *)); }; @@ -698,6 +702,9 @@ extern long _bfd_elf_canonicalize_dynamic_symtab PARAMS ((bfd *, asymbol **)); extern long _bfd_elf_get_reloc_upper_bound PARAMS ((bfd *, sec_ptr)); extern long _bfd_elf_canonicalize_reloc PARAMS ((bfd *, sec_ptr, arelent **, asymbol **)); +extern long _bfd_elf_get_dynamic_reloc_upper_bound PARAMS ((bfd *)); +extern long _bfd_elf_canonicalize_dynamic_reloc PARAMS ((bfd *, arelent **, + asymbol **)); extern asymbol *_bfd_elf_make_empty_symbol PARAMS ((bfd *)); extern void _bfd_elf_get_symbol_info PARAMS ((bfd *, asymbol *, symbol_info *)); @@ -719,6 +726,7 @@ extern void _bfd_elf_no_info_to_howto PARAMS ((bfd *, arelent *, Elf_Internal_Rela *)); extern boolean bfd_section_from_shdr PARAMS ((bfd *, unsigned int shindex)); +extern boolean bfd_section_from_phdr PARAMS ((bfd *, Elf_Internal_Phdr *, int)); extern int _bfd_elf_symbol_from_bfd_symbol PARAMS ((bfd *, asymbol **)); @@ -835,6 +843,8 @@ extern boolean bfd_elf32_add_dynamic_entry PARAMS ((struct bfd_link_info *, bfd_vma, bfd_vma)); extern boolean bfd_elf32_link_create_dynamic_sections PARAMS ((bfd *, struct bfd_link_info *)); +extern Elf_Internal_Rela *_bfd_elf32_link_read_relocs + PARAMS ((bfd *, asection *, PTR, Elf_Internal_Rela *, boolean)); extern const bfd_target *bfd_elf64_object_p PARAMS ((bfd *)); extern const bfd_target *bfd_elf64_core_file_p PARAMS ((bfd *)); @@ -876,6 +886,8 @@ extern boolean bfd_elf64_add_dynamic_entry PARAMS ((struct bfd_link_info *, bfd_vma, bfd_vma)); extern boolean bfd_elf64_link_create_dynamic_sections PARAMS ((bfd *, struct bfd_link_info *)); +extern Elf_Internal_Rela *_bfd_elf64_link_read_relocs + PARAMS ((bfd *, asection *, PTR, Elf_Internal_Rela *, boolean)); #define bfd_elf32_link_record_dynamic_symbol _bfd_elf_link_record_dynamic_symbol #define bfd_elf64_link_record_dynamic_symbol _bfd_elf_link_record_dynamic_symbol @@ -895,5 +907,23 @@ extern void _bfd_mips_elf_symbol_processing PARAMS ((bfd *, asymbol *)); extern boolean _bfd_mips_elf_read_ecoff_info PARAMS ((bfd *, asection *, struct ecoff_debug_info *)); extern void _bfd_mips_elf_final_write_processing PARAMS ((bfd *, boolean)); +extern bfd_reloc_status_type _bfd_mips_elf_hi16_reloc + PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **)); +extern bfd_reloc_status_type _bfd_mips_elf_lo16_reloc + PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **)); +extern bfd_reloc_status_type _bfd_mips_elf_gprel16_reloc + PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **)); +extern bfd_reloc_status_type _bfd_mips_elf_got16_reloc + PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **)); +extern bfd_reloc_status_type _bfd_mips_elf_gprel32_reloc + PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **)); +extern boolean _bfd_mips_elf_set_private_flags PARAMS ((bfd *, flagword)); +extern boolean _bfd_mips_elf_copy_private_bfd_data PARAMS ((bfd *, bfd *)); +extern boolean _bfd_mips_elf_merge_private_bfd_data PARAMS ((bfd *, bfd *)); +extern boolean _bfd_mips_elf_find_nearest_line + PARAMS ((bfd *, asection *, asymbol **, bfd_vma, const char **, + const char **, unsigned int *)); +extern boolean _bfd_mips_elf_set_section_contents + PARAMS ((bfd *, asection *, PTR, file_ptr, bfd_size_type)); #endif /* _LIBELF_H_ */ diff --git a/bfd/elf.c b/bfd/elf.c index 73c60d3117..94d953f5a9 100644 --- a/bfd/elf.c +++ b/bfd/elf.c @@ -868,6 +868,7 @@ bfd_section_from_shdr (abfd, shindex) if (! _bfd_elf_make_section_from_shdr (abfd, hdr, name)) return false; if (hdr->bfd_section != NULL + && hdr->sh_info > 0 && bfd_section_from_shdr (abfd, hdr->sh_info)) { target_sect = bfd_section_from_elf_index (abfd, hdr->sh_info); @@ -3249,7 +3250,10 @@ _bfd_elf_canonicalize_reloc (abfd, section, relptr, symbols) arelent *tblptr; unsigned int i; - if (! get_elf_backend_data (abfd)->s->slurp_reloc_table (abfd, section, symbols)) + if (! get_elf_backend_data (abfd)->s->slurp_reloc_table (abfd, + section, + symbols, + false)) return -1; tblptr = section->relocation; @@ -3281,6 +3285,86 @@ _bfd_elf_canonicalize_dynamic_symtab (abfd, alocation) return get_elf_backend_data (abfd)->s->slurp_symbol_table (abfd, alocation, true); } +/* Return the size required for the dynamic reloc entries. Any + section that was actually installed in the BFD, and has type + SHT_REL or SHT_RELA, and uses the dynamic symbol table, is + considered to be a dynamic reloc section. */ + +long +_bfd_elf_get_dynamic_reloc_upper_bound (abfd) + bfd *abfd; +{ + long ret; + asection *s; + + if (elf_dynsymtab (abfd) == 0) + { + bfd_set_error (bfd_error_invalid_operation); + return -1; + } + + ret = sizeof (arelent *); + for (s = abfd->sections; s != NULL; s = s->next) + if (elf_section_data (s)->this_hdr.sh_link == elf_dynsymtab (abfd) + && (elf_section_data (s)->this_hdr.sh_type == SHT_REL + || elf_section_data (s)->this_hdr.sh_type == SHT_RELA)) + ret += ((s->_raw_size / elf_section_data (s)->this_hdr.sh_entsize) + * sizeof (arelent *)); + + return ret; +} + +/* Canonicalize the dynamic relocation entries. Note that we return + the dynamic relocations as a single block, although they are + actually associated with particular sections; the interface, which + was designed for SunOS style shared libraries, expects that there + is only one set of dynamic relocs. Any section that was actually + installed in the BFD, and has type SHT_REL or SHT_RELA, and uses + the dynamic symbol table, is considered to be a dynamic reloc + section. */ + +long +_bfd_elf_canonicalize_dynamic_reloc (abfd, storage, syms) + bfd *abfd; + arelent **storage; + asymbol **syms; +{ + boolean (*slurp_relocs) PARAMS ((bfd *, asection *, asymbol **, boolean)); + asection *s; + long ret; + + if (elf_dynsymtab (abfd) == 0) + { + bfd_set_error (bfd_error_invalid_operation); + return -1; + } + + slurp_relocs = get_elf_backend_data (abfd)->s->slurp_reloc_table; + ret = 0; + for (s = abfd->sections; s != NULL; s = s->next) + { + if (elf_section_data (s)->this_hdr.sh_link == elf_dynsymtab (abfd) + && (elf_section_data (s)->this_hdr.sh_type == SHT_REL + || elf_section_data (s)->this_hdr.sh_type == SHT_RELA)) + { + arelent *p; + long count, i; + + if (! (*slurp_relocs) (abfd, s, syms, true)) + return -1; + count = s->_raw_size / elf_section_data (s)->this_hdr.sh_entsize; + p = s->relocation; + for (i = 0; i < count; i++) + *storage++ = p++; + ret += count; + } + } + + *storage = NULL; + + return ret; +} + asymbol * _bfd_elf_make_empty_symbol (abfd) bfd *abfd; diff --git a/bfd/elf64-mips.c b/bfd/elf64-mips.c index ff0b0f242f..30ea6a7673 100644 --- a/bfd/elf64-mips.c +++ b/bfd/elf64-mips.c @@ -22,11 +22,14 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ The MIPS 64-bit ELF ABI uses an unusual reloc format. This file overrides the usual ELF reloc handling, and handles reading and - writing the relocations here. */ + writing the relocations here. + + The MIPS 64-bit ELF ABI also uses an unusual archive map format. */ #include "bfd.h" #include "sysdep.h" #include "libbfd.h" +#include "aout/ar.h" #include "bfdlink.h" #include "genlink.h" #include "elf-bfd.h" @@ -69,6 +72,9 @@ static boolean mips_elf64_section_from_shdr PARAMS ((bfd *, Elf_Internal_Shdr *, char *)); static boolean mips_elf64_section_processing PARAMS ((bfd *, Elf_Internal_Shdr *)); +static boolean mips_elf64_slurp_armap PARAMS ((bfd *)); +static boolean mips_elf64_write_armap + PARAMS ((bfd *, unsigned int, struct orl *, unsigned int, int)); /* The relocation types. */ @@ -1537,13 +1543,20 @@ mips_elf64_slurp_one_reloc_table (abfd, asect, symbols, rel_hdr) associated with a single data section. */ static boolean -mips_elf64_slurp_reloc_table (abfd, asect, symbols) +mips_elf64_slurp_reloc_table (abfd, asect, symbols, dynamic) bfd *abfd; asection *asect; asymbol **symbols; + boolean dynamic; { struct bfd_elf_section_data * const d = elf_section_data (asect); + if (dynamic) + { + bfd_set_error (bfd_error_invalid_operation); + return false; + } + if (asect->relocation != NULL || (asect->flags & SEC_RELOC) == 0 || asect->reloc_count == 0) @@ -1720,47 +1733,6 @@ mips_elf64_write_relocs (abfd, sec, data) == count); } -/* The .MIPS.options section holds register information in an - Elf64_Reginfo structure. These routines swap them in and out. - They are globally visible because they are used outside of BFD. */ - -void -bfd_mips_elf64_swap_reginfo_in (abfd, ex, in) - bfd *abfd; - const Elf64_External_RegInfo *ex; - Elf64_Internal_RegInfo *in; -{ - in->ri_gprmask = bfd_h_get_32 (abfd, (bfd_byte *) ex->ri_gprmask); - in->ri_pad = bfd_h_get_32 (abfd, (bfd_byte *) ex->ri_pad); - in->ri_cprmask[0] = bfd_h_get_32 (abfd, (bfd_byte *) ex->ri_cprmask[0]); - in->ri_cprmask[1] = bfd_h_get_32 (abfd, (bfd_byte *) ex->ri_cprmask[1]); - in->ri_cprmask[2] = bfd_h_get_32 (abfd, (bfd_byte *) ex->ri_cprmask[2]); - in->ri_cprmask[3] = bfd_h_get_32 (abfd, (bfd_byte *) ex->ri_cprmask[3]); - in->ri_gp_value = bfd_h_get_64 (abfd, (bfd_byte *) ex->ri_gp_value); -} - -void -bfd_mips_elf64_swap_reginfo_out (abfd, in, ex) - bfd *abfd; - const Elf64_Internal_RegInfo *in; - Elf64_External_RegInfo *ex; -{ - bfd_h_put_32 (abfd, (bfd_vma) in->ri_gprmask, - (bfd_byte *) ex->ri_gprmask); - bfd_h_put_32 (abfd, (bfd_vma) in->ri_pad, - (bfd_byte *) ex->ri_pad); - bfd_h_put_32 (abfd, (bfd_vma) in->ri_cprmask[0], - (bfd_byte *) ex->ri_cprmask[0]); - bfd_h_put_32 (abfd, (bfd_vma) in->ri_cprmask[1], - (bfd_byte *) ex->ri_cprmask[1]); - bfd_h_put_32 (abfd, (bfd_vma) in->ri_cprmask[2], - (bfd_byte *) ex->ri_cprmask[2]); - bfd_h_put_32 (abfd, (bfd_vma) in->ri_cprmask[3], - (bfd_byte *) ex->ri_cprmask[3]); - bfd_h_put_64 (abfd, (bfd_vma) in->ri_gp_value, - (bfd_byte *) ex->ri_gp_value); -} - /* Handle a 64-bit MIPS ELF specific section. */ static boolean @@ -1870,6 +1842,215 @@ mips_elf64_section_processing (abfd, hdr) return _bfd_mips_elf_section_processing (abfd, hdr); } +/* Irix 6 defines a brand new archive map format, so that they can + have archives more than 4 GB in size. */ + +/* Read an Irix 6 armap. */ + +static boolean +mips_elf64_slurp_armap (abfd) + bfd *abfd; +{ + struct artdata *ardata = bfd_ardata (abfd); + char nextname[17]; + file_ptr arhdrpos; + bfd_size_type i, parsed_size, nsymz, stringsize, carsym_size, ptrsize; + struct areltdata *mapdata; + bfd_byte int_buf[8]; + char *stringbase; + bfd_byte *raw_armap = NULL; + carsym *carsyms; + + ardata->symdefs = NULL; + + /* Get the name of the first element. */ + arhdrpos = bfd_tell (abfd); + i = bfd_read ((PTR) nextname, 1, 16, abfd); + if (i == 0) + return true; + if (i != 16) + return false; + + if (bfd_seek (abfd, (file_ptr) - 16, SEEK_CUR) != 0) + return false; + + /* Archives with traditional armaps are still permitted. */ + if (strncmp (nextname, "/ ", 16) == 0) + return bfd_slurp_armap (abfd); + + if (strncmp (nextname, "/SYM64/ ", 16) != 0) + { + bfd_has_map (abfd) = false; + return true; + } + + mapdata = (struct areltdata *) _bfd_read_ar_hdr (abfd); + if (mapdata == NULL) + return false; + parsed_size = mapdata->parsed_size; + bfd_release (abfd, (PTR) mapdata); + + if (bfd_read (int_buf, 1, 8, abfd) != 8) + { + if (bfd_get_error () != bfd_error_system_call) + bfd_set_error (bfd_error_malformed_archive); + return false; + } + + nsymz = bfd_getb64 (int_buf); + stringsize = parsed_size - 8 * nsymz - 8; + + carsym_size = nsymz * sizeof (carsym); + ptrsize = 8 * nsymz; + + ardata->symdefs = (carsym *) bfd_zalloc (abfd, carsym_size + stringsize + 1); + if (ardata->symdefs == NULL) + return false; + carsyms = ardata->symdefs; + stringbase = ((char *) ardata->symdefs) + carsym_size; + + raw_armap = (bfd_byte *) bfd_alloc (abfd, ptrsize); + if (raw_armap == NULL) + goto error_return; + + if (bfd_read (raw_armap, 1, ptrsize, abfd) != ptrsize + || bfd_read (stringbase, 1, stringsize, abfd) != stringsize) + { + if (bfd_get_error () != bfd_error_system_call) + bfd_set_error (bfd_error_malformed_archive); + goto error_return; + } + + for (i = 0; i < nsymz; i++) + { + carsyms->file_offset = bfd_getb64 (raw_armap + i * 8); + carsyms->name = stringbase; + stringbase += strlen (stringbase) + 1; + ++carsyms; + } + *stringbase = '\0'; + + ardata->symdef_count = nsymz; + ardata->first_file_filepos = arhdrpos + sizeof (struct ar_hdr) + parsed_size; + + bfd_has_map (abfd) = true; + bfd_release (abfd, raw_armap); + + return true; + + error_return: + if (raw_armap != NULL) + bfd_release (abfd, raw_armap); + if (ardata->symdefs != NULL) + bfd_release (abfd, ardata->symdefs); + return false; +} + +/* Write out an Irix 6 armap. The Irix 6 tools are supposed to be + able to handle ordinary ELF armaps, but at least on Irix 6.2 the + linker crashes. */ + +static boolean +mips_elf64_write_armap (arch, elength, map, symbol_count, stridx) + bfd *arch; + unsigned int elength; + struct orl *map; + unsigned int symbol_count; + int stridx; +{ + unsigned int ranlibsize = (symbol_count * 8) + 8; + unsigned int stringsize = stridx; + unsigned int mapsize = stringsize + ranlibsize; + file_ptr archive_member_file_ptr; + bfd *current = arch->archive_head; + unsigned int count; + struct ar_hdr hdr; + unsigned int i; + int padding; + bfd_byte buf[8]; + + padding = BFD_ALIGN (mapsize, 8) - mapsize; + mapsize += padding; + + /* work out where the first object file will go in the archive */ + archive_member_file_ptr = (mapsize + + elength + + sizeof (struct ar_hdr) + + SARMAG); + + memset ((char *) (&hdr), 0, sizeof (struct ar_hdr)); + strcpy (hdr.ar_name, "/SYM64/"); + sprintf (hdr.ar_size, "%-10d", (int) mapsize); + sprintf (hdr.ar_date, "%ld", (long) time (NULL)); + /* This, at least, is what Intel coff sets the values to.: */ + sprintf ((hdr.ar_uid), "%d", 0); + sprintf ((hdr.ar_gid), "%d", 0); + sprintf ((hdr.ar_mode), "%-7o", (unsigned) 0); + strncpy (hdr.ar_fmag, ARFMAG, 2); + + for (i = 0; i < sizeof (struct ar_hdr); i++) + if (((char *) (&hdr))[i] == '\0') + (((char *) (&hdr))[i]) = ' '; + + /* Write the ar header for this item and the number of symbols */ + + if (bfd_write ((PTR) &hdr, 1, sizeof (struct ar_hdr), arch) + != sizeof (struct ar_hdr)) + return false; + + bfd_putb64 (symbol_count, buf); + if (bfd_write (buf, 1, 8, arch) != 8) + return false; + + /* Two passes, first write the file offsets for each symbol - + remembering that each offset is on a two byte boundary. */ + + /* Write out the file offset for the file associated with each + symbol, and remember to keep the offsets padded out. */ + + current = arch->archive_head; + count = 0; + while (current != (bfd *) NULL && count < symbol_count) + { + /* For each symbol which is used defined in this object, write out + the object file's address in the archive */ + + while (((bfd *) (map[count]).pos) == current) + { + bfd_putb64 (archive_member_file_ptr, buf); + if (bfd_write (buf, 1, 8, arch) != 8) + return false; + count++; + } + /* Add size of this archive entry */ + archive_member_file_ptr += (arelt_size (current) + + sizeof (struct ar_hdr)); + /* remember about the even alignment */ + archive_member_file_ptr += archive_member_file_ptr % 2; + current = current->next; + } + + /* now write the strings themselves */ + for (count = 0; count < symbol_count; count++) + { + size_t len = strlen (*map[count].name) + 1; + + if (bfd_write (*map[count].name, 1, len, arch) != len) + return false; + } + + /* The spec says that this should be padded to an 8 byte boundary. + However, the Irix 6.2 tools do not appear to do this. */ + while (padding != 0) + { + if (bfd_write ("", 1, 1, arch) != 1) + return false; + --padding; + } + + return true; +} + /* ECOFF swapping routines. These are used when dealing with the .mdebug section, which is in the ECOFF debugging format. */ static const struct ecoff_debug_swap mips_elf64_ecoff_debug_swap = @@ -1969,4 +2150,23 @@ const struct elf_size_info mips_elf64_size_info = _bfd_mips_elf_merge_private_bfd_data #define bfd_elf64_bfd_set_private_flags _bfd_mips_elf_set_private_flags +#define bfd_elf64_archive_functions +#define bfd_elf64_archive_slurp_armap mips_elf64_slurp_armap +#define bfd_elf64_archive_slurp_extended_name_table \ + _bfd_archive_coff_slurp_extended_name_table +#define bfd_elf64_archive_construct_extended_name_table \ + _bfd_archive_coff_construct_extended_name_table +#define bfd_elf64_archive_truncate_arname \ + _bfd_archive_coff_truncate_arname +#define bfd_elf64_archive_write_armap mips_elf64_write_armap +#define bfd_elf64_archive_read_ar_hdr _bfd_archive_coff_read_ar_hdr +#define bfd_elf64_archive_openr_next_archived_file \ + _bfd_archive_coff_openr_next_archived_file +#define bfd_elf64_archive_get_elt_at_index \ + _bfd_archive_coff_get_elt_at_index +#define bfd_elf64_archive_generic_stat_arch_elt \ + _bfd_archive_coff_generic_stat_arch_elt +#define bfd_elf64_archive_update_armap_timestamp \ + _bfd_archive_coff_update_armap_timestamp + #include "elf64-target.h" diff --git a/bfd/elfcode.h b/bfd/elfcode.h index 405e79f6ce..87e02f2523 100644 --- a/bfd/elfcode.h +++ b/bfd/elfcode.h @@ -154,21 +154,13 @@ static void elf_swap_shdr_out #define elf_stringtab_init _bfd_elf_stringtab_init -extern struct bfd_strtab_hash *_bfd_elf_stringtab_init PARAMS ((void)); #define section_from_elf_index bfd_section_from_elf_index -extern boolean bfd_section_from_phdr PARAMS ((bfd *, Elf_Internal_Phdr *, - int)); -static boolean elf_slurp_reloc_table PARAMS ((bfd *, asection *, asymbol **)); +static boolean elf_slurp_reloc_table + PARAMS ((bfd *, asection *, asymbol **, boolean)); - int _bfd_elf_symbol_from_bfd_symbol PARAMS ((bfd *, - struct symbol_cache_entry **)); - -static boolean validate_reloc PARAMS ((bfd *, arelent *)); static void write_relocs PARAMS ((bfd *, asection *, PTR)); - boolean bfd_section_from_shdr PARAMS ((bfd *, unsigned int shindex)); - #ifdef DEBUG static void elf_debug_section PARAMS ((int, Elf_Internal_Shdr *)); static void elf_debug_file PARAMS ((Elf_Internal_Ehdr *)); @@ -594,6 +586,15 @@ elf_object_p (abfd) goto got_no_match; elf_swap_shdr_in (abfd, &x_shdr, i_shdrp + shindex); elf_elfsections (abfd)[shindex] = i_shdrp + shindex; + + /* If the section is loaded, but not page aligned, clear + D_PAGED. */ + if ((i_shdrp[shindex].sh_flags & SHF_ALLOC) != 0 + && i_shdrp[shindex].sh_type != SHT_NOBITS + && (((i_shdrp[shindex].sh_addr - i_shdrp[shindex].sh_offset) + % ebd->maxpagesize) + != 0)) + abfd->flags &= ~D_PAGED; } if (i_ehdrp->e_shstrndx) { @@ -676,104 +677,6 @@ got_no_match: /* ELF .o/exec file writing */ -/* Try to convert a non-ELF reloc into an ELF one. */ - -static boolean -validate_reloc (abfd, areloc) - bfd *abfd; - arelent *areloc; -{ - /* Check whether we really have an ELF howto. */ - - if ((*areloc->sym_ptr_ptr)->the_bfd->xvec != abfd->xvec) - { - bfd_reloc_code_real_type code; - reloc_howto_type *howto; - - /* Alien reloc: Try to determine its type to replace it with an - equivalent ELF reloc. */ - - if (areloc->howto->pc_relative) - { - switch (areloc->howto->bitsize) - { - case 8: - code = BFD_RELOC_8_PCREL; - break; - case 12: - code = BFD_RELOC_12_PCREL; - break; - case 16: - code = BFD_RELOC_16_PCREL; - break; - case 24: - code = BFD_RELOC_24_PCREL; - break; - case 32: - code = BFD_RELOC_32_PCREL; - break; - case 64: - code = BFD_RELOC_64_PCREL; - break; - default: - goto fail; - } - - howto = bfd_reloc_type_lookup (abfd, code); - - if (areloc->howto->pcrel_offset != howto->pcrel_offset) - { - if (howto->pcrel_offset) - areloc->addend += areloc->address; - else - areloc->addend -= areloc->address; /* addend is unsigned!! */ - } - } - else - { - switch (areloc->howto->bitsize) - { - case 8: - code = BFD_RELOC_8; - break; - case 14: - code = BFD_RELOC_14; - break; - case 16: - code = BFD_RELOC_16; - break; - case 26: - code = BFD_RELOC_26; - break; - case 32: - code = BFD_RELOC_32; - break; - case 64: - code = BFD_RELOC_64; - break; - default: - goto fail; - } - - howto = bfd_reloc_type_lookup (abfd, code); - } - - if (howto) - areloc->howto = howto; - else - goto fail; - } - - return true; - - fail: - (*_bfd_error_handler) - ("%s: unsupported relocation type %s", - bfd_get_filename (abfd), areloc->howto->name); - bfd_set_error (bfd_error_bad_value); - return false; -} - /* Write out the relocs. */ static void @@ -842,6 +745,8 @@ write_relocs (abfd, sec, data) sym = *ptr->sym_ptr_ptr; if (sym == last_sym) n = last_sym_idx; + else if (bfd_is_abs_section (sym->section) && sym->value == 0) + n = STN_UNDEF; else { last_sym = sym; @@ -854,8 +759,9 @@ write_relocs (abfd, sec, data) last_sym_idx = n; } - if ((*ptr->sym_ptr_ptr)->the_bfd->xvec != abfd->xvec - && ! validate_reloc (abfd, ptr)) + if ((*ptr->sym_ptr_ptr)->the_bfd != NULL + && (*ptr->sym_ptr_ptr)->the_bfd->xvec != abfd->xvec + && ! _bfd_elf_validate_reloc (abfd, ptr)) { *failedp = true; return; @@ -907,7 +813,7 @@ write_relocs (abfd, sec, data) } if ((*ptr->sym_ptr_ptr)->the_bfd->xvec != abfd->xvec - && ! validate_reloc (abfd, ptr)) + && ! _bfd_elf_validate_reloc (abfd, ptr)) { *failedp = true; return; @@ -1177,13 +1083,16 @@ error_return: /* Read in and swap the external relocs. */ static boolean -elf_slurp_reloc_table (abfd, asect, symbols) +elf_slurp_reloc_table (abfd, asect, symbols, dynamic) bfd *abfd; asection *asect; asymbol **symbols; + boolean dynamic; { struct elf_backend_data * const ebd = get_elf_backend_data (abfd); struct bfd_elf_section_data * const d = elf_section_data (asect); + Elf_Internal_Shdr *rel_hdr; + bfd_size_type reloc_count; PTR allocated = NULL; bfd_byte *native_relocs; arelent *relents; @@ -1191,37 +1100,51 @@ elf_slurp_reloc_table (abfd, asect, symbols) unsigned int i; int entsize; - if (asect->relocation != NULL - || (asect->flags & SEC_RELOC) == 0 - || asect->reloc_count == 0) + if (asect->relocation != NULL) return true; - BFD_ASSERT (asect->rel_filepos == d->rel_hdr.sh_offset - && (asect->reloc_count - == d->rel_hdr.sh_size / d->rel_hdr.sh_entsize)); + if (! dynamic) + { + if ((asect->flags & SEC_RELOC) == 0 + || asect->reloc_count == 0) + return true; - allocated = (PTR) bfd_malloc ((size_t) d->rel_hdr.sh_size); + rel_hdr = &d->rel_hdr; + reloc_count = asect->reloc_count; + + BFD_ASSERT (asect->rel_filepos == rel_hdr->sh_offset + && reloc_count == rel_hdr->sh_size / rel_hdr->sh_entsize); + } + else + { + if (asect->_raw_size == 0) + return true; + + rel_hdr = &d->this_hdr; + reloc_count = rel_hdr->sh_size / rel_hdr->sh_entsize; + } + + allocated = (PTR) bfd_malloc ((size_t) rel_hdr->sh_size); if (allocated == NULL) goto error_return; - if (bfd_seek (abfd, asect->rel_filepos, SEEK_SET) != 0 - || (bfd_read (allocated, 1, d->rel_hdr.sh_size, abfd) - != d->rel_hdr.sh_size)) + if (bfd_seek (abfd, rel_hdr->sh_offset, SEEK_SET) != 0 + || (bfd_read (allocated, 1, rel_hdr->sh_size, abfd) + != rel_hdr->sh_size)) goto error_return; native_relocs = (bfd_byte *) allocated; - relents = ((arelent *) - bfd_alloc (abfd, asect->reloc_count * sizeof (arelent))); + relents = (arelent *) bfd_alloc (abfd, reloc_count * sizeof (arelent)); if (relents == NULL) goto error_return; - entsize = d->rel_hdr.sh_entsize; + entsize = rel_hdr->sh_entsize; BFD_ASSERT (entsize == sizeof (Elf_External_Rel) || entsize == sizeof (Elf_External_Rela)); for (i = 0, relent = relents; - i < asect->reloc_count; + i < reloc_count; i++, relent++, native_relocs += entsize) { Elf_Internal_Rela rela; @@ -1239,8 +1162,9 @@ elf_slurp_reloc_table (abfd, asect, symbols) /* The address of an ELF reloc is section relative for an object file, and absolute for an executable file or shared library. - The address of a BFD reloc is always section relative. */ - if ((abfd->flags & (EXEC_P | DYNAMIC)) == 0) + The address of a normal BFD reloc is always section relative, + and the address of a dynamic reloc is absolute.. */ + if ((abfd->flags & (EXEC_P | DYNAMIC)) == 0 || dynamic) relent->address = rela.r_offset; else relent->address = rela.r_offset - asect->vma; diff --git a/bfd/elfxx-target.h b/bfd/elfxx-target.h index b4e68ecc2b..291e3c9459 100644 --- a/bfd/elfxx-target.h +++ b/bfd/elfxx-target.h @@ -40,7 +40,9 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #define bfd_elfNN_minisymbol_to_symbol _bfd_elf_minisymbol_to_symbol #define bfd_elfNN_get_dynamic_symtab_upper_bound _bfd_elf_get_dynamic_symtab_upper_bound #define bfd_elfNN_get_lineno _bfd_elf_get_lineno +#ifndef bfd_elfNN_get_reloc_upper_bound #define bfd_elfNN_get_reloc_upper_bound _bfd_elf_get_reloc_upper_bound +#endif #define bfd_elfNN_get_symbol_info _bfd_elf_get_symbol_info #define bfd_elfNN_get_symtab _bfd_elf_get_symtab #define bfd_elfNN_get_symtab_upper_bound _bfd_elf_get_symtab_upper_bound @@ -78,7 +80,10 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ bfd_generic_get_relocated_section_contents #endif +#ifndef bfd_elfNN_bfd_relax_section #define bfd_elfNN_bfd_relax_section bfd_generic_relax_section +#endif + #define bfd_elfNN_bfd_make_debug_symbol \ ((asymbol *(*) PARAMS ((bfd *, void *, unsigned long))) bfd_nullvoidptr) @@ -113,11 +118,11 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef bfd_elfNN_get_dynamic_reloc_upper_bound #define bfd_elfNN_get_dynamic_reloc_upper_bound \ - _bfd_nodynamic_get_dynamic_reloc_upper_bound + _bfd_elf_get_dynamic_reloc_upper_bound #endif #ifndef bfd_elfNN_canonicalize_dynamic_reloc #define bfd_elfNN_canonicalize_dynamic_reloc \ - _bfd_nodynamic_canonicalize_dynamic_reloc + _bfd_elf_canonicalize_dynamic_reloc #endif #ifdef elf_backend_relocate_section @@ -141,6 +146,18 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #define bfd_elfNN_bfd_link_split_section _bfd_generic_link_split_section #endif +#ifndef bfd_elfNN_archive_p +#define bfd_elfNN_archive_p bfd_generic_archive_p +#endif + +#ifndef bfd_elfNN_write_archive_contents +#define bfd_elfNN_write_archive_contents _bfd_write_archive_contents +#endif + +#ifndef bfd_elfNN_mkarchive +#define bfd_elfNN_mkarchive _bfd_generic_mkarchive +#endif + #ifndef elf_symbol_leading_char #define elf_symbol_leading_char 0 #endif @@ -340,28 +357,32 @@ const bfd_target TARGET_BIG_SYM = /* bfd_check_format: check the format of a file being read */ { _bfd_dummy_target, /* unknown format */ bfd_elfNN_object_p, /* assembler/linker output (object file) */ - bfd_generic_archive_p, /* an archive */ + bfd_elfNN_archive_p, /* an archive */ bfd_elfNN_core_file_p /* a core file */ }, /* bfd_set_format: set the format of a file being written */ { bfd_false, bfd_elf_mkobject, - _bfd_generic_mkarchive, + bfd_elfNN_mkarchive, bfd_false }, /* bfd_write_contents: write cached information into a file being written */ { bfd_false, bfd_elfNN_write_object_contents, - _bfd_write_archive_contents, + bfd_elfNN_write_archive_contents, bfd_false }, BFD_JUMP_TABLE_GENERIC (bfd_elfNN), BFD_JUMP_TABLE_COPY (bfd_elfNN), BFD_JUMP_TABLE_CORE (bfd_elfNN), +#ifdef bfd_elfNN_archive_functions + BFD_JUMP_TABLE_ARCHIVE (bfd_elfNN_archive), +#else BFD_JUMP_TABLE_ARCHIVE (_bfd_archive_coff), +#endif BFD_JUMP_TABLE_SYMBOLS (bfd_elfNN), BFD_JUMP_TABLE_RELOCS (bfd_elfNN), BFD_JUMP_TABLE_WRITE (bfd_elfNN), @@ -424,28 +445,32 @@ const bfd_target TARGET_LITTLE_SYM = /* bfd_check_format: check the format of a file being read */ { _bfd_dummy_target, /* unknown format */ bfd_elfNN_object_p, /* assembler/linker output (object file) */ - bfd_generic_archive_p, /* an archive */ + bfd_elfNN_archive_p, /* an archive */ bfd_elfNN_core_file_p /* a core file */ }, /* bfd_set_format: set the format of a file being written */ { bfd_false, bfd_elf_mkobject, - _bfd_generic_mkarchive, + bfd_elfNN_mkarchive, bfd_false }, /* bfd_write_contents: write cached information into a file being written */ { bfd_false, bfd_elfNN_write_object_contents, - _bfd_write_archive_contents, + bfd_elfNN_write_archive_contents, bfd_false }, BFD_JUMP_TABLE_GENERIC (bfd_elfNN), BFD_JUMP_TABLE_COPY (bfd_elfNN), BFD_JUMP_TABLE_CORE (bfd_elfNN), +#ifdef bfd_elfNN_archive_functions + BFD_JUMP_TABLE_ARCHIVE (bfd_elfNN_archive), +#else BFD_JUMP_TABLE_ARCHIVE (_bfd_archive_coff), +#endif BFD_JUMP_TABLE_SYMBOLS (bfd_elfNN), BFD_JUMP_TABLE_RELOCS (bfd_elfNN), BFD_JUMP_TABLE_WRITE (bfd_elfNN),