From 6cdc0ccc1276096134b1870e92875487ffdc8292 Mon Sep 17 00:00:00 2001 From: Alan Modra Date: Sun, 7 Jul 2002 09:10:41 +0000 Subject: [PATCH] * elf-bfd.h (struct elf_reloc_cookie): Remove locsym_shndx, change type of locsyms. (bfd_elf_get_elf_syms): Declare. * elf.c (bfd_elf_get_elf_syms): New function. (group_signature): Use bfd_elf_get_elf_syms. (bfd_section_from_r_symndx): Likewise. * elfcode.h (elf_slurp_symbol_table): Likewise. * elflink.h (elf_link_is_defined_archive_symbol): Likewise. (elf_link_add_object_symbols): Likewise. Reorganise to increase locality of various data structures. Properly free internal relocs. (elf_bfd_final_link): Properly free internal relocs. (elf_link_check_versioned_symbol): Use bfd_elf_get_elf_syms. (elf_link_input_bfd): Likewise. (elf_gc_mark): Likewise. Properly free internal relocs. (elf_gc_sweep): Properly free internal relocs. (elf_reloc_symbol_deleted_p): No need to swap syms in. (elf_bfd_discard_info): Use bfd_elf_get_elf_syms. Properly free internal relocs. * elf-m10200.c (mn10200_elf_relax_section): Use bfd_elf_get_elf_syms. Properly free possibly cached info. (mn10200_elf_relax_delete_bytes): Remove symbol swapping code. (mn10200_elf_symbol_address_p): Pass in internal syms. Remove symbol swapping code. (mn10200_elf_get_relocated_section_contents): Use bfd_elf_get_elf_syms. Properly free possibly cached info. * elf-m10300.c (mn10300_elf_relax_section): As above for elf-m10200.c. (mn10300_elf_relax_delete_bytes): Likewise. (mn10300_elf_symbol_address_p): Likewise. (mn10300_elf_get_relocated_section_contents): Likewise. * elf32-h8300.c (elf32_h8_relax_section): As above for elf-m10200.c. (elf32_h8_relax_delete_bytes): Likewise. (elf32_h8_symbol_address_p): Likewise. (elf32_h8_get_relocated_section_contents): Likewise. * elf32-m32r.c (m32r_elf_relax_section): As above for elf-m10200.c. (m32r_elf_relax_delete_bytes): Likewise. (m32r_elf_get_relocated_section_contents): Likewise. * elf32-sh.c (sh_elf_reloc_loop): Free section contents using elf_section_data to determine whether cached. (sh_elf_relax_section): As above for elf-m10200.c. (sh_elf_relax_delete_bytes): Likewise. (sh_elf_get_relocated_section_contents): Likewise. * elf32-xstormy16.c (xstormy16_elf_relax_section): As above. * elf64-alpha.c (elf64_alpha_relax_section): As above. Also delay reading of local syms. * elf64-mmix.c (mmix_elf_relax_section): Likewise. * elf64-sh64.c (sh_elf64_get_relocated_section_contents): As above. * elfxx-ia64.c (elfNN_ia64_relax_section): As above. * elfxx-mips.c (_bfd_mips_elf_check_relocs): Properly free internal relocs. * elf32-arm.h (bfd_elf32_arm_process_before_allocation): Properly free internal relocs and section contents. Don't read symbols. * elf32-hppa.c (get_local_syms): Use bfd_elf_get_elf_syms. (elf32_hppa_size_stubs): Don't free local syms. * elf32-m68k.c (bfd_m68k_elf32_create_embedded_relocs): Delay reading of local syms. Use bfd_elf_get_elf_syms. Properly free possibly cached info. * elf32-mips.c (bfd_mips_elf32_create_embedded_relocs): Likewise. * elf64-hppa.c (elf64_hppa_check_relocs): Use bfd_elf_get_elf_syms. * elf64-ppc.c (struct ppc_link_hash_table): Delete bfd_count and all_local_syms. (get_local_syms): Delete function. (edit_opd): Use bfd_elf_get_elf_syms. Free on error exit. Cache on exit. (ppc64_elf_size_stubs): Use bfd_elf_get_elf_syms. Free/cache on exit. --- bfd/ChangeLog | 67 +++++ bfd/elf-bfd.h | 6 +- bfd/elf-m10200.c | 338 +++++++-------------- bfd/elf-m10300.c | 665 +++++++++++++---------------------------- bfd/elf.c | 173 +++++++---- bfd/elf32-arm.h | 64 ++-- bfd/elf32-h8300.c | 329 ++++++--------------- bfd/elf32-hppa.c | 73 +---- bfd/elf32-m32r.c | 247 ++++++---------- bfd/elf32-m68k.c | 90 ++---- bfd/elf32-mips.c | 87 ++---- bfd/elf32-sh.c | 306 ++++++------------- bfd/elf32-xstormy16.c | 85 ++---- bfd/elf64-alpha.c | 130 ++++---- bfd/elf64-hppa.c | 93 ++---- bfd/elf64-mmix.c | 119 +++----- bfd/elf64-ppc.c | 230 +++++---------- bfd/elf64-sh64.c | 85 ++---- bfd/elfcode.h | 137 +++------ bfd/elflink.h | 673 +++++++++++++++--------------------------- bfd/elfxx-ia64.c | 137 ++++----- bfd/elfxx-mips.c | 2 +- 22 files changed, 1432 insertions(+), 2704 deletions(-) diff --git a/bfd/ChangeLog b/bfd/ChangeLog index 7c00bb4903..0e66cda7c8 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,70 @@ +2002-07-07 Alan Modra + + * elf-bfd.h (struct elf_reloc_cookie): Remove locsym_shndx, + change type of locsyms. + (bfd_elf_get_elf_syms): Declare. + * elf.c (bfd_elf_get_elf_syms): New function. + (group_signature): Use bfd_elf_get_elf_syms. + (bfd_section_from_r_symndx): Likewise. + * elfcode.h (elf_slurp_symbol_table): Likewise. + * elflink.h (elf_link_is_defined_archive_symbol): Likewise. + (elf_link_add_object_symbols): Likewise. Reorganise to increase + locality of various data structures. Properly free internal relocs. + (elf_bfd_final_link): Properly free internal relocs. + (elf_link_check_versioned_symbol): Use bfd_elf_get_elf_syms. + (elf_link_input_bfd): Likewise. + (elf_gc_mark): Likewise. Properly free internal relocs. + (elf_gc_sweep): Properly free internal relocs. + (elf_reloc_symbol_deleted_p): No need to swap syms in. + (elf_bfd_discard_info): Use bfd_elf_get_elf_syms. Properly free + internal relocs. + * elf-m10200.c (mn10200_elf_relax_section): Use bfd_elf_get_elf_syms. + Properly free possibly cached info. + (mn10200_elf_relax_delete_bytes): Remove symbol swapping code. + (mn10200_elf_symbol_address_p): Pass in internal syms. Remove + symbol swapping code. + (mn10200_elf_get_relocated_section_contents): Use bfd_elf_get_elf_syms. + Properly free possibly cached info. + * elf-m10300.c (mn10300_elf_relax_section): As above for elf-m10200.c. + (mn10300_elf_relax_delete_bytes): Likewise. + (mn10300_elf_symbol_address_p): Likewise. + (mn10300_elf_get_relocated_section_contents): Likewise. + * elf32-h8300.c (elf32_h8_relax_section): As above for elf-m10200.c. + (elf32_h8_relax_delete_bytes): Likewise. + (elf32_h8_symbol_address_p): Likewise. + (elf32_h8_get_relocated_section_contents): Likewise. + * elf32-m32r.c (m32r_elf_relax_section): As above for elf-m10200.c. + (m32r_elf_relax_delete_bytes): Likewise. + (m32r_elf_get_relocated_section_contents): Likewise. + * elf32-sh.c (sh_elf_reloc_loop): Free section contents using + elf_section_data to determine whether cached. + (sh_elf_relax_section): As above for elf-m10200.c. + (sh_elf_relax_delete_bytes): Likewise. + (sh_elf_get_relocated_section_contents): Likewise. + * elf32-xstormy16.c (xstormy16_elf_relax_section): As above. + * elf64-alpha.c (elf64_alpha_relax_section): As above. Also delay + reading of local syms. + * elf64-mmix.c (mmix_elf_relax_section): Likewise. + * elf64-sh64.c (sh_elf64_get_relocated_section_contents): As above. + * elfxx-ia64.c (elfNN_ia64_relax_section): As above. + * elfxx-mips.c (_bfd_mips_elf_check_relocs): Properly free internal + relocs. + * elf32-arm.h (bfd_elf32_arm_process_before_allocation): Properly + free internal relocs and section contents. Don't read symbols. + * elf32-hppa.c (get_local_syms): Use bfd_elf_get_elf_syms. + (elf32_hppa_size_stubs): Don't free local syms. + * elf32-m68k.c (bfd_m68k_elf32_create_embedded_relocs): Delay + reading of local syms. Use bfd_elf_get_elf_syms. Properly free + possibly cached info. + * elf32-mips.c (bfd_mips_elf32_create_embedded_relocs): Likewise. + * elf64-hppa.c (elf64_hppa_check_relocs): Use bfd_elf_get_elf_syms. + * elf64-ppc.c (struct ppc_link_hash_table): Delete bfd_count and + all_local_syms. + (get_local_syms): Delete function. + (edit_opd): Use bfd_elf_get_elf_syms. Free on error exit. Cache + on exit. + (ppc64_elf_size_stubs): Use bfd_elf_get_elf_syms. Free/cache on exit. + 2002-07-05 Jim Wilson * syms.c (decode_section_type): New. diff --git a/bfd/elf-bfd.h b/bfd/elf-bfd.h index b264d56f2b..c79919fdc7 100644 --- a/bfd/elf-bfd.h +++ b/bfd/elf-bfd.h @@ -417,8 +417,7 @@ enum elf_reloc_type_class { struct elf_reloc_cookie { Elf_Internal_Rela *rels, *rel, *relend; - PTR locsyms; - PTR locsym_shndx; + Elf_Internal_Sym *locsyms; bfd *abfd; size_t locsymcount; size_t extsymoff; @@ -1216,6 +1215,9 @@ extern char *bfd_elf_string_from_elf_section PARAMS ((bfd *, unsigned, unsigned)); extern char *bfd_elf_get_str_section PARAMS ((bfd *, unsigned)); +extern Elf_Internal_Sym *bfd_elf_get_elf_syms + PARAMS ((bfd *, Elf_Internal_Shdr *, size_t, size_t, + Elf_Internal_Sym *, PTR, Elf_External_Sym_Shndx *)); extern boolean _bfd_elf_copy_private_bfd_data PARAMS ((bfd *, bfd *)); diff --git a/bfd/elf-m10200.c b/bfd/elf-m10200.c index e833af6037..025e3ad92a 100644 --- a/bfd/elf-m10200.c +++ b/bfd/elf-m10200.c @@ -30,7 +30,7 @@ static void mn10200_info_to_howto static boolean mn10200_elf_relax_delete_bytes PARAMS ((bfd *, asection *, bfd_vma, int)); static boolean mn10200_elf_symbol_address_p - PARAMS ((bfd *, asection *, bfd_vma)); + PARAMS ((bfd *, asection *, Elf_Internal_Sym *, bfd_vma)); static bfd_reloc_status_type mn10200_elf_final_link_relocate PARAMS ((reloc_howto_type *, bfd *, bfd *, asection *, bfd_byte *, bfd_vma, bfd_vma, bfd_vma, @@ -508,15 +508,10 @@ mn10200_elf_relax_section (abfd, sec, link_info, again) boolean *again; { Elf_Internal_Shdr *symtab_hdr; - Elf_Internal_Shdr *shndx_hdr; Elf_Internal_Rela *internal_relocs; - Elf_Internal_Rela *free_relocs = NULL; Elf_Internal_Rela *irel, *irelend; bfd_byte *contents = NULL; - bfd_byte *free_contents = NULL; - Elf32_External_Sym *extsyms = NULL; - Elf32_External_Sym *free_extsyms = NULL; - Elf_External_Sym_Shndx *shndx_buf = NULL; + Elf_Internal_Sym *isymbuf = NULL; /* Assume nothing changes. */ *again = false; @@ -536,7 +531,6 @@ mn10200_elf_relax_section (abfd, sec, link_info, again) sec->_cooked_size = sec->_raw_size; symtab_hdr = &elf_tdata (abfd)->symtab_hdr; - shndx_hdr = &elf_tdata (abfd)->symtab_shndx_hdr; /* Get a copy of the native relocations. */ internal_relocs = (_bfd_elf32_link_read_relocs @@ -544,8 +538,6 @@ mn10200_elf_relax_section (abfd, sec, link_info, again) link_info->keep_memory)); if (internal_relocs == NULL) goto error_return; - if (! link_info->keep_memory) - free_relocs = internal_relocs; /* Walk through them looking for relaxing opportunities. */ irelend = internal_relocs + sec->reloc_count; @@ -572,7 +564,6 @@ mn10200_elf_relax_section (abfd, sec, link_info, again) contents = (bfd_byte *) bfd_malloc (sec->_raw_size); if (contents == NULL) goto error_return; - free_contents = contents; if (! bfd_get_section_contents (abfd, sec, contents, (file_ptr) 0, sec->_raw_size)) @@ -580,68 +571,35 @@ mn10200_elf_relax_section (abfd, sec, link_info, again) } } - /* Read this BFD's symbols if we haven't done so already. */ - if (extsyms == NULL) + /* Read this BFD's local symbols if we haven't done so already. */ + if (isymbuf == NULL && symtab_hdr->sh_info != 0) { - /* Get cached copy if it exists. */ - if (symtab_hdr->contents != NULL) - extsyms = (Elf32_External_Sym *) symtab_hdr->contents; - else - { - /* Go get them off disk. */ - bfd_size_type amt; - - amt = symtab_hdr->sh_info; - amt *= sizeof (Elf32_External_Sym); - extsyms = (Elf32_External_Sym *) bfd_malloc (amt); - if (extsyms == NULL) - goto error_return; - free_extsyms = extsyms; - if (bfd_seek (abfd, symtab_hdr->sh_offset, SEEK_SET) != 0 - || bfd_bread ((PTR) extsyms, amt, abfd) != amt) - goto error_return; - symtab_hdr->contents = (bfd_byte *) extsyms; - } - - if (shndx_hdr->sh_size != 0) - { - bfd_size_type amt; - - amt = symtab_hdr->sh_info; - amt *= sizeof (Elf_External_Sym_Shndx); - shndx_buf = (Elf_External_Sym_Shndx *) bfd_malloc (amt); - if (shndx_buf == NULL) - goto error_return; - if (bfd_seek (abfd, shndx_hdr->sh_offset, SEEK_SET) != 0 - || bfd_bread ((PTR) shndx_buf, amt, abfd) != amt) - goto error_return; - shndx_hdr->contents = (bfd_byte *) shndx_buf; - } + isymbuf = (Elf_Internal_Sym *) symtab_hdr->contents; + if (isymbuf == NULL) + isymbuf = bfd_elf_get_elf_syms (abfd, symtab_hdr, + symtab_hdr->sh_info, 0, + NULL, NULL, NULL); + if (isymbuf == NULL) + goto error_return; } /* Get the value of the symbol referred to by the reloc. */ if (ELF32_R_SYM (irel->r_info) < symtab_hdr->sh_info) { /* A local symbol. */ - Elf32_External_Sym *esym; - Elf_External_Sym_Shndx *shndx; - Elf_Internal_Sym isym; + Elf_Internal_Sym *isym; asection *sym_sec; - esym = extsyms + ELF32_R_SYM (irel->r_info); - shndx = shndx_buf + (shndx_buf ? ELF32_R_SYM (irel->r_info) : 0); - bfd_elf32_swap_symbol_in (abfd, (const PTR) esym, (const PTR) shndx, - &isym); - - if (isym.st_shndx == SHN_UNDEF) + isym = isymbuf + ELF32_R_SYM (irel->r_info); + if (isym->st_shndx == SHN_UNDEF) sym_sec = bfd_und_section_ptr; - else if (isym.st_shndx == SHN_ABS) + else if (isym->st_shndx == SHN_ABS) sym_sec = bfd_abs_section_ptr; - else if (isym.st_shndx == SHN_COMMON) + else if (isym->st_shndx == SHN_COMMON) sym_sec = bfd_com_section_ptr; else - sym_sec = bfd_section_from_elf_index (abfd, isym.st_shndx); - symval = (isym.st_value + sym_sec = bfd_section_from_elf_index (abfd, isym->st_shndx); + symval = (isym->st_value + sym_sec->output_section->vma + sym_sec->output_offset); } @@ -702,12 +660,8 @@ mn10200_elf_relax_section (abfd, sec, link_info, again) /* Note that we've changed the relocs, section contents, etc. */ elf_section_data (sec)->relocs = internal_relocs; - free_relocs = NULL; - elf_section_data (sec)->this_hdr.contents = contents; - free_contents = NULL; - - free_extsyms = NULL; + symtab_hdr->contents = (unsigned char *) isymbuf; /* Fix the opcode. */ if (code == 0xe0) @@ -759,12 +713,8 @@ mn10200_elf_relax_section (abfd, sec, link_info, again) /* Note that we've changed the relocs, section contents, etc. */ elf_section_data (sec)->relocs = internal_relocs; - free_relocs = NULL; - elf_section_data (sec)->this_hdr.contents = contents; - free_contents = NULL; - - free_extsyms = NULL; + symtab_hdr->contents = (unsigned char *) isymbuf; /* Fix the opcode. */ bfd_put_8 (abfd, 0xea, contents + irel->r_offset - 1); @@ -849,17 +799,14 @@ mn10200_elf_relax_section (abfd, sec, link_info, again) /* We also have to be sure there is no symbol/label at the unconditional branch. */ - if (mn10200_elf_symbol_address_p (abfd, sec, irel->r_offset + 1)) + if (mn10200_elf_symbol_address_p (abfd, sec, isymbuf, + irel->r_offset + 1)) continue; /* Note that we've changed the relocs, section contents, etc. */ elf_section_data (sec)->relocs = internal_relocs; - free_relocs = NULL; - elf_section_data (sec)->this_hdr.contents = contents; - free_contents = NULL; - - free_extsyms = NULL; + symtab_hdr->contents = (unsigned char *) isymbuf; /* Reverse the condition of the first branch. */ switch (code) @@ -977,12 +924,8 @@ mn10200_elf_relax_section (abfd, sec, link_info, again) /* Note that we've changed the reldection contents, etc. */ elf_section_data (sec)->relocs = internal_relocs; - free_relocs = NULL; - elf_section_data (sec)->this_hdr.contents = contents; - free_contents = NULL; - - free_extsyms = NULL; + symtab_hdr->contents = (unsigned char *) isymbuf; /* Fix the opcode. */ bfd_put_8 (abfd, 0xf8 + (code & 0x03), @@ -1020,12 +963,8 @@ mn10200_elf_relax_section (abfd, sec, link_info, again) case 0xc8: /* Note that we've changed the reldection contents, etc. */ elf_section_data (sec)->relocs = internal_relocs; - free_relocs = NULL; - elf_section_data (sec)->this_hdr.contents = contents; - free_contents = NULL; - - free_extsyms = NULL; + symtab_hdr->contents = (unsigned char *) isymbuf; if ((code & 0xfc) == 0x74) code = 0xdc + (code & 0x03); @@ -1107,12 +1046,8 @@ mn10200_elf_relax_section (abfd, sec, link_info, again) /* Note that we've changed the reldection contents, etc. */ elf_section_data (sec)->relocs = internal_relocs; - free_relocs = NULL; - elf_section_data (sec)->this_hdr.contents = contents; - free_contents = NULL; - - free_extsyms = NULL; + symtab_hdr->contents = (unsigned char *) isymbuf; /* Fix the opcode. */ bfd_put_8 (abfd, 0xf7, contents + irel->r_offset - 2); @@ -1170,12 +1105,8 @@ mn10200_elf_relax_section (abfd, sec, link_info, again) case 0xc4: /* Note that we've changed the reldection contents, etc. */ elf_section_data (sec)->relocs = internal_relocs; - free_relocs = NULL; - elf_section_data (sec)->this_hdr.contents = contents; - free_contents = NULL; - - free_extsyms = NULL; + symtab_hdr->contents = (unsigned char *) isymbuf; bfd_put_8 (abfd, 0xcc + (code & 0x03), contents + irel->r_offset - 2); @@ -1205,13 +1136,23 @@ mn10200_elf_relax_section (abfd, sec, link_info, again) } } - if (free_relocs != NULL) - free (free_relocs); - - if (free_contents != NULL) + if (isymbuf != NULL + && symtab_hdr->contents != (unsigned char *) isymbuf) { if (! link_info->keep_memory) - free (free_contents); + free (isymbuf); + else + { + /* Cache the symbols for elf_link_input_bfd. */ + symtab_hdr->contents = (unsigned char *) isymbuf; + } + } + + if (contents != NULL + && elf_section_data (sec)->this_hdr.contents != contents) + { + if (! link_info->keep_memory) + free (contents); else { /* Cache the section contents for elf_link_input_bfd. */ @@ -1219,38 +1160,22 @@ mn10200_elf_relax_section (abfd, sec, link_info, again) } } - if (shndx_buf != NULL) - { - shndx_hdr->contents = NULL; - free (shndx_buf); - } - - if (free_extsyms != NULL) - { - if (! link_info->keep_memory) - { - symtab_hdr->contents = NULL; - free (free_extsyms); - } - } + if (internal_relocs != NULL + && elf_section_data (sec)->relocs != internal_relocs) + free (internal_relocs); return true; error_return: - if (free_relocs != NULL) - free (free_relocs); - if (free_contents != NULL) - free (free_contents); - if (shndx_buf != NULL) - { - shndx_hdr->contents = NULL; - free (shndx_buf); - } - if (free_extsyms != NULL) - { - symtab_hdr->contents = NULL; - free (free_extsyms); - } + if (isymbuf != NULL + && symtab_hdr->contents != (unsigned char *) isymbuf) + free (isymbuf); + if (contents != NULL + && elf_section_data (sec)->this_hdr.contents != contents) + free (contents); + if (internal_relocs != NULL + && elf_section_data (sec)->relocs != internal_relocs) + free (internal_relocs); return false; } @@ -1265,22 +1190,17 @@ mn10200_elf_relax_delete_bytes (abfd, sec, addr, count) int count; { Elf_Internal_Shdr *symtab_hdr; - Elf_Internal_Shdr *shndx_hdr; - Elf32_External_Sym *extsyms; unsigned int sec_shndx; bfd_byte *contents; Elf_Internal_Rela *irel, *irelend; Elf_Internal_Rela *irelalign; bfd_vma toaddr; - Elf32_External_Sym *esym, *esymend; - Elf_External_Sym_Shndx *shndx; + Elf_Internal_Sym *isym; + Elf_Internal_Sym *isymend; struct elf_link_hash_entry **sym_hashes; struct elf_link_hash_entry **end_hashes; unsigned int symcount; - symtab_hdr = &elf_tdata (abfd)->symtab_hdr; - extsyms = (Elf32_External_Sym *) symtab_hdr->contents; - sec_shndx = _bfd_elf_section_from_bfd_section (abfd, sec); contents = elf_section_data (sec)->this_hdr.contents; @@ -1309,25 +1229,14 @@ mn10200_elf_relax_delete_bytes (abfd, sec, addr, count) } /* Adjust the local symbols defined in this section. */ - shndx_hdr = &elf_tdata (abfd)->symtab_shndx_hdr; - shndx = (Elf_External_Sym_Shndx *) shndx_hdr->contents; - esym = extsyms; - esymend = esym + symtab_hdr->sh_info; - for (; esym < esymend; esym++, shndx = (shndx ? shndx + 1 : NULL)) + symtab_hdr = &elf_tdata (abfd)->symtab_hdr; + isym = (Elf_Internal_Sym *) symtab_hdr->contents; + for (isymend = isym + symtab_hdr->sh_info; isym < isymend; isym++) { - Elf_Internal_Sym isym; - Elf_External_Sym_Shndx dummy; - - bfd_elf32_swap_symbol_in (abfd, (const PTR) esym, (const PTR) shndx, - &isym); - - if (isym.st_shndx == sec_shndx - && isym.st_value > addr - && isym.st_value < toaddr) - { - isym.st_value -= count; - bfd_elf32_swap_symbol_out (abfd, &isym, (PTR) esym, (PTR) &dummy); - } + if (isym->st_shndx == sec_shndx + && isym->st_value > addr + && isym->st_value < toaddr) + isym->st_value -= count; } /* Now adjust the global symbols defined in this section. */ @@ -1354,37 +1263,27 @@ mn10200_elf_relax_delete_bytes (abfd, sec, addr, count) /* Return true if a symbol exists at the given address, else return false. */ static boolean -mn10200_elf_symbol_address_p (abfd, sec, addr) +mn10200_elf_symbol_address_p (abfd, sec, isym, addr) bfd *abfd; asection *sec; + Elf_Internal_Sym *isym; bfd_vma addr; { Elf_Internal_Shdr *symtab_hdr; - Elf_Internal_Shdr *shndx_hdr; unsigned int sec_shndx; - Elf32_External_Sym *esym, *esymend; - Elf_External_Sym_Shndx *shndx; + Elf_Internal_Sym *isymend; struct elf_link_hash_entry **sym_hashes; struct elf_link_hash_entry **end_hashes; unsigned int symcount; sec_shndx = _bfd_elf_section_from_bfd_section (abfd, sec); - /* Examine all the symbols. */ + /* Examine all the local symbols. */ symtab_hdr = &elf_tdata (abfd)->symtab_hdr; - shndx_hdr = &elf_tdata (abfd)->symtab_shndx_hdr; - shndx = (Elf_External_Sym_Shndx *) shndx_hdr->contents; - esym = (Elf32_External_Sym *) symtab_hdr->contents; - esymend = esym + symtab_hdr->sh_info; - for (; esym < esymend; esym++, shndx = (shndx ? shndx + 1 : NULL)) + for (isymend = isym + symtab_hdr->sh_info; isym < isymend; isym++) { - Elf_Internal_Sym isym; - - bfd_elf32_swap_symbol_in (abfd, (const PTR) esym, (const PTR) shndx, - &isym); - - if (isym.st_shndx == sec_shndx - && isym.st_value == addr) + if (isym->st_shndx == sec_shndx + && isym->st_value == addr) return true; } @@ -1419,15 +1318,11 @@ mn10200_elf_get_relocated_section_contents (output_bfd, link_info, link_order, asymbol **symbols; { Elf_Internal_Shdr *symtab_hdr; - Elf_Internal_Shdr *shndx_hdr; asection *input_section = link_order->u.indirect.section; bfd *input_bfd = input_section->owner; asection **sections = NULL; Elf_Internal_Rela *internal_relocs = NULL; - Elf32_External_Sym *external_syms = NULL; - Elf_External_Sym_Shndx *shndx_buf = NULL; - Elf_External_Sym_Shndx *shndx; - Elf_Internal_Sym *internal_syms = NULL; + Elf_Internal_Sym *isymbuf = NULL; /* We only need to handle the case of relaxing, or of having a particular set of section contents, specially. */ @@ -1439,7 +1334,6 @@ mn10200_elf_get_relocated_section_contents (output_bfd, link_info, link_order, symbols); symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr; - shndx_hdr = &elf_tdata (input_bfd)->symtab_shndx_hdr; memcpy (data, elf_section_data (input_section)->this_hdr.contents, (size_t) input_section->_raw_size); @@ -1447,48 +1341,27 @@ mn10200_elf_get_relocated_section_contents (output_bfd, link_info, link_order, if ((input_section->flags & SEC_RELOC) != 0 && input_section->reloc_count > 0) { - Elf_Internal_Sym *isymp; + Elf_Internal_Sym *isym; + Elf_Internal_Sym *isymend; asection **secpp; - Elf32_External_Sym *esym, *esymend; bfd_size_type amt; - if (symtab_hdr->contents != NULL) - external_syms = (Elf32_External_Sym *) symtab_hdr->contents; - else if (symtab_hdr->sh_info != 0) - { - amt = symtab_hdr->sh_info; - amt *= sizeof (Elf32_External_Sym); - external_syms = (Elf32_External_Sym *) bfd_malloc (amt); - if (external_syms == NULL) - goto error_return; - if (bfd_seek (input_bfd, symtab_hdr->sh_offset, SEEK_SET) != 0 - || bfd_bread ((PTR) external_syms, amt, input_bfd) != amt) - goto error_return; - } - - if (symtab_hdr->sh_info != 0 && shndx_hdr->sh_size != 0) - { - amt = symtab_hdr->sh_info; - amt *= sizeof (Elf_External_Sym_Shndx); - shndx_buf = (Elf_External_Sym_Shndx *) bfd_malloc (amt); - if (shndx_buf == NULL) - goto error_return; - if (bfd_seek (input_bfd, shndx_hdr->sh_offset, SEEK_SET) != 0 - || bfd_bread ((PTR) shndx_buf, amt, input_bfd) != amt) - goto error_return; - } - internal_relocs = (_bfd_elf32_link_read_relocs (input_bfd, input_section, (PTR) NULL, (Elf_Internal_Rela *) NULL, false)); if (internal_relocs == NULL) goto error_return; - amt = symtab_hdr->sh_info; - amt *= sizeof (Elf_Internal_Sym); - internal_syms = (Elf_Internal_Sym *) bfd_malloc (amt); - if (internal_syms == NULL && amt != 0) - goto error_return; + if (symtab_hdr->sh_info != 0) + { + isymbuf = (Elf_Internal_Sym *) symtab_hdr->contents; + if (isymbuf == NULL) + isymbuf = bfd_elf_get_elf_syms (input_bfd, symtab_hdr, + symtab_hdr->sh_info, 0, + NULL, NULL, NULL); + if (isymbuf == NULL) + goto error_return; + } amt = symtab_hdr->sh_info; amt *= sizeof (asection *); @@ -1496,59 +1369,48 @@ mn10200_elf_get_relocated_section_contents (output_bfd, link_info, link_order, if (sections == NULL && amt != 0) goto error_return; - for (isymp = internal_syms, secpp = sections, shndx = shndx_buf, - esym = external_syms, esymend = esym + symtab_hdr->sh_info; - esym < esymend; - ++esym, ++isymp, ++secpp, shndx = (shndx ? shndx + 1 : NULL)) + isymend = isymbuf + symtab_hdr->sh_info; + for (isym = isymbuf, secpp = sections; isym < isymend; ++isym, ++secpp) { asection *isec; - bfd_elf32_swap_symbol_in (input_bfd, (const PTR) esym, - (const PTR) shndx, isymp); - - if (isymp->st_shndx == SHN_UNDEF) + if (isym->st_shndx == SHN_UNDEF) isec = bfd_und_section_ptr; - else if (isymp->st_shndx == SHN_ABS) + else if (isym->st_shndx == SHN_ABS) isec = bfd_abs_section_ptr; - else if (isymp->st_shndx == SHN_COMMON) + else if (isym->st_shndx == SHN_COMMON) isec = bfd_com_section_ptr; else - isec = bfd_section_from_elf_index (input_bfd, isymp->st_shndx); + isec = bfd_section_from_elf_index (input_bfd, isym->st_shndx); *secpp = isec; } if (! mn10200_elf_relocate_section (output_bfd, link_info, input_bfd, input_section, data, internal_relocs, - internal_syms, sections)) + isymbuf, sections)) goto error_return; if (sections != NULL) free (sections); - if (internal_syms != NULL) - free (internal_syms); - if (shndx_buf != NULL) - free (shndx_buf); - if (external_syms != NULL && symtab_hdr->contents == NULL) - free (external_syms); - if (internal_relocs != elf_section_data (input_section)->relocs) + if (isymbuf != NULL + && symtab_hdr->contents != (unsigned char *) isymbuf) + free (isymbuf); + if (elf_section_data (input_section)->relocs != internal_relocs) free (internal_relocs); } return data; error_return: - if (internal_relocs != NULL - && internal_relocs != elf_section_data (input_section)->relocs) - free (internal_relocs); - if (shndx_buf != NULL) - free (shndx_buf); - if (external_syms != NULL && symtab_hdr->contents == NULL) - free (external_syms); - if (internal_syms != NULL) - free (internal_syms); if (sections != NULL) free (sections); + if (isymbuf != NULL + && symtab_hdr->contents != (unsigned char *) isymbuf) + free (isymbuf); + if (internal_relocs != NULL + && elf_section_data (input_section)->relocs != internal_relocs) + free (internal_relocs); return NULL; } diff --git a/bfd/elf-m10300.c b/bfd/elf-m10300.c index 501c3dd49f..2c9b4a928a 100644 --- a/bfd/elf-m10300.c +++ b/bfd/elf-m10300.c @@ -127,7 +127,7 @@ static asection *mn10300_elf_gc_mark_hook static boolean mn10300_elf_relax_delete_bytes PARAMS ((bfd *, asection *, bfd_vma, int)); static boolean mn10300_elf_symbol_address_p - PARAMS ((bfd *, asection *, bfd_vma)); +PARAMS ((bfd *, asection *, Elf_Internal_Sym *, bfd_vma)); static boolean elf32_mn10300_finish_hash_table_entry PARAMS ((struct bfd_hash_entry *, PTR)); static void compute_function_info @@ -783,16 +783,12 @@ mn10300_elf_relax_section (abfd, sec, link_info, again) boolean *again; { Elf_Internal_Shdr *symtab_hdr; - Elf_Internal_Shdr *shndx_hdr; Elf_Internal_Rela *internal_relocs = NULL; - Elf_Internal_Rela *free_relocs = NULL; Elf_Internal_Rela *irel, *irelend; bfd_byte *contents = NULL; - bfd_byte *free_contents = NULL; - Elf32_External_Sym *extsyms = NULL; - Elf32_External_Sym *free_extsyms = NULL; - Elf_External_Sym_Shndx *shndx_buf = NULL; + Elf_Internal_Sym *isymbuf = NULL; struct elf32_mn10300_link_hash_table *hash_table; + asection *section = sec; /* Assume nothing changes. */ *again = false; @@ -810,42 +806,16 @@ mn10300_elf_relax_section (abfd, sec, link_info, again) input_bfd != NULL; input_bfd = input_bfd->link_next) { - asection *section; - /* We're going to need all the symbols for each bfd. */ symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr; - shndx_hdr = &elf_tdata (input_bfd)->symtab_shndx_hdr; - - /* Get cached copy if it exists. */ - if (symtab_hdr->contents != NULL) - extsyms = (Elf32_External_Sym *) symtab_hdr->contents; - else + if (symtab_hdr->sh_info != 0) { - /* Go get them off disk. */ - bfd_size_type amt; - - amt = symtab_hdr->sh_info; - amt *= sizeof (Elf32_External_Sym); - extsyms = (Elf32_External_Sym *) bfd_malloc (amt); - if (extsyms == NULL) - goto error_return; - free_extsyms = extsyms; - if (bfd_seek (input_bfd, symtab_hdr->sh_offset, SEEK_SET) != 0 - || bfd_bread ((PTR) extsyms, amt, input_bfd) != amt) - goto error_return; - } - - if (shndx_hdr->sh_size != 0) - { - bfd_size_type amt; - - amt = symtab_hdr->sh_info; - amt *= sizeof (Elf_External_Sym_Shndx); - shndx_buf = (Elf_External_Sym_Shndx *) bfd_malloc (amt); - if (shndx_buf == NULL) - goto error_return; - if (bfd_seek (input_bfd, shndx_hdr->sh_offset, SEEK_SET) != 0 - || bfd_bread ((PTR) shndx_buf, amt, input_bfd) != amt) + isymbuf = (Elf_Internal_Sym *) symtab_hdr->contents; + if (isymbuf == NULL) + isymbuf = bfd_elf_get_elf_syms (input_bfd, symtab_hdr, + symtab_hdr->sh_info, 0, + NULL, NULL, NULL); + if (isymbuf == NULL) goto error_return; } @@ -875,7 +845,6 @@ mn10300_elf_relax_section (abfd, sec, link_info, again) contents = (bfd_byte *) bfd_malloc (section->_raw_size); if (contents == NULL) goto error_return; - free_contents = contents; if (!bfd_get_section_contents (input_bfd, section, contents, (file_ptr) 0, @@ -883,10 +852,7 @@ mn10300_elf_relax_section (abfd, sec, link_info, again) goto error_return; } else - { - contents = NULL; - free_contents = NULL; - } + contents = NULL; /* If there aren't any relocs, then there's nothing to do. */ if ((section->flags & SEC_RELOC) != 0 @@ -900,8 +866,6 @@ mn10300_elf_relax_section (abfd, sec, link_info, again) link_info->keep_memory)); if (internal_relocs == NULL) goto error_return; - if (! link_info->keep_memory) - free_relocs = internal_relocs; /* Now examine each relocation. */ irel = internal_relocs; @@ -927,40 +891,31 @@ mn10300_elf_relax_section (abfd, sec, link_info, again) if (r_index < symtab_hdr->sh_info) { /* A local symbol. */ - Elf32_External_Sym *esym; - Elf_External_Sym_Shndx *shndx; - Elf_Internal_Sym isym; + Elf_Internal_Sym *isym; struct elf_link_hash_table *elftab; bfd_size_type amt; - esym = extsyms + r_index; - shndx = shndx_buf + (shndx_buf ? r_index : 0); - bfd_elf32_swap_symbol_in (input_bfd, - (const PTR) esym, - (const PTR) shndx, - &isym); - - if (isym.st_shndx == SHN_UNDEF) + isym = isymbuf + r_index; + if (isym->st_shndx == SHN_UNDEF) sym_sec = bfd_und_section_ptr; - else if (isym.st_shndx == SHN_ABS) + else if (isym->st_shndx == SHN_ABS) sym_sec = bfd_abs_section_ptr; - else if (isym.st_shndx == SHN_COMMON) + else if (isym->st_shndx == SHN_COMMON) sym_sec = bfd_com_section_ptr; else sym_sec = bfd_section_from_elf_index (input_bfd, - isym.st_shndx); + isym->st_shndx); sym_name = bfd_elf_string_from_elf_section (input_bfd, (symtab_hdr ->sh_link), - isym.st_name); + isym->st_name); /* If it isn't a function, then we don't care about it. */ - if (r_index < symtab_hdr->sh_info - && ELF_ST_TYPE (isym.st_info) != STT_FUNC) + if (ELF_ST_TYPE (isym->st_info) != STT_FUNC) continue; /* Tack on an ID so we can uniquely identify this @@ -995,8 +950,9 @@ mn10300_elf_relax_section (abfd, sec, link_info, again) if (code != 0xdd && code != 0xcd) hash->flags |= MN10300_CONVERT_CALL_TO_CALLS; - /* If this is a jump/call, then bump the direct_calls - counter. Else force "call" to "calls" conversions. */ + /* If this is a jump/call, then bump the + direct_calls counter. Else force "call" to + "calls" conversions. */ if (r_type == R_MN10300_PCREL32 || r_type == R_MN10300_PCREL16) hash->direct_calls++; @@ -1010,46 +966,40 @@ mn10300_elf_relax_section (abfd, sec, link_info, again) (ie movm_args). */ if ((section->flags & SEC_CODE) != 0) { - - Elf32_External_Sym *esym, *esymend; - Elf_External_Sym_Shndx *shndx; - int idx; + Elf_Internal_Sym *isym, *isymend; unsigned int sec_shndx; + struct elf_link_hash_entry **hashes; + struct elf_link_hash_entry **end_hashes; + unsigned int symcount; sec_shndx = _bfd_elf_section_from_bfd_section (input_bfd, section); /* Look at each function defined in this section and update info for that function. */ - for (esym = extsyms, esymend = esym + symtab_hdr->sh_info, - shndx = shndx_buf; - esym < esymend; - esym++, shndx = (shndx ? shndx + 1 : NULL)) + isymend = isymbuf + symtab_hdr->sh_info; + for (isym = isymbuf; isym < isymend; isym++) { - Elf_Internal_Sym isym; - - bfd_elf32_swap_symbol_in (input_bfd, (const PTR) esym, - (const PTR) shndx, &isym); - if (isym.st_shndx == sec_shndx - && ELF_ST_TYPE (isym.st_info) == STT_FUNC) + if (isym->st_shndx == sec_shndx + && ELF_ST_TYPE (isym->st_info) == STT_FUNC) { struct elf_link_hash_table *elftab; bfd_size_type amt; - if (isym.st_shndx == SHN_UNDEF) + if (isym->st_shndx == SHN_UNDEF) sym_sec = bfd_und_section_ptr; - else if (isym.st_shndx == SHN_ABS) + else if (isym->st_shndx == SHN_ABS) sym_sec = bfd_abs_section_ptr; - else if (isym.st_shndx == SHN_COMMON) + else if (isym->st_shndx == SHN_COMMON) sym_sec = bfd_com_section_ptr; else sym_sec = bfd_section_from_elf_index (input_bfd, - isym.st_shndx); + isym->st_shndx); sym_name = (bfd_elf_string_from_elf_section (input_bfd, symtab_hdr->sh_link, - isym.st_name)); + isym->st_name)); /* Tack on an ID so we can uniquely identify this local symbol in the global hash table. */ @@ -1068,23 +1018,21 @@ mn10300_elf_relax_section (abfd, sec, link_info, again) true, true, false)); free (new_name); compute_function_info (input_bfd, hash, - isym.st_value, contents); + isym->st_value, contents); } } - esym = extsyms + symtab_hdr->sh_info; - esymend = extsyms + (symtab_hdr->sh_size - / sizeof (Elf32_External_Sym)); - for (idx = 0; esym < esymend; esym++, idx++) + symcount = (symtab_hdr->sh_size / sizeof (Elf32_External_Sym) + - symtab_hdr->sh_info); + hashes = elf_sym_hashes (abfd); + end_hashes = hashes + symcount; + for (; hashes < end_hashes; hashes++) { - Elf_Internal_Sym isym; - - hash = (struct elf32_mn10300_link_hash_entry *) - elf_sym_hashes (input_bfd)[idx]; + hash = (struct elf32_mn10300_link_hash_entry *) *hashes; if ((hash->root.root.type == bfd_link_hash_defined || hash->root.root.type == bfd_link_hash_defweak) && hash->root.root.u.def.section == section - && ELF_ST_TYPE (isym.st_info) == STT_FUNC) + && ELF_ST_TYPE (isym->st_info) == STT_FUNC) compute_function_info (input_bfd, hash, (hash)->root.root.u.def.value, contents); @@ -1092,44 +1040,39 @@ mn10300_elf_relax_section (abfd, sec, link_info, again) } /* Cache or free any memory we allocated for the relocs. */ - if (free_relocs != NULL) - { - free (free_relocs); - free_relocs = NULL; - } + if (internal_relocs != NULL + && elf_section_data (section)->relocs != internal_relocs) + free (internal_relocs); + internal_relocs = NULL; /* Cache or free any memory we allocated for the contents. */ - if (free_contents != NULL) + if (contents != NULL + && elf_section_data (section)->this_hdr.contents != contents) { if (! link_info->keep_memory) - free (free_contents); + free (contents); else { /* Cache the section contents for elf_link_input_bfd. */ elf_section_data (section)->this_hdr.contents = contents; } - free_contents = NULL; } - } - - if (shndx_buf != NULL) - { - free (shndx_buf); - shndx_buf = NULL; + contents = NULL; } /* Cache or free any memory we allocated for the symbols. */ - if (free_extsyms != NULL) + if (isymbuf != NULL + && symtab_hdr->contents != (unsigned char *) isymbuf) { if (! link_info->keep_memory) - free (free_extsyms); + free (isymbuf); else { /* Cache the symbols for elf_link_input_bfd. */ - symtab_hdr->contents = (unsigned char *) extsyms; + symtab_hdr->contents = (unsigned char *) isymbuf; } - free_extsyms = NULL; } + isymbuf = NULL; } /* Now iterate on each symbol in the hash table and perform @@ -1152,45 +1095,17 @@ mn10300_elf_relax_section (abfd, sec, link_info, again) input_bfd != NULL; input_bfd = input_bfd->link_next) { - asection *section; - /* We're going to need all the local symbols for each bfd. */ symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr; - shndx_hdr = &elf_tdata (input_bfd)->symtab_shndx_hdr; - - /* Get cached copy if it exists. */ - if (symtab_hdr->contents != NULL) - extsyms = (Elf32_External_Sym *) symtab_hdr->contents; - else + if (symtab_hdr->sh_info != 0) { - /* Go get them off disk. */ - bfd_size_type amt; - - amt = symtab_hdr->sh_info; - amt *= sizeof (Elf32_External_Sym); - extsyms = (Elf32_External_Sym *) bfd_malloc (amt); - if (extsyms == NULL) + isymbuf = (Elf_Internal_Sym *) symtab_hdr->contents; + if (isymbuf == NULL) + isymbuf = bfd_elf_get_elf_syms (input_bfd, symtab_hdr, + symtab_hdr->sh_info, 0, + NULL, NULL, NULL); + if (isymbuf == NULL) goto error_return; - free_extsyms = extsyms; - if (bfd_seek (input_bfd, symtab_hdr->sh_offset, SEEK_SET) != 0 - || bfd_bread ((PTR) extsyms, amt, input_bfd) != amt) - goto error_return; - symtab_hdr->contents = (bfd_byte *) extsyms; - } - - if (shndx_hdr->sh_size != 0) - { - bfd_size_type amt; - - amt = symtab_hdr->sh_info; - amt *= sizeof (Elf_External_Sym_Shndx); - shndx_buf = (Elf_External_Sym_Shndx *) bfd_malloc (amt); - if (shndx_buf == NULL) - goto error_return; - if (bfd_seek (input_bfd, shndx_hdr->sh_offset, SEEK_SET) != 0 - || bfd_bread ((PTR) shndx_buf, amt, input_bfd) != amt) - goto error_return; - shndx_hdr->contents = (bfd_byte *) shndx_buf; } /* Walk over each section in this bfd. */ @@ -1199,9 +1114,10 @@ mn10300_elf_relax_section (abfd, sec, link_info, again) section = section->next) { unsigned int sec_shndx; - Elf32_External_Sym *esym, *esymend; - Elf_External_Sym_Shndx *shndx; - unsigned int idx; + Elf_Internal_Sym *isym, *isymend; + struct elf_link_hash_entry **hashes; + struct elf_link_hash_entry **end_hashes; + unsigned int symcount; /* Skip non-code sections and empty sections. */ if ((section->flags & SEC_CODE) == 0 || section->_raw_size == 0) @@ -1216,8 +1132,6 @@ mn10300_elf_relax_section (abfd, sec, link_info, again) link_info->keep_memory)); if (internal_relocs == NULL) goto error_return; - if (! link_info->keep_memory) - free_relocs = internal_relocs; } /* Get cached copy of section contents if it exists. */ @@ -1229,7 +1143,6 @@ mn10300_elf_relax_section (abfd, sec, link_info, again) contents = (bfd_byte *) bfd_malloc (section->_raw_size); if (contents == NULL) goto error_return; - free_contents = contents; if (!bfd_get_section_contents (input_bfd, section, contents, (file_ptr) 0, @@ -1242,12 +1155,9 @@ mn10300_elf_relax_section (abfd, sec, link_info, again) /* Now look for any function in this section which needs insns deleted from its prologue. */ - for (esym = extsyms, esymend = esym + symtab_hdr->sh_info, - shndx = shndx_buf; - esym < esymend; - esym++, shndx = (shndx ? shndx + 1 : NULL)) + isymend = isymbuf + symtab_hdr->sh_info; + for (isym = isymbuf; isym < isymend; isym++) { - Elf_Internal_Sym isym; struct elf32_mn10300_link_hash_entry *sym_hash; asection *sym_sec = NULL; const char *sym_name; @@ -1255,26 +1165,23 @@ mn10300_elf_relax_section (abfd, sec, link_info, again) struct elf_link_hash_table *elftab; bfd_size_type amt; - bfd_elf32_swap_symbol_in (input_bfd, (const PTR) esym, - (const PTR) shndx, &isym); - - if (isym.st_shndx != sec_shndx) + if (isym->st_shndx != sec_shndx) continue; - if (isym.st_shndx == SHN_UNDEF) + if (isym->st_shndx == SHN_UNDEF) sym_sec = bfd_und_section_ptr; - else if (isym.st_shndx == SHN_ABS) + else if (isym->st_shndx == SHN_ABS) sym_sec = bfd_abs_section_ptr; - else if (isym.st_shndx == SHN_COMMON) + else if (isym->st_shndx == SHN_COMMON) sym_sec = bfd_com_section_ptr; else sym_sec - = bfd_section_from_elf_index (input_bfd, isym.st_shndx); + = bfd_section_from_elf_index (input_bfd, isym->st_shndx); sym_name = bfd_elf_string_from_elf_section (input_bfd, symtab_hdr->sh_link, - isym.st_name); + isym->st_name); /* Tack on an ID so we can uniquely identify this local symbol in the global hash table. */ @@ -1301,12 +1208,8 @@ mn10300_elf_relax_section (abfd, sec, link_info, again) /* Note that we've changed things. */ elf_section_data (section)->relocs = internal_relocs; - free_relocs = NULL; - elf_section_data (section)->this_hdr.contents = contents; - free_contents = NULL; - - free_extsyms = NULL; + symtab_hdr->contents = (unsigned char *) isymbuf; /* Count how many bytes we're going to delete. */ if (sym_hash->movm_args) @@ -1325,7 +1228,7 @@ mn10300_elf_relax_section (abfd, sec, link_info, again) /* Actually delete the bytes. */ if (!mn10300_elf_relax_delete_bytes (input_bfd, section, - isym.st_value, + isym->st_value, bytes)) goto error_return; @@ -1337,15 +1240,15 @@ mn10300_elf_relax_section (abfd, sec, link_info, again) /* Look for any global functions in this section which need insns deleted from their prologues. */ - for (idx = 0; - idx < (symtab_hdr->sh_size / sizeof (Elf32_External_Sym) + symcount = (symtab_hdr->sh_size / sizeof (Elf32_External_Sym) - symtab_hdr->sh_info); - idx++) + hashes = elf_sym_hashes (abfd); + end_hashes = hashes + symcount; + for (; hashes < end_hashes; hashes++) { struct elf32_mn10300_link_hash_entry *sym_hash; - sym_hash = (struct elf32_mn10300_link_hash_entry *) - (elf_sym_hashes (input_bfd)[idx]); + sym_hash = (struct elf32_mn10300_link_hash_entry *) *hashes; if ((sym_hash->root.root.type == bfd_link_hash_defined || sym_hash->root.root.type == bfd_link_hash_defweak) && sym_hash->root.root.u.def.section == section @@ -1357,12 +1260,8 @@ mn10300_elf_relax_section (abfd, sec, link_info, again) /* Note that we've changed things. */ elf_section_data (section)->relocs = internal_relocs; - free_relocs = NULL; - elf_section_data (section)->this_hdr.contents = contents; - free_contents = NULL; - - free_extsyms = NULL; + symtab_hdr->contents = (unsigned char *) isymbuf; /* Count how many bytes we're going to delete. */ if (sym_hash->movm_args) @@ -1393,53 +1292,48 @@ mn10300_elf_relax_section (abfd, sec, link_info, again) } /* Cache or free any memory we allocated for the relocs. */ - if (free_relocs != NULL) - { - free (free_relocs); - free_relocs = NULL; - } + if (internal_relocs != NULL + && elf_section_data (section)->relocs != internal_relocs) + free (internal_relocs); + internal_relocs = NULL; /* Cache or free any memory we allocated for the contents. */ - if (free_contents != NULL) + if (contents != NULL + && elf_section_data (section)->this_hdr.contents != contents) { if (! link_info->keep_memory) - free (free_contents); + free (contents); else { /* Cache the section contents for elf_link_input_bfd. */ elf_section_data (section)->this_hdr.contents = contents; } - free_contents = NULL; } - } - - if (shndx_buf != NULL) - { - shndx_hdr->contents = NULL; - free (shndx_buf); - shndx_buf = NULL; + contents = NULL; } /* Cache or free any memory we allocated for the symbols. */ - if (free_extsyms != NULL) + if (isymbuf != NULL + && symtab_hdr->contents != (unsigned char *) isymbuf) { if (! link_info->keep_memory) + free (isymbuf); + else { - symtab_hdr->contents = NULL; - free (free_extsyms); + /* Cache the symbols for elf_link_input_bfd. */ + symtab_hdr->contents = (unsigned char *) isymbuf; } - free_extsyms = NULL; } + isymbuf = NULL; } } /* (Re)initialize for the basic instruction shortening/relaxing pass. */ contents = NULL; - extsyms = NULL; internal_relocs = NULL; - free_relocs = NULL; - free_contents = NULL; - free_extsyms = NULL; + isymbuf = NULL; + /* For error_return. */ + section = sec; /* We don't have to do anything for a relocateable link, if this section does not have relocs, or if this is not a @@ -1456,7 +1350,6 @@ mn10300_elf_relax_section (abfd, sec, link_info, again) sec->_cooked_size = sec->_raw_size; symtab_hdr = &elf_tdata (abfd)->symtab_hdr; - shndx_hdr = &elf_tdata (abfd)->symtab_shndx_hdr; /* Get a copy of the native relocations. */ internal_relocs = (_bfd_elf32_link_read_relocs @@ -1464,8 +1357,6 @@ mn10300_elf_relax_section (abfd, sec, link_info, again) link_info->keep_memory)); if (internal_relocs == NULL) goto error_return; - if (! link_info->keep_memory) - free_relocs = internal_relocs; /* Walk through them looking for relaxing opportunities. */ irelend = internal_relocs + sec->reloc_count; @@ -1493,7 +1384,6 @@ mn10300_elf_relax_section (abfd, sec, link_info, again) contents = (bfd_byte *) bfd_malloc (sec->_raw_size); if (contents == NULL) goto error_return; - free_contents = contents; if (! bfd_get_section_contents (abfd, sec, contents, (file_ptr) 0, sec->_raw_size)) @@ -1501,76 +1391,43 @@ mn10300_elf_relax_section (abfd, sec, link_info, again) } } - /* Read this BFD's symbols if we haven't done so already. */ - if (extsyms == NULL) + /* Read this BFD's symbols if we haven't done so already. */ + if (isymbuf == NULL && symtab_hdr->sh_info != 0) { - /* Get cached copy if it exists. */ - if (symtab_hdr->contents != NULL) - extsyms = (Elf32_External_Sym *) symtab_hdr->contents; - else - { - /* Go get them off disk. */ - bfd_size_type amt; - - amt = symtab_hdr->sh_info; - amt *= sizeof (Elf32_External_Sym); - extsyms = (Elf32_External_Sym *) bfd_malloc (amt); - if (extsyms == NULL) - goto error_return; - free_extsyms = extsyms; - if (bfd_seek (abfd, symtab_hdr->sh_offset, SEEK_SET) != 0 - || bfd_bread ((PTR) extsyms, amt, abfd) != amt) - goto error_return; - symtab_hdr->contents = (bfd_byte *) extsyms; - } - - if (shndx_hdr->sh_size != 0) - { - bfd_size_type amt; - - amt = symtab_hdr->sh_info; - amt *= sizeof (Elf_External_Sym_Shndx); - shndx_buf = (Elf_External_Sym_Shndx *) bfd_malloc (amt); - if (shndx_buf == NULL) - goto error_return; - if (bfd_seek (abfd, shndx_hdr->sh_offset, SEEK_SET) != 0 - || bfd_bread ((PTR) shndx_buf, amt, abfd) != amt) - goto error_return; - shndx_hdr->contents = (bfd_byte *) shndx_buf; - } + isymbuf = (Elf_Internal_Sym *) symtab_hdr->contents; + if (isymbuf == NULL) + isymbuf = bfd_elf_get_elf_syms (abfd, symtab_hdr, + symtab_hdr->sh_info, 0, + NULL, NULL, NULL); + if (isymbuf == NULL) + goto error_return; } /* Get the value of the symbol referred to by the reloc. */ if (ELF32_R_SYM (irel->r_info) < symtab_hdr->sh_info) { - Elf32_External_Sym *esym; - Elf_External_Sym_Shndx *shndx; - Elf_Internal_Sym isym; + Elf_Internal_Sym *isym; asection *sym_sec = NULL; const char *sym_name; char *new_name; /* A local symbol. */ - esym = extsyms + ELF32_R_SYM (irel->r_info); - shndx = shndx_buf + (shndx_buf ? ELF32_R_SYM (irel->r_info) : 0); - bfd_elf32_swap_symbol_in (abfd, (const PTR) esym, - (const PTR) shndx, &isym); - - if (isym.st_shndx == SHN_UNDEF) + isym = isymbuf + ELF32_R_SYM (irel->r_info); + if (isym->st_shndx == SHN_UNDEF) sym_sec = bfd_und_section_ptr; - else if (isym.st_shndx == SHN_ABS) + else if (isym->st_shndx == SHN_ABS) sym_sec = bfd_abs_section_ptr; - else if (isym.st_shndx == SHN_COMMON) + else if (isym->st_shndx == SHN_COMMON) sym_sec = bfd_com_section_ptr; else - sym_sec = bfd_section_from_elf_index (abfd, isym.st_shndx); + sym_sec = bfd_section_from_elf_index (abfd, isym->st_shndx); - symval = (isym.st_value + symval = (isym->st_value + sym_sec->output_section->vma + sym_sec->output_offset); sym_name = bfd_elf_string_from_elf_section (abfd, symtab_hdr->sh_link, - isym.st_name); + isym->st_name); /* Tack on an ID so we can uniquely identify this local symbol in the global hash table. */ @@ -1638,12 +1495,8 @@ mn10300_elf_relax_section (abfd, sec, link_info, again) /* Note that we've changed the relocs, section contents, etc. */ elf_section_data (sec)->relocs = internal_relocs; - free_relocs = NULL; - elf_section_data (sec)->this_hdr.contents = contents; - free_contents = NULL; - - free_extsyms = NULL; + symtab_hdr->contents = (unsigned char *) isymbuf; /* Fix the opcode. */ bfd_put_8 (abfd, 0xfc, contents + irel->r_offset - 1); @@ -1702,12 +1555,8 @@ mn10300_elf_relax_section (abfd, sec, link_info, again) /* Note that we've changed the relocs, section contents, etc. */ elf_section_data (sec)->relocs = internal_relocs; - free_relocs = NULL; - elf_section_data (sec)->this_hdr.contents = contents; - free_contents = NULL; - - free_extsyms = NULL; + symtab_hdr->contents = (unsigned char *) isymbuf; /* Fix the opcode. */ if (code == 0xdc) @@ -1753,12 +1602,8 @@ mn10300_elf_relax_section (abfd, sec, link_info, again) /* Note that we've changed the relocs, section contents, etc. */ elf_section_data (sec)->relocs = internal_relocs; - free_relocs = NULL; - elf_section_data (sec)->this_hdr.contents = contents; - free_contents = NULL; - - free_extsyms = NULL; + symtab_hdr->contents = (unsigned char *) isymbuf; /* Fix the opcode. */ bfd_put_8 (abfd, 0xfa, contents + irel->r_offset - 1); @@ -1815,12 +1660,8 @@ mn10300_elf_relax_section (abfd, sec, link_info, again) /* Note that we've changed the relocs, section contents, etc. */ elf_section_data (sec)->relocs = internal_relocs; - free_relocs = NULL; - elf_section_data (sec)->this_hdr.contents = contents; - free_contents = NULL; - - free_extsyms = NULL; + symtab_hdr->contents = (unsigned char *) isymbuf; /* Fix the opcode. */ bfd_put_8 (abfd, 0xca, contents + irel->r_offset - 1); @@ -1904,17 +1745,14 @@ mn10300_elf_relax_section (abfd, sec, link_info, again) /* We also have to be sure there is no symbol/label at the unconditional branch. */ - if (mn10300_elf_symbol_address_p (abfd, sec, irel->r_offset + 1)) + if (mn10300_elf_symbol_address_p (abfd, sec, isymbuf, + irel->r_offset + 1)) continue; /* Note that we've changed the relocs, section contents, etc. */ elf_section_data (sec)->relocs = internal_relocs; - free_relocs = NULL; - elf_section_data (sec)->this_hdr.contents = contents; - free_contents = NULL; - - free_extsyms = NULL; + symtab_hdr->contents = (unsigned char *) isymbuf; /* Reverse the condition of the first branch. */ switch (code) @@ -2022,12 +1860,8 @@ mn10300_elf_relax_section (abfd, sec, link_info, again) /* Note that we've changed the relocation contents, etc. */ elf_section_data (sec)->relocs = internal_relocs; - free_relocs = NULL; - elf_section_data (sec)->this_hdr.contents = contents; - free_contents = NULL; - - free_extsyms = NULL; + symtab_hdr->contents = (unsigned char *) isymbuf; /* Fix the opcode. */ bfd_put_8 (abfd, 0xfb, contents + irel->r_offset - 3); @@ -2097,12 +1931,8 @@ mn10300_elf_relax_section (abfd, sec, link_info, again) /* Note that we've changed the relocation contents, etc. */ elf_section_data (sec)->relocs = internal_relocs; - free_relocs = NULL; - elf_section_data (sec)->this_hdr.contents = contents; - free_contents = NULL; - - free_extsyms = NULL; + symtab_hdr->contents = (unsigned char *) isymbuf; /* Fix the opcode. */ bfd_put_8 (abfd, 0xfd, contents + irel->r_offset - 3); @@ -2180,12 +2010,8 @@ mn10300_elf_relax_section (abfd, sec, link_info, again) /* Note that we've changed the relocation contents, etc. */ elf_section_data (sec)->relocs = internal_relocs; - free_relocs = NULL; - elf_section_data (sec)->this_hdr.contents = contents; - free_contents = NULL; - - free_extsyms = NULL; + symtab_hdr->contents = (unsigned char *) isymbuf; /* Fix the opcode. */ bfd_put_8 (abfd, 0xfa, contents + irel->r_offset - 2); @@ -2217,12 +2043,8 @@ mn10300_elf_relax_section (abfd, sec, link_info, again) case 0x83: /* Note that we've changed the relocation contents, etc. */ elf_section_data (sec)->relocs = internal_relocs; - free_relocs = NULL; - elf_section_data (sec)->this_hdr.contents = contents; - free_contents = NULL; - - free_extsyms = NULL; + symtab_hdr->contents = (unsigned char *) isymbuf; if ((code & 0xf3) == 0x81) code = 0x01 + (code & 0x0c); @@ -2271,12 +2093,8 @@ mn10300_elf_relax_section (abfd, sec, link_info, again) /* Note that we've changed the relocation contents, etc. */ elf_section_data (sec)->relocs = internal_relocs; - free_relocs = NULL; - elf_section_data (sec)->this_hdr.contents = contents; - free_contents = NULL; - - free_extsyms = NULL; + symtab_hdr->contents = (unsigned char *) isymbuf; /* Fix the opcode. */ bfd_put_8 (abfd, 0xfa, contents + irel->r_offset - 2); @@ -2323,12 +2141,8 @@ mn10300_elf_relax_section (abfd, sec, link_info, again) /* Note that we've changed the relocation contents, etc. */ elf_section_data (sec)->relocs = internal_relocs; - free_relocs = NULL; - elf_section_data (sec)->this_hdr.contents = contents; - free_contents = NULL; - - free_extsyms = NULL; + symtab_hdr->contents = (unsigned char *) isymbuf; if ((code & 0xfc) == 0xcc) code = 0x2c + (code & 0x03); @@ -2404,12 +2218,8 @@ mn10300_elf_relax_section (abfd, sec, link_info, again) /* Note that we've changed the relocation contents, etc. */ elf_section_data (sec)->relocs = internal_relocs; - free_relocs = NULL; - elf_section_data (sec)->this_hdr.contents = contents; - free_contents = NULL; - - free_extsyms = NULL; + symtab_hdr->contents = (unsigned char *) isymbuf; /* Fix the opcode. */ bfd_put_8 (abfd, 0xfa, contents + irel->r_offset - 2); @@ -2435,12 +2245,8 @@ mn10300_elf_relax_section (abfd, sec, link_info, again) /* Note that we've changed the relocation contents, etc. */ elf_section_data (sec)->relocs = internal_relocs; - free_relocs = NULL; - elf_section_data (sec)->this_hdr.contents = contents; - free_contents = NULL; - - free_extsyms = NULL; + symtab_hdr->contents = (unsigned char *) isymbuf; /* Fix the opcode. */ bfd_put_8 (abfd, 0xfa, contents + irel->r_offset - 2); @@ -2464,13 +2270,23 @@ mn10300_elf_relax_section (abfd, sec, link_info, again) } } - if (free_relocs != NULL) - free (free_relocs); - - if (free_contents != NULL) + if (isymbuf != NULL + && symtab_hdr->contents != (unsigned char *) isymbuf) { if (! link_info->keep_memory) - free (free_contents); + free (isymbuf); + else + { + /* Cache the symbols for elf_link_input_bfd. */ + symtab_hdr->contents = (unsigned char *) isymbuf; + } + } + + if (contents != NULL + && elf_section_data (sec)->this_hdr.contents != contents) + { + if (! link_info->keep_memory) + free (contents); else { /* Cache the section contents for elf_link_input_bfd. */ @@ -2478,38 +2294,22 @@ mn10300_elf_relax_section (abfd, sec, link_info, again) } } - if (shndx_buf != NULL) - { - shndx_hdr->contents = NULL; - free (shndx_buf); - } - - if (free_extsyms != NULL) - { - if (! link_info->keep_memory) - { - symtab_hdr->contents = NULL; - free (free_extsyms); - } - } + if (internal_relocs != NULL + && elf_section_data (sec)->relocs != internal_relocs) + free (internal_relocs); return true; error_return: - if (free_relocs != NULL) - free (free_relocs); - if (free_contents != NULL) - free (free_contents); - if (shndx_buf != NULL) - { - shndx_hdr->contents = NULL; - free (shndx_buf); - } - if (free_extsyms != NULL) - { - symtab_hdr->contents = NULL; - free (free_extsyms); - } + if (isymbuf != NULL + && symtab_hdr->contents != (unsigned char *) isymbuf) + free (isymbuf); + if (contents != NULL + && elf_section_data (section)->this_hdr.contents != contents) + free (contents); + if (internal_relocs != NULL + && elf_section_data (section)->relocs != internal_relocs) + free (internal_relocs); return false; } @@ -2624,22 +2424,16 @@ mn10300_elf_relax_delete_bytes (abfd, sec, addr, count) int count; { Elf_Internal_Shdr *symtab_hdr; - Elf_Internal_Shdr *shndx_hdr; - Elf32_External_Sym *extsyms; unsigned int sec_shndx; bfd_byte *contents; Elf_Internal_Rela *irel, *irelend; Elf_Internal_Rela *irelalign; bfd_vma toaddr; - Elf32_External_Sym *esym, *esymend; - Elf_External_Sym_Shndx *shndx; + Elf_Internal_Sym *isym, *isymend; struct elf_link_hash_entry **sym_hashes; struct elf_link_hash_entry **end_hashes; unsigned int symcount; - symtab_hdr = &elf_tdata (abfd)->symtab_hdr; - extsyms = (Elf32_External_Sym *) symtab_hdr->contents; - sec_shndx = _bfd_elf_section_from_bfd_section (abfd, sec); contents = elf_section_data (sec)->this_hdr.contents; @@ -2668,25 +2462,14 @@ mn10300_elf_relax_delete_bytes (abfd, sec, addr, count) } /* Adjust the local symbols defined in this section. */ - shndx_hdr = &elf_tdata (abfd)->symtab_shndx_hdr; - shndx = (Elf_External_Sym_Shndx *) shndx_hdr->contents; - esym = extsyms; - esymend = esym + symtab_hdr->sh_info; - for (; esym < esymend; esym++, shndx = (shndx ? shndx + 1 : NULL)) + symtab_hdr = &elf_tdata (abfd)->symtab_hdr; + isym = (Elf_Internal_Sym *) symtab_hdr->contents; + for (isymend = isym + symtab_hdr->sh_info; isym < isymend; isym++) { - Elf_Internal_Sym isym; - Elf_External_Sym_Shndx dummy; - - bfd_elf32_swap_symbol_in (abfd, (const PTR) esym, (const PTR) shndx, - &isym); - - if (isym.st_shndx == sec_shndx - && isym.st_value > addr - && isym.st_value < toaddr) - { - isym.st_value -= count; - bfd_elf32_swap_symbol_out (abfd, &isym, (PTR) esym, (PTR) &dummy); - } + if (isym->st_shndx == sec_shndx + && isym->st_value > addr + && isym->st_value < toaddr) + isym->st_value -= count; } /* Now adjust the global symbols defined in this section. */ @@ -2713,16 +2496,15 @@ mn10300_elf_relax_delete_bytes (abfd, sec, addr, count) /* Return true if a symbol exists at the given address, else return false. */ static boolean -mn10300_elf_symbol_address_p (abfd, sec, addr) +mn10300_elf_symbol_address_p (abfd, sec, isym, addr) bfd *abfd; asection *sec; + Elf_Internal_Sym *isym; bfd_vma addr; { Elf_Internal_Shdr *symtab_hdr; - Elf_Internal_Shdr *shndx_hdr; unsigned int sec_shndx; - Elf32_External_Sym *esym, *esymend; - Elf_External_Sym_Shndx *shndx; + Elf_Internal_Sym *isymend; struct elf_link_hash_entry **sym_hashes; struct elf_link_hash_entry **end_hashes; unsigned int symcount; @@ -2731,19 +2513,10 @@ mn10300_elf_symbol_address_p (abfd, sec, addr) /* Examine all the symbols. */ symtab_hdr = &elf_tdata (abfd)->symtab_hdr; - shndx_hdr = &elf_tdata (abfd)->symtab_shndx_hdr; - shndx = (Elf_External_Sym_Shndx *) shndx_hdr->contents; - esym = (Elf32_External_Sym *) symtab_hdr->contents; - esymend = esym + symtab_hdr->sh_info; - for (; esym < esymend; esym++, shndx = (shndx ? shndx + 1 : NULL)) + for (isymend = isym + symtab_hdr->sh_info; isym < isymend; isym++) { - Elf_Internal_Sym isym; - - bfd_elf32_swap_symbol_in (abfd, (const PTR) esym, (const PTR) shndx, - &isym); - - if (isym.st_shndx == sec_shndx - && isym.st_value == addr) + if (isym->st_shndx == sec_shndx + && isym->st_value == addr) return true; } @@ -2778,15 +2551,11 @@ mn10300_elf_get_relocated_section_contents (output_bfd, link_info, link_order, asymbol **symbols; { Elf_Internal_Shdr *symtab_hdr; - Elf_Internal_Shdr *shndx_hdr; asection *input_section = link_order->u.indirect.section; bfd *input_bfd = input_section->owner; asection **sections = NULL; Elf_Internal_Rela *internal_relocs = NULL; - Elf32_External_Sym *external_syms = NULL; - Elf_External_Sym_Shndx *shndx_buf = NULL; - Elf_External_Sym_Shndx *shndx; - Elf_Internal_Sym *internal_syms = NULL; + Elf_Internal_Sym *isymbuf = NULL; /* We only need to handle the case of relaxing, or of having a particular set of section contents, specially. */ @@ -2798,7 +2567,6 @@ mn10300_elf_get_relocated_section_contents (output_bfd, link_info, link_order, symbols); symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr; - shndx_hdr = &elf_tdata (input_bfd)->symtab_shndx_hdr; memcpy (data, elf_section_data (input_section)->this_hdr.contents, (size_t) input_section->_raw_size); @@ -2806,48 +2574,26 @@ mn10300_elf_get_relocated_section_contents (output_bfd, link_info, link_order, if ((input_section->flags & SEC_RELOC) != 0 && input_section->reloc_count > 0) { - Elf_Internal_Sym *isymp; asection **secpp; - Elf32_External_Sym *esym, *esymend; + Elf_Internal_Sym *isym, *isymend; bfd_size_type amt; - if (symtab_hdr->contents != NULL) - external_syms = (Elf32_External_Sym *) symtab_hdr->contents; - else if (symtab_hdr->sh_info != 0) - { - amt = symtab_hdr->sh_info; - amt *= sizeof (Elf32_External_Sym); - external_syms = (Elf32_External_Sym *) bfd_malloc (amt); - if (external_syms == NULL) - goto error_return; - if (bfd_seek (input_bfd, symtab_hdr->sh_offset, SEEK_SET) != 0 - || bfd_bread ((PTR) external_syms, amt, input_bfd) != amt) - goto error_return; - } - - if (symtab_hdr->sh_info != 0 && shndx_hdr->sh_size != 0) - { - amt = symtab_hdr->sh_info; - amt *= sizeof (Elf_External_Sym_Shndx); - shndx_buf = (Elf_External_Sym_Shndx *) bfd_malloc (amt); - if (shndx_buf == NULL) - goto error_return; - if (bfd_seek (input_bfd, shndx_hdr->sh_offset, SEEK_SET) != 0 - || bfd_bread ((PTR) shndx_buf, amt, input_bfd) != amt) - goto error_return; - } - internal_relocs = (_bfd_elf32_link_read_relocs (input_bfd, input_section, (PTR) NULL, (Elf_Internal_Rela *) NULL, false)); if (internal_relocs == NULL) goto error_return; - amt = symtab_hdr->sh_info; - amt *= sizeof (Elf_Internal_Sym); - internal_syms = (Elf_Internal_Sym *) bfd_malloc (amt); - if (internal_syms == NULL && amt != 0) - goto error_return; + if (symtab_hdr->sh_info != 0) + { + isymbuf = (Elf_Internal_Sym *) symtab_hdr->contents; + if (isymbuf == NULL) + isymbuf = bfd_elf_get_elf_syms (input_bfd, symtab_hdr, + symtab_hdr->sh_info, 0, + NULL, NULL, NULL); + if (isymbuf == NULL) + goto error_return; + } amt = symtab_hdr->sh_info; amt *= sizeof (asection *); @@ -2855,41 +2601,32 @@ mn10300_elf_get_relocated_section_contents (output_bfd, link_info, link_order, if (sections == NULL && amt != 0) goto error_return; - for (isymp = internal_syms, secpp = sections, shndx = shndx_buf, - esym = external_syms, esymend = esym + symtab_hdr->sh_info; - esym < esymend; - ++esym, ++isymp, ++secpp, shndx = (shndx ? shndx + 1 : NULL)) + isymend = isymbuf + symtab_hdr->sh_info; + for (isym = isymbuf, secpp = sections; isym < isymend; ++isym, ++secpp) { asection *isec; - bfd_elf32_swap_symbol_in (input_bfd, (const PTR) esym, - (const PTR) shndx, isymp); - - if (isymp->st_shndx == SHN_UNDEF) + if (isym->st_shndx == SHN_UNDEF) isec = bfd_und_section_ptr; - else if (isymp->st_shndx == SHN_ABS) + else if (isym->st_shndx == SHN_ABS) isec = bfd_abs_section_ptr; - else if (isymp->st_shndx == SHN_COMMON) + else if (isym->st_shndx == SHN_COMMON) isec = bfd_com_section_ptr; else - isec = bfd_section_from_elf_index (input_bfd, isymp->st_shndx); + isec = bfd_section_from_elf_index (input_bfd, isym->st_shndx); *secpp = isec; } if (! mn10300_elf_relocate_section (output_bfd, link_info, input_bfd, input_section, data, internal_relocs, - internal_syms, sections)) + isymbuf, sections)) goto error_return; if (sections != NULL) free (sections); - if (internal_syms != NULL) - free (internal_syms); - if (shndx_buf != NULL) - free (shndx_buf); - if (external_syms != NULL && symtab_hdr->contents == NULL) - free (external_syms); + if (isymbuf != NULL && symtab_hdr->contents != (unsigned char *) isymbuf) + free (isymbuf); if (internal_relocs != elf_section_data (input_section)->relocs) free (internal_relocs); } @@ -2897,17 +2634,13 @@ mn10300_elf_get_relocated_section_contents (output_bfd, link_info, link_order, return data; error_return: + if (sections != NULL) + free (sections); + if (isymbuf != NULL && symtab_hdr->contents != (unsigned char *) isymbuf) + free (isymbuf); if (internal_relocs != NULL && internal_relocs != elf_section_data (input_section)->relocs) free (internal_relocs); - if (shndx_buf != NULL) - free (shndx_buf); - if (external_syms != NULL && symtab_hdr->contents == NULL) - free (external_syms); - if (internal_syms != NULL) - free (internal_syms); - if (sections != NULL) - free (sections); return NULL; } diff --git a/bfd/elf.c b/bfd/elf.c index 3188213d6d..b89882e9a0 100644 --- a/bfd/elf.c +++ b/bfd/elf.c @@ -352,6 +352,107 @@ bfd_elf_string_from_elf_section (abfd, shindex, strindex) return ((char *) hdr->contents) + strindex; } +/* Read and convert symbols to internal format. + SYMCOUNT specifies the number of symbols to read, starting from + symbol SYMOFFSET. If any of INTSYM_BUF, EXTSYM_BUF or EXTSHNDX_BUF + are non-NULL, they are used to store the internal symbols, external + symbols, and symbol section index extensions, respectively. */ + +Elf_Internal_Sym * +bfd_elf_get_elf_syms (ibfd, symtab_hdr, symcount, symoffset, + intsym_buf, extsym_buf, extshndx_buf) + bfd *ibfd; + Elf_Internal_Shdr *symtab_hdr; + size_t symcount; + size_t symoffset; + Elf_Internal_Sym *intsym_buf; + PTR extsym_buf; + Elf_External_Sym_Shndx *extshndx_buf; +{ + Elf_Internal_Shdr *shndx_hdr; + PTR alloc_ext; + const PTR esym; + Elf_External_Sym_Shndx *alloc_extshndx; + Elf_External_Sym_Shndx *shndx; + Elf_Internal_Sym *isym; + Elf_Internal_Sym *isymend; + struct elf_backend_data *bed; + size_t extsym_size; + bfd_size_type amt; + file_ptr pos; + + if (symcount == 0) + return intsym_buf; + + /* Normal syms might have section extension entries. */ + shndx_hdr = NULL; + if (symtab_hdr == &elf_tdata (ibfd)->symtab_hdr) + shndx_hdr = &elf_tdata (ibfd)->symtab_shndx_hdr; + + /* Read the symbols. */ + alloc_ext = NULL; + alloc_extshndx = NULL; + bed = get_elf_backend_data (ibfd); + extsym_size = bed->s->sizeof_sym; + amt = symcount * extsym_size; + pos = symtab_hdr->sh_offset + symoffset * extsym_size; + if (extsym_buf == NULL) + { + alloc_ext = bfd_malloc (amt); + extsym_buf = alloc_ext; + } + if (extsym_buf == NULL + || bfd_seek (ibfd, pos, SEEK_SET) != 0 + || bfd_bread (extsym_buf, amt, ibfd) != amt) + { + intsym_buf = NULL; + goto out; + } + + if (shndx_hdr == NULL || shndx_hdr->sh_size == 0) + extshndx_buf = NULL; + else + { + amt = symcount * sizeof (Elf_External_Sym_Shndx); + pos = shndx_hdr->sh_offset + symoffset * sizeof (Elf_External_Sym_Shndx); + if (extshndx_buf == NULL) + { + alloc_extshndx = (Elf_External_Sym_Shndx *) bfd_malloc (amt); + extshndx_buf = alloc_extshndx; + } + if (extshndx_buf == NULL + || bfd_seek (ibfd, pos, SEEK_SET) != 0 + || bfd_bread (extshndx_buf, amt, ibfd) != amt) + { + intsym_buf = NULL; + goto out; + } + } + + if (intsym_buf == NULL) + { + bfd_size_type amt = symcount * sizeof (Elf_Internal_Sym); + intsym_buf = (Elf_Internal_Sym *) bfd_malloc (amt); + if (intsym_buf == NULL) + goto out; + } + + /* Convert the symbols to internal form. */ + isymend = intsym_buf + symcount; + for (esym = extsym_buf, isym = intsym_buf, shndx = extshndx_buf; + isym < isymend; + esym += extsym_size, isym++, shndx = shndx != NULL ? shndx + 1 : NULL) + (*bed->s->swap_symbol_in) (ibfd, esym, (const PTR) shndx, isym); + + out: + if (alloc_ext != NULL) + free (alloc_ext); + if (alloc_extshndx != NULL) + free (alloc_extshndx); + + return intsym_buf; +} + /* Elf_Internal_Shdr->contents is an array of these for SHT_GROUP sections. The first element is the flags, the rest are section pointers. */ @@ -369,11 +470,7 @@ group_signature (abfd, ghdr) bfd *abfd; Elf_Internal_Shdr *ghdr; { - struct elf_backend_data *bed; - file_ptr pos; - bfd_size_type amt; Elf_Internal_Shdr *hdr; - Elf_Internal_Shdr *shndx_hdr; unsigned char esym[sizeof (Elf64_External_Sym)]; Elf_External_Sym_Shndx eshndx; Elf_Internal_Sym isym; @@ -386,29 +483,10 @@ group_signature (abfd, ghdr) /* Go read the symbol. */ hdr = &elf_tdata (abfd)->symtab_hdr; - bed = get_elf_backend_data (abfd); - amt = bed->s->sizeof_sym; - pos = hdr->sh_offset + ghdr->sh_info * amt; - if (bfd_seek (abfd, pos, SEEK_SET) != 0 - || bfd_bread (esym, amt, abfd) != amt) + if (bfd_elf_get_elf_syms (abfd, hdr, 1, ghdr->sh_info, + &isym, esym, &eshndx) == NULL) return NULL; - /* And possibly the symbol section index extension. */ - shndx_hdr = &elf_tdata (abfd)->symtab_shndx_hdr; - if (elf_elfsections (abfd) != NULL - && elf_elfsections (abfd)[shndx_hdr->sh_link] == hdr) - { - amt = sizeof (Elf_External_Sym_Shndx); - pos = shndx_hdr->sh_offset + ghdr->sh_info * amt; - if (bfd_seek (abfd, pos, SEEK_SET) != 0 - || bfd_bread ((PTR) &eshndx, amt, abfd) != amt) - return NULL; - } - - /* Convert to internal format. */ - (*bed->s->swap_symbol_in) (abfd, (const PTR *) &esym, (const PTR *) &eshndx, - &isym); - /* Look up the symbol name. */ iname = isym.st_name; shindex = hdr->sh_link; @@ -1976,50 +2054,19 @@ bfd_section_from_r_symndx (abfd, cache, sec, r_symndx) asection *sec; unsigned long r_symndx; { - unsigned char esym_shndx[4]; - unsigned int isym_shndx; Elf_Internal_Shdr *symtab_hdr; - file_ptr pos; - bfd_size_type amt; + unsigned char esym[sizeof (Elf64_External_Sym)]; + Elf_External_Sym_Shndx eshndx; + Elf_Internal_Sym isym; unsigned int ent = r_symndx % LOCAL_SYM_CACHE_SIZE; if (cache->abfd == abfd && cache->indx[ent] == r_symndx) return cache->sec[ent]; symtab_hdr = &elf_tdata (abfd)->symtab_hdr; - pos = symtab_hdr->sh_offset; - if (get_elf_backend_data (abfd)->s->sizeof_sym - == sizeof (Elf64_External_Sym)) - { - pos += r_symndx * sizeof (Elf64_External_Sym); - pos += offsetof (Elf64_External_Sym, st_shndx); - amt = sizeof (((Elf64_External_Sym *) 0)->st_shndx); - } - else - { - pos += r_symndx * sizeof (Elf32_External_Sym); - pos += offsetof (Elf32_External_Sym, st_shndx); - amt = sizeof (((Elf32_External_Sym *) 0)->st_shndx); - } - if (bfd_seek (abfd, pos, SEEK_SET) != 0 - || bfd_bread ((PTR) esym_shndx, amt, abfd) != amt) + if (bfd_elf_get_elf_syms (abfd, symtab_hdr, 1, r_symndx, + &isym, esym, &eshndx) == NULL) return NULL; - isym_shndx = H_GET_16 (abfd, esym_shndx); - - if (isym_shndx == SHN_XINDEX) - { - Elf_Internal_Shdr *shndx_hdr = &elf_tdata (abfd)->symtab_shndx_hdr; - if (shndx_hdr->sh_size != 0) - { - pos = shndx_hdr->sh_offset; - pos += r_symndx * sizeof (Elf_External_Sym_Shndx); - amt = sizeof (Elf_External_Sym_Shndx); - if (bfd_seek (abfd, pos, SEEK_SET) != 0 - || bfd_bread ((PTR) esym_shndx, amt, abfd) != amt) - return NULL; - isym_shndx = H_GET_32 (abfd, esym_shndx); - } - } if (cache->abfd != abfd) { @@ -2028,10 +2075,10 @@ bfd_section_from_r_symndx (abfd, cache, sec, r_symndx) } cache->indx[ent] = r_symndx; cache->sec[ent] = sec; - if (isym_shndx < SHN_LORESERVE || isym_shndx > SHN_HIRESERVE) + if (isym.st_shndx < SHN_LORESERVE || isym.st_shndx > SHN_HIRESERVE) { asection *s; - s = bfd_section_from_elf_index (abfd, isym_shndx); + s = bfd_section_from_elf_index (abfd, isym.st_shndx); if (s != NULL) cache->sec[ent] = s; } diff --git a/bfd/elf32-arm.h b/bfd/elf32-arm.h index d1b8fa7926..39b1d248a0 100644 --- a/bfd/elf32-arm.h +++ b/bfd/elf32-arm.h @@ -639,12 +639,9 @@ bfd_elf32_arm_process_before_allocation (abfd, link_info, no_pipeline_knowledge) int no_pipeline_knowledge; { Elf_Internal_Shdr *symtab_hdr; - Elf_Internal_Rela *free_relocs = NULL; + Elf_Internal_Rela *internal_relocs = NULL; Elf_Internal_Rela *irel, *irelend; bfd_byte *contents = NULL; - bfd_byte *free_contents = NULL; - Elf32_External_Sym *extsyms = NULL; - Elf32_External_Sym *free_extsyms = NULL; asection *sec; struct elf32_arm_link_hash_table *globals; @@ -677,13 +674,15 @@ bfd_elf32_arm_process_before_allocation (abfd, link_info, no_pipeline_knowledge) symtab_hdr = &elf_tdata (abfd)->symtab_hdr; /* Load the relocs. */ - irel = (_bfd_elf32_link_read_relocs (abfd, sec, (PTR) NULL, - (Elf_Internal_Rela *) NULL, false)); + internal_relocs + = _bfd_elf32_link_read_relocs (abfd, sec, (PTR) NULL, + (Elf_Internal_Rela *) NULL, false); - BFD_ASSERT (irel != 0); + if (internal_relocs == NULL) + goto error_return; - irelend = irel + sec->reloc_count; - for (; irel < irelend; irel++) + irelend = internal_relocs + sec->reloc_count; + for (irel = internal_relocs; irel < irelend; irel++) { long r_type; unsigned long r_index; @@ -711,37 +710,12 @@ bfd_elf32_arm_process_before_allocation (abfd, link_info, no_pipeline_knowledge) if (contents == NULL) goto error_return; - free_contents = contents; - if (!bfd_get_section_contents (abfd, sec, contents, (file_ptr) 0, sec->_raw_size)) goto error_return; } } - /* Read this BFD's symbols if we haven't done so already. */ - if (extsyms == NULL) - { - /* Get cached copy if it exists. */ - if (symtab_hdr->contents != NULL) - extsyms = (Elf32_External_Sym *) symtab_hdr->contents; - else - { - /* Go get them off disk. */ - extsyms = ((Elf32_External_Sym *) - bfd_malloc (symtab_hdr->sh_size)); - if (extsyms == NULL) - goto error_return; - - free_extsyms = extsyms; - - if (bfd_seek (abfd, symtab_hdr->sh_offset, SEEK_SET) != 0 - || (bfd_bread (extsyms, symtab_hdr->sh_size, abfd) - != symtab_hdr->sh_size)) - goto error_return; - } - } - /* If the relocation is not against a symbol it cannot concern us. */ h = NULL; @@ -781,17 +755,27 @@ bfd_elf32_arm_process_before_allocation (abfd, link_info, no_pipeline_knowledge) break; } } + + if (contents != NULL + && elf_section_data (sec)->this_hdr.contents != contents) + free (contents); + contents = NULL; + + if (internal_relocs != NULL + && elf_section_data (sec)->relocs != internal_relocs) + free (internal_relocs); + internal_relocs = NULL; } return true; error_return: - if (free_relocs != NULL) - free (free_relocs); - if (free_contents != NULL) - free (free_contents); - if (free_extsyms != NULL) - free (free_extsyms); + if (contents != NULL + && elf_section_data (sec)->this_hdr.contents != contents) + free (contents); + if (internal_relocs != NULL + && elf_section_data (sec)->relocs != internal_relocs) + free (internal_relocs); return false; } diff --git a/bfd/elf32-h8300.c b/bfd/elf32-h8300.c index 1a841a7e74..0c7be53367 100644 --- a/bfd/elf32-h8300.c +++ b/bfd/elf32-h8300.c @@ -688,15 +688,10 @@ elf32_h8_relax_section (abfd, sec, link_info, again) boolean *again; { Elf_Internal_Shdr *symtab_hdr; - Elf_Internal_Shdr *shndx_hdr; Elf_Internal_Rela *internal_relocs; - Elf_Internal_Rela *free_relocs = NULL; Elf_Internal_Rela *irel, *irelend; bfd_byte *contents = NULL; - bfd_byte *free_contents = NULL; - Elf32_External_Sym *extsyms = NULL; - Elf32_External_Sym *free_extsyms = NULL; - Elf_External_Sym_Shndx *shndx_buf = NULL; + Elf_Internal_Sym *isymbuf = NULL; static asection *last_input_section = NULL; static Elf_Internal_Rela *last_reloc = NULL; @@ -718,7 +713,6 @@ elf32_h8_relax_section (abfd, sec, link_info, again) sec->_cooked_size = sec->_raw_size; symtab_hdr = &elf_tdata (abfd)->symtab_hdr; - shndx_hdr = &elf_tdata (abfd)->symtab_shndx_hdr; /* Get a copy of the native relocations. */ internal_relocs = (_bfd_elf32_link_read_relocs @@ -726,8 +720,6 @@ elf32_h8_relax_section (abfd, sec, link_info, again) link_info->keep_memory)); if (internal_relocs == NULL) goto error_return; - if (! link_info->keep_memory) - free_relocs = internal_relocs; if (sec != last_input_section) last_reloc = NULL; @@ -764,7 +756,6 @@ elf32_h8_relax_section (abfd, sec, link_info, again) contents = (bfd_byte *) bfd_malloc (sec->_raw_size); if (contents == NULL) goto error_return; - free_contents = contents; if (! bfd_get_section_contents (abfd, sec, contents, (file_ptr) 0, sec->_raw_size)) @@ -773,58 +764,27 @@ elf32_h8_relax_section (abfd, sec, link_info, again) } /* Read this BFD's local symbols if we haven't done so already. */ - if (extsyms == NULL) + if (isymbuf == NULL && symtab_hdr->sh_info != 0) { - /* Get cached copy if it exists. */ - if (symtab_hdr->contents != NULL) - extsyms = (Elf32_External_Sym *) symtab_hdr->contents; - else - { - /* Go get them off disk. */ - bfd_size_type amt; - - amt = symtab_hdr->sh_info * sizeof (Elf32_External_Sym); - extsyms = (Elf32_External_Sym *) bfd_malloc (amt); - if (extsyms == NULL) - goto error_return; - free_extsyms = extsyms; - if (bfd_seek (abfd, symtab_hdr->sh_offset, SEEK_SET) != 0 - || bfd_bread ((PTR) extsyms, amt, abfd) != amt) - goto error_return; - symtab_hdr->contents = (PTR) extsyms; - } - - if (shndx_hdr->sh_size != 0) - { - bfd_size_type amt; - - amt = symtab_hdr->sh_info * sizeof (Elf_External_Sym_Shndx); - shndx_buf = (Elf_External_Sym_Shndx *) bfd_malloc (amt); - if (shndx_buf == NULL) - goto error_return; - if (bfd_seek (abfd, shndx_hdr->sh_offset, SEEK_SET) != 0 - || bfd_bread ((PTR) shndx_buf, amt, abfd) != amt) - goto error_return; - shndx_hdr->contents = (PTR) shndx_buf; - } + isymbuf = (Elf_Internal_Sym *) symtab_hdr->contents; + if (isymbuf == NULL) + isymbuf = bfd_elf_get_elf_syms (abfd, symtab_hdr, + symtab_hdr->sh_info, 0, + NULL, NULL, NULL); + if (isymbuf == NULL) + goto error_return; } /* Get the value of the symbol referred to by the reloc. */ if (ELF32_R_SYM (irel->r_info) < symtab_hdr->sh_info) { - Elf32_External_Sym *esym; - Elf_External_Sym_Shndx *shndx; - Elf_Internal_Sym isym; + /* A local symbol. */ + Elf_Internal_Sym *isym; asection *sym_sec; - /* A local symbol. */ - esym = extsyms + ELF32_R_SYM (irel->r_info); - shndx = shndx_buf + (shndx_buf ? ELF32_R_SYM (irel->r_info) : 0); - bfd_elf32_swap_symbol_in (abfd, (const PTR) esym, (const PTR) shndx, - &isym); - - sym_sec = bfd_section_from_elf_index (abfd, isym.st_shndx); - symval = (isym.st_value + isym = isymbuf + ELF64_R_SYM (irel->r_info); + sym_sec = bfd_section_from_elf_index (abfd, isym->st_shndx); + symval = (isym->st_value + sym_sec->output_section->vma + sym_sec->output_offset); } @@ -884,12 +844,8 @@ elf32_h8_relax_section (abfd, sec, link_info, again) /* Note that we've changed the relocs, section contents, etc. */ elf_section_data (sec)->relocs = internal_relocs; - free_relocs = NULL; - elf_section_data (sec)->this_hdr.contents = contents; - free_contents = NULL; - - free_extsyms = NULL; + symtab_hdr->contents = (unsigned char *) isymbuf; /* If the previous instruction conditionally jumped around this instruction, we may be able to reverse the condition @@ -904,26 +860,17 @@ elf32_h8_relax_section (abfd, sec, link_info, again) && ELF32_R_TYPE (last_reloc->r_info) == R_H8_PCREL8 && ELF32_R_SYM (last_reloc->r_info) < symtab_hdr->sh_info) { - Elf32_External_Sym *esym; - Elf_External_Sym_Shndx *shndx; bfd_vma last_value; asection *last_sym_sec; - Elf_Internal_Sym last_symbol; + Elf_Internal_Sym *last_sym; /* We will need to examine the symbol used by the previous relocation. */ - esym = extsyms + ELF32_R_SYM (last_reloc->r_info); - shndx = shndx_buf; - if (shndx != NULL) - shndx += ELF32_R_SYM (last_reloc->r_info); - bfd_elf32_swap_symbol_in (abfd, (const PTR) esym, - (const PTR) shndx, - &last_symbol); - + last_sym = isymbuf + ELF32_R_SYM (last_reloc->r_info); last_sym_sec - = bfd_section_from_elf_index (abfd, last_symbol.st_shndx); - last_value = (last_symbol.st_value + = bfd_section_from_elf_index (abfd, last_sym->st_shndx); + last_value = (last_sym->st_value + last_sym_sec->output_section->vma + last_sym_sec->output_offset); @@ -1015,12 +962,8 @@ elf32_h8_relax_section (abfd, sec, link_info, again) /* Note that we've changed the relocs, section contents, etc. */ elf_section_data (sec)->relocs = internal_relocs; - free_relocs = NULL; - elf_section_data (sec)->this_hdr.contents = contents; - free_contents = NULL; - - free_extsyms = NULL; + symtab_hdr->contents = (unsigned char *) isymbuf; /* Get the opcode. */ code = bfd_get_8 (abfd, contents + irel->r_offset - 2); @@ -1076,12 +1019,8 @@ elf32_h8_relax_section (abfd, sec, link_info, again) /* Note that we've changed the relocs, section contents, etc. */ elf_section_data (sec)->relocs = internal_relocs; - free_relocs = NULL; - elf_section_data (sec)->this_hdr.contents = contents; - free_contents = NULL; - - free_extsyms = NULL; + symtab_hdr->contents = (unsigned char *) isymbuf; /* Get the opcode. */ code = bfd_get_8 (abfd, contents + irel->r_offset - 2); @@ -1138,12 +1077,8 @@ elf32_h8_relax_section (abfd, sec, link_info, again) /* Note that we've changed the relocs, section contents, etc. */ elf_section_data (sec)->relocs = internal_relocs; - free_relocs = NULL; - elf_section_data (sec)->this_hdr.contents = contents; - free_contents = NULL; - - free_extsyms = NULL; + symtab_hdr->contents = (unsigned char *) isymbuf; /* Get the opcode. */ code = bfd_get_8 (abfd, contents + irel->r_offset - 2); @@ -1194,12 +1129,8 @@ elf32_h8_relax_section (abfd, sec, link_info, again) /* Note that we've changed the relocs, section contents, etc. */ elf_section_data (sec)->relocs = internal_relocs; - free_relocs = NULL; - elf_section_data (sec)->this_hdr.contents = contents; - free_contents = NULL; - - free_extsyms = NULL; + symtab_hdr->contents = (unsigned char *) isymbuf; /* Get the opcode. */ code = bfd_get_8 (abfd, contents + irel->r_offset - 1); @@ -1230,56 +1161,43 @@ elf32_h8_relax_section (abfd, sec, link_info, again) } } - if (free_relocs != NULL) - { - free (free_relocs); - free_relocs = NULL; - } - - if (free_contents != NULL) + if (isymbuf != NULL + && symtab_hdr->contents != (unsigned char *) isymbuf) { if (! link_info->keep_memory) - free (free_contents); + free (isymbuf); + else + symtab_hdr->contents = (unsigned char *) isymbuf; + } + + if (contents != NULL + && elf_section_data (sec)->this_hdr.contents != contents) + { + if (! link_info->keep_memory) + free (contents); else { /* Cache the section contents for elf_link_input_bfd. */ elf_section_data (sec)->this_hdr.contents = contents; } - free_contents = NULL; } - if (shndx_buf != NULL) - { - shndx_hdr->contents = NULL; - free (shndx_buf); - } - - if (free_extsyms != NULL) - { - if (! link_info->keep_memory) - { - symtab_hdr->contents = NULL; - free (free_extsyms); - } - } + if (internal_relocs != NULL + && elf_section_data (sec)->relocs != internal_relocs) + free (internal_relocs); return true; error_return: - if (free_relocs != NULL) - free (free_relocs); - if (free_contents != NULL) - free (free_contents); - if (shndx_buf != NULL) - { - shndx_hdr->contents = NULL; - free (shndx_buf); - } - if (free_extsyms != NULL) - { - symtab_hdr->contents = NULL; - free (free_extsyms); - } + if (isymbuf != NULL + && symtab_hdr->contents != (unsigned char *) isymbuf) + free (isymbuf); + if (contents != NULL + && elf_section_data (sec)->this_hdr.contents != contents) + free (contents); + if (internal_relocs != NULL + && elf_section_data (sec)->relocs != internal_relocs) + free (internal_relocs); return false; } @@ -1293,22 +1211,17 @@ elf32_h8_relax_delete_bytes (abfd, sec, addr, count) int count; { Elf_Internal_Shdr *symtab_hdr; - Elf_Internal_Shdr *shndx_hdr; - Elf32_External_Sym *extsyms; unsigned int sec_shndx; bfd_byte *contents; Elf_Internal_Rela *irel, *irelend; Elf_Internal_Rela *irelalign; + Elf_Internal_Sym *isym; + Elf_Internal_Sym *isymend; bfd_vma toaddr; - Elf32_External_Sym *esym, *esymend; - Elf_External_Sym_Shndx *shndx; struct elf_link_hash_entry **sym_hashes; struct elf_link_hash_entry **end_hashes; unsigned int symcount; - symtab_hdr = &elf_tdata (abfd)->symtab_hdr; - extsyms = (Elf32_External_Sym *) symtab_hdr->contents; - sec_shndx = _bfd_elf_section_from_bfd_section (abfd, sec); contents = elf_section_data (sec)->this_hdr.contents; @@ -1337,25 +1250,15 @@ elf32_h8_relax_delete_bytes (abfd, sec, addr, count) } /* Adjust the local symbols defined in this section. */ - shndx_hdr = &elf_tdata (abfd)->symtab_shndx_hdr; - shndx = (Elf_External_Sym_Shndx *) shndx_hdr->contents; - esym = extsyms; - esymend = esym + symtab_hdr->sh_info; - for (; esym < esymend; esym++, shndx = (shndx ? shndx + 1 : NULL)) + symtab_hdr = &elf_tdata (abfd)->symtab_hdr; + isym = (Elf_Internal_Sym *) symtab_hdr->contents; + isymend = isym + symtab_hdr->sh_info; + for (; isym < isymend; isym++) { - Elf_Internal_Sym isym; - Elf_External_Sym_Shndx dummy; - - bfd_elf32_swap_symbol_in (abfd, (const PTR) esym, (const PTR) shndx, - &isym); - - if (isym.st_shndx == sec_shndx - && isym.st_value > addr - && isym.st_value < toaddr) - { - isym.st_value -= count; - bfd_elf32_swap_symbol_out (abfd, &isym, esym, &dummy); - } + if (isym->st_shndx == sec_shndx + && isym->st_value > addr + && isym->st_value < toaddr) + isym->st_value -= count; } /* Now adjust the global symbols defined in this section. */ @@ -1388,10 +1291,9 @@ elf32_h8_symbol_address_p (abfd, sec, addr) bfd_vma addr; { Elf_Internal_Shdr *symtab_hdr; - Elf_Internal_Shdr *shndx_hdr; unsigned int sec_shndx; - Elf32_External_Sym *esym, *esymend; - Elf_External_Sym_Shndx *shndx; + Elf_Internal_Sym *isym; + Elf_Internal_Sym *isymend; struct elf_link_hash_entry **sym_hashes; struct elf_link_hash_entry **end_hashes; unsigned int symcount; @@ -1400,19 +1302,12 @@ elf32_h8_symbol_address_p (abfd, sec, addr) /* Examine all the symbols. */ symtab_hdr = &elf_tdata (abfd)->symtab_hdr; - shndx_hdr = &elf_tdata (abfd)->symtab_shndx_hdr; - shndx = (Elf_External_Sym_Shndx *) shndx_hdr->contents; - esym = (Elf32_External_Sym *) symtab_hdr->contents; - esymend = esym + symtab_hdr->sh_info; - for (; esym < esymend; esym++, shndx = (shndx ? shndx + 1 : NULL)) + isym = (Elf_Internal_Sym *) symtab_hdr->contents; + isymend = isym + symtab_hdr->sh_info; + for (; isym < isymend; isym++) { - Elf_Internal_Sym isym; - - bfd_elf32_swap_symbol_in (abfd, (const PTR) esym, (const PTR) shndx, - &isym); - - if (isym.st_shndx == sec_shndx - && isym.st_value == addr) + if (isym->st_shndx == sec_shndx + && isym->st_value == addr) return true; } @@ -1447,15 +1342,11 @@ elf32_h8_get_relocated_section_contents (output_bfd, link_info, link_order, asymbol **symbols; { Elf_Internal_Shdr *symtab_hdr; - Elf_Internal_Shdr *shndx_hdr; asection *input_section = link_order->u.indirect.section; bfd *input_bfd = input_section->owner; asection **sections = NULL; Elf_Internal_Rela *internal_relocs = NULL; - Elf32_External_Sym *external_syms = NULL; - Elf_External_Sym_Shndx *shndx_buf = NULL; - Elf_External_Sym_Shndx *shndx; - Elf_Internal_Sym *internal_syms = NULL; + Elf_Internal_Sym *isymbuf = NULL; /* We only need to handle the case of relaxing, or of having a particular set of section contents, specially. */ @@ -1467,7 +1358,6 @@ elf32_h8_get_relocated_section_contents (output_bfd, link_info, link_order, symbols); symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr; - shndx_hdr = &elf_tdata (input_bfd)->symtab_shndx_hdr; memcpy (data, elf_section_data (input_section)->this_hdr.contents, (size_t) input_section->_raw_size); @@ -1475,48 +1365,26 @@ elf32_h8_get_relocated_section_contents (output_bfd, link_info, link_order, if ((input_section->flags & SEC_RELOC) != 0 && input_section->reloc_count > 0) { - Elf_Internal_Sym *isymp; asection **secpp; - Elf32_External_Sym *esym, *esymend; + Elf_Internal_Sym *isym, *isymend; bfd_size_type amt; - if (symtab_hdr->contents != NULL) - external_syms = (Elf32_External_Sym *) symtab_hdr->contents; - else if (symtab_hdr->sh_info != 0) - { - amt = symtab_hdr->sh_info; - amt *= sizeof (Elf32_External_Sym); - external_syms = (Elf32_External_Sym *) bfd_malloc (amt); - if (external_syms == NULL) - goto error_return; - if (bfd_seek (input_bfd, symtab_hdr->sh_offset, SEEK_SET) != 0 - || bfd_bread ((PTR) external_syms, amt, input_bfd) != amt) - goto error_return; - } - - if (symtab_hdr->sh_info != 0 && shndx_hdr->sh_size != 0) - { - amt = symtab_hdr->sh_info; - amt *= sizeof (Elf_External_Sym_Shndx); - shndx_buf = (Elf_External_Sym_Shndx *) bfd_malloc (amt); - if (shndx_buf == NULL) - goto error_return; - if (bfd_seek (input_bfd, shndx_hdr->sh_offset, SEEK_SET) != 0 - || bfd_bread ((PTR) shndx_buf, amt, input_bfd) != amt) - goto error_return; - } - internal_relocs = (_bfd_elf32_link_read_relocs (input_bfd, input_section, (PTR) NULL, (Elf_Internal_Rela *) NULL, false)); if (internal_relocs == NULL) goto error_return; - amt = symtab_hdr->sh_info; - amt *= sizeof (Elf_Internal_Sym); - internal_syms = (Elf_Internal_Sym *) bfd_malloc (amt); - if (internal_syms == NULL && amt != 0) - goto error_return; + if (symtab_hdr->sh_info != 0) + { + isymbuf = (Elf_Internal_Sym *) symtab_hdr->contents; + if (isymbuf == NULL) + isymbuf = bfd_elf_get_elf_syms (input_bfd, symtab_hdr, + symtab_hdr->sh_info, 0, + NULL, NULL, NULL); + if (isymbuf == NULL) + goto error_return; + } amt = symtab_hdr->sh_info; amt *= sizeof (asection *); @@ -1524,59 +1392,48 @@ elf32_h8_get_relocated_section_contents (output_bfd, link_info, link_order, if (sections == NULL && amt != 0) goto error_return; - for (isymp = internal_syms, secpp = sections, shndx = shndx_buf, - esym = external_syms, esymend = esym + symtab_hdr->sh_info; - esym < esymend; - ++esym, ++isymp, ++secpp, shndx = (shndx ? shndx + 1 : NULL)) + isymend = isymbuf + symtab_hdr->sh_info; + for (isym = isymbuf, secpp = sections; isym < isymend; ++isym, ++secpp) { asection *isec; - bfd_elf32_swap_symbol_in (input_bfd, (const PTR) esym, - (const PTR) shndx, isymp); - - if (isymp->st_shndx == SHN_UNDEF) + if (isym->st_shndx == SHN_UNDEF) isec = bfd_und_section_ptr; - else if (isymp->st_shndx == SHN_ABS) + else if (isym->st_shndx == SHN_ABS) isec = bfd_abs_section_ptr; - else if (isymp->st_shndx == SHN_COMMON) + else if (isym->st_shndx == SHN_COMMON) isec = bfd_com_section_ptr; else - isec = bfd_section_from_elf_index (input_bfd, isymp->st_shndx); + isec = bfd_section_from_elf_index (input_bfd, isym->st_shndx); *secpp = isec; } if (! elf32_h8_relocate_section (output_bfd, link_info, input_bfd, input_section, data, internal_relocs, - internal_syms, sections)) + isymbuf, sections)) goto error_return; if (sections != NULL) free (sections); - if (internal_syms != NULL) - free (internal_syms); - if (shndx_buf != NULL) - free (shndx_buf); - if (external_syms != NULL && symtab_hdr->contents == NULL) - free (external_syms); - if (internal_relocs != elf_section_data (input_section)->relocs) + if (isymbuf != NULL + && symtab_hdr->contents != (unsigned char *) isymbuf) + free (isymbuf); + if (elf_section_data (input_section)->relocs != internal_relocs) free (internal_relocs); } return data; error_return: - if (internal_relocs != NULL - && internal_relocs != elf_section_data (input_section)->relocs) - free (internal_relocs); - if (shndx_buf != NULL) - free (shndx_buf); - if (external_syms != NULL && symtab_hdr->contents == NULL) - free (external_syms); - if (internal_syms != NULL) - free (internal_syms); if (sections != NULL) free (sections); + if (isymbuf != NULL + && symtab_hdr->contents != (unsigned char *) isymbuf) + free (isymbuf); + if (internal_relocs != NULL + && elf_section_data (input_section)->relocs != internal_relocs) + free (internal_relocs); return NULL; } diff --git a/bfd/elf32-hppa.c b/bfd/elf32-hppa.c index 8bea3c67d1..7a244eca30 100644 --- a/bfd/elf32-hppa.c +++ b/bfd/elf32-hppa.c @@ -2770,69 +2770,26 @@ get_local_syms (output_bfd, input_bfd, info) input_bfd = input_bfd->link_next, bfd_indx++) { Elf_Internal_Shdr *symtab_hdr; - Elf_Internal_Shdr *shndx_hdr; - Elf_Internal_Sym *isym; - Elf32_External_Sym *ext_syms, *esym, *end_sy; - Elf_External_Sym_Shndx *shndx_buf, *shndx; - bfd_size_type sec_size; /* We'll need the symbol table in a second. */ symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr; if (symtab_hdr->sh_info == 0) continue; - /* We need an array of the local symbols attached to the input bfd. - Unfortunately, we're going to have to read & swap them in. */ - sec_size = symtab_hdr->sh_info; - sec_size *= sizeof (Elf_Internal_Sym); - local_syms = (Elf_Internal_Sym *) bfd_malloc (sec_size); + /* We need an array of the local symbols attached to the input bfd. */ + local_syms = (Elf_Internal_Sym *) symtab_hdr->contents; + if (local_syms == NULL) + { + local_syms = bfd_elf_get_elf_syms (input_bfd, symtab_hdr, + symtab_hdr->sh_info, 0, + NULL, NULL, NULL); + /* Cache them for elf_link_input_bfd. */ + symtab_hdr->contents = (unsigned char *) local_syms; + } if (local_syms == NULL) return -1; all_local_syms[bfd_indx] = local_syms; - sec_size = symtab_hdr->sh_info; - sec_size *= sizeof (Elf32_External_Sym); - ext_syms = (Elf32_External_Sym *) bfd_malloc (sec_size); - if (ext_syms == NULL) - return -1; - - if (bfd_seek (input_bfd, symtab_hdr->sh_offset, SEEK_SET) != 0 - || bfd_bread ((PTR) ext_syms, sec_size, input_bfd) != sec_size) - { - error_ret_free_ext_syms: - free (ext_syms); - return -1; - } - - shndx_buf = NULL; - shndx_hdr = &elf_tdata (input_bfd)->symtab_shndx_hdr; - if (shndx_hdr->sh_size != 0) - { - sec_size = symtab_hdr->sh_info; - sec_size *= sizeof (Elf_External_Sym_Shndx); - shndx_buf = (Elf_External_Sym_Shndx *) bfd_malloc (sec_size); - if (shndx_buf == NULL) - goto error_ret_free_ext_syms; - - if (bfd_seek (input_bfd, shndx_hdr->sh_offset, SEEK_SET) != 0 - || bfd_bread ((PTR) shndx_buf, sec_size, input_bfd) != sec_size) - { - free (shndx_buf); - goto error_ret_free_ext_syms; - } - } - - /* Swap the local symbols in. */ - for (esym = ext_syms, end_sy = esym + symtab_hdr->sh_info, - isym = local_syms, shndx = shndx_buf; - esym < end_sy; - esym++, isym++, shndx = (shndx ? shndx + 1 : NULL)) - bfd_elf32_swap_symbol_in (input_bfd, (const PTR) esym, - (const PTR) shndx, isym); - - /* Now we can free the external symbols. */ - free (shndx_buf); - free (ext_syms); if (info->shared && htab->multi_subspace) { @@ -2927,7 +2884,6 @@ elf32_hppa_size_stubs (output_bfd, stub_bfd, info, multi_subspace, group_size, bfd_size_type stub_group_size; boolean stubs_always_before_branch; boolean stub_changed; - boolean ret = 0; struct elf32_hppa_link_hash_table *htab = hppa_link_hash_table (info); /* Stash our params away. */ @@ -3186,15 +3142,12 @@ elf32_hppa_size_stubs (output_bfd, stub_bfd, info, multi_subspace, group_size, stub_changed = false; } - ret = true; + free (htab->all_local_syms); + return true; error_ret_free_local: - while (htab->bfd_count-- > 0) - if (htab->all_local_syms[htab->bfd_count]) - free (htab->all_local_syms[htab->bfd_count]); free (htab->all_local_syms); - - return ret; + return false; } /* For a final link, this function is called after we have sized the diff --git a/bfd/elf32-m32r.c b/bfd/elf32-m32r.c index b3f87367b7..56c3f04746 100644 --- a/bfd/elf32-m32r.c +++ b/bfd/elf32-m32r.c @@ -1337,13 +1337,10 @@ m32r_elf_relax_section (abfd, sec, link_info, again) /* The Rela structures are used here because that's what _bfd_elf32_link_read_relocs uses [for convenience - it sets the addend field to 0]. */ - Elf_Internal_Rela *internal_relocs; - Elf_Internal_Rela *free_relocs = NULL; + Elf_Internal_Rela *internal_relocs = NULL; Elf_Internal_Rela *irel, *irelend; bfd_byte *contents = NULL; - bfd_byte *free_contents = NULL; - Elf32_External_Sym *extsyms = NULL; - Elf32_External_Sym *free_extsyms = NULL; + Elf_Internal_Sym *isymbuf = NULL; /* Assume nothing changes. */ *again = false; @@ -1371,8 +1368,6 @@ m32r_elf_relax_section (abfd, sec, link_info, again) link_info->keep_memory)); if (internal_relocs == NULL) goto error_return; - if (! link_info->keep_memory) - free_relocs = internal_relocs; /* Walk through them looking for relaxing opportunities. */ irelend = internal_relocs + sec->reloc_count; @@ -1397,7 +1392,6 @@ m32r_elf_relax_section (abfd, sec, link_info, again) contents = (bfd_byte *) bfd_malloc (sec->_raw_size); if (contents == NULL) goto error_return; - free_contents = contents; if (! bfd_get_section_contents (abfd, sec, contents, (file_ptr) 0, sec->_raw_size)) @@ -1405,39 +1399,28 @@ m32r_elf_relax_section (abfd, sec, link_info, again) } } - /* Read this BFD's symbols if we haven't done so already. */ - if (extsyms == NULL) + /* Read this BFD's local symbols if we haven't done so already. */ + if (isymbuf == NULL && symtab_hdr->sh_info != 0) { - /* Get cached copy if it exists. */ - if (symtab_hdr->contents != NULL) - extsyms = (Elf32_External_Sym *) symtab_hdr->contents; - else - { - bfd_size_type amt = symtab_hdr->sh_size; - /* Go get them off disk. */ - extsyms = (Elf32_External_Sym *) bfd_malloc (amt); - if (extsyms == NULL) - goto error_return; - free_extsyms = extsyms; - if (bfd_seek (abfd, symtab_hdr->sh_offset, SEEK_SET) != 0 - || bfd_bread (extsyms, amt, abfd) != amt) - goto error_return; - } + isymbuf = (Elf_Internal_Sym *) symtab_hdr->contents; + if (isymbuf == NULL) + isymbuf = bfd_elf_get_elf_syms (abfd, symtab_hdr, + symtab_hdr->sh_info, 0, + NULL, NULL, NULL); + if (isymbuf == NULL) + goto error_return; } /* Get the value of the symbol referred to by the reloc. */ if (ELF32_R_SYM (irel->r_info) < symtab_hdr->sh_info) { - Elf_Internal_Sym isym; + /* A local symbol. */ + Elf_Internal_Sym *isym; asection *sym_sec; - /* A local symbol. */ - bfd_elf32_swap_symbol_in (abfd, - extsyms + ELF32_R_SYM (irel->r_info), - &isym); - - sym_sec = bfd_section_from_elf_index (abfd, isym.st_shndx); - symval = (isym.st_value + isym = isymbuf + ELF32_R_SYM (irel->r_info), + sym_sec = bfd_section_from_elf_index (abfd, isym->st_shndx); + symval = (isym->st_value + sym_sec->output_section->vma + sym_sec->output_offset); } @@ -1599,13 +1582,8 @@ m32r_elf_relax_section (abfd, sec, link_info, again) /* Note that we've changed the relocs, section contents, etc. */ elf_section_data (sec)->relocs = internal_relocs; - free_relocs = NULL; - elf_section_data (sec)->this_hdr.contents = contents; - free_contents = NULL; - - symtab_hdr->contents = (bfd_byte *) extsyms; - free_extsyms = NULL; + symtab_hdr->contents = (unsigned char *) isymbuf; /* Delete TO_DELETE bytes of data. */ if (!m32r_elf_relax_delete_bytes (abfd, sec, @@ -1633,45 +1611,47 @@ m32r_elf_relax_section (abfd, sec, link_info, again) /* loop to try the next reloc */ } - if (free_relocs != NULL) - { - free (free_relocs); - free_relocs = NULL; - } - - if (free_contents != NULL) + if (isymbuf != NULL + && symtab_hdr->contents != (unsigned char *) isymbuf) { if (! link_info->keep_memory) - free (free_contents); + free (isymbuf); + else + { + /* Cache the symbols for elf_link_input_bfd. */ + symtab_hdr->contents = (unsigned char *) isymbuf; + } + } + + if (contents != NULL + && elf_section_data (sec)->this_hdr.contents != contents) + { + if (! link_info->keep_memory) + free (contents); else { /* Cache the section contents for elf_link_input_bfd. */ elf_section_data (sec)->this_hdr.contents = contents; } - free_contents = NULL; } - if (free_extsyms != NULL) - { - if (! link_info->keep_memory) - free (free_extsyms); - else - { - /* Cache the symbols for elf_link_input_bfd. */ - symtab_hdr->contents = extsyms; - } - free_extsyms = NULL; - } + if (internal_relocs != NULL + && elf_section_data (sec)->relocs != internal_relocs) + free (internal_relocs); return true; error_return: - if (free_relocs != NULL) - free (free_relocs); - if (free_contents != NULL) - free (free_contents); - if (free_extsyms != NULL) - free (free_extsyms); + if (isymbuf != NULL + && symtab_hdr->contents != (unsigned char *) isymbuf) + free (isymbuf); + if (contents != NULL + && elf_section_data (sec)->this_hdr.contents != contents) + free (contents); + if (internal_relocs != NULL + && elf_section_data (sec)->relocs != internal_relocs) + free (internal_relocs); + return false; } @@ -1685,17 +1665,15 @@ m32r_elf_relax_delete_bytes (abfd, sec, addr, count) int count; { Elf_Internal_Shdr *symtab_hdr; - Elf32_External_Sym *extsyms; - int shndx, index; + int shndx; bfd_byte *contents; Elf_Internal_Rela *irel, *irelend; Elf_Internal_Rela *irelalign; bfd_vma toaddr; - Elf32_External_Sym *esym, *esymend; - struct elf_link_hash_entry *sym_hash; - - symtab_hdr = &elf_tdata (abfd)->symtab_hdr; - extsyms = (Elf32_External_Sym *) symtab_hdr->contents; + Elf_Internal_Sym *isym, *isymend; + struct elf_link_hash_entry **sym_hashes; + struct elf_link_hash_entry **end_hashes; + unsigned int symcount; shndx = _bfd_elf_section_from_bfd_section (abfd, sec); @@ -1724,40 +1702,32 @@ m32r_elf_relax_delete_bytes (abfd, sec, addr, count) } /* Adjust the local symbols defined in this section. */ - esym = extsyms; - esymend = esym + symtab_hdr->sh_info; - for (; esym < esymend; esym++) + symtab_hdr = &elf_tdata (abfd)->symtab_hdr; + isym = (Elf_Internal_Sym *) symtab_hdr->contents; + for (isymend = isym + symtab_hdr->sh_info; isym < isymend; isym++) { - Elf_Internal_Sym isym; - - bfd_elf32_swap_symbol_in (abfd, esym, &isym); - - if (isym.st_shndx == shndx - && isym.st_value > addr - && isym.st_value < toaddr) - { - isym.st_value -= count; - bfd_elf32_swap_symbol_out (abfd, &isym, esym); - } + if (isym->st_shndx == shndx + && isym->st_value > addr + && isym->st_value < toaddr) + isym->st_value -= count; } /* Now adjust the global symbols defined in this section. */ - esym = extsyms + symtab_hdr->sh_info; - esymend = extsyms + (symtab_hdr->sh_size / sizeof (Elf32_External_Sym)); - for (index = 0; esym < esymend; esym++, index++) + symcount = (symtab_hdr->sh_size / sizeof (Elf32_External_Sym) + - symtab_hdr->sh_info); + sym_hashes = elf_sym_hashes (abfd); + end_hashes = sym_hashes + symcount; + for (; sym_hashes < end_hashes; sym_hashes++) { - Elf_Internal_Sym isym; + struct elf_link_hash_entry *sym_hash = *sym_hashes; - bfd_elf32_swap_symbol_in (abfd, esym, &isym); - sym_hash = elf_sym_hashes (abfd)[index]; - if (isym.st_shndx == shndx - && ((sym_hash)->root.type == bfd_link_hash_defined - || (sym_hash)->root.type == bfd_link_hash_defweak) - && (sym_hash)->root.u.def.section == sec - && (sym_hash)->root.u.def.value > addr - && (sym_hash)->root.u.def.value < toaddr) + if ((sym_hash->root.type == bfd_link_hash_defined + || sym_hash->root.type == bfd_link_hash_defweak) + && sym_hash->root.u.def.section == sec + && sym_hash->root.u.def.value > addr + && sym_hash->root.u.def.value < toaddr) { - (sym_hash)->root.u.def.value -= count; + sym_hash->root.u.def.value -= count; } } @@ -1782,8 +1752,7 @@ m32r_elf_get_relocated_section_contents (output_bfd, link_info, link_order, bfd *input_bfd = input_section->owner; asection **sections = NULL; Elf_Internal_Rela *internal_relocs = NULL; - Elf32_External_Sym *external_syms = NULL; - Elf_Internal_Sym *internal_syms = NULL; + Elf_Internal_Sym *isymbuf = NULL; bfd_size_type amt; /* We only need to handle the case of relaxing, or of having a @@ -1807,31 +1776,22 @@ m32r_elf_get_relocated_section_contents (output_bfd, link_info, link_order, asection **secpp; Elf32_External_Sym *esym, *esymend; - if (symtab_hdr->contents != NULL) - external_syms = (Elf32_External_Sym *) symtab_hdr->contents; - else - { - amt = symtab_hdr->sh_info; - amt *= sizeof (Elf32_External_Sym); - external_syms = (Elf32_External_Sym *) bfd_malloc (amt); - if (external_syms == NULL && symtab_hdr->sh_info > 0) - goto error_return; - if (bfd_seek (input_bfd, symtab_hdr->sh_offset, SEEK_SET) != 0 - || bfd_bread (external_syms, amt, input_bfd) != amt) - goto error_return; - } - internal_relocs = (_bfd_elf32_link_read_relocs (input_bfd, input_section, (PTR) NULL, (Elf_Internal_Rela *) NULL, false)); if (internal_relocs == NULL) goto error_return; - amt = symtab_hdr->sh_info; - amt *= sizeof (Elf_Internal_Sym); - internal_syms = (Elf_Internal_Sym *) bfd_malloc (amt); - if (internal_syms == NULL && symtab_hdr->sh_info > 0) - goto error_return; + if (symtab_hdr->sh_info != 0) + { + isymbuf = (Elf_Internal_Sym *) symtab_hdr->contents; + if (isymbuf == NULL) + isymbuf = bfd_elf_get_elf_syms (input_bfd, symtab_hdr, + symtab_hdr->sh_info, 0, + NULL, NULL, NULL); + if (isymbuf == NULL) + goto error_return; + } amt = symtab_hdr->sh_info; amt *= sizeof (asection *); @@ -1839,61 +1799,50 @@ m32r_elf_get_relocated_section_contents (output_bfd, link_info, link_order, if (sections == NULL && symtab_hdr->sh_info > 0) goto error_return; - isymp = internal_syms; - secpp = sections; - esym = external_syms; - esymend = esym + symtab_hdr->sh_info; - for (; esym < esymend; ++esym, ++isymp, ++secpp) + isymend = isymbuf + symtab_hdr->sh_info; + for (isym = isymbuf, secpp = sections; isym < isymend; ++isym, ++secpp) { asection *isec; - bfd_elf32_swap_symbol_in (input_bfd, esym, isymp); - - if (isymp->st_shndx == SHN_UNDEF) + if (isym->st_shndx == SHN_UNDEF) isec = bfd_und_section_ptr; - else if (isymp->st_shndx == SHN_ABS) + else if (isym->st_shndx == SHN_ABS) isec = bfd_abs_section_ptr; - else if (isymp->st_shndx == SHN_COMMON) + else if (isym->st_shndx == SHN_COMMON) isec = bfd_com_section_ptr; - else if (isymp->st_shndx == SHN_M32R_SCOMMON) + else if (isym->st_shndx == SHN_M32R_SCOMMON) isec = &m32r_elf_scom_section; else - isec = bfd_section_from_elf_index (input_bfd, isymp->st_shndx); + isec = bfd_section_from_elf_index (input_bfd, isym->st_shndx); *secpp = isec; } if (! m32r_elf_relocate_section (output_bfd, link_info, input_bfd, input_section, data, internal_relocs, - internal_syms, sections)) + isymbuf, sections)) goto error_return; if (sections != NULL) free (sections); - sections = NULL; - if (internal_syms != NULL) - free (internal_syms); - internal_syms = NULL; - if (external_syms != NULL && symtab_hdr->contents == NULL) - free (external_syms); - external_syms = NULL; - if (internal_relocs != elf_section_data (input_section)->relocs) + if (isymbuf != NULL + && symtab_hdr->contents != (unsigned char *) isymbuf) + free (isymbuf); + if (elf_section_data (input_section)->relocs != internal_relocs) free (internal_relocs); - internal_relocs = NULL; } return data; error_return: - if (internal_relocs != NULL - && internal_relocs != elf_section_data (input_section)->relocs) - free (internal_relocs); - if (external_syms != NULL && symtab_hdr->contents == NULL) - free (external_syms); - if (internal_syms != NULL) - free (internal_syms); if (sections != NULL) free (sections); + if (isymbuf != NULL + && symtab_hdr->contents != (unsigned char *) isymbuf) + free (isymbuf); + if (internal_relocs != NULL + && elf_section_data (input_section)->relocs != internal_relocs) + free (internal_relocs); return NULL; } diff --git a/bfd/elf32-m68k.c b/bfd/elf32-m68k.c index 0b97cb5f75..6c71418b4e 100644 --- a/bfd/elf32-m68k.c +++ b/bfd/elf32-m68k.c @@ -2111,12 +2111,8 @@ bfd_m68k_elf32_create_embedded_relocs (abfd, info, datasec, relsec, errmsg) char **errmsg; { Elf_Internal_Shdr *symtab_hdr; - Elf_Internal_Shdr *shndx_hdr; - Elf32_External_Sym *extsyms; - Elf32_External_Sym *free_extsyms = NULL; - Elf_External_Sym_Shndx *shndx_buf = NULL; - Elf_Internal_Rela *internal_relocs; - Elf_Internal_Rela *free_relocs = NULL; + Elf_Internal_Sym *isymbuf = NULL; + Elf_Internal_Rela *internal_relocs = NULL; Elf_Internal_Rela *irel, *irelend; bfd_byte *p; bfd_size_type amt; @@ -2129,40 +2125,6 @@ bfd_m68k_elf32_create_embedded_relocs (abfd, info, datasec, relsec, errmsg) return true; symtab_hdr = &elf_tdata (abfd)->symtab_hdr; - /* Read this BFD's symbols if we haven't done so already, or get the cached - copy if it exists. */ - if (symtab_hdr->contents != NULL) - extsyms = (Elf32_External_Sym *) symtab_hdr->contents; - else - { - /* Go get them off disk. */ - amt = symtab_hdr->sh_info * sizeof (Elf32_External_Sym); - if (info->keep_memory) - extsyms = (Elf32_External_Sym *) bfd_alloc (abfd, amt); - else - extsyms = (Elf32_External_Sym *) bfd_malloc (amt); - if (extsyms == NULL) - goto error_return; - if (! info->keep_memory) - free_extsyms = extsyms; - if (bfd_seek (abfd, symtab_hdr->sh_offset, SEEK_SET) != 0 - || bfd_bread (extsyms, amt, abfd) != amt) - goto error_return; - if (info->keep_memory) - symtab_hdr->contents = (unsigned char *) extsyms; - } - - shndx_hdr = &elf_tdata (abfd)->symtab_shndx_hdr; - if (shndx_hdr->sh_size != 0) - { - amt = symtab_hdr->sh_info * sizeof (Elf_External_Sym_Shndx); - shndx_buf = (Elf_External_Sym_Shndx *) bfd_malloc (amt); - if (shndx_buf == NULL) - goto error_return; - if (bfd_seek (abfd, shndx_hdr->sh_offset, SEEK_SET) != 0 - || bfd_bread ((PTR) shndx_buf, amt, abfd) != amt) - goto error_return; - } /* Get a copy of the native relocations. */ internal_relocs = (_bfd_elf32_link_read_relocs @@ -2170,8 +2132,6 @@ bfd_m68k_elf32_create_embedded_relocs (abfd, info, datasec, relsec, errmsg) info->keep_memory)); if (internal_relocs == NULL) goto error_return; - if (! info->keep_memory) - free_relocs = internal_relocs; amt = (bfd_size_type) datasec->reloc_count * 12; relsec->contents = (bfd_byte *) bfd_alloc (abfd, amt); @@ -2202,17 +2162,23 @@ bfd_m68k_elf32_create_embedded_relocs (abfd, info, datasec, relsec, errmsg) /* Get the target section referred to by the reloc. */ if (ELF32_R_SYM (irel->r_info) < symtab_hdr->sh_info) { - Elf32_External_Sym *esym; - Elf_External_Sym_Shndx *shndx; - Elf_Internal_Sym isym; - /* A local symbol. */ - esym = extsyms + ELF32_R_SYM (irel->r_info); - shndx = shndx_buf + (shndx_buf ? ELF32_R_SYM (irel->r_info) : 0); - bfd_elf32_swap_symbol_in (abfd, (const PTR) esym, (const PTR) shndx, - &isym); + Elf_Internal_Sym *isym; - targetsec = bfd_section_from_elf_index (abfd, isym.st_shndx); + /* Read this BFD's local symbols if we haven't done so already. */ + if (isymbuf == NULL) + { + isymbuf = (Elf_Internal_Sym *) symtab_hdr->contents; + if (isymbuf == NULL) + isymbuf = bfd_elf_get_elf_syms (abfd, symtab_hdr, + symtab_hdr->sh_info, 0, + NULL, NULL, NULL); + if (isymbuf == NULL) + goto error_return; + } + + isym = isymbuf + ELF32_R_SYM (irel->r_info); + targetsec = bfd_section_from_elf_index (abfd, isym->st_shndx); } else { @@ -2236,21 +2202,19 @@ bfd_m68k_elf32_create_embedded_relocs (abfd, info, datasec, relsec, errmsg) strncpy (p + 4, targetsec->output_section->name, 8); } - if (shndx_buf != NULL) - free (shndx_buf); - if (free_extsyms != NULL) - free (free_extsyms); - if (free_relocs != NULL) - free (free_relocs); + if (isymbuf != NULL && symtab_hdr->contents != (unsigned char *) isymbuf) + free (isymbuf); + if (internal_relocs != NULL + && elf_section_data (datasec)->relocs != internal_relocs) + free (internal_relocs); return true; error_return: - if (shndx_buf != NULL) - free (shndx_buf); - if (free_extsyms != NULL) - free (free_extsyms); - if (free_relocs != NULL) - free (free_relocs); + if (isymbuf != NULL && symtab_hdr->contents != (unsigned char *) isymbuf) + free (isymbuf); + if (internal_relocs != NULL + && elf_section_data (datasec)->relocs != internal_relocs) + free (internal_relocs); return false; } diff --git a/bfd/elf32-mips.c b/bfd/elf32-mips.c index 9288738574..4672f12f0d 100644 --- a/bfd/elf32-mips.c +++ b/bfd/elf32-mips.c @@ -1786,15 +1786,10 @@ bfd_mips_elf32_create_embedded_relocs (abfd, info, datasec, relsec, errmsg) char **errmsg; { Elf_Internal_Shdr *symtab_hdr; - Elf_Internal_Shdr *shndx_hdr; - Elf32_External_Sym *extsyms; - Elf32_External_Sym *free_extsyms = NULL; - Elf_External_Sym_Shndx *shndx_buf = NULL; - Elf_Internal_Rela *internal_relocs; - Elf_Internal_Rela *free_relocs = NULL; + Elf_Internal_Sym *isymbuf = NULL; + Elf_Internal_Rela *internal_relocs = NULL; Elf_Internal_Rela *irel, *irelend; bfd_byte *p; - bfd_size_type amt; BFD_ASSERT (! info->relocateable); @@ -1803,41 +1798,17 @@ bfd_mips_elf32_create_embedded_relocs (abfd, info, datasec, relsec, errmsg) if (datasec->reloc_count == 0) return true; - symtab_hdr = &elf_tdata (abfd)->symtab_hdr; /* Read this BFD's symbols if we haven't done so already, or get the cached copy if it exists. */ - if (symtab_hdr->contents != NULL) - extsyms = (Elf32_External_Sym *) symtab_hdr->contents; - else + symtab_hdr = &elf_tdata (abfd)->symtab_hdr; + if (symtab_hdr->sh_info != 0) { - /* Go get them off disk. */ - if (info->keep_memory) - extsyms = ((Elf32_External_Sym *) - bfd_alloc (abfd, symtab_hdr->sh_size)); - else - extsyms = ((Elf32_External_Sym *) - bfd_malloc (symtab_hdr->sh_size)); - if (extsyms == NULL) - goto error_return; - if (! info->keep_memory) - free_extsyms = extsyms; - if (bfd_seek (abfd, symtab_hdr->sh_offset, SEEK_SET) != 0 - || (bfd_bread (extsyms, symtab_hdr->sh_size, abfd) - != symtab_hdr->sh_size)) - goto error_return; - if (info->keep_memory) - symtab_hdr->contents = (unsigned char *) extsyms; - } - - shndx_hdr = &elf_tdata (abfd)->symtab_shndx_hdr; - if (shndx_hdr->sh_size != 0) - { - amt = symtab_hdr->sh_info * sizeof (Elf_External_Sym_Shndx); - shndx_buf = (Elf_External_Sym_Shndx *) bfd_malloc (amt); - if (shndx_buf == NULL) - goto error_return; - if (bfd_seek (abfd, shndx_hdr->sh_offset, SEEK_SET) != 0 - || bfd_bread ((PTR) shndx_buf, amt, abfd) != amt) + isymbuf = (Elf_Internal_Sym *) symtab_hdr->contents; + if (isymbuf == NULL) + isymbuf = bfd_elf_get_elf_syms (abfd, symtab_hdr, + symtab_hdr->sh_info, 0, + NULL, NULL, NULL); + if (isymbuf == NULL) goto error_return; } @@ -1847,8 +1818,6 @@ bfd_mips_elf32_create_embedded_relocs (abfd, info, datasec, relsec, errmsg) info->keep_memory)); if (internal_relocs == NULL) goto error_return; - if (! info->keep_memory) - free_relocs = internal_relocs; relsec->contents = (bfd_byte *) bfd_alloc (abfd, datasec->reloc_count * 12); if (relsec->contents == NULL) @@ -1879,17 +1848,11 @@ bfd_mips_elf32_create_embedded_relocs (abfd, info, datasec, relsec, errmsg) /* Get the target section referred to by the reloc. */ if (ELF32_R_SYM (irel->r_info) < symtab_hdr->sh_info) { - Elf32_External_Sym *esym; - Elf_External_Sym_Shndx *shndx; - Elf_Internal_Sym isym; + Elf_Internal_Sym *isym; /* A local symbol. */ - esym = extsyms + ELF32_R_SYM (irel->r_info); - shndx = shndx_buf + (shndx_buf ? ELF32_R_SYM (irel->r_info) : 0); - bfd_elf32_swap_symbol_in (abfd, (const PTR) esym, (const PTR) shndx, - &isym); - - targetsec = bfd_section_from_elf_index (abfd, isym.st_shndx); + isym = isymbuf + ELF32_R_SYM (irel->r_info); + targetsec = bfd_section_from_elf_index (abfd, isym->st_shndx); } else { @@ -1926,21 +1889,21 @@ bfd_mips_elf32_create_embedded_relocs (abfd, info, datasec, relsec, errmsg) strncpy (p + 4, targetsec->output_section->name, 8); } - if (shndx_buf != NULL) - free (shndx_buf); - if (free_extsyms != NULL) - free (free_extsyms); - if (free_relocs != NULL) - free (free_relocs); + if (internal_relocs != NULL + && elf_section_data (datasec)->relocs != internal_relocs) + free (internal_relocs); + if (isymbuf != NULL + && symtab_hdr->contents != (unsigned char *) isymbuf) + free (isymbuf); return true; error_return: - if (shndx_buf != NULL) - free (shndx_buf); - if (free_extsyms != NULL) - free (free_extsyms); - if (free_relocs != NULL) - free (free_relocs); + if (internal_relocs != NULL + && elf_section_data (datasec)->relocs != internal_relocs) + free (internal_relocs); + if (isymbuf != NULL + && symtab_hdr->contents != (unsigned char *) isymbuf) + free (isymbuf); return false; } diff --git a/bfd/elf32-sh.c b/bfd/elf32-sh.c index fdadb6d466..522b81680f 100644 --- a/bfd/elf32-sh.c +++ b/bfd/elf32-sh.c @@ -1546,7 +1546,6 @@ sh_elf_reloc_loop (r_type, input_bfd, input_section, contents, addr, { static bfd_vma last_addr; static asection *last_symbol_section; - bfd_byte *free_contents = NULL; bfd_byte *start_ptr, *ptr, *last_ptr; int diff, cum_diff; bfd_signed_vma x; @@ -1581,7 +1580,6 @@ sh_elf_reloc_loop (r_type, input_bfd, input_section, contents, addr, contents = (bfd_byte *) bfd_malloc (symbol_section->_raw_size); if (contents == NULL) return bfd_reloc_outofrange; - free_contents = contents; if (! bfd_get_section_contents (input_bfd, symbol_section, contents, (file_ptr) 0, symbol_section->_raw_size)) @@ -1621,8 +1619,9 @@ sh_elf_reloc_loop (r_type, input_bfd, input_section, contents, addr, end = start0; } - if (free_contents) - free (free_contents); + if (contents != NULL + && elf_section_data (symbol_section)->this_hdr.contents != contents) + free (contents); insn = bfd_get_16 (input_bfd, contents + addr); @@ -1888,16 +1887,11 @@ sh_elf_relax_section (abfd, sec, link_info, again) boolean *again; { Elf_Internal_Shdr *symtab_hdr; - Elf_Internal_Shdr *shndx_hdr; Elf_Internal_Rela *internal_relocs; - Elf_Internal_Rela *free_relocs = NULL; boolean have_code; Elf_Internal_Rela *irel, *irelend; bfd_byte *contents = NULL; - bfd_byte *free_contents = NULL; - Elf32_External_Sym *extsyms = NULL; - Elf32_External_Sym *free_extsyms = NULL; - Elf_External_Sym_Shndx *shndx_buf = NULL; + Elf_Internal_Sym *isymbuf = NULL; *again = false; @@ -1920,15 +1914,12 @@ sh_elf_relax_section (abfd, sec, link_info, again) sec->_cooked_size = sec->_raw_size; symtab_hdr = &elf_tdata (abfd)->symtab_hdr; - shndx_hdr = &elf_tdata (abfd)->symtab_shndx_hdr; internal_relocs = (_bfd_elf32_link_read_relocs (abfd, sec, (PTR) NULL, (Elf_Internal_Rela *) NULL, link_info->keep_memory)); if (internal_relocs == NULL) goto error_return; - if (! link_info->keep_memory) - free_relocs = internal_relocs; have_code = false; @@ -1956,7 +1947,6 @@ sh_elf_relax_section (abfd, sec, link_info, again) contents = (bfd_byte *) bfd_malloc (sec->_raw_size); if (contents == NULL) goto error_return; - free_contents = contents; if (! bfd_get_section_contents (abfd, sec, contents, (file_ptr) 0, sec->_raw_size)) @@ -2021,56 +2011,25 @@ sh_elf_relax_section (abfd, sec, link_info, again) } /* Read this BFD's symbols if we haven't done so already. */ - if (extsyms == NULL) + if (isymbuf == NULL && symtab_hdr->sh_info != 0) { - if (symtab_hdr->contents != NULL) - extsyms = (Elf32_External_Sym *) symtab_hdr->contents; - else - { - bfd_size_type amt; - - amt = symtab_hdr->sh_info; - amt *= sizeof (Elf32_External_Sym); - extsyms = (Elf32_External_Sym *) bfd_malloc (amt); - if (extsyms == NULL) - goto error_return; - free_extsyms = extsyms; - if (bfd_seek (abfd, symtab_hdr->sh_offset, SEEK_SET) != 0 - || bfd_bread ((PTR) extsyms, amt, abfd) != amt) - goto error_return; - symtab_hdr->contents = (bfd_byte *) extsyms; - } - - if (shndx_hdr->sh_size != 0) - { - bfd_size_type amt; - - amt = symtab_hdr->sh_info; - amt *= sizeof (Elf_External_Sym_Shndx); - shndx_buf = (Elf_External_Sym_Shndx *) bfd_malloc (amt); - if (shndx_buf == NULL) - goto error_return; - if (bfd_seek (abfd, shndx_hdr->sh_offset, SEEK_SET) != 0 - || bfd_bread ((PTR) shndx_buf, amt, abfd) != amt) - goto error_return; - shndx_hdr->contents = (bfd_byte *) shndx_buf; - } + isymbuf = (Elf_Internal_Sym *) symtab_hdr->contents; + if (isymbuf == NULL) + isymbuf = bfd_elf_get_elf_syms (abfd, symtab_hdr, + symtab_hdr->sh_info, 0, + NULL, NULL, NULL); + if (isymbuf == NULL) + goto error_return; } /* Get the value of the symbol referred to by the reloc. */ if (ELF32_R_SYM (irelfn->r_info) < symtab_hdr->sh_info) { /* A local symbol. */ - Elf32_External_Sym *esym; - Elf_External_Sym_Shndx *shndx; - Elf_Internal_Sym isym; + Elf_Internal_Sym *isym; - esym = extsyms + ELF32_R_SYM (irelfn->r_info); - shndx = shndx_buf + (shndx_buf ? ELF32_R_SYM (irelfn->r_info) : 0); - bfd_elf32_swap_symbol_in (abfd, (const PTR) esym, (const PTR) shndx, - &isym); - - if (isym.st_shndx + isym = isymbuf + ELF32_R_SYM (irelfn->r_info); + if (isym->st_shndx != (unsigned int) _bfd_elf_section_from_bfd_section (abfd, sec)) { ((*_bfd_error_handler) @@ -2079,7 +2038,7 @@ sh_elf_relax_section (abfd, sec, link_info, again) continue; } - symval = (isym.st_value + symval = (isym->st_value + sec->output_section->vma + sec->output_offset); } @@ -2130,12 +2089,8 @@ sh_elf_relax_section (abfd, sec, link_info, again) the linker is run. */ elf_section_data (sec)->relocs = internal_relocs; - free_relocs = NULL; - elf_section_data (sec)->this_hdr.contents = contents; - free_contents = NULL; - - free_extsyms = NULL; + symtab_hdr->contents = (unsigned char *) isymbuf; /* Replace the jsr with a bsr. */ @@ -2240,7 +2195,6 @@ sh_elf_relax_section (abfd, sec, link_info, again) contents = (bfd_byte *) bfd_malloc (sec->_raw_size); if (contents == NULL) goto error_return; - free_contents = contents; if (! bfd_get_section_contents (abfd, sec, contents, (file_ptr) 0, sec->_raw_size)) @@ -2255,22 +2209,28 @@ sh_elf_relax_section (abfd, sec, link_info, again) if (swapped) { elf_section_data (sec)->relocs = internal_relocs; - free_relocs = NULL; - elf_section_data (sec)->this_hdr.contents = contents; - free_contents = NULL; - - free_extsyms = NULL; + symtab_hdr->contents = (unsigned char *) isymbuf; } } - if (free_relocs != NULL) - free (free_relocs); - - if (free_contents != NULL) + if (isymbuf != NULL + && symtab_hdr->contents != (unsigned char *) isymbuf) { if (! link_info->keep_memory) - free (free_contents); + free (isymbuf); + else + { + /* Cache the symbols for elf_link_input_bfd. */ + symtab_hdr->contents = (unsigned char *) isymbuf; + } + } + + if (contents != NULL + && elf_section_data (sec)->this_hdr.contents != contents) + { + if (! link_info->keep_memory) + free (contents); else { /* Cache the section contents for elf_link_input_bfd. */ @@ -2278,38 +2238,22 @@ sh_elf_relax_section (abfd, sec, link_info, again) } } - if (shndx_buf != NULL) - { - shndx_hdr->contents = NULL; - free (shndx_buf); - } - - if (free_extsyms != NULL) - { - if (! link_info->keep_memory) - { - symtab_hdr->contents = NULL; - free (free_extsyms); - } - } + if (internal_relocs != NULL + && elf_section_data (sec)->relocs != internal_relocs) + free (internal_relocs); return true; error_return: - if (free_relocs != NULL) - free (free_relocs); - if (free_contents != NULL) - free (free_contents); - if (shndx_buf != NULL) - { - shndx_hdr->contents = NULL; - free (shndx_buf); - } - if (free_extsyms != NULL) - { - symtab_hdr->contents = NULL; - free (free_extsyms); - } + if (isymbuf != NULL + && symtab_hdr->contents != (unsigned char *) isymbuf) + free (isymbuf); + if (contents != NULL + && elf_section_data (sec)->this_hdr.contents != contents) + free (contents); + if (internal_relocs != NULL + && elf_section_data (sec)->relocs != internal_relocs) + free (internal_relocs); return false; } @@ -2326,25 +2270,19 @@ sh_elf_relax_delete_bytes (abfd, sec, addr, count) int count; { Elf_Internal_Shdr *symtab_hdr; - Elf_Internal_Shdr *shndx_hdr; - Elf32_External_Sym *extsyms; unsigned int sec_shndx; bfd_byte *contents; Elf_Internal_Rela *irel, *irelend; Elf_Internal_Rela *irelalign; bfd_vma toaddr; - Elf32_External_Sym *esym, *esymend; - Elf_External_Sym_Shndx *shndx_buf, *shndx; + Elf_Internal_Sym *isymbuf, *isym, *isymend; struct elf_link_hash_entry **sym_hashes; struct elf_link_hash_entry **end_hashes; unsigned int symcount; asection *o; symtab_hdr = &elf_tdata (abfd)->symtab_hdr; - extsyms = (Elf32_External_Sym *) symtab_hdr->contents; - - shndx_hdr = &elf_tdata (abfd)->symtab_shndx_hdr; - shndx_buf = (Elf_External_Sym_Shndx *) shndx_hdr->contents; + isymbuf = (Elf_Internal_Sym *) symtab_hdr->contents; sec_shndx = _bfd_elf_section_from_bfd_section (abfd, sec); @@ -2392,7 +2330,6 @@ sh_elf_relax_delete_bytes (abfd, sec, addr, count) bfd_vma nraddr, stop; bfd_vma start = 0; int insn = 0; - Elf_Internal_Sym sym; int off, adjust, oinsn; bfd_signed_vma voff = 0; boolean overflow; @@ -2446,19 +2383,15 @@ sh_elf_relax_delete_bytes (abfd, sec, addr, count) range to be adjusted, and hence must be changed. */ if (ELF32_R_SYM (irel->r_info) < symtab_hdr->sh_info) { - esym = extsyms + ELF32_R_SYM (irel->r_info); - shndx = shndx_buf + (shndx_buf ? ELF32_R_SYM (irel->r_info) : 0); - bfd_elf32_swap_symbol_in (abfd, (const PTR) esym, - (const PTR) shndx, &sym); - - if (sym.st_shndx == sec_shndx - && (sym.st_value <= addr - || sym.st_value >= toaddr)) + isym = isymbuf + ELF32_R_SYM (irel->r_info); + if (isym->st_shndx == sec_shndx + && (isym->st_value <= addr + || isym->st_value >= toaddr)) { bfd_vma val; val = bfd_get_32 (abfd, contents + nraddr); - val += sym.st_value; + val += isym->st_value; if (val > addr && val < toaddr) bfd_put_32 (abfd, val - count, contents + nraddr); } @@ -2651,8 +2584,6 @@ sh_elf_relax_delete_bytes (abfd, sec, addr, count) irelscanend = internal_relocs + o->reloc_count; for (irelscan = internal_relocs; irelscan < irelscanend; irelscan++) { - Elf_Internal_Sym sym; - /* Dwarf line numbers use R_SH_SWITCH32 relocs. */ if (ELF32_R_TYPE (irelscan->r_info) == (int) R_SH_SWITCH32) { @@ -2710,14 +2641,10 @@ sh_elf_relax_delete_bytes (abfd, sec, addr, count) continue; - esym = extsyms + ELF32_R_SYM (irelscan->r_info); - shndx = shndx_buf + (shndx_buf ? ELF32_R_SYM (irelscan->r_info) : 0); - bfd_elf32_swap_symbol_in (abfd, (const PTR) esym, (const PTR) shndx, - &sym); - - if (sym.st_shndx == sec_shndx - && (sym.st_value <= addr - || sym.st_value >= toaddr)) + isym = isymbuf + ELF32_R_SYM (irelscan->r_info); + if (isym->st_shndx == sec_shndx + && (isym->st_value <= addr + || isym->st_value >= toaddr)) { bfd_vma val; @@ -2743,7 +2670,7 @@ sh_elf_relax_delete_bytes (abfd, sec, addr, count) } val = bfd_get_32 (abfd, ocontents + irelscan->r_offset); - val += sym.st_value; + val += isym->st_value; if (val > addr && val < toaddr) bfd_put_32 (abfd, val - count, ocontents + irelscan->r_offset); @@ -2752,24 +2679,13 @@ sh_elf_relax_delete_bytes (abfd, sec, addr, count) } /* Adjust the local symbols defined in this section. */ - shndx = shndx_buf; - esym = extsyms; - esymend = esym + symtab_hdr->sh_info; - for (; esym < esymend; esym++, shndx = (shndx ? shndx + 1 : NULL)) + isymend = isymbuf + symtab_hdr->sh_info; + for (isym = isymbuf; isym < isymend; isym++) { - Elf_Internal_Sym isym; - Elf_External_Sym_Shndx dummy; - - bfd_elf32_swap_symbol_in (abfd, (const PTR) esym, (const PTR) shndx, - &isym); - - if (isym.st_shndx == sec_shndx - && isym.st_value > addr - && isym.st_value < toaddr) - { - isym.st_value -= count; - bfd_elf32_swap_symbol_out (abfd, &isym, (PTR) esym, (PTR) &dummy); - } + if (isym->st_shndx == sec_shndx + && isym->st_value > addr + && isym->st_value < toaddr) + isym->st_value -= count; } /* Now adjust the global symbols defined in this section. */ @@ -4844,15 +4760,11 @@ sh_elf_get_relocated_section_contents (output_bfd, link_info, link_order, asymbol **symbols; { Elf_Internal_Shdr *symtab_hdr; - Elf_Internal_Shdr *shndx_hdr; asection *input_section = link_order->u.indirect.section; bfd *input_bfd = input_section->owner; asection **sections = NULL; Elf_Internal_Rela *internal_relocs = NULL; - Elf32_External_Sym *external_syms = NULL; - Elf_External_Sym_Shndx *shndx_buf = NULL; - Elf_External_Sym_Shndx *shndx; - Elf_Internal_Sym *internal_syms = NULL; + Elf_Internal_Sym *isymbuf = NULL; /* We only need to handle the case of relaxing, or of having a particular set of section contents, specially. */ @@ -4864,7 +4776,6 @@ sh_elf_get_relocated_section_contents (output_bfd, link_info, link_order, symbols); symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr; - shndx_hdr = &elf_tdata (input_bfd)->symtab_shndx_hdr; memcpy (data, elf_section_data (input_section)->this_hdr.contents, (size_t) input_section->_raw_size); @@ -4872,48 +4783,26 @@ sh_elf_get_relocated_section_contents (output_bfd, link_info, link_order, if ((input_section->flags & SEC_RELOC) != 0 && input_section->reloc_count > 0) { - Elf_Internal_Sym *isymp; asection **secpp; - Elf32_External_Sym *esym, *esymend; + Elf_Internal_Sym *isym, *isymend; bfd_size_type amt; - if (symtab_hdr->contents != NULL) - external_syms = (Elf32_External_Sym *) symtab_hdr->contents; - else if (symtab_hdr->sh_info != 0) - { - amt = symtab_hdr->sh_info; - amt *= sizeof (Elf32_External_Sym); - external_syms = (Elf32_External_Sym *) bfd_malloc (amt); - if (external_syms == NULL) - goto error_return; - if (bfd_seek (input_bfd, symtab_hdr->sh_offset, SEEK_SET) != 0 - || bfd_bread ((PTR) external_syms, amt, input_bfd) != amt) - goto error_return; - } - - if (symtab_hdr->sh_info != 0 && shndx_hdr->sh_size != 0) - { - amt = symtab_hdr->sh_info; - amt *= sizeof (Elf_External_Sym_Shndx); - shndx_buf = (Elf_External_Sym_Shndx *) bfd_malloc (amt); - if (shndx_buf == NULL) - goto error_return; - if (bfd_seek (input_bfd, shndx_hdr->sh_offset, SEEK_SET) != 0 - || bfd_bread ((PTR) shndx_buf, amt, input_bfd) != amt) - goto error_return; - } - internal_relocs = (_bfd_elf32_link_read_relocs (input_bfd, input_section, (PTR) NULL, (Elf_Internal_Rela *) NULL, false)); if (internal_relocs == NULL) goto error_return; - amt = symtab_hdr->sh_info; - amt *= sizeof (Elf_Internal_Sym); - internal_syms = (Elf_Internal_Sym *) bfd_malloc (amt); - if (internal_syms == NULL && amt != 0) - goto error_return; + if (symtab_hdr->sh_info != 0) + { + isymbuf = (Elf_Internal_Sym *) symtab_hdr->contents; + if (isymbuf == NULL) + isymbuf = bfd_elf_get_elf_syms (input_bfd, symtab_hdr, + symtab_hdr->sh_info, 0, + NULL, NULL, NULL); + if (isymbuf == NULL) + goto error_return; + } amt = symtab_hdr->sh_info; amt *= sizeof (asection *); @@ -4921,59 +4810,48 @@ sh_elf_get_relocated_section_contents (output_bfd, link_info, link_order, if (sections == NULL && amt != 0) goto error_return; - for (isymp = internal_syms, secpp = sections, shndx = shndx_buf, - esym = external_syms, esymend = esym + symtab_hdr->sh_info; - esym < esymend; - ++esym, ++isymp, ++secpp, shndx = (shndx ? shndx + 1 : NULL)) + isymend = isymbuf + symtab_hdr->sh_info; + for (isym = isymbuf, secpp = sections; isym < isymend; ++isym, ++secpp) { asection *isec; - bfd_elf32_swap_symbol_in (input_bfd, (const PTR) esym, - (const PTR) shndx, isymp); - - if (isymp->st_shndx == SHN_UNDEF) + if (isym->st_shndx == SHN_UNDEF) isec = bfd_und_section_ptr; - else if (isymp->st_shndx == SHN_ABS) + else if (isym->st_shndx == SHN_ABS) isec = bfd_abs_section_ptr; - else if (isymp->st_shndx == SHN_COMMON) + else if (isym->st_shndx == SHN_COMMON) isec = bfd_com_section_ptr; else - isec = bfd_section_from_elf_index (input_bfd, isymp->st_shndx); + isec = bfd_section_from_elf_index (input_bfd, isym->st_shndx); *secpp = isec; } if (! sh_elf_relocate_section (output_bfd, link_info, input_bfd, input_section, data, internal_relocs, - internal_syms, sections)) + isymbuf, sections)) goto error_return; if (sections != NULL) free (sections); - if (internal_syms != NULL) - free (internal_syms); - if (shndx_buf != NULL) - free (shndx_buf); - if (external_syms != NULL && symtab_hdr->contents == NULL) - free (external_syms); - if (internal_relocs != elf_section_data (input_section)->relocs) + if (isymbuf != NULL + && symtab_hdr->contents != (unsigned char *) isymbuf) + free (isymbuf); + if (elf_section_data (input_section)->relocs != internal_relocs) free (internal_relocs); } return data; error_return: - if (internal_relocs != NULL - && internal_relocs != elf_section_data (input_section)->relocs) - free (internal_relocs); - if (shndx_buf != NULL) - free (shndx_buf); - if (external_syms != NULL && symtab_hdr->contents == NULL) - free (external_syms); - if (internal_syms != NULL) - free (internal_syms); if (sections != NULL) free (sections); + if (isymbuf != NULL + && symtab_hdr->contents != (unsigned char *) isymbuf) + free (isymbuf); + if (internal_relocs != NULL + && elf_section_data (input_section)->relocs != internal_relocs) + free (internal_relocs); return NULL; } diff --git a/bfd/elf32-xstormy16.c b/bfd/elf32-xstormy16.c index 8f83f31581..ada29d8db4 100644 --- a/bfd/elf32-xstormy16.c +++ b/bfd/elf32-xstormy16.c @@ -586,88 +586,51 @@ xstormy16_elf_relax_section (dynobj, splt, info, again) &relax_plt_data); /* Likewise for local symbols, though that's somewhat less convenient - as we have walk the list of input bfds and swap in symbol data. */ + as we have to walk the list of input bfds and swap in symbol data. */ for (ibfd = info->input_bfds; ibfd ; ibfd = ibfd->link_next) { bfd_vma *local_plt_offsets = elf_local_got_offsets (ibfd); Elf_Internal_Shdr *symtab_hdr; - Elf_Internal_Shdr *shndx_hdr; - Elf32_External_Sym *extsyms; - Elf_External_Sym_Shndx *shndx_buf; + Elf_Internal_Sym *isymbuf = NULL; unsigned int idx; if (! local_plt_offsets) continue; symtab_hdr = &elf_tdata (ibfd)->symtab_hdr; - shndx_hdr = &elf_tdata (ibfd)->symtab_shndx_hdr; - - if (symtab_hdr->contents != NULL) - extsyms = (Elf32_External_Sym *) symtab_hdr->contents; - else + if (symtab_hdr->sh_info != 0) { - bfd_size_type amt; - - amt = symtab_hdr->sh_info; - amt *= sizeof (Elf32_External_Sym); - extsyms = (Elf32_External_Sym *) bfd_malloc (amt); - if (extsyms == NULL) + isymbuf = (Elf_Internal_Sym *) symtab_hdr->contents; + if (isymbuf == NULL) + isymbuf = bfd_elf_get_elf_syms (ibfd, symtab_hdr, + symtab_hdr->sh_info, 0, + NULL, NULL, NULL); + if (isymbuf == NULL) return false; - if (bfd_seek (ibfd, symtab_hdr->sh_offset, SEEK_SET) != 0 - || bfd_bread ((PTR) extsyms, amt, ibfd) != amt) - { - error_ret_free_extsyms: - free (extsyms); - return false; - } - } - - shndx_buf = NULL; - if (shndx_hdr->sh_size != 0) - { - bfd_size_type amt; - - amt = symtab_hdr->sh_info; - amt *= sizeof (Elf_External_Sym_Shndx); - shndx_buf = (Elf_External_Sym_Shndx *) bfd_malloc (amt); - if (shndx_buf == NULL) - goto error_ret_free_extsyms; - if (bfd_seek (ibfd, shndx_hdr->sh_offset, SEEK_SET) != 0 - || bfd_bread ((PTR) shndx_buf, amt, ibfd) != amt) - { - free (shndx_buf); - goto error_ret_free_extsyms; - } - shndx_hdr->contents = (bfd_byte *) shndx_buf; } for (idx = 0; idx < symtab_hdr->sh_info; ++idx) { - Elf_External_Sym_Shndx *shndx; - Elf_Internal_Sym isym; + Elf_Internal_Sym *isym; asection *tsec; bfd_vma address; if (local_plt_offsets[idx] == (bfd_vma) -1) continue; - shndx = shndx_buf; - if (shndx != NULL) - shndx += idx; - bfd_elf32_swap_symbol_in (ibfd, (const PTR) (extsyms + idx), - (const PTR) shndx, &isym); - if (isym.st_shndx == SHN_UNDEF) + isym = &isymbuf[idx]; + if (isym->st_shndx == SHN_UNDEF) continue; - else if (isym.st_shndx == SHN_ABS) + else if (isym->st_shndx == SHN_ABS) tsec = bfd_abs_section_ptr; - else if (isym.st_shndx == SHN_COMMON) + else if (isym->st_shndx == SHN_COMMON) tsec = bfd_com_section_ptr; else - tsec = bfd_section_from_elf_index (ibfd, isym.st_shndx); + tsec = bfd_section_from_elf_index (ibfd, isym->st_shndx); address = (tsec->output_section->vma + tsec->output_offset - + isym.st_value); + + isym->st_value); if (address <= 0xffff) { local_plt_offsets[idx] = -1; @@ -676,11 +639,17 @@ xstormy16_elf_relax_section (dynobj, splt, info, again) } } - if (shndx_buf != NULL) - free (shndx_buf); - - if ((Elf32_External_Sym *) symtab_hdr->contents != extsyms) - free (extsyms); + if (isymbuf != NULL + && symtab_hdr->contents != (unsigned char *) isymbuf) + { + if (! info->keep_memory) + free (isymbuf); + else + { + /* Cache the symbols for elf_link_input_bfd. */ + symtab_hdr->contents = (unsigned char *) isymbuf; + } + } } /* If we changed anything, walk the symbols again to reallocate diff --git a/bfd/elf64-alpha.c b/bfd/elf64-alpha.c index 32546f4ed1..36b0cb69d4 100644 --- a/bfd/elf64-alpha.c +++ b/bfd/elf64-alpha.c @@ -2037,14 +2037,9 @@ elf64_alpha_relax_section (abfd, sec, link_info, again) boolean *again; { Elf_Internal_Shdr *symtab_hdr; - Elf_Internal_Shdr *shndx_hdr; Elf_Internal_Rela *internal_relocs; - Elf_Internal_Rela *free_relocs = NULL; Elf_Internal_Rela *irel, *irelend; - bfd_byte *free_contents = NULL; - Elf64_External_Sym *extsyms; - Elf64_External_Sym *free_extsyms = NULL; - Elf_External_Sym_Shndx *shndx_buf = NULL; + Elf_Internal_Sym *isymbuf = NULL; struct alpha_elf_got_entry **local_got_entries; struct alpha_relax_info info; struct elf_link_tls_segment tls_segment; @@ -2070,9 +2065,7 @@ elf64_alpha_relax_section (abfd, sec, link_info, again) (abfd, sec, (PTR) NULL, (Elf_Internal_Rela *) NULL, link_info->keep_memory)); if (internal_relocs == NULL) - goto error_return; - if (! link_info->keep_memory) - free_relocs = internal_relocs; + return false; memset(&info, 0, sizeof (info)); info.abfd = abfd; @@ -2101,41 +2094,12 @@ elf64_alpha_relax_section (abfd, sec, link_info, again) info.contents = (bfd_byte *) bfd_malloc (sec->_raw_size); if (info.contents == NULL) goto error_return; - free_contents = info.contents; if (! bfd_get_section_contents (abfd, sec, info.contents, (file_ptr) 0, sec->_raw_size)) goto error_return; } - /* Read this BFD's symbols. */ - if (symtab_hdr->contents != NULL) - extsyms = (Elf64_External_Sym *) symtab_hdr->contents; - else - { - bfd_size_type amt = symtab_hdr->sh_info * sizeof (Elf64_External_Sym); - extsyms = (Elf64_External_Sym *) bfd_malloc (amt); - if (extsyms == NULL) - goto error_return; - free_extsyms = extsyms; - if (bfd_seek (abfd, symtab_hdr->sh_offset, SEEK_SET) != 0 - || bfd_bread ((PTR) extsyms, amt, abfd) != amt) - goto error_return; - } - - shndx_hdr = &elf_tdata (abfd)->symtab_shndx_hdr; - if (shndx_hdr->sh_size != 0) - { - bfd_size_type amt; - amt = symtab_hdr->sh_info * sizeof (Elf_External_Sym_Shndx); - shndx_buf = (Elf_External_Sym_Shndx *) bfd_malloc (amt); - if (shndx_buf == NULL) - goto error_return; - if (bfd_seek (abfd, shndx_hdr->sh_offset, SEEK_SET) != 0 - || bfd_bread ((PTR) shndx_buf, amt, abfd) != amt) - goto error_return; - } - /* Compute the TLS segment information. The version normally found in elf_hash_table (link_info)->tls_segment isn't built until final_link. ??? Probably should look into extracting this into a common function. */ @@ -2144,7 +2108,6 @@ elf64_alpha_relax_section (abfd, sec, link_info, again) for (irel = internal_relocs; irel < irelend; irel++) { bfd_vma symval; - Elf_Internal_Sym isym; struct alpha_elf_got_entry *gotent; unsigned long r_type = ELF64_R_TYPE (irel->r_info); @@ -2167,26 +2130,34 @@ elf64_alpha_relax_section (abfd, sec, link_info, again) if (ELF64_R_SYM (irel->r_info) < symtab_hdr->sh_info) { /* A local symbol. */ - Elf64_External_Sym *esym; - Elf_External_Sym_Shndx *shndx; + Elf_Internal_Sym *isym; - esym = extsyms + ELF64_R_SYM (irel->r_info); - shndx = shndx_buf + (shndx_buf ? ELF64_R_SYM (irel->r_info) : 0); - bfd_elf64_swap_symbol_in (abfd, (const PTR) esym, (const PTR) shndx, - &isym); - if (isym.st_shndx == SHN_UNDEF) + /* Read this BFD's local symbols. */ + if (isymbuf == NULL) + { + isymbuf = (Elf_Internal_Sym *) symtab_hdr->contents; + if (isymbuf == NULL) + isymbuf = bfd_elf_get_elf_syms (abfd, symtab_hdr, + symtab_hdr->sh_info, 0, + NULL, NULL, NULL); + if (isymbuf == NULL) + goto error_return; + } + + isym = isymbuf + ELF64_R_SYM (irel->r_info); + if (isym->st_shndx == SHN_UNDEF) continue; - else if (isym.st_shndx == SHN_ABS) + else if (isym->st_shndx == SHN_ABS) info.tsec = bfd_abs_section_ptr; - else if (isym.st_shndx == SHN_COMMON) + else if (isym->st_shndx == SHN_COMMON) info.tsec = bfd_com_section_ptr; else - info.tsec = bfd_section_from_elf_index (abfd, isym.st_shndx); + info.tsec = bfd_section_from_elf_index (abfd, isym->st_shndx); info.h = NULL; - info.other = isym.st_other; + info.other = isym->st_other; info.first_gotent = &local_got_entries[ELF64_R_SYM(irel->r_info)]; - symval = isym.st_value; + symval = isym->st_value; } else { @@ -2281,17 +2252,23 @@ elf64_alpha_relax_section (abfd, sec, link_info, again) if (!elf64_alpha_size_rela_got_section (link_info)) return false; - if (info.changed_relocs) - elf_section_data (sec)->relocs = internal_relocs; - else if (free_relocs != NULL) - free (free_relocs); - - if (info.changed_contents) - elf_section_data (sec)->this_hdr.contents = info.contents; - else if (free_contents != NULL) + if (isymbuf != NULL + && symtab_hdr->contents != (unsigned char *) isymbuf) { - if (! link_info->keep_memory) - free (free_contents); + if (!link_info->keep_memory) + free (isymbuf); + else + { + /* Cache the symbols for elf_link_input_bfd. */ + symtab_hdr->contents = (unsigned char *) isymbuf; + } + } + + if (info.contents != NULL + && elf_section_data (sec)->this_hdr.contents != info.contents) + { + if (!info.changed_contents && !link_info->keep_memory) + free (info.contents); else { /* Cache the section contents for elf_link_input_bfd. */ @@ -2299,18 +2276,12 @@ elf64_alpha_relax_section (abfd, sec, link_info, again) } } - if (shndx_buf != NULL) - free (shndx_buf); - - if (free_extsyms != NULL) + if (elf_section_data (sec)->relocs != internal_relocs) { - if (! link_info->keep_memory) - free (free_extsyms); + if (!info.changed_relocs) + free (internal_relocs); else - { - /* Cache the symbols for elf_link_input_bfd. */ - symtab_hdr->contents = (unsigned char *) extsyms; - } + elf_section_data (sec)->relocs = internal_relocs; } *again = info.changed_contents || info.changed_relocs; @@ -2318,14 +2289,15 @@ elf64_alpha_relax_section (abfd, sec, link_info, again) return true; error_return: - if (free_relocs != NULL) - free (free_relocs); - if (free_contents != NULL) - free (free_contents); - if (shndx_buf != NULL) - free (shndx_buf); - if (free_extsyms != NULL) - free (free_extsyms); + if (isymbuf != NULL + && symtab_hdr->contents != (unsigned char *) isymbuf) + free (isymbuf); + if (info.contents != NULL + && elf_section_data (sec)->this_hdr.contents != info.contents) + free (info.contents); + if (internal_relocs != NULL + && elf_section_data (sec)->relocs != internal_relocs) + free (internal_relocs); return false; } diff --git a/bfd/elf64-hppa.c b/bfd/elf64-hppa.c index 929cacd18e..7ebbb52dcc 100644 --- a/bfd/elf64-hppa.c +++ b/bfd/elf64-hppa.c @@ -591,7 +591,6 @@ elf64_hppa_check_relocs (abfd, info, sec, relocs) struct elf64_hppa_link_hash_table *hppa_info; const Elf_Internal_Rela *relend; Elf_Internal_Shdr *symtab_hdr; - Elf_Internal_Shdr *shndx_hdr; const Elf_Internal_Rela *rel; asection *dlt, *plt, *stubs; char *buf; @@ -613,15 +612,14 @@ elf64_hppa_check_relocs (abfd, info, sec, relocs) symtab_hdr = &elf_tdata (abfd)->symtab_hdr; /* If necessary, build a new table holding section symbols indices - for this BFD. This is disgusting. */ + for this BFD. */ if (info->shared && hppa_info->section_syms_bfd != abfd) { unsigned long i; unsigned int highest_shndx; - Elf_Internal_Sym *local_syms, *isym; - Elf64_External_Sym *ext_syms, *esym; - Elf_External_Sym_Shndx *shndx_buf, *shndx; + Elf_Internal_Sym *local_syms = NULL; + Elf_Internal_Sym *isym, *isymend; bfd_size_type amt; /* We're done with the old cache of section index to section symbol @@ -632,72 +630,27 @@ elf64_hppa_check_relocs (abfd, info, sec, relocs) if (hppa_info->section_syms) free (hppa_info->section_syms); - /* Allocate memory for the internal and external symbols. */ - amt = symtab_hdr->sh_info; - amt *= sizeof (Elf_Internal_Sym); - local_syms = (Elf_Internal_Sym *) bfd_malloc (amt); - if (local_syms == NULL) - return false; - - amt = symtab_hdr->sh_info; - amt *= sizeof (Elf64_External_Sym); - ext_syms = (Elf64_External_Sym *) bfd_malloc (amt); - if (ext_syms == NULL) + /* Read this BFD's local symbols. */ + if (symtab_hdr->sh_info != 0) { - free (local_syms); - return false; + local_syms = (Elf_Internal_Sym *) symtab_hdr->contents; + if (local_syms == NULL) + local_syms = bfd_elf_get_elf_syms (abfd, symtab_hdr, + symtab_hdr->sh_info, 0, + NULL, NULL, NULL); + if (local_syms == NULL) + return false; } - /* Read in the local symbols. */ - if (bfd_seek (abfd, symtab_hdr->sh_offset, SEEK_SET) != 0 - || bfd_bread (ext_syms, amt, abfd) != amt) - { - free (ext_syms); - free (local_syms); - return false; - } - - shndx_buf = NULL; - shndx_hdr = &elf_tdata (abfd)->symtab_shndx_hdr; - if (shndx_hdr->sh_size != 0) - { - amt = symtab_hdr->sh_info; - amt *= sizeof (Elf_External_Sym_Shndx); - shndx_buf = (Elf_External_Sym_Shndx *) bfd_malloc (amt); - if (shndx_buf == NULL) - { - free (ext_syms); - free (local_syms); - return false; - } - - if (bfd_seek (abfd, shndx_hdr->sh_offset, SEEK_SET) != 0 - || bfd_bread (shndx_buf, amt, abfd) != amt) - { - free (shndx_buf); - free (ext_syms); - free (local_syms); - return false; - } - } - - /* Swap in the local symbols, also record the highest section index - referenced by the local symbols. */ + /* Record the highest section index referenced by the local symbols. */ highest_shndx = 0; - for (i = 0, isym = local_syms, esym = ext_syms, shndx = shndx_buf; - i < symtab_hdr->sh_info; - i++, esym++, isym++, shndx = (shndx != NULL ? shndx + 1 : NULL)) + isymend = local_syms + symtab_hdr->sh_info; + for (isym = local_syms; isym < isymend; isym++) { - bfd_elf64_swap_symbol_in (abfd, (const PTR) esym, (const PTR) shndx, - isym); if (isym->st_shndx > highest_shndx) highest_shndx = isym->st_shndx; } - /* Now we can free the external symbols. */ - free (shndx_buf); - free (ext_syms); - /* Allocate an array to hold the section index to section symbol index mapping. Bump by one since we start counting at zero. */ highest_shndx++; @@ -707,14 +660,24 @@ elf64_hppa_check_relocs (abfd, info, sec, relocs) /* Now walk the local symbols again. If we find a section symbol, record the index of the symbol into the section_syms array. */ - for (isym = local_syms, i = 0; i < symtab_hdr->sh_info; i++, isym++) + for (i = 0, isym = local_syms; isym < isymend; i++, isym++) { if (ELF_ST_TYPE (isym->st_info) == STT_SECTION) hppa_info->section_syms[isym->st_shndx] = i; } - /* We are finished with the local symbols. Get rid of them. */ - free (local_syms); + /* We are finished with the local symbols. */ + if (local_syms != NULL + && symtab_hdr->contents != (unsigned char *) local_syms) + { + if (! info->keep_memory) + free (local_syms); + else + { + /* Cache the symbols for elf_link_input_bfd. */ + symtab_hdr->contents = (unsigned char *) local_syms; + } + } /* Record which BFD we built the section_syms mapping for. */ hppa_info->section_syms_bfd = abfd; diff --git a/bfd/elf64-mmix.c b/bfd/elf64-mmix.c index 9dc2d74ec7..8b76f34e03 100644 --- a/bfd/elf64-mmix.c +++ b/bfd/elf64-mmix.c @@ -2305,9 +2305,7 @@ mmix_elf_relax_section (abfd, sec, link_info, again) boolean *again; { Elf_Internal_Shdr *symtab_hdr; - Elf_Internal_Shdr *shndx_hdr; Elf_Internal_Rela *internal_relocs; - Elf_Internal_Rela *free_relocs = NULL; Elf_Internal_Rela *irel, *irelend; asection *bpo_gregs_section = NULL; struct bpo_greg_section_info *gregdata; @@ -2316,9 +2314,7 @@ mmix_elf_relax_section (abfd, sec, link_info, again) elf_section_data (sec)->tdata; size_t bpono; bfd *bpo_greg_owner; - Elf64_External_Sym *extsyms = NULL; - Elf64_External_Sym *free_extsyms = NULL; - Elf_External_Sym_Shndx *shndx_buf = NULL; + Elf_Internal_Sym *isymbuf = NULL; /* Assume nothing changes. */ *again = false; @@ -2341,7 +2337,6 @@ mmix_elf_relax_section (abfd, sec, link_info, again) return true; symtab_hdr = &elf_tdata (abfd)->symtab_hdr; - shndx_hdr = &elf_tdata (abfd)->symtab_shndx_hdr; bpo_greg_owner = (bfd *) link_info->base_file; bpo_gregs_section = bpodata->bpo_greg_section; @@ -2357,8 +2352,6 @@ mmix_elf_relax_section (abfd, sec, link_info, again) link_info->keep_memory); if (internal_relocs == NULL) goto error_return; - if (! link_info->keep_memory) - free_relocs = internal_relocs; /* Walk through them looking for relaxing opportunities. */ irelend = internal_relocs + sec->reloc_count; @@ -2369,70 +2362,35 @@ mmix_elf_relax_section (abfd, sec, link_info, again) if (ELF64_R_TYPE (irel->r_info) != (int) R_MMIX_BASE_PLUS_OFFSET) continue; - /* Read this BFD's symbols if we haven't done so already. */ - if (extsyms == NULL) - { - /* Get cached copy if it exists. */ - if (symtab_hdr->contents != NULL) - extsyms = (Elf64_External_Sym *) symtab_hdr->contents; - else - { - /* Go get them off disk. */ - bfd_size_type amt; - - amt = symtab_hdr->sh_info; - amt *= sizeof (Elf64_External_Sym); - extsyms = (Elf64_External_Sym *) bfd_malloc (amt); - if (extsyms == NULL) - goto error_return; - free_extsyms = extsyms; - if (bfd_seek (abfd, symtab_hdr->sh_offset, SEEK_SET) != 0 - || bfd_bread ((PTR) extsyms, amt, abfd) != amt) - goto error_return; - symtab_hdr->contents = (bfd_byte *) extsyms; - } - - /* If >64k sections, this presumable happens. No test-case. */ - if (shndx_hdr->sh_size != 0) - { - bfd_size_type amt; - - amt = symtab_hdr->sh_info; - amt *= sizeof (Elf_External_Sym_Shndx); - shndx_buf = (Elf_External_Sym_Shndx *) bfd_malloc (amt); - if (shndx_buf == NULL) - goto error_return; - if (bfd_seek (abfd, shndx_hdr->sh_offset, SEEK_SET) != 0 - || bfd_bread ((PTR) shndx_buf, amt, abfd) != amt) - goto error_return; - shndx_hdr->contents = (bfd_byte *) shndx_buf; - } - } - /* Get the value of the symbol referred to by the reloc. */ if (ELF64_R_SYM (irel->r_info) < symtab_hdr->sh_info) { /* A local symbol. */ - Elf64_External_Sym *esym; - Elf_External_Sym_Shndx *shndx; - Elf_Internal_Sym isym; + Elf_Internal_Sym *isym; asection *sym_sec; - esym = extsyms + ELF64_R_SYM (irel->r_info); - shndx = shndx_buf + (shndx_buf - ? ELF64_R_SYM (irel->r_info) : 0); - bfd_elf64_swap_symbol_in (abfd, (const PTR) esym, (const PTR) shndx, - &isym); + /* Read this BFD's local symbols if we haven't already. */ + if (isymbuf == NULL) + { + isymbuf = (Elf_Internal_Sym *) symtab_hdr->contents; + if (isymbuf == NULL) + isymbuf = bfd_elf_get_elf_syms (abfd, symtab_hdr, + symtab_hdr->sh_info, 0, + NULL, NULL, NULL); + if (isymbuf == 0) + goto error_return; + } - if (isym.st_shndx == SHN_UNDEF) + isym = isymbuf + ELF64_R_SYM (irel->r_info); + if (isym->st_shndx == SHN_UNDEF) sym_sec = bfd_und_section_ptr; - else if (isym.st_shndx == SHN_ABS) + else if (isym->st_shndx == SHN_ABS) sym_sec = bfd_abs_section_ptr; - else if (isym.st_shndx == SHN_COMMON) + else if (isym->st_shndx == SHN_COMMON) sym_sec = bfd_com_section_ptr; else - sym_sec = bfd_section_from_elf_index (abfd, isym.st_shndx); - symval = (isym.st_value + sym_sec = bfd_section_from_elf_index (abfd, isym->st_shndx); + symval = (isym->st_value + sym_sec->output_section->vma + sym_sec->output_offset); } @@ -2529,40 +2487,29 @@ mmix_elf_relax_section (abfd, sec, link_info, again) bpo_gregs_section->_cooked_size = (regindex + 1) * 8; } - if (free_relocs != NULL) - free (free_relocs); - - if (shndx_buf != NULL) - { - shndx_hdr->contents = NULL; - free (shndx_buf); - } - - if (free_extsyms != NULL) + if (isymbuf != NULL && (unsigned char *) isymbuf != symtab_hdr->contents) { if (! link_info->keep_memory) + free (isymbuf); + else { - symtab_hdr->contents = NULL; - free (free_extsyms); + /* Cache the symbols for elf_link_input_bfd. */ + symtab_hdr->contents = (unsigned char *) isymbuf; } } + if (internal_relocs != NULL + && elf_section_data (sec)->relocs != internal_relocs) + free (internal_relocs); + return true; error_return: - if (free_relocs != NULL) - free (free_relocs); - if (shndx_buf != NULL) - { - shndx_hdr->contents = NULL; - free (shndx_buf); - } - if (free_extsyms != NULL) - { - symtab_hdr->contents = NULL; - free (free_extsyms); - } - + if (isymbuf != NULL && (unsigned char *) isymbuf != symtab_hdr->contents) + free (isymbuf); + if (internal_relocs != NULL + && elf_section_data (sec)->relocs != internal_relocs) + free (internal_relocs); return false; } diff --git a/bfd/elf64-ppc.c b/bfd/elf64-ppc.c index ca39bd40fd..1e70f4105f 100644 --- a/bfd/elf64-ppc.c +++ b/bfd/elf64-ppc.c @@ -2036,10 +2036,8 @@ struct ppc_link_hash_table } *stub_group; /* Assorted information used by ppc64_elf_size_stubs. */ - unsigned int bfd_count; int top_index; asection **input_list; - Elf_Internal_Sym **all_local_syms; /* Short-cuts to get to dynamic linker sections. */ asection *sgot; @@ -2134,8 +2132,6 @@ static boolean ppc_size_one_stub PARAMS ((struct bfd_hash_entry *, PTR)); static void group_sections PARAMS ((struct ppc_link_hash_table *, bfd_size_type, boolean)); -static boolean get_local_syms - PARAMS ((bfd *, struct ppc_link_hash_table *)); static boolean ppc64_elf_fake_sections PARAMS ((bfd *, Elf64_Internal_Shdr *, asection *)); static boolean ppc64_elf_relocate_section @@ -2295,7 +2291,6 @@ ppc64_elf_link_hash_table_create (abfd) htab->add_stub_section = NULL; htab->layout_sections_again = NULL; htab->stub_group = NULL; - htab->all_local_syms = NULL; htab->sgot = NULL; htab->srelgot = NULL; htab->splt = NULL; @@ -3689,7 +3684,6 @@ edit_opd (obfd, info) { bfd *ibfd; unsigned int bfd_indx; - struct ppc_link_hash_table *htab = ppc_hash_table (info); for (bfd_indx = 0, ibfd = info->input_bfds; ibfd != NULL; @@ -3698,6 +3692,7 @@ edit_opd (obfd, info) asection *sec; Elf_Internal_Rela *relstart, *rel, *relend; Elf_Internal_Shdr *symtab_hdr; + Elf_Internal_Sym *local_syms; struct elf_link_hash_entry **sym_hashes; bfd_vma offset; long *adjust; @@ -3718,6 +3713,7 @@ edit_opd (obfd, info) if ((sec->flags & SEC_RELOC) == 0 || sec->reloc_count == 0) continue; + local_syms = NULL; symtab_hdr = &elf_tdata (ibfd)->symtab_hdr; sym_hashes = elf_sym_hashes (ibfd); @@ -3793,7 +3789,17 @@ edit_opd (obfd, info) } else { - sym = htab->all_local_syms[bfd_indx] + r_symndx; + if (local_syms == NULL) + { + local_syms = (Elf_Internal_Sym *) symtab_hdr->contents; + if (local_syms == NULL) + local_syms = bfd_elf_get_elf_syms (ibfd, symtab_hdr, + symtab_hdr->sh_info, 0, + NULL, NULL, NULL); + if (local_syms == NULL) + goto error_free_rel; + } + sym = local_syms + r_symndx; if ((sym->st_shndx != SHN_UNDEF && sym->st_shndx < SHN_LORESERVE) || sym->st_shndx > SHN_HIRESERVE) @@ -3833,11 +3839,18 @@ edit_opd (obfd, info) if ((sec->flags & SEC_IN_MEMORY) == 0) { bfd_byte *loc = bfd_alloc (ibfd, sec->_raw_size); - if (loc == NULL) - return false; - if (! bfd_get_section_contents (ibfd, sec, loc, (bfd_vma) 0, - sec->_raw_size)) - return false; + if (loc == NULL + || !bfd_get_section_contents (ibfd, sec, loc, (bfd_vma) 0, + sec->_raw_size)) + { + if (local_syms != NULL + && symtab_hdr->contents != (unsigned char *) local_syms) + free (local_syms); + error_free_rel: + if (elf_section_data (sec)->relocs != relstart) + free (relstart); + return false; + } sec->contents = loc; sec->flags |= (SEC_IN_MEMORY | SEC_HAS_CONTENTS); } @@ -3874,7 +3887,7 @@ edit_opd (obfd, info) } else { - sym = htab->all_local_syms[bfd_indx] + r_symndx; + sym = local_syms + r_symndx; if ((sym->st_shndx != SHN_UNDEF && sym->st_shndx < SHN_LORESERVE) || sym->st_shndx > SHN_HIRESERVE) @@ -3903,13 +3916,12 @@ edit_opd (obfd, info) } else { - /* Local syms are a bit tricky. Other parts - of the linker re-read them so it's not - possible to tweak local sym values. In - any case, we'd need to look through the - local syms for the function descriptor - sym which we don't have at the moment. - So keep an array of adjustments. */ + /* Local syms are a bit tricky. We could + tweak them as they can be cached, but + we'd need to look through the local syms + for the function descriptor sym which we + don't have at the moment. So keep an + array of adjustments. */ adjust[(rel->r_offset + wptr - rptr) / 24] = wptr - rptr; } @@ -3937,8 +3949,17 @@ edit_opd (obfd, info) sec->_cooked_size = wptr - sec->contents; sec->reloc_count = write_rel - relstart; } - else if (elf_section_data (sec)->relocs == NULL) + else if (elf_section_data (sec)->relocs != relstart) free (relstart); + + if (local_syms != NULL + && symtab_hdr->contents != (unsigned char *) local_syms) + { + if (!info->keep_memory) + free (local_syms); + else + symtab_hdr->contents = (unsigned char *) local_syms; + } } return true; @@ -4242,9 +4263,6 @@ ppc64_elf_size_dynamic_sections (output_bfd, info) } } - if (!get_local_syms (info->input_bfds, htab)) - return false; - if (!edit_opd (output_bfd, info)) return false; @@ -4890,110 +4908,6 @@ group_sections (htab, stub_group_size, stubs_always_before_branch) #undef PREV_SEC } -/* Read in all local syms for all input bfds. */ - -static boolean -get_local_syms (input_bfd, htab) - bfd *input_bfd; - struct ppc_link_hash_table *htab; -{ - unsigned int bfd_indx; - bfd *ibfd; - Elf_Internal_Sym *local_syms, **all_local_syms; - bfd_size_type amt; - - if (htab->all_local_syms != NULL) - return true; - - /* We want to read in symbol extension records only once. To do this - we need to read in the local symbols in parallel and save them for - later use; so hold pointers to the local symbols in an array. */ - for (ibfd = input_bfd, bfd_indx = 0; ibfd != NULL; ibfd = ibfd->link_next) - bfd_indx += 1; - htab->bfd_count = bfd_indx; - amt = sizeof (Elf_Internal_Sym *) * bfd_indx; - all_local_syms = (Elf_Internal_Sym **) bfd_zmalloc (amt); - htab->all_local_syms = all_local_syms; - if (all_local_syms == NULL) - return false; - - /* Walk over all the input BFDs, swapping in local symbols. */ - for (bfd_indx = 0; - input_bfd != NULL; - input_bfd = input_bfd->link_next, bfd_indx++) - { - Elf_Internal_Shdr *symtab_hdr; - Elf_Internal_Shdr *shndx_hdr; - Elf_Internal_Sym *isym; - Elf64_External_Sym *ext_syms, *esym, *end_sy; - Elf_External_Sym_Shndx *shndx_buf, *shndx; - bfd_size_type sec_size; - - if (bfd_get_flavour (input_bfd) != bfd_target_elf_flavour) - continue; - - /* We'll need the symbol table in a second. */ - symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr; - if (symtab_hdr->sh_info == 0) - continue; - - /* We need an array of the local symbols attached to the input bfd. - Unfortunately, we're going to have to read & swap them in. */ - sec_size = symtab_hdr->sh_info; - sec_size *= sizeof (Elf_Internal_Sym); - local_syms = (Elf_Internal_Sym *) bfd_malloc (sec_size); - if (local_syms == NULL) - return false; - - all_local_syms[bfd_indx] = local_syms; - sec_size = symtab_hdr->sh_info; - sec_size *= sizeof (Elf64_External_Sym); - ext_syms = (Elf64_External_Sym *) bfd_malloc (sec_size); - if (ext_syms == NULL) - return false; - - if (bfd_seek (input_bfd, symtab_hdr->sh_offset, SEEK_SET) != 0 - || bfd_bread ((PTR) ext_syms, sec_size, input_bfd) != sec_size) - { - error_ret_free_ext_syms: - free (ext_syms); - return false; - } - - shndx_buf = NULL; - shndx_hdr = &elf_tdata (input_bfd)->symtab_shndx_hdr; - if (shndx_hdr->sh_size != 0) - { - sec_size = symtab_hdr->sh_info; - sec_size *= sizeof (Elf_External_Sym_Shndx); - shndx_buf = (Elf_External_Sym_Shndx *) bfd_malloc (sec_size); - if (shndx_buf == NULL) - goto error_ret_free_ext_syms; - - if (bfd_seek (input_bfd, shndx_hdr->sh_offset, SEEK_SET) != 0 - || bfd_bread ((PTR) shndx_buf, sec_size, input_bfd) != sec_size) - { - free (shndx_buf); - goto error_ret_free_ext_syms; - } - } - - /* Swap the local symbols in. */ - for (esym = ext_syms, end_sy = esym + symtab_hdr->sh_info, - isym = local_syms, shndx = shndx_buf; - esym < end_sy; - esym++, isym++, shndx = (shndx ? shndx + 1 : NULL)) - bfd_elf64_swap_symbol_in (input_bfd, (const PTR) esym, - (const PTR) shndx, isym); - - /* Now we can free the external symbols. */ - free (shndx_buf); - free (ext_syms); - } - - return true; -} - /* Determine and set the size of the stub section for a final link. The basic idea here is to examine all the relocations looking for @@ -5012,7 +4926,6 @@ ppc64_elf_size_stubs (output_bfd, stub_bfd, info, group_size, { bfd_size_type stub_group_size; boolean stubs_always_before_branch; - boolean ret = false; struct ppc_link_hash_table *htab = ppc_hash_table (info); /* Stash our params away. */ @@ -5034,13 +4947,6 @@ ppc64_elf_size_stubs (output_bfd, stub_bfd, info, group_size, group_sections (htab, stub_group_size, stubs_always_before_branch); - if (! get_local_syms (info->input_bfds, htab)) - { - if (htab->all_local_syms) - goto error_ret_free_local; - return false; - } - while (1) { bfd *input_bfd; @@ -5057,15 +4963,13 @@ ppc64_elf_size_stubs (output_bfd, stub_bfd, info, group_size, { Elf_Internal_Shdr *symtab_hdr; asection *section; - Elf_Internal_Sym *local_syms; + Elf_Internal_Sym *local_syms = NULL; /* We'll need the symbol table in a second. */ symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr; if (symtab_hdr->sh_info == 0) continue; - local_syms = htab->all_local_syms[bfd_indx]; - /* Walk over each section attached to the input bfd. */ for (section = input_bfd->sections; section != NULL; @@ -5114,10 +5018,7 @@ ppc64_elf_size_stubs (output_bfd, stub_bfd, info, group_size, if (r_type >= (unsigned int) R_PPC_max) { bfd_set_error (bfd_error_bad_value); - error_ret_free_internal: - if (elf_section_data (section)->relocs == NULL) - free (internal_relocs); - goto error_ret_free_local; + goto error_ret_free_internal; } /* Only look for stubs on branch instructions. */ @@ -5139,6 +5040,18 @@ ppc64_elf_size_stubs (output_bfd, stub_bfd, info, group_size, Elf_Internal_Sym *sym; Elf_Internal_Shdr *hdr; + if (local_syms == NULL) + { + local_syms + = (Elf_Internal_Sym *) symtab_hdr->contents; + if (local_syms == NULL) + local_syms + = bfd_elf_get_elf_syms (input_bfd, symtab_hdr, + symtab_hdr->sh_info, 0, + NULL, NULL, NULL); + if (local_syms == NULL) + goto error_ret_free_internal; + } sym = local_syms + r_indx; hdr = elf_elfsections (input_bfd)[sym->st_shndx]; sym_sec = hdr->bfd_section; @@ -5210,7 +5123,15 @@ ppc64_elf_size_stubs (output_bfd, stub_bfd, info, group_size, if (stub_entry == NULL) { free (stub_name); - goto error_ret_free_internal; + error_ret_free_internal: + if (elf_section_data (section)->relocs == NULL) + free (internal_relocs); + error_ret_free_local: + if (local_syms != NULL + && (symtab_hdr->contents + != (unsigned char *) local_syms)) + free (local_syms); + return false; } stub_entry->target_value = sym_value; @@ -5221,9 +5142,18 @@ ppc64_elf_size_stubs (output_bfd, stub_bfd, info, group_size, } /* We're done with the internal relocs, free them. */ - if (elf_section_data (section)->relocs == NULL) + if (elf_section_data (section)->relocs != internal_relocs) free (internal_relocs); } + + if (local_syms != NULL + && symtab_hdr->contents != (unsigned char *) local_syms) + { + if (!info->keep_memory) + free (local_syms); + else + symtab_hdr->contents = (unsigned char *) local_syms; + } } if (!stub_changed) @@ -5252,15 +5182,7 @@ ppc64_elf_size_stubs (output_bfd, stub_bfd, info, group_size, the dynamic symbol table is corrupted since the section symbol for the stripped section isn't written. */ - ret = true; - - error_ret_free_local: - while (htab->bfd_count-- > 0) - if (htab->all_local_syms[htab->bfd_count]) - free (htab->all_local_syms[htab->bfd_count]); - free (htab->all_local_syms); - - return ret; + return true; } /* Called after we have determined section placement. If sections diff --git a/bfd/elf64-sh64.c b/bfd/elf64-sh64.c index 1e5e12b193..ba5df98ce1 100644 --- a/bfd/elf64-sh64.c +++ b/bfd/elf64-sh64.c @@ -2144,15 +2144,11 @@ sh_elf64_get_relocated_section_contents (output_bfd, link_info, link_order, asymbol **symbols; { Elf_Internal_Shdr *symtab_hdr; - Elf_Internal_Shdr *shndx_hdr; asection *input_section = link_order->u.indirect.section; bfd *input_bfd = input_section->owner; asection **sections = NULL; Elf_Internal_Rela *internal_relocs = NULL; - Elf64_External_Sym *external_syms = NULL; - Elf_External_Sym_Shndx *shndx_buf = NULL; - Elf_External_Sym_Shndx *shndx; - Elf_Internal_Sym *internal_syms = NULL; + Elf_Internal_Sym *isymbuf = NULL; /* We only need to handle the case of relaxing, or of having a particular set of section contents, specially. */ @@ -2164,7 +2160,6 @@ sh_elf64_get_relocated_section_contents (output_bfd, link_info, link_order, symbols); symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr; - shndx_hdr = &elf_tdata (input_bfd)->symtab_shndx_hdr; memcpy (data, elf_section_data (input_section)->this_hdr.contents, input_section->_raw_size); @@ -2173,37 +2168,18 @@ sh_elf64_get_relocated_section_contents (output_bfd, link_info, link_order, && input_section->reloc_count > 0) { Elf_Internal_Sym *isymp; + Elf_Internal_Sym *isymend; asection **secpp; - Elf64_External_Sym *esym, *esymend; - bfd_size_type amt; - if (symtab_hdr->contents != NULL) - external_syms = (Elf64_External_Sym *) symtab_hdr->contents; - else + /* Read this BFD's local symbols. */ + if (symtab_hdr->sh_info != 0) { - amt = symtab_hdr->sh_info; - amt *= sizeof (Elf64_External_Sym); - - external_syms = (Elf64_External_Sym *) bfd_malloc (amt); - if (external_syms == NULL && symtab_hdr->sh_info > 0) - goto error_return; - - if (bfd_seek (input_bfd, symtab_hdr->sh_offset, SEEK_SET) != 0 - || (bfd_bread ((PTR) external_syms, amt, input_bfd) != amt)) - goto error_return; - } - - if (symtab_hdr->sh_info != 0 && shndx_hdr->sh_size != 0) - { - amt = symtab_hdr->sh_info; - amt *= sizeof (Elf_External_Sym_Shndx); - - shndx_buf = (Elf_External_Sym_Shndx *) bfd_malloc (amt); - if (shndx_buf == NULL) - goto error_return; - - if (bfd_seek (input_bfd, shndx_hdr->sh_offset, SEEK_SET) != 0 - || bfd_bread ((PTR) shndx_buf, amt, input_bfd) != amt) + isymbuf = (Elf_Internal_Sym *) symtab_hdr->contents; + if (isymbuf == NULL) + isymbuf = bfd_elf_get_elf_syms (input_bfd, symtab_hdr, + symtab_hdr->sh_info, 0, + NULL, NULL, NULL); + if (isymbuf == NULL) goto error_return; } @@ -2213,30 +2189,17 @@ sh_elf64_get_relocated_section_contents (output_bfd, link_info, link_order, if (internal_relocs == NULL) goto error_return; - internal_syms = ((Elf_Internal_Sym *) - bfd_malloc (symtab_hdr->sh_info - * sizeof (Elf_Internal_Sym))); - if (internal_syms == NULL && symtab_hdr->sh_info > 0) - goto error_return; - sections = (asection **) bfd_malloc (symtab_hdr->sh_info * sizeof (asection *)); if (sections == NULL && symtab_hdr->sh_info > 0) goto error_return; - isymp = internal_syms; secpp = sections; - esym = external_syms; - esymend = esym + symtab_hdr->sh_info; - shndx = shndx_buf; - for (; esym < esymend; - ++esym, ++isymp, ++secpp, shndx = (shndx ? shndx + 1 : NULL)) + isymend = isymbuf + symtab_hdr->sh_info; + for (isymp = isymbuf; isymp < isymend; ++isymp, ++secpp) { asection *isec; - bfd_elf64_swap_symbol_in (input_bfd, (const PTR) esym, - (const PTR) shndx, isymp); - if (isymp->st_shndx == SHN_UNDEF) isec = bfd_und_section_ptr; else if (isymp->st_shndx > 0 && isymp->st_shndx < SHN_LORESERVE) @@ -2256,35 +2219,29 @@ sh_elf64_get_relocated_section_contents (output_bfd, link_info, link_order, if (! sh_elf64_relocate_section (output_bfd, link_info, input_bfd, input_section, data, internal_relocs, - internal_syms, sections)) + isymbuf, sections)) goto error_return; if (sections != NULL) free (sections); - sections = NULL; - if (internal_syms != NULL) - free (internal_syms); - internal_syms = NULL; - if (external_syms != NULL && symtab_hdr->contents == NULL) - free (external_syms); - external_syms = NULL; if (internal_relocs != elf_section_data (input_section)->relocs) free (internal_relocs); - internal_relocs = NULL; + if (isymbuf != NULL + && (unsigned char *) isymbuf != symtab_hdr->contents) + free (isymbuf); } return data; error_return: + if (sections != NULL) + free (sections); if (internal_relocs != NULL && internal_relocs != elf_section_data (input_section)->relocs) free (internal_relocs); - if (external_syms != NULL && symtab_hdr->contents == NULL) - free (external_syms); - if (internal_syms != NULL) - free (internal_syms); - if (sections != NULL) - free (sections); + if (isymbuf != NULL + && (unsigned char *) isymbuf != symtab_hdr->contents) + free (isymbuf); return NULL; } diff --git a/bfd/elfcode.h b/bfd/elfcode.h index c113dd7d18..eb667eb50e 100644 --- a/bfd/elfcode.h +++ b/bfd/elfcode.h @@ -1133,10 +1133,12 @@ elf_slurp_symbol_table (abfd, symptrs, dynamic) unsigned long symcount; /* Number of external ELF symbols */ elf_symbol_type *sym; /* Pointer to current bfd symbol */ elf_symbol_type *symbase; /* Buffer for generated bfd symbols */ - Elf_Internal_Sym i_sym; - Elf_External_Sym *x_symp = NULL; - Elf_External_Sym_Shndx *x_shndx = NULL; - Elf_External_Versym *x_versymp = NULL; + Elf_Internal_Sym *isym; + Elf_Internal_Sym *isymend; + Elf_Internal_Sym *isymbuf = NULL; + Elf_External_Versym *xver; + Elf_External_Versym *xverbuf = NULL; + struct elf_backend_data *ebd; bfd_size_type amt; /* Read each raw ELF symbol, converting from external ELF form to @@ -1151,24 +1153,8 @@ elf_slurp_symbol_table (abfd, symptrs, dynamic) if (! dynamic) { - Elf_Internal_Shdr *shndx_hdr; - hdr = &elf_tdata (abfd)->symtab_hdr; - shndx_hdr = &elf_tdata (abfd)->symtab_shndx_hdr; verhdr = NULL; - - /* If we have a SHT_SYMTAB_SHNDX section for the symbol table, - read the raw contents. */ - if (elf_elfsections (abfd) != NULL - && elf_elfsections (abfd)[shndx_hdr->sh_link] == hdr) - { - amt = shndx_hdr->sh_size; - x_shndx = (Elf_External_Sym_Shndx *) bfd_malloc (amt); - if (x_shndx == NULL - || bfd_seek (abfd, shndx_hdr->sh_offset, SEEK_SET) != 0 - || bfd_bread ((PTR) x_shndx, amt, abfd) != amt) - goto error_return; - } } else { @@ -1187,39 +1173,24 @@ elf_slurp_symbol_table (abfd, symptrs, dynamic) } } - if (bfd_seek (abfd, hdr->sh_offset, SEEK_SET) != 0) - goto error_return; - + ebd = get_elf_backend_data (abfd); symcount = hdr->sh_size / sizeof (Elf_External_Sym); - if (symcount == 0) sym = symbase = NULL; else { - unsigned long i; - - if (bfd_seek (abfd, hdr->sh_offset, SEEK_SET) != 0) - goto error_return; + isymbuf = bfd_elf_get_elf_syms (abfd, hdr, symcount, 0, + NULL, NULL, NULL); + if (isymbuf == NULL) + return -1; amt = symcount; amt *= sizeof (elf_symbol_type); symbase = (elf_symbol_type *) bfd_zalloc (abfd, amt); if (symbase == (elf_symbol_type *) NULL) goto error_return; - sym = symbase; - - /* Temporarily allocate room for the raw ELF symbols. */ - amt = symcount; - amt *= sizeof (Elf_External_Sym); - x_symp = (Elf_External_Sym *) bfd_malloc (amt); - if (x_symp == NULL) - goto error_return; - - if (bfd_bread ((PTR) x_symp, amt, abfd) != amt) - goto error_return; /* Read the raw ELF version symbol information. */ - if (verhdr != NULL && verhdr->sh_size / sizeof (Elf_External_Versym) != symcount) { @@ -1239,42 +1210,40 @@ elf_slurp_symbol_table (abfd, symptrs, dynamic) if (bfd_seek (abfd, verhdr->sh_offset, SEEK_SET) != 0) goto error_return; - x_versymp = (Elf_External_Versym *) bfd_malloc (verhdr->sh_size); - if (x_versymp == NULL && verhdr->sh_size != 0) + xverbuf = (Elf_External_Versym *) bfd_malloc (verhdr->sh_size); + if (xverbuf == NULL && verhdr->sh_size != 0) goto error_return; - if (bfd_bread ((PTR) x_versymp, verhdr->sh_size, abfd) + if (bfd_bread ((PTR) xverbuf, verhdr->sh_size, abfd) != verhdr->sh_size) goto error_return; } /* Skip first symbol, which is a null dummy. */ - for (i = 1; i < symcount; i++) + xver = xverbuf; + if (xver != NULL) + ++xver; + isymend = isymbuf + symcount; + for (isym = isymbuf + 1, sym = symbase; isym < isymend; isym++, sym++) { - elf_swap_symbol_in (abfd, (const PTR) (x_symp + i), - (const PTR) (x_shndx + (x_shndx ? i : 0)), - &i_sym); - memcpy (&sym->internal_elf_sym, &i_sym, sizeof (Elf_Internal_Sym)); -#ifdef ELF_KEEP_EXTSYM - memcpy (&sym->native_elf_sym, x_symp + i, sizeof (Elf_External_Sym)); -#endif + memcpy (&sym->internal_elf_sym, isym, sizeof (Elf_Internal_Sym)); sym->symbol.the_bfd = abfd; sym->symbol.name = bfd_elf_string_from_elf_section (abfd, hdr->sh_link, - i_sym.st_name); + isym->st_name); - sym->symbol.value = i_sym.st_value; + sym->symbol.value = isym->st_value; - if (i_sym.st_shndx == SHN_UNDEF) + if (isym->st_shndx == SHN_UNDEF) { sym->symbol.section = bfd_und_section_ptr; } - else if (i_sym.st_shndx < SHN_LORESERVE - || i_sym.st_shndx > SHN_HIRESERVE) + else if (isym->st_shndx < SHN_LORESERVE + || isym->st_shndx > SHN_HIRESERVE) { sym->symbol.section = section_from_elf_index (abfd, - i_sym.st_shndx); + isym->st_shndx); if (sym->symbol.section == NULL) { /* This symbol is in a section for which we did not @@ -1283,18 +1252,18 @@ elf_slurp_symbol_table (abfd, symptrs, dynamic) sym->symbol.section = bfd_abs_section_ptr; } } - else if (i_sym.st_shndx == SHN_ABS) + else if (isym->st_shndx == SHN_ABS) { sym->symbol.section = bfd_abs_section_ptr; } - else if (i_sym.st_shndx == SHN_COMMON) + else if (isym->st_shndx == SHN_COMMON) { sym->symbol.section = bfd_com_section_ptr; /* Elf puts the alignment into the `value' field, and the size into the `size' field. BFD wants to see the size in the value field, and doesn't care (at the moment) about the alignment. */ - sym->symbol.value = i_sym.st_size; + sym->symbol.value = isym->st_size; } else sym->symbol.section = bfd_abs_section_ptr; @@ -1304,14 +1273,13 @@ elf_slurp_symbol_table (abfd, symptrs, dynamic) if ((abfd->flags & (EXEC_P | DYNAMIC)) != 0) sym->symbol.value -= sym->symbol.section->vma; - switch (ELF_ST_BIND (i_sym.st_info)) + switch (ELF_ST_BIND (isym->st_info)) { case STB_LOCAL: sym->symbol.flags |= BSF_LOCAL; break; case STB_GLOBAL: - if (i_sym.st_shndx != SHN_UNDEF - && i_sym.st_shndx != SHN_COMMON) + if (isym->st_shndx != SHN_UNDEF && isym->st_shndx != SHN_COMMON) sym->symbol.flags |= BSF_GLOBAL; break; case STB_WEAK: @@ -1319,7 +1287,7 @@ elf_slurp_symbol_table (abfd, symptrs, dynamic) break; } - switch (ELF_ST_TYPE (i_sym.st_info)) + switch (ELF_ST_TYPE (isym->st_info)) { case STT_SECTION: sym->symbol.flags |= BSF_SECTION_SYM | BSF_DEBUGGING; @@ -1338,31 +1306,24 @@ elf_slurp_symbol_table (abfd, symptrs, dynamic) if (dynamic) sym->symbol.flags |= BSF_DYNAMIC; - if (x_versymp != NULL) + if (xver != NULL) { Elf_Internal_Versym iversym; - _bfd_elf_swap_versym_in (abfd, x_versymp + i, &iversym); + _bfd_elf_swap_versym_in (abfd, xver, &iversym); sym->version = iversym.vs_vers; + xver++; } /* Do some backend-specific processing on this symbol. */ - { - struct elf_backend_data *ebd = get_elf_backend_data (abfd); - if (ebd->elf_backend_symbol_processing) - (*ebd->elf_backend_symbol_processing) (abfd, &sym->symbol); - } - - sym++; + if (ebd->elf_backend_symbol_processing) + (*ebd->elf_backend_symbol_processing) (abfd, &sym->symbol); } } /* Do some backend-specific processing on this symbol table. */ - { - struct elf_backend_data *ebd = get_elf_backend_data (abfd); - if (ebd->elf_backend_symbol_table_processing) - (*ebd->elf_backend_symbol_table_processing) (abfd, symbase, symcount); - } + if (ebd->elf_backend_symbol_table_processing) + (*ebd->elf_backend_symbol_table_processing) (abfd, symbase, symcount); /* We rely on the zalloc to clear out the final symbol entry. */ @@ -1382,21 +1343,17 @@ elf_slurp_symbol_table (abfd, symptrs, dynamic) *symptrs = 0; /* Final null pointer */ } - if (x_shndx != NULL) - free (x_shndx); - if (x_versymp != NULL) - free (x_versymp); - if (x_symp != NULL) - free (x_symp); + if (xverbuf != NULL) + free (xverbuf); + if (isymbuf != NULL && hdr->contents != (unsigned char *) isymbuf) + free (isymbuf); return symcount; error_return: - if (x_shndx != NULL) - free (x_shndx); - if (x_versymp != NULL) - free (x_versymp); - if (x_symp != NULL) - free (x_symp); + if (xverbuf != NULL) + free (xverbuf); + if (isymbuf != NULL && hdr->contents != (unsigned char *) isymbuf) + free (isymbuf); return -1; } diff --git a/bfd/elflink.h b/bfd/elflink.h index 6c1d0d92b8..57819e9958 100644 --- a/bfd/elflink.h +++ b/bfd/elflink.h @@ -149,18 +149,13 @@ elf_link_is_defined_archive_symbol (abfd, symdef) carsym * symdef; { Elf_Internal_Shdr * hdr; - Elf_Internal_Shdr * shndx_hdr; - Elf_External_Sym * esym; - Elf_External_Sym * esymend; - Elf_External_Sym * buf = NULL; - Elf_External_Sym_Shndx * shndx_buf = NULL; - Elf_External_Sym_Shndx * shndx; bfd_size_type symcount; bfd_size_type extsymcount; bfd_size_type extsymoff; - boolean result = false; - file_ptr pos; - bfd_size_type amt; + Elf_Internal_Sym *isymbuf; + Elf_Internal_Sym *isym; + Elf_Internal_Sym *isymend; + boolean result; abfd = _bfd_get_elt_at_filepos (abfd, symdef->file_offset); if (abfd == (bfd *) NULL) @@ -178,15 +173,9 @@ elf_link_is_defined_archive_symbol (abfd, symdef) /* Select the appropriate symbol table. */ if ((abfd->flags & DYNAMIC) == 0 || elf_dynsymtab (abfd) == 0) - { - hdr = &elf_tdata (abfd)->symtab_hdr; - shndx_hdr = &elf_tdata (abfd)->symtab_shndx_hdr; - } + hdr = &elf_tdata (abfd)->symtab_hdr; else - { - hdr = &elf_tdata (abfd)->dynsymtab_hdr; - shndx_hdr = NULL; - } + hdr = &elf_tdata (abfd)->dynsymtab_hdr; symcount = hdr->sh_size / sizeof (Elf_External_Sym); @@ -203,58 +192,34 @@ elf_link_is_defined_archive_symbol (abfd, symdef) extsymoff = hdr->sh_info; } - amt = extsymcount * sizeof (Elf_External_Sym); - buf = (Elf_External_Sym *) bfd_malloc (amt); - if (buf == NULL && extsymcount != 0) + if (extsymcount == 0) return false; - /* Read in the symbol table. - FIXME: This ought to be cached somewhere. */ - pos = hdr->sh_offset + extsymoff * sizeof (Elf_External_Sym); - if (bfd_seek (abfd, pos, SEEK_SET) != 0 - || bfd_bread ((PTR) buf, amt, abfd) != amt) - goto error_exit; - - if (shndx_hdr != NULL && shndx_hdr->sh_size != 0) - { - amt = extsymcount * sizeof (Elf_External_Sym_Shndx); - shndx_buf = (Elf_External_Sym_Shndx *) bfd_malloc (amt); - if (shndx_buf == NULL && extsymcount != 0) - goto error_exit; - - pos = shndx_hdr->sh_offset + extsymoff * sizeof (Elf_External_Sym_Shndx); - if (bfd_seek (abfd, pos, SEEK_SET) != 0 - || bfd_bread ((PTR) shndx_buf, amt, abfd) != amt) - goto error_exit; - } + /* Read in the symbol table. */ + isymbuf = bfd_elf_get_elf_syms (abfd, hdr, extsymcount, extsymoff, + NULL, NULL, NULL); + if (isymbuf == NULL) + return false; /* Scan the symbol table looking for SYMDEF. */ - esymend = buf + extsymcount; - for (esym = buf, shndx = shndx_buf; - esym < esymend; - esym++, shndx = (shndx != NULL ? shndx + 1 : NULL)) + result = false; + for (isym = isymbuf, isymend = isymbuf + extsymcount; isym < isymend; isym++) { - Elf_Internal_Sym sym; - const char * name; + const char *name; - elf_swap_symbol_in (abfd, (const PTR) esym, (const PTR) shndx, &sym); - - name = bfd_elf_string_from_elf_section (abfd, hdr->sh_link, sym.st_name); + name = bfd_elf_string_from_elf_section (abfd, hdr->sh_link, + isym->st_name); if (name == (const char *) NULL) break; if (strcmp (name, symdef->name) == 0) { - result = is_global_data_symbol_definition (abfd, & sym); + result = is_global_data_symbol_definition (abfd, isym); break; } } - error_exit: - if (shndx_buf != NULL) - free (shndx_buf); - if (buf != NULL) - free (buf); + free (isymbuf); return result; } @@ -1186,25 +1151,20 @@ elf_link_add_object_symbols (abfd, info) asection *, const Elf_Internal_Rela *)); boolean collect; Elf_Internal_Shdr *hdr; - Elf_Internal_Shdr *shndx_hdr; bfd_size_type symcount; bfd_size_type extsymcount; bfd_size_type extsymoff; - Elf_External_Sym *buf = NULL; - Elf_External_Sym_Shndx *shndx_buf = NULL; - Elf_External_Sym_Shndx *shndx; struct elf_link_hash_entry **sym_hash; boolean dynamic; Elf_External_Versym *extversym = NULL; Elf_External_Versym *ever; - Elf_External_Dyn *dynbuf = NULL; struct elf_link_hash_entry *weaks; - Elf_External_Sym *esym; - Elf_External_Sym *esymend; + Elf_Internal_Sym *isymbuf = NULL; + Elf_Internal_Sym *isym; + Elf_Internal_Sym *isymend; struct elf_backend_data *bed; boolean dt_needed; struct elf_link_hash_table * hash_table; - file_ptr pos; bfd_size_type amt; hash_table = elf_hash_table (info); @@ -1303,85 +1263,7 @@ elf_link_add_object_symbols (abfd, info) } } - /* If this is a dynamic object, we always link against the .dynsym - symbol table, not the .symtab symbol table. The dynamic linker - will only see the .dynsym symbol table, so there is no reason to - look at .symtab for a dynamic object. */ - - if (! dynamic || elf_dynsymtab (abfd) == 0) - { - hdr = &elf_tdata (abfd)->symtab_hdr; - shndx_hdr = &elf_tdata (abfd)->symtab_shndx_hdr; - } - else - { - hdr = &elf_tdata (abfd)->dynsymtab_hdr; - shndx_hdr = NULL; - } - - if (dynamic) - { - /* Read in any version definitions. */ - - if (! _bfd_elf_slurp_version_tables (abfd)) - goto error_return; - - /* Read in the symbol versions, but don't bother to convert them - to internal format. */ - if (elf_dynversym (abfd) != 0) - { - Elf_Internal_Shdr *versymhdr; - - versymhdr = &elf_tdata (abfd)->dynversym_hdr; - extversym = (Elf_External_Versym *) bfd_malloc (versymhdr->sh_size); - if (extversym == NULL) - goto error_return; - amt = versymhdr->sh_size; - if (bfd_seek (abfd, versymhdr->sh_offset, SEEK_SET) != 0 - || bfd_bread ((PTR) extversym, amt, abfd) != amt) - goto error_return; - } - } - - symcount = hdr->sh_size / sizeof (Elf_External_Sym); - - /* The sh_info field of the symtab header tells us where the - external symbols start. We don't care about the local symbols at - this point. */ - if (elf_bad_symtab (abfd)) - { - extsymcount = symcount; - extsymoff = 0; - } - else - { - extsymcount = symcount - hdr->sh_info; - extsymoff = hdr->sh_info; - } - - amt = extsymcount * sizeof (Elf_External_Sym); - buf = (Elf_External_Sym *) bfd_malloc (amt); - if (buf == NULL && extsymcount != 0) - goto error_return; - - if (shndx_hdr != NULL && shndx_hdr->sh_size != 0) - { - amt = extsymcount * sizeof (Elf_External_Sym_Shndx); - shndx_buf = (Elf_External_Sym_Shndx *) bfd_malloc (amt); - if (shndx_buf == NULL && extsymcount != 0) - goto error_return; - } - - /* We store a pointer to the hash table entry for each external - symbol. */ - amt = extsymcount * sizeof (struct elf_link_hash_entry *); - sym_hash = (struct elf_link_hash_entry **) bfd_alloc (abfd, amt); - if (sym_hash == NULL) - goto error_return; - elf_sym_hashes (abfd) = sym_hash; - dt_needed = false; - if (! dynamic) { /* If we are creating a shared library, create all the dynamic @@ -1431,6 +1313,7 @@ elf_link_add_object_symbols (abfd, info) s = bfd_get_section_by_name (abfd, ".dynamic"); if (s != NULL) { + Elf_External_Dyn *dynbuf = NULL; Elf_External_Dyn *extdyn; Elf_External_Dyn *extdynend; int elfsec; @@ -1444,11 +1327,11 @@ elf_link_add_object_symbols (abfd, info) if (! bfd_get_section_contents (abfd, s, (PTR) dynbuf, (file_ptr) 0, s->_raw_size)) - goto error_return; + goto error_free_dyn; elfsec = _bfd_elf_section_from_bfd_section (abfd, s); if (elfsec == -1) - goto error_return; + goto error_free_dyn; shlink = elf_elfsections (abfd)[elfsec]->sh_link; extdyn = dynbuf; @@ -1465,7 +1348,7 @@ elf_link_add_object_symbols (abfd, info) unsigned int tagv = dyn.d_un.d_val; name = bfd_elf_string_from_elf_section (abfd, shlink, tagv); if (name == NULL) - goto error_return; + goto error_free_dyn; } if (dyn.d_tag == DT_NEEDED) { @@ -1477,11 +1360,11 @@ elf_link_add_object_symbols (abfd, info) n = (struct bfd_link_needed_list *) bfd_alloc (abfd, amt); fnm = bfd_elf_string_from_elf_section (abfd, shlink, tagv); if (n == NULL || fnm == NULL) - goto error_return; + goto error_free_dyn; amt = strlen (fnm) + 1; anm = bfd_alloc (abfd, amt); if (anm == NULL) - goto error_return; + goto error_free_dyn; memcpy (anm, fnm, (size_t) amt); n->name = anm; n->by = abfd; @@ -1509,11 +1392,11 @@ elf_link_add_object_symbols (abfd, info) n = (struct bfd_link_needed_list *) bfd_alloc (abfd, amt); fnm = bfd_elf_string_from_elf_section (abfd, shlink, tagv); if (n == NULL || fnm == NULL) - goto error_return; + goto error_free_dyn; amt = strlen (fnm) + 1; anm = bfd_alloc (abfd, amt); if (anm == NULL) - goto error_return; + goto error_free_dyn; memcpy (anm, fnm, (size_t) amt); n->name = anm; n->by = abfd; @@ -1537,11 +1420,15 @@ elf_link_add_object_symbols (abfd, info) n = (struct bfd_link_needed_list *) bfd_alloc (abfd, amt); fnm = bfd_elf_string_from_elf_section (abfd, shlink, tagv); if (n == NULL || fnm == NULL) - goto error_return; + goto error_free_dyn; amt = strlen (fnm) + 1; anm = bfd_alloc (abfd, amt); if (anm == NULL) - goto error_return; + { + error_free_dyn: + free (dynbuf); + goto error_return; + } memcpy (anm, fnm, (size_t) amt); n->name = anm; n->by = abfd; @@ -1556,7 +1443,6 @@ elf_link_add_object_symbols (abfd, info) } free (dynbuf); - dynbuf = NULL; } /* We do not want to include any of the sections in a dynamic @@ -1606,10 +1492,6 @@ elf_link_add_object_symbols (abfd, info) if (dyn.d_tag == DT_NEEDED && dyn.d_un.d_val == strindex) { - if (buf != NULL) - free (buf); - if (extversym != NULL) - free (extversym); _bfd_elf_strtab_delref (hash_table->dynstr, strindex); return true; } @@ -1627,31 +1509,79 @@ elf_link_add_object_symbols (abfd, info) elf_dt_name (abfd) = name; } - pos = hdr->sh_offset + extsymoff * sizeof (Elf_External_Sym); - amt = extsymcount * sizeof (Elf_External_Sym); - if (bfd_seek (abfd, pos, SEEK_SET) != 0 - || bfd_bread ((PTR) buf, amt, abfd) != amt) - goto error_return; + /* If this is a dynamic object, we always link against the .dynsym + symbol table, not the .symtab symbol table. The dynamic linker + will only see the .dynsym symbol table, so there is no reason to + look at .symtab for a dynamic object. */ - if (shndx_hdr != NULL && shndx_hdr->sh_size != 0) + if (! dynamic || elf_dynsymtab (abfd) == 0) + hdr = &elf_tdata (abfd)->symtab_hdr; + else + hdr = &elf_tdata (abfd)->dynsymtab_hdr; + + symcount = hdr->sh_size / sizeof (Elf_External_Sym); + + /* The sh_info field of the symtab header tells us where the + external symbols start. We don't care about the local symbols at + this point. */ + if (elf_bad_symtab (abfd)) { - amt = extsymcount * sizeof (Elf_External_Sym_Shndx); - pos = shndx_hdr->sh_offset + extsymoff * sizeof (Elf_External_Sym_Shndx); - if (bfd_seek (abfd, pos, SEEK_SET) != 0 - || bfd_bread ((PTR) shndx_buf, amt, abfd) != amt) + extsymcount = symcount; + extsymoff = 0; + } + else + { + extsymcount = symcount - hdr->sh_info; + extsymoff = hdr->sh_info; + } + + sym_hash = NULL; + if (extsymcount != 0) + { + isymbuf = bfd_elf_get_elf_syms (abfd, hdr, extsymcount, extsymoff, + NULL, NULL, NULL); + if (isymbuf == NULL) goto error_return; + + /* We store a pointer to the hash table entry for each external + symbol. */ + amt = extsymcount * sizeof (struct elf_link_hash_entry *); + sym_hash = (struct elf_link_hash_entry **) bfd_alloc (abfd, amt); + if (sym_hash == NULL) + goto error_free_sym; + elf_sym_hashes (abfd) = sym_hash; + } + + if (dynamic) + { + /* Read in any version definitions. */ + if (! _bfd_elf_slurp_version_tables (abfd)) + goto error_free_sym; + + /* Read in the symbol versions, but don't bother to convert them + to internal format. */ + if (elf_dynversym (abfd) != 0) + { + Elf_Internal_Shdr *versymhdr; + + versymhdr = &elf_tdata (abfd)->dynversym_hdr; + extversym = (Elf_External_Versym *) bfd_malloc (versymhdr->sh_size); + if (extversym == NULL) + goto error_free_sym; + amt = versymhdr->sh_size; + if (bfd_seek (abfd, versymhdr->sh_offset, SEEK_SET) != 0 + || bfd_bread ((PTR) extversym, amt, abfd) != amt) + goto error_free_vers; + } } weaks = NULL; ever = extversym != NULL ? extversym + extsymoff : NULL; - esymend = buf + extsymcount; - for (esym = buf, shndx = shndx_buf; - esym < esymend; - esym++, sym_hash++, ever = (ever != NULL ? ever + 1 : NULL), - shndx = (shndx != NULL ? shndx + 1 : NULL)) + for (isym = isymbuf, isymend = isymbuf + extsymcount; + isym < isymend; + isym++, sym_hash++, ever = (ever != NULL ? ever + 1 : NULL)) { - Elf_Internal_Sym sym; int bind; bfd_vma value; asection *sec; @@ -1666,14 +1596,12 @@ elf_link_add_object_symbols (abfd, info) override = false; - elf_swap_symbol_in (abfd, (const PTR) esym, (const PTR) shndx, &sym); - flags = BSF_NO_FLAGS; sec = NULL; - value = sym.st_value; + value = isym->st_value; *sym_hash = NULL; - bind = ELF_ST_BIND (sym.st_info); + bind = ELF_ST_BIND (isym->st_info); if (bind == STB_LOCAL) { /* This should be impossible, since ELF requires that all @@ -1684,8 +1612,8 @@ elf_link_add_object_symbols (abfd, info) } else if (bind == STB_GLOBAL) { - if (sym.st_shndx != SHN_UNDEF - && sym.st_shndx != SHN_COMMON) + if (isym->st_shndx != SHN_UNDEF + && isym->st_shndx != SHN_COMMON) flags = BSF_GLOBAL; } else if (bind == STB_WEAK) @@ -1695,35 +1623,37 @@ elf_link_add_object_symbols (abfd, info) /* Leave it up to the processor backend. */ } - if (sym.st_shndx == SHN_UNDEF) + if (isym->st_shndx == SHN_UNDEF) sec = bfd_und_section_ptr; - else if (sym.st_shndx < SHN_LORESERVE || sym.st_shndx > SHN_HIRESERVE) + else if (isym->st_shndx < SHN_LORESERVE || isym->st_shndx > SHN_HIRESERVE) { - sec = section_from_elf_index (abfd, sym.st_shndx); + sec = section_from_elf_index (abfd, isym->st_shndx); if (sec == NULL) sec = bfd_abs_section_ptr; else if ((abfd->flags & (EXEC_P | DYNAMIC)) != 0) value -= sec->vma; } - else if (sym.st_shndx == SHN_ABS) + else if (isym->st_shndx == SHN_ABS) sec = bfd_abs_section_ptr; - else if (sym.st_shndx == SHN_COMMON) + else if (isym->st_shndx == SHN_COMMON) { sec = bfd_com_section_ptr; /* What ELF calls the size we call the value. What ELF calls the value we call the alignment. */ - value = sym.st_size; + value = isym->st_size; } else { /* Leave it up to the processor backend. */ } - name = bfd_elf_string_from_elf_section (abfd, hdr->sh_link, sym.st_name); + name = bfd_elf_string_from_elf_section (abfd, hdr->sh_link, + isym->st_name); if (name == (const char *) NULL) - goto error_return; + goto error_free_vers; - if (sym.st_shndx == SHN_COMMON && ELF_ST_TYPE (sym.st_info) == STT_TLS) + if (isym->st_shndx == SHN_COMMON + && ELF_ST_TYPE (isym->st_info) == STT_TLS) { asection *tcomm = bfd_get_section_by_name (abfd, ".tcommon"); @@ -1735,15 +1665,15 @@ elf_link_add_object_symbols (abfd, info) | SEC_IS_COMMON | SEC_LINKER_CREATED | SEC_THREAD_LOCAL))) - goto error_return; + goto error_free_vers; } sec = tcomm; } else if (add_symbol_hook) { - if (! (*add_symbol_hook) (abfd, info, &sym, &name, &flags, &sec, + if (! (*add_symbol_hook) (abfd, info, isym, &name, &flags, &sec, &value)) - goto error_return; + goto error_free_vers; /* The hook function sets the name to NULL if this symbol should be skipped for some reason. */ @@ -1755,7 +1685,7 @@ elf_link_add_object_symbols (abfd, info) if (sec == (asection *) NULL) { bfd_set_error (bfd_error_bad_value); - goto error_return; + goto error_free_vers; } if (bfd_is_und_section (sec) @@ -1789,7 +1719,7 @@ elf_link_add_object_symbols (abfd, info) size_t namelen, verlen, newlen; char *newname, *p; - if (sym.st_shndx != SHN_UNDEF) + if (isym->st_shndx != SHN_UNDEF) { if (vernum > elf_tdata (abfd)->dynverdef_hdr.sh_info) { @@ -1798,7 +1728,7 @@ elf_link_add_object_symbols (abfd, info) bfd_archive_filename (abfd), name, vernum, elf_tdata (abfd)->dynverdef_hdr.sh_info); bfd_set_error (bfd_error_bad_value); - goto error_return; + goto error_free_vers; } else if (vernum > 1) verstr = @@ -1838,7 +1768,7 @@ elf_link_add_object_symbols (abfd, info) (_("%s: %s: invalid needed version %d"), bfd_archive_filename (abfd), name, vernum); bfd_set_error (bfd_error_bad_value); - goto error_return; + goto error_free_vers; } } @@ -1846,12 +1776,12 @@ elf_link_add_object_symbols (abfd, info) verlen = strlen (verstr); newlen = namelen + verlen + 2; if ((iver.vs_vers & VERSYM_HIDDEN) == 0 - && sym.st_shndx != SHN_UNDEF) + && isym->st_shndx != SHN_UNDEF) ++newlen; newname = (char *) bfd_alloc (abfd, (bfd_size_type) newlen); if (newname == NULL) - goto error_return; + goto error_free_vers; memcpy (newname, name, namelen); p = newname + namelen; *p++ = ELF_VER_CHR; @@ -1859,7 +1789,7 @@ elf_link_add_object_symbols (abfd, info) we add another @ to the name. This indicates the default version of the symbol. */ if ((iver.vs_vers & VERSYM_HIDDEN) == 0 - && sym.st_shndx != SHN_UNDEF) + && isym->st_shndx != SHN_UNDEF) *p++ = ELF_VER_CHR; memcpy (p, verstr, verlen + 1); @@ -1867,10 +1797,10 @@ elf_link_add_object_symbols (abfd, info) } } - if (! elf_merge_symbol (abfd, info, name, &sym, &sec, &value, + if (! elf_merge_symbol (abfd, info, name, isym, &sec, &value, sym_hash, &override, &type_change_ok, &size_change_ok, dt_needed)) - goto error_return; + goto error_free_vers; if (override) definition = false; @@ -1898,7 +1828,7 @@ elf_link_add_object_symbols (abfd, info) if (! (_bfd_generic_link_add_one_symbol (info, abfd, name, flags, sec, value, (const char *) NULL, false, collect, (struct bfd_link_hash_entry **) sym_hash))) - goto error_return; + goto error_free_vers; h = *sym_hash; while (h->root.type == bfd_link_hash_indirect @@ -1910,7 +1840,7 @@ elf_link_add_object_symbols (abfd, info) if (dynamic && definition && (flags & BSF_WEAK) != 0 - && ELF_ST_TYPE (sym.st_info) != STT_FUNC + && ELF_ST_TYPE (isym->st_info) != STT_FUNC && info->hash->creator->flavour == bfd_target_elf_flavour && h->weakdef == NULL) { @@ -1932,16 +1862,16 @@ elf_link_add_object_symbols (abfd, info) } /* Set the alignment of a common symbol. */ - if (sym.st_shndx == SHN_COMMON + if (isym->st_shndx == SHN_COMMON && h->root.type == bfd_link_hash_common) { unsigned int align; - align = bfd_log2 (sym.st_value); + align = bfd_log2 (isym->st_value); if (align > old_alignment /* Permit an alignment power of zero if an alignment of one is specified and no other alignments have been specified. */ - || (sym.st_value == 1 && old_alignment == 0)) + || (isym->st_value == 1 && old_alignment == 0)) h->root.u.c.p->alignment_power = align; } @@ -1952,16 +1882,16 @@ elf_link_add_object_symbols (abfd, info) int new_flag; /* Remember the symbol size and type. */ - if (sym.st_size != 0 + if (isym->st_size != 0 && (definition || h->size == 0)) { - if (h->size != 0 && h->size != sym.st_size && ! size_change_ok) + if (h->size != 0 && h->size != isym->st_size && ! size_change_ok) (*_bfd_error_handler) (_("Warning: size of symbol `%s' changed from %lu to %lu in %s"), - name, (unsigned long) h->size, (unsigned long) sym.st_size, - bfd_archive_filename (abfd)); + name, (unsigned long) h->size, + (unsigned long) isym->st_size, bfd_archive_filename (abfd)); - h->size = sym.st_size; + h->size = isym->st_size; } /* If this is a common symbol, then we always want H->SIZE @@ -1972,37 +1902,37 @@ elf_link_add_object_symbols (abfd, info) if (h->root.type == bfd_link_hash_common) h->size = h->root.u.c.size; - if (ELF_ST_TYPE (sym.st_info) != STT_NOTYPE + if (ELF_ST_TYPE (isym->st_info) != STT_NOTYPE && (definition || h->type == STT_NOTYPE)) { if (h->type != STT_NOTYPE - && h->type != ELF_ST_TYPE (sym.st_info) + && h->type != ELF_ST_TYPE (isym->st_info) && ! type_change_ok) (*_bfd_error_handler) (_("Warning: type of symbol `%s' changed from %d to %d in %s"), - name, h->type, ELF_ST_TYPE (sym.st_info), + name, h->type, ELF_ST_TYPE (isym->st_info), bfd_archive_filename (abfd)); - h->type = ELF_ST_TYPE (sym.st_info); + h->type = ELF_ST_TYPE (isym->st_info); } /* If st_other has a processor-specific meaning, specific code might be needed here. */ - if (sym.st_other != 0) + if (isym->st_other != 0) { /* Combine visibilities, using the most constraining one. */ unsigned char hvis = ELF_ST_VISIBILITY (h->other); - unsigned char symvis = ELF_ST_VISIBILITY (sym.st_other); + unsigned char symvis = ELF_ST_VISIBILITY (isym->st_other); if (symvis && (hvis > symvis || hvis == 0)) - h->other = sym.st_other; + h->other = isym->st_other; /* If neither has visibility, use the st_other of the definition. This is an arbitrary choice, since the other bits have no general meaning. */ if (!symvis && !hvis && (definition || h->other == 0)) - h->other = sym.st_other; + h->other = isym->st_other; } /* Set a flag in the hash table entry indicating the type of @@ -2046,21 +1976,21 @@ elf_link_add_object_symbols (abfd, info) /* Check to see if we need to add an indirect symbol for the default name. */ if (definition || h->root.type == bfd_link_hash_common) - if (! elf_add_default_symbol (abfd, info, h, name, &sym, + if (! elf_add_default_symbol (abfd, info, h, name, isym, &sec, &value, &dynsym, override, dt_needed)) - goto error_return; + goto error_free_vers; if (dynsym && h->dynindx == -1) { if (! _bfd_elf_link_record_dynamic_symbol (info, h)) - goto error_return; + goto error_free_vers; if (h->weakdef != NULL && ! new_weakdef && h->weakdef->dynindx == -1) { if (! _bfd_elf_link_record_dynamic_symbol (info, h->weakdef)) - goto error_return; + goto error_free_vers; } } else if (dynsym && h->dynindx != -1) @@ -2083,7 +2013,7 @@ elf_link_add_object_symbols (abfd, info) bfd_size_type strindex; if (! is_elf_hash_table (info)) - goto error_return; + goto error_free_vers; /* The symbol from a DT_NEEDED object is referenced from the regular object to create a dynamic executable. We @@ -2094,7 +2024,7 @@ elf_link_add_object_symbols (abfd, info) strindex = _bfd_elf_strtab_add (hash_table->dynstr, elf_dt_soname (abfd), false); if (strindex == (bfd_size_type) -1) - goto error_return; + goto error_free_vers; if (oldsize == _bfd_elf_strtab_size (hash_table->dynstr)) { @@ -2120,11 +2050,21 @@ elf_link_add_object_symbols (abfd, info) } if (! elf_add_dynamic_entry (info, (bfd_vma) DT_NEEDED, strindex)) - goto error_return; + goto error_free_vers; } } } + if (extversym != NULL) + { + free (extversym); + extversym = NULL; + } + + if (isymbuf != NULL) + free (isymbuf); + isymbuf = NULL; + /* Now set the weakdefs field correctly for all the weak defined symbols we found. The only way to do this is to search all the symbols. Since we only need the information for non functions in @@ -2192,24 +2132,11 @@ elf_link_add_object_symbols (abfd, info) if (! _bfd_elf_link_record_dynamic_symbol (info, hlook)) goto error_return; } - break; } } } - if (buf != NULL) - { - free (buf); - buf = NULL; - } - - if (extversym != NULL) - { - free (extversym); - extversym = NULL; - } - /* If this object is the same format as the output object, and it is not a shared library, then let the backend look through the relocs. @@ -2255,7 +2182,7 @@ elf_link_add_object_symbols (abfd, info) ok = (*check_relocs) (abfd, info, o, internal_relocs); - if (! info->keep_memory) + if (elf_section_data (o)->relocs != internal_relocs) free (internal_relocs); if (! ok) @@ -2334,13 +2261,13 @@ elf_link_add_object_symbols (abfd, info) return true; - error_return: - if (buf != NULL) - free (buf); - if (dynbuf != NULL) - free (dynbuf); + error_free_vers: if (extversym != NULL) free (extversym); + error_free_sym: + if (isymbuf != NULL) + free (isymbuf); + error_return: return false; } @@ -5050,7 +4977,7 @@ elf_bfd_final_link (abfd, info) o->reloc_count += (*bed->elf_backend_count_relocs) (sec, relocs); - if (!info->keep_memory) + if (elf_section_data (o)->relocs != relocs) free (relocs); } @@ -6072,8 +5999,6 @@ elf_link_check_versioned_symbol (info, h) { bfd *undef_bfd = h->root.u.undef.abfd; struct elf_link_loaded_list *loaded; - Elf_External_Sym *buf; - Elf_External_Versym *extversym; if ((undef_bfd->flags & DYNAMIC) == 0 || info->hash->creator->flavour != bfd_target_elf_flavour @@ -6090,11 +6015,11 @@ elf_link_check_versioned_symbol (info, h) bfd_size_type extsymcount; bfd_size_type extsymoff; Elf_Internal_Shdr *versymhdr; + Elf_Internal_Sym *isym; + Elf_Internal_Sym *isymend; + Elf_Internal_Sym *isymbuf; Elf_External_Versym *ever; - Elf_External_Sym *esym; - Elf_External_Sym *esymend; - bfd_size_type count; - file_ptr pos; + Elf_External_Versym *extversym; input = loaded->abfd; @@ -6121,17 +6046,11 @@ elf_link_check_versioned_symbol (info, h) if (extsymcount == 0) continue; - count = extsymcount * sizeof (Elf_External_Sym); - buf = (Elf_External_Sym *) bfd_malloc (count); - if (buf == NULL) + isymbuf = bfd_elf_get_elf_syms (input, hdr, extsymcount, extsymoff, + NULL, NULL, NULL); + if (isymbuf == NULL) return false; - /* Read in the symbol table. */ - pos = hdr->sh_offset + extsymoff * sizeof (Elf_External_Sym); - if (bfd_seek (input, pos, SEEK_SET) != 0 - || bfd_bread ((PTR) buf, count, input) != count) - goto error_ret; - /* Read in any version definitions. */ versymhdr = &elf_tdata (input)->dynversym_hdr; extversym = (Elf_External_Versym *) bfd_malloc (versymhdr->sh_size); @@ -6144,26 +6063,24 @@ elf_link_check_versioned_symbol (info, h) { free (extversym); error_ret: - free (buf); + free (isymbuf); return false; } ever = extversym + extsymoff; - esymend = buf + extsymcount; - for (esym = buf; esym < esymend; esym++, ever++) + isymend = isymbuf + extsymcount; + for (isym = isymbuf; isym < isymend; isym++, ever++) { const char *name; - Elf_Internal_Sym sym; Elf_Internal_Versym iver; - elf_swap_symbol_in (input, esym, NULL, &sym); - if (ELF_ST_BIND (sym.st_info) == STB_LOCAL - || sym.st_shndx == SHN_UNDEF) + if (ELF_ST_BIND (isym->st_info) == STB_LOCAL + || isym->st_shndx == SHN_UNDEF) continue; name = bfd_elf_string_from_elf_section (input, hdr->sh_link, - sym.st_name); + isym->st_name); if (strcmp (name, h->root.root.string) != 0) continue; @@ -6180,13 +6097,13 @@ elf_link_check_versioned_symbol (info, h) { /* This is the oldest (default) sym. We can use it. */ free (extversym); - free (buf); + free (isymbuf); return true; } } free (extversym); - free (buf); + free (isymbuf); } return false; @@ -6611,15 +6528,11 @@ elf_link_input_bfd (finfo, input_bfd) Elf_Internal_Sym *, asection **)); bfd *output_bfd; Elf_Internal_Shdr *symtab_hdr; - Elf_Internal_Shdr *shndx_hdr; size_t locsymcount; size_t extsymoff; - Elf_External_Sym *external_syms; - Elf_External_Sym *esym; - Elf_External_Sym *esymend; - Elf_External_Sym_Shndx *shndx_buf; - Elf_External_Sym_Shndx *shndx; + Elf_Internal_Sym *isymbuf; Elf_Internal_Sym *isym; + Elf_Internal_Sym *isymend; long *pindex; asection **ppsection; asection *o; @@ -6654,45 +6567,29 @@ elf_link_input_bfd (finfo, input_bfd) } /* Read the local symbols. */ - if (symtab_hdr->contents != NULL) - external_syms = (Elf_External_Sym *) symtab_hdr->contents; - else if (locsymcount == 0) - external_syms = NULL; - else + isymbuf = (Elf_Internal_Sym *) symtab_hdr->contents; + if (isymbuf == NULL && locsymcount != 0) { - bfd_size_type amt = locsymcount * sizeof (Elf_External_Sym); - external_syms = finfo->external_syms; - if (bfd_seek (input_bfd, symtab_hdr->sh_offset, SEEK_SET) != 0 - || bfd_bread (external_syms, amt, input_bfd) != amt) + isymbuf = bfd_elf_get_elf_syms (input_bfd, symtab_hdr, locsymcount, 0, + finfo->internal_syms, + finfo->external_syms, + finfo->locsym_shndx); + if (isymbuf == NULL) return false; } - shndx_hdr = &elf_tdata (input_bfd)->symtab_shndx_hdr; - shndx_buf = NULL; - if (shndx_hdr->sh_size != 0 && locsymcount != 0) - { - bfd_size_type amt = locsymcount * sizeof (Elf_External_Sym_Shndx); - shndx_buf = finfo->locsym_shndx; - if (bfd_seek (input_bfd, shndx_hdr->sh_offset, SEEK_SET) != 0 - || bfd_bread (shndx_buf, amt, input_bfd) != amt) - return false; - } - - /* Swap in the local symbols and write out the ones which we know - are going into the output file. */ - for (esym = external_syms, esymend = esym + locsymcount, - isym = finfo->internal_syms, pindex = finfo->indices, - ppsection = finfo->sections, shndx = shndx_buf; - esym < esymend; - esym++, isym++, pindex++, ppsection++, - shndx = (shndx != NULL ? shndx + 1 : NULL)) + /* Find local symbol sections and adjust values of symbols in + SEC_MERGE sections. Write out those local symbols we know are + going into the output file. */ + isymend = isymbuf + locsymcount; + for (isym = isymbuf, pindex = finfo->indices, ppsection = finfo->sections; + isym < isymend; + isym++, pindex++, ppsection++) { asection *isec; const char *name; Elf_Internal_Sym osym; - elf_swap_symbol_in (input_bfd, (const PTR) esym, (const PTR) shndx, - isym); *pindex = -1; if (elf_bad_symtab (input_bfd)) @@ -6731,7 +6628,7 @@ elf_link_input_bfd (finfo, input_bfd) *ppsection = isec; /* Don't output the first, undefined, symbol. */ - if (esym == external_syms) + if (ppsection == finfo->sections) continue; if (ELF_ST_TYPE (isym->st_info) == STT_SECTION) @@ -7001,7 +6898,7 @@ elf_link_input_bfd (finfo, input_bfd) if (! (*relocate_section) (output_bfd, finfo->info, input_bfd, o, contents, internal_relocs, - finfo->internal_syms, + isymbuf, finfo->sections)) return false; @@ -7085,7 +6982,7 @@ elf_link_input_bfd (finfo, input_bfd) /* This is a reloc against a local symbol. */ *rel_hash = NULL; - isym = finfo->internal_syms + r_symndx; + isym = isymbuf + r_symndx; sec = finfo->sections[r_symndx]; if (ELF_ST_TYPE (isym->st_info) == STT_SECTION) { @@ -7762,17 +7659,12 @@ elf_gc_mark (info, sec, gc_mark_hook) { Elf_Internal_Rela *relstart, *rel, *relend; Elf_Internal_Shdr *symtab_hdr; - Elf_Internal_Shdr *shndx_hdr; struct elf_link_hash_entry **sym_hashes; size_t nlocsyms; size_t extsymoff; - Elf_External_Sym *locsyms, *freesyms = NULL; - Elf_External_Sym_Shndx *locsym_shndx; bfd *input_bfd = sec->owner; struct elf_backend_data *bed = get_elf_backend_data (input_bfd); - - /* GCFIXME: how to arrange so that relocs and symbols are not - reread continually? */ + Elf_Internal_Sym *isym = NULL; symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr; sym_hashes = elf_sym_hashes (input_bfd); @@ -7786,37 +7678,18 @@ elf_gc_mark (info, sec, gc_mark_hook) else extsymoff = nlocsyms = symtab_hdr->sh_info; - if (symtab_hdr->contents) - locsyms = (Elf_External_Sym *) symtab_hdr->contents; - else if (nlocsyms == 0) - locsyms = NULL; - else + isym = (Elf_Internal_Sym *) symtab_hdr->contents; + if (isym == NULL && nlocsyms != 0) { - bfd_size_type amt = nlocsyms * sizeof (Elf_External_Sym); - locsyms = freesyms = bfd_malloc (amt); - if (freesyms == NULL - || bfd_seek (input_bfd, symtab_hdr->sh_offset, SEEK_SET) != 0 - || bfd_bread (locsyms, amt, input_bfd) != amt) - { - ret = false; - goto out1; - } - } - - shndx_hdr = &elf_tdata (input_bfd)->symtab_shndx_hdr; - locsym_shndx = NULL; - if (shndx_hdr->sh_size != 0 && nlocsyms != 0) - { - bfd_size_type amt = nlocsyms * sizeof (Elf_External_Sym_Shndx); - locsym_shndx = (Elf_External_Sym_Shndx *) bfd_malloc (amt); - if (bfd_seek (input_bfd, shndx_hdr->sh_offset, SEEK_SET) != 0 - || bfd_bread (locsym_shndx, amt, input_bfd) != amt) + isym = bfd_elf_get_elf_syms (input_bfd, symtab_hdr, nlocsyms, 0, + NULL, NULL, NULL); + if (isym == NULL) return false; } /* Read the relocations. */ relstart = (NAME(_bfd_elf,link_read_relocs) - (sec->owner, sec, NULL, (Elf_Internal_Rela *) NULL, + (input_bfd, sec, NULL, (Elf_Internal_Rela *) NULL, info->keep_memory)); if (relstart == NULL) { @@ -7830,41 +7703,20 @@ elf_gc_mark (info, sec, gc_mark_hook) unsigned long r_symndx; asection *rsec; struct elf_link_hash_entry *h; - Elf_Internal_Sym s; - Elf_External_Sym_Shndx *locshndx; r_symndx = ELF_R_SYM (rel->r_info); if (r_symndx == 0) continue; - if (elf_bad_symtab (sec->owner)) - { - locshndx = locsym_shndx + (locsym_shndx ? r_symndx : 0); - elf_swap_symbol_in (input_bfd, - (const PTR) (locsyms + r_symndx), - (const PTR) locshndx, - &s); - if (ELF_ST_BIND (s.st_info) == STB_LOCAL) - rsec = (*gc_mark_hook) (sec, info, rel, NULL, &s); - else - { - h = sym_hashes[r_symndx - extsymoff]; - rsec = (*gc_mark_hook) (sec, info, rel, h, NULL); - } - } - else if (r_symndx >= nlocsyms) + if (r_symndx >= nlocsyms + || ELF_ST_BIND (isym[r_symndx].st_info) != STB_LOCAL) { h = sym_hashes[r_symndx - extsymoff]; rsec = (*gc_mark_hook) (sec, info, rel, h, NULL); } else { - locshndx = locsym_shndx + (locsym_shndx ? r_symndx : 0); - elf_swap_symbol_in (input_bfd, - (const PTR) (locsyms + r_symndx), - (const PTR) locshndx, - &s); - rsec = (*gc_mark_hook) (sec, info, rel, NULL, &s); + rsec = (*gc_mark_hook) (sec, info, rel, NULL, &isym[r_symndx]); } if (rsec && !rsec->gc_mark) @@ -7880,11 +7732,16 @@ elf_gc_mark (info, sec, gc_mark_hook) } out2: - if (!info->keep_memory) + if (elf_section_data (sec)->relocs != relstart) free (relstart); out1: - if (freesyms) - free (freesyms); + if (isym != NULL && symtab_hdr->contents != (unsigned char *) isym) + { + if (! info->keep_memory) + free (isym); + else + symtab_hdr->contents = (unsigned char *) isym; + } } return ret; @@ -7941,7 +7798,7 @@ elf_gc_sweep (info, gc_sweep_hook) r = (*gc_sweep_hook) (o->owner, info, o, internal_relocs); - if (!info->keep_memory) + if (elf_section_data (o)->relocs != internal_relocs) free (internal_relocs); if (!r) @@ -8439,7 +8296,6 @@ elf_reloc_symbol_deleted_p (offset, cookie) for (; rcookie->rel < rcookie->relend; rcookie->rel++) { unsigned long r_symndx = ELF_R_SYM (rcookie->rel->r_info); - Elf_Internal_Sym isym; if (! rcookie->bad_symtab) if (rcookie->rel->r_offset > offset) @@ -8447,22 +8303,8 @@ elf_reloc_symbol_deleted_p (offset, cookie) if (rcookie->rel->r_offset != offset) continue; - if (rcookie->locsyms && r_symndx < rcookie->locsymcount) - { - Elf_External_Sym *lsym; - Elf_External_Sym_Shndx *lshndx; - - lsym = (Elf_External_Sym *) rcookie->locsyms + r_symndx; - lshndx = (Elf_External_Sym_Shndx *) rcookie->locsym_shndx; - if (lshndx != NULL) - lshndx += r_symndx; - elf_swap_symbol_in (rcookie->abfd, (const PTR) lsym, - (const PTR) lshndx, &isym); - } - if (r_symndx >= rcookie->locsymcount - || (rcookie->locsyms - && ELF_ST_BIND (isym.st_info) != STB_LOCAL)) + || ELF_ST_BIND (rcookie->locsyms[r_symndx].st_info) != STB_LOCAL) { struct elf_link_hash_entry *h; @@ -8479,17 +8321,19 @@ elf_reloc_symbol_deleted_p (offset, cookie) else return false; } - else if (rcookie->locsyms) + else { /* It's not a relocation against a global symbol, but it could be a relocation against a local symbol for a discarded section. */ asection *isec; + Elf_Internal_Sym *isym; /* Need to: get the symbol; get the section. */ - if (isym.st_shndx < SHN_LORESERVE || isym.st_shndx > SHN_HIRESERVE) + isym = &rcookie->locsyms[r_symndx]; + if (isym->st_shndx < SHN_LORESERVE || isym->st_shndx > SHN_HIRESERVE) { - isec = section_from_elf_index (rcookie->abfd, isym.st_shndx); + isec = section_from_elf_index (rcookie->abfd, isym->st_shndx); if (isec != NULL && elf_discarded_section (isec)) return true; } @@ -8512,8 +8356,6 @@ elf_bfd_discard_info (output_bfd, info) struct elf_reloc_cookie cookie; asection *stab, *eh, *ehdr; Elf_Internal_Shdr *symtab_hdr; - Elf_Internal_Shdr *shndx_hdr; - Elf_External_Sym *freesyms; struct elf_backend_data *bed; bfd *abfd; boolean ret = false; @@ -8564,8 +8406,6 @@ elf_bfd_discard_info (output_bfd, info) continue; symtab_hdr = &elf_tdata (abfd)->symtab_hdr; - shndx_hdr = &elf_tdata (abfd)->symtab_shndx_hdr; - cookie.abfd = abfd; cookie.sym_hashes = elf_sym_hashes (abfd); cookie.bad_symtab = elf_bad_symtab (abfd); @@ -8581,48 +8421,20 @@ elf_bfd_discard_info (output_bfd, info) cookie.extsymoff = symtab_hdr->sh_info; } - freesyms = NULL; - if (symtab_hdr->contents) - cookie.locsyms = (void *) symtab_hdr->contents; - else if (cookie.locsymcount == 0) - cookie.locsyms = NULL; - else + cookie.locsyms = (Elf_Internal_Sym *) symtab_hdr->contents; + if (cookie.locsyms == NULL && cookie.locsymcount != 0) { - bfd_size_type amt = cookie.locsymcount * sizeof (Elf_External_Sym); - cookie.locsyms = bfd_malloc (amt); + cookie.locsyms = bfd_elf_get_elf_syms (abfd, symtab_hdr, + cookie.locsymcount, 0, + NULL, NULL, NULL); if (cookie.locsyms == NULL) return false; - freesyms = cookie.locsyms; - if (bfd_seek (abfd, symtab_hdr->sh_offset, SEEK_SET) != 0 - || bfd_bread (cookie.locsyms, amt, abfd) != amt) - { - error_ret_free_loc: - free (cookie.locsyms); - return false; - } - } - - cookie.locsym_shndx = NULL; - if (shndx_hdr->sh_size != 0 && cookie.locsymcount != 0) - { - bfd_size_type amt; - amt = cookie.locsymcount * sizeof (Elf_External_Sym_Shndx); - cookie.locsym_shndx = bfd_malloc (amt); - if (cookie.locsym_shndx == NULL) - goto error_ret_free_loc; - if (bfd_seek (abfd, shndx_hdr->sh_offset, SEEK_SET) != 0 - || bfd_bread (cookie.locsym_shndx, amt, abfd) != amt) - { - free (cookie.locsym_shndx); - goto error_ret_free_loc; - } } if (stab) { cookie.rels = (NAME(_bfd_elf,link_read_relocs) - (abfd, stab, (PTR) NULL, - (Elf_Internal_Rela *) NULL, + (abfd, stab, (PTR) NULL, (Elf_Internal_Rela *) NULL, info->keep_memory)); if (cookie.rels) { @@ -8634,7 +8446,7 @@ elf_bfd_discard_info (output_bfd, info) elf_reloc_symbol_deleted_p, &cookie)) ret = true; - if (! info->keep_memory) + if (elf_section_data (stab)->relocs != cookie.rels) free (cookie.rels); } } @@ -8658,7 +8470,7 @@ elf_bfd_discard_info (output_bfd, info) elf_reloc_symbol_deleted_p, &cookie)) ret = true; - if (! info->keep_memory) + if (cookie.rels && elf_section_data (eh)->relocs != cookie.rels) free (cookie.rels); } @@ -8668,11 +8480,14 @@ elf_bfd_discard_info (output_bfd, info) ret = true; } - if (cookie.locsym_shndx != NULL) - free (cookie.locsym_shndx); - - if (freesyms != NULL) - free (freesyms); + if (cookie.locsyms != NULL + && symtab_hdr->contents != (unsigned char *) cookie.locsyms) + { + if (! info->keep_memory) + free (cookie.locsyms); + else + symtab_hdr->contents = (unsigned char *) cookie.locsyms; + } } if (ehdr && _bfd_elf_discard_section_eh_frame_hdr (output_bfd, info, ehdr)) diff --git a/bfd/elfxx-ia64.c b/bfd/elfxx-ia64.c index c86ad43ac8..108cdf0664 100644 --- a/bfd/elfxx-ia64.c +++ b/bfd/elfxx-ia64.c @@ -691,15 +691,10 @@ elfNN_ia64_relax_section (abfd, sec, link_info, again) }; Elf_Internal_Shdr *symtab_hdr; - Elf_Internal_Shdr *shndx_hdr; Elf_Internal_Rela *internal_relocs; - Elf_Internal_Rela *free_relocs = NULL; Elf_Internal_Rela *irel, *irelend; bfd_byte *contents; - bfd_byte *free_contents = NULL; - ElfNN_External_Sym *extsyms; - ElfNN_External_Sym *free_extsyms = NULL; - Elf_External_Sym_Shndx *shndx_buf = NULL; + Elf_Internal_Sym *isymbuf = NULL; struct elfNN_ia64_link_hash_table *ia64_info; struct one_fixup *fixups = NULL; boolean changed_contents = false; @@ -726,10 +721,7 @@ elfNN_ia64_relax_section (abfd, sec, link_info, again) (abfd, sec, (PTR) NULL, (Elf_Internal_Rela *) NULL, link_info->keep_memory)); if (internal_relocs == NULL) - goto error_return; - - if (! link_info->keep_memory) - free_relocs = internal_relocs; + return false; ia64_info = elfNN_ia64_hash_table (link_info); irelend = internal_relocs + sec->reloc_count; @@ -741,8 +733,8 @@ elfNN_ia64_relax_section (abfd, sec, link_info, again) /* No branch-type relocations. */ if (irel == irelend) { - if (free_relocs != NULL) - free (free_relocs); + if (elf_section_data (sec)->relocs != internal_relocs) + free (internal_relocs); return true; } @@ -754,48 +746,15 @@ elfNN_ia64_relax_section (abfd, sec, link_info, again) contents = (bfd_byte *) bfd_malloc (sec->_raw_size); if (contents == NULL) goto error_return; - free_contents = contents; if (! bfd_get_section_contents (abfd, sec, contents, (file_ptr) 0, sec->_raw_size)) goto error_return; } - /* Read this BFD's local symbols. */ - if (symtab_hdr->contents != NULL) - extsyms = (ElfNN_External_Sym *) symtab_hdr->contents; - else - { - bfd_size_type amt; - - amt = symtab_hdr->sh_info * sizeof (ElfNN_External_Sym); - extsyms = (ElfNN_External_Sym *) bfd_malloc (amt); - if (extsyms == NULL) - goto error_return; - free_extsyms = extsyms; - if (bfd_seek (abfd, symtab_hdr->sh_offset, SEEK_SET) != 0 - || bfd_bread (extsyms, amt, abfd) != amt) - goto error_return; - } - - shndx_hdr = &elf_tdata (abfd)->symtab_shndx_hdr; - if (shndx_hdr->sh_size != 0) - { - bfd_size_type amt; - - amt = symtab_hdr->sh_info * sizeof (Elf_External_Sym_Shndx); - shndx_buf = (Elf_External_Sym_Shndx *) bfd_malloc (amt); - if (shndx_buf == NULL) - goto error_return; - if (bfd_seek (abfd, shndx_hdr->sh_offset, SEEK_SET) != 0 - || bfd_bread (shndx_buf, amt, abfd) != amt) - goto error_return; - } - for (; irel < irelend; irel++) { bfd_vma symaddr, reladdr, trampoff, toff, roff; - Elf_Internal_Sym isym; asection *tsec; struct one_fixup *f; bfd_size_type amt; @@ -806,26 +765,34 @@ elfNN_ia64_relax_section (abfd, sec, link_info, again) /* Get the value of the symbol referred to by the reloc. */ if (ELFNN_R_SYM (irel->r_info) < symtab_hdr->sh_info) { - ElfNN_External_Sym *esym; - Elf_External_Sym_Shndx *shndx; - /* A local symbol. */ - esym = extsyms + ELFNN_R_SYM (irel->r_info); - shndx = shndx_buf + (shndx_buf ? ELFNN_R_SYM (irel->r_info) : 0); - bfd_elfNN_swap_symbol_in (abfd, (const PTR) esym, (const PTR) shndx, - &isym); - if (isym.st_shndx == SHN_UNDEF) + Elf_Internal_Sym *isym; + + /* Read this BFD's local symbols. */ + if (isymbuf == NULL) + { + isymbuf = (Elf_Internal_Sym *) symtab_hdr->contents; + if (isymbuf == NULL) + isymbuf = bfd_elf_get_elf_syms (abfd, symtab_hdr, + symtab_hdr->sh_info, 0, + NULL, NULL, NULL); + if (isymbuf == 0) + goto error_return; + } + + isym = isymbuf + ELF64_R_SYM (irel->r_info); + if (isym->st_shndx == SHN_UNDEF) continue; /* We can't do anthing with undefined symbols. */ - else if (isym.st_shndx == SHN_ABS) + else if (isym->st_shndx == SHN_ABS) tsec = bfd_abs_section_ptr; - else if (isym.st_shndx == SHN_COMMON) + else if (isym->st_shndx == SHN_COMMON) tsec = bfd_com_section_ptr; - else if (isym.st_shndx == SHN_IA_64_ANSI_COMMON) + else if (isym->st_shndx == SHN_IA_64_ANSI_COMMON) tsec = bfd_com_section_ptr; else - tsec = bfd_section_from_elf_index (abfd, isym.st_shndx); + tsec = bfd_section_from_elf_index (abfd, isym->st_shndx); - toff = isym.st_value; + toff = isym->st_value; } else { @@ -973,17 +940,23 @@ elfNN_ia64_relax_section (abfd, sec, link_info, again) free (f); } - if (changed_relocs) - elf_section_data (sec)->relocs = internal_relocs; - else if (free_relocs != NULL) - free (free_relocs); - - if (changed_contents) - elf_section_data (sec)->this_hdr.contents = contents; - else if (free_contents != NULL) + if (isymbuf != NULL + && symtab_hdr->contents != (unsigned char *) isymbuf) { if (! link_info->keep_memory) - free (free_contents); + free (isymbuf); + else + { + /* Cache the symbols for elf_link_input_bfd. */ + symtab_hdr->contents = (unsigned char *) isymbuf; + } + } + + if (contents != NULL + && elf_section_data (sec)->this_hdr.contents != contents) + { + if (!changed_contents && !link_info->keep_memory) + free (contents); else { /* Cache the section contents for elf_link_input_bfd. */ @@ -991,32 +964,26 @@ elfNN_ia64_relax_section (abfd, sec, link_info, again) } } - if (shndx_buf != NULL) - free (shndx_buf); - - if (free_extsyms != NULL) + if (elf_section_data (sec)->relocs != internal_relocs) { - if (! link_info->keep_memory) - free (free_extsyms); + if (!changed_relocs) + free (internal_relocs); else - { - /* Cache the symbols for elf_link_input_bfd. */ - symtab_hdr->contents = (unsigned char *) extsyms; - } + elf_section_data (sec)->relocs = internal_relocs; } *again = changed_contents || changed_relocs; return true; error_return: - if (free_relocs != NULL) - free (free_relocs); - if (free_contents != NULL) - free (free_contents); - if (shndx_buf != NULL) - free (shndx_buf); - if (free_extsyms != NULL) - free (free_extsyms); + if (isymbuf != NULL && (unsigned char *) isymbuf != symtab_hdr->contents) + free (isymbuf); + if (contents != NULL + && elf_section_data (sec)->this_hdr.contents != contents) + free (contents); + if (internal_relocs != NULL + && elf_section_data (sec)->relocs != internal_relocs) + free (internal_relocs); return false; } diff --git a/bfd/elfxx-mips.c b/bfd/elfxx-mips.c index 7b3bcc65bf..8ae1930415 100644 --- a/bfd/elfxx-mips.c +++ b/bfd/elfxx-mips.c @@ -4122,7 +4122,7 @@ _bfd_mips_elf_check_relocs (abfd, info, sec, relocs) && ELF_R_TYPE (abfd, r->r_info) != R_MIPS16_26) break; - if (! info->keep_memory) + if (elf_section_data (o)->relocs != sec_relocs) free (sec_relocs); if (r < rend)