]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
Support for more than 64k ELF sections.
authorAlan Modra <amodra@gmail.com>
Mon, 17 Dec 2001 00:52:35 +0000 (00:52 +0000)
committerAlan Modra <amodra@gmail.com>
Mon, 17 Dec 2001 00:52:35 +0000 (00:52 +0000)
include/elf/ChangeLog
* external.h (Elf_External_Sym_Shndx): Declare.
* internal.h (struct elf_internal_sym <st_shndx>): Make it an
unsigned int.
* common.h (SHN_BAD): Define.

bfd/ChangeLog
* configure.in: Bump bfd version.
* configure: Regenerate.
* elf-bfd.h (elf_size_info <swap_symbol_out>): Add shndx param.
(bfd_elf32_swap_symbol_in): Likewise.
(bfd_elf32_swap_symbol_out): Likewise.
(bfd_elf64_swap_symbol_in): Likewise.
(bfd_elf64_swap_symbol_out): Likewise.
(elf_reloc_cookie): Add locsym_shndx field.  Make locsyms a PTR.
(elf_obj_tdata): Add num_elf_sections, symtab_shndx_hdr and
symtab_shndx_section.
(elf_numsections): Define.
(elf_symtab_shndx): Define.
* elf.c (setup_group): Use elf_numsections rather than header e_shnum.
(bfd_elf_find_section): Likewise.
(bfd_section_from_elf_index): Likewise.
(bfd_section_from_shdr): Likewise.  Handle SHT_SYMTAB_SHNDX.
(bfd_section_from_r_symndx): Read symbol shndx extension, and
translate st_shndx for > SHN_HIRESERVE.
(assign_section_numbers): Skip reserved sections.  Assign
symtab_shndx_section and elf_numsections.  Exclude reserved
sections from e_shnum.  Set up symtab_shndx_hdr.
(_bfd_elf_compute_section_file_positions): Handle symtab_shndx_hdr.
(map_sections_to_segments): Don't map eh_frame_hdr unless required.
(assign_file_positions_except_relocs): Use elf_numsections rather
than header e_shnum.  Skip reserved sections and symtab_shndx_section.
(prep_headers): Set name for symtab_shndx_hdr.
(_bfd_elf_assign_file_positions_for_relocs): Use elf_numsections.
(_bfd_elf_write_object_contents): Likewise.  Skip reserved sections.
(_bfd_elf_section_from_bfd_section): Check bfd_{abs,com,und}_section
first.  Use elf_section_data if available.  Use elf_numsections.
Start scan at index 1.
(copy_private_bfd_data ): Comment fixes.
(MAP_ONESYMTAB): Define above SHN_HIOS.
(MAP_DYNSYMTAB): Likewise.
(MAP_STRTAB): Likewise.
(MAP_SHSTRTAB): Likewise.
(MAP_SYM_SHNDX): New define.
(_bfd_elf_copy_private_symbol_data): Handle symtab_shndx_section.
(swap_out_syms): Swap out SHT_SYMTAB_SHNDX section too.
* elfcode.h (elf_swap_symbol_in): Add shndx param, and handle shndx
extension.
(elf_swap_symbol_out): Likewise.
(elf_object_p): Set elf_numsections, and use instead of e_shnum.
Initialialise reserved elf_elfsections to point at shdr[0].  Remove
redundant bfd_release calls.
(elf_slurp_symbol_table): Read symbol shndx extension, and use with
elf_swap_symbol_in.  Translate st_shndx for > SHN_HIRESERVE too.
* elflink.h (elf_link_is_defined_archive_symbol): Read symbol shndx
extension, and use with elf_swap_symbol_in.
(elf_link_record_local_dynamic_symbol): Likewise.
(elf_link_add_object_symbols): Likewise.  Also translate st_shndx
for elf sections > SHN_HIRESERVE.
(NAME(bfd_elf,size_dynamic_sections)): Adjust elf_swap_symbol_out
call.
(struct elf_final_link_info): Add locsym_shndx and symshndxbuf.
(elf_bfd_final_link): Allocate the above, and tidy code allocating
other buffers.  Use elf_numsections instead of e_shnum.  Adjust
elf_swap_symbol_out calls.
(elf_link_output_sym): Swap out symbol shndx extension too.
(elf_link_flush_output_syms): And flush them to disk.
(elf_link_output_extsym): Use SHN_BAD.  Adjust elf_swap_symbol_out
calls.
(elf_gc_mark): Read symbol shndx extension, and use with
elf_swap_symbol_in.
(elf_link_input_bfd): Likewise,  Translate st_shndx for elf sections
> SHN_HIRESERVE too.  Use SHN_BAD.
(elf_reloc_symbol_deleted_p): Use symbol shndx extensions with
elf_swap_symbol_in.  Translate st_shndx > SHN_HIRESERVE too.
(elf_bfd_discard_info): Read symbol shndx extension.  Don't attempt
to continue after a bfd error.
* elf-m10200.c (mn10200_elf_relax_section): Only read local syms.
Stash them immediately to symtab_hdr->contents rather than later
in multiple places.  Clean up afterwards.  Read symbol shndx
extension, and use with swap_symbol_in.  Translate SHN_UNDEF,
SHN_ABS, SHN_COMMON and elf sections > SHN_HIRESERVE to bfd
sections too.  Remove dead code.
(mn10200_elf_relax_delete_bytes): Use symbol shndx extension
when swapping in symbols.  Tidy code adjusting global syms.
Don't swap in global syms.
(mn10200_elf_symbol_address_p): Likewise.  Remove extsyms param.
(mn10200_elf_get_relocated_section_contents): Read symbol shndx
extension, and use with swap_symbol_in.  Rename "size" -> "amt"
to maximize code in common with other files.  Translate st_shndx
for > SHN_HIRESERVE too.  Remove dead code.
* elf-m10300.c (mn10300_elf_relax_section): Only read local syms.
Stash them immediately to symtab_hdr->contents rather than later
in multiple places.  Clean up afterwards.  Read symbol shndx
extension, and use with swap_symbol_in.  Remove dead code.
(mn10300_elf_relax_delete_bytes): As for elf-m10200.c.
(mn10300_elf_symbol_address_p): Likewise.
(mn10300_elf_get_relocated_section_contents): Likewise.
* elf32-h8300.c (elf32_h8_relax_section): As for elf-m10300.c.
(elf32_h8_relax_delete_bytes): Likewise.
(elf32_h8_symbol_address_p): Likewise.
(elf32_h8_get_relocated_section_contents): Likewise.
* elf32-hppa.c (elf32_hppa_size_stubs): Read symbol shndx
extension, and use with swap_symbol_in.
* elf64-hppa.c (elf64_hppa_check_relocs): Likewise.
* elf32-i370.c (i370_elf_finish_dynamic_sections): Adjust call to
bfd_elf32_swap_symbol_out.
* elf32-m32r.c (m32r_elf_get_relocated_section_contents): Translate
elf sections > SHN_HIRESERVE too.
* elf32-m68k.c (bfd_m68k_elf32_create_embedded_relocs): Only read
local syms.  Read symbol shndx extension, and use with swap_symbol_in.
* elf32-mips.c (_bfd_mips_elf_final_write_processing): Use
elf_numsections rather than header e_shnum.
* elf32-sh.c (sh_elf_relax_section): As for elf-m10300.c.
(sh_elf_relax_delete_bytes): Likewise.
(sh_elf_get_relocated_section_contents): Likewise.  Only read local
symbols.
* elf32-v850.c (v850_elf_symbol_processing): Use an unsigned int to
hold section index.  Use elf_numsections rather than e_shnum.
Rename "index" -> "indx" to avoid shadowing warning.
(v850_elf_add_symbol_hook): Likewise.
* elf64-alpha.c (elf64_alpha_relax_section): Only read local syms.
Read symbol shndx extension, and use with swap_symbol_in.
* elf32-xstormy16.c (xstormy16_elf_relax_section): Likewise.
Translate SHN_COMMON and elf sections > SHN_HIRESERVE too.
* elfxx-ia64.c (elfNN_ia64_relax_section): Likewise.
(elfNN_ia64_aix_add_symbol_hook): Use elf_numsections.

* elf-m10300.c (mn10300_elf_gc_mark_hook): Remove unnecessary checks
before calling bfd_section_from_elf_index on local syms.
* elf32-arm.h (elf32_arm_gc_mark_hook): Likewise.
* elf32-avr.c (elf32_avr_gc_mark_hook): Likewise.
* elf32-cris.c (cris_elf_gc_mark_hook): Likewise.
* elf32-d10v.c (elf32_d10v_gc_mark_hook): Likewise.
* elf32-fr30.c (fr30_elf_gc_mark_hook): Likewise.
* elf32-hppa.c (elf32_hppa_gc_mark_hook): Likewise.
* elf32-i386.c (elf_i386_gc_mark_hook): Likewise.
* elf32-m32r.c (m32r_elf_gc_mark_hook): Likewise.
* elf32-m68k.c (elf_m68k_gc_mark_hook): Likewise.
* elf32-mcore.c (mcore_elf_gc_mark_hook): Likewise.
* elf32-mips.c (_bfd_mips_elf_gc_mark_hook): Likewise.
* elf32-openrisc.c (openrisc_elf_gc_mark_hook): Likewise.
* elf32-ppc.c (ppc_elf_gc_mark_hook): Likewise.
* elf32-s390.c (elf_s390_gc_mark_hook): Likewise.
* elf32-sh.c (sh_elf_gc_mark_hook): Likewise.
* elf32-sparc.c (elf32_sparc_gc_mark_hook): Likewise.
* elf32-v850.c (v850_elf_gc_mark_hook): Likewise.
* elf32-xstormy16.c (xstormy16_elf_gc_mark_hook): Likewise.
* elf64-mips.c (mips_elf64_gc_mark_hook): Likewise.
* elf64-mmix.c (mmix_elf_gc_mark_hook): Likewise.
* elf64-ppc.c (ppc64_elf_gc_mark_hook): Likewise.
* elf64-s390.c (elf_s390_gc_mark_hook): Likewise.
* elf64-x86-64.c (elf64_x86_64_gc_mark_hook): Likewise.

binutils/ChangeLog
* readelf.c (symtab_shndx_hdr): New global.
(SECTION_HEADER_INDEX): Define.
(SECTION_HEADER_NUM): Define.
(SECTION_HEADER): Define.
(GET_ELF_SYMBOLS): Pass two params rather than three.
(get_32bit_elf_symbols): Take file and section args.  Read and
use SHT_SYMTAB_SHNDX.
(get_64bit_elf_symbols): Likewise.
(dump_relocations): Use SECTION_HEADER to index "section_headers".
(process_section_headers): Likewise.  Use SECTION_HEADER_NUM too.
Remember symtab_shdx_hdr.
(process_program_headers): Scan from index 1 for segment map.
(slurp_ia64_unwind_table): Use SECTION_HEADER to index
"section_headers".
(process_relocs): Likewise.  Also adjust call to GET_ELF_SYMBOLS.
(process_unwind): Likewise.
(process_version_sections): Likewise.
(process_symbol_table): Likewise.
(display_debug_info): Likewise.
(process_dynamic_segment): Fake up a symtab section for changed
GET_ELF_SYMBOLS.
(get_symbol_index_type): Check SHN_LOOS before SHN_LORESERVE.
(process_program_headers): Kill signed/unsigned warning.
(load_debug_str): Likewise.
(display_debug_info): Likewise.

41 files changed:
bfd/ChangeLog
bfd/elf-bfd.h
bfd/elf-m10200.c
bfd/elf-m10300.c
bfd/elf.c
bfd/elf32-arm.h
bfd/elf32-avr.c
bfd/elf32-cris.c
bfd/elf32-d10v.c
bfd/elf32-fr30.c
bfd/elf32-h8300.c
bfd/elf32-hppa.c
bfd/elf32-i370.c
bfd/elf32-i386.c
bfd/elf32-m32r.c
bfd/elf32-m68k.c
bfd/elf32-mcore.c
bfd/elf32-mips.c
bfd/elf32-openrisc.c
bfd/elf32-ppc.c
bfd/elf32-s390.c
bfd/elf32-sh.c
bfd/elf32-sparc.c
bfd/elf32-v850.c
bfd/elf32-xstormy16.c
bfd/elf64-alpha.c
bfd/elf64-hppa.c
bfd/elf64-mips.c
bfd/elf64-mmix.c
bfd/elf64-ppc.c
bfd/elf64-s390.c
bfd/elf64-x86-64.c
bfd/elfcode.h
bfd/elflink.h
bfd/elfxx-ia64.c
binutils/ChangeLog
binutils/readelf.c
include/elf/ChangeLog
include/elf/common.h
include/elf/external.h
include/elf/internal.h

index c4df452b071b2d38899fc6acd2641f763cabb7da..8e11fb0f531290e35cba1d759cdc567acd49afbe 100644 (file)
@@ -1,5 +1,153 @@
+2001-12-17  Alan Modra  <amodra@bigpond.net.au>
+       Support for more than 64k ELF sections.
+       * elf-bfd.h (elf_size_info <swap_symbol_out>): Add shndx param.
+       (bfd_elf32_swap_symbol_in): Likewise.
+       (bfd_elf32_swap_symbol_out): Likewise.
+       (bfd_elf64_swap_symbol_in): Likewise.
+       (bfd_elf64_swap_symbol_out): Likewise.
+       (elf_reloc_cookie): Add locsym_shndx field.  Make locsyms a PTR.
+       (elf_obj_tdata): Add num_elf_sections, symtab_shndx_hdr and
+       symtab_shndx_section.
+       (elf_numsections): Define.
+       (elf_symtab_shndx): Define.
+       * elf.c (setup_group): Use elf_numsections rather than header e_shnum.
+       (bfd_elf_find_section): Likewise.
+       (bfd_section_from_elf_index): Likewise.
+       (bfd_section_from_shdr): Likewise.  Handle SHT_SYMTAB_SHNDX.
+       (bfd_section_from_r_symndx): Read symbol shndx extension, and
+       translate st_shndx for > SHN_HIRESERVE.
+       (assign_section_numbers): Skip reserved sections.  Assign
+       symtab_shndx_section and elf_numsections.  Exclude reserved
+       sections from e_shnum.  Set up symtab_shndx_hdr.
+       (_bfd_elf_compute_section_file_positions): Handle symtab_shndx_hdr.
+       (map_sections_to_segments): Don't map eh_frame_hdr unless required.
+       (assign_file_positions_except_relocs): Use elf_numsections rather
+       than header e_shnum.  Skip reserved sections and symtab_shndx_section.
+       (prep_headers): Set name for symtab_shndx_hdr.
+       (_bfd_elf_assign_file_positions_for_relocs): Use elf_numsections.
+       (_bfd_elf_write_object_contents): Likewise.  Skip reserved sections.
+       (_bfd_elf_section_from_bfd_section): Check bfd_{abs,com,und}_section
+       first.  Use elf_section_data if available.  Use elf_numsections.
+       Start scan at index 1.
+       (copy_private_bfd_data ): Comment fixes.
+       (MAP_ONESYMTAB): Define above SHN_HIOS.
+       (MAP_DYNSYMTAB): Likewise.
+       (MAP_STRTAB): Likewise.
+       (MAP_SHSTRTAB): Likewise.
+       (MAP_SYM_SHNDX): New define.
+       (_bfd_elf_copy_private_symbol_data): Handle symtab_shndx_section.
+       (swap_out_syms): Swap out SHT_SYMTAB_SHNDX section too.
+       * elfcode.h (elf_swap_symbol_in): Add shndx param, and handle shndx
+       extension.
+       (elf_swap_symbol_out): Likewise.
+       (elf_object_p): Set elf_numsections, and use instead of e_shnum.
+       Initialialise reserved elf_elfsections to point at shdr[0].  Remove
+       redundant bfd_release calls.
+       (elf_slurp_symbol_table): Read symbol shndx extension, and use with
+       elf_swap_symbol_in.  Translate st_shndx for > SHN_HIRESERVE too.
+       * elflink.h (elf_link_is_defined_archive_symbol): Read symbol shndx
+       extension, and use with elf_swap_symbol_in.
+       (elf_link_record_local_dynamic_symbol): Likewise.
+       (elf_link_add_object_symbols): Likewise.  Also translate st_shndx
+       for elf sections > SHN_HIRESERVE.
+       (NAME(bfd_elf,size_dynamic_sections)): Adjust elf_swap_symbol_out
+       call.
+       (struct elf_final_link_info): Add locsym_shndx and symshndxbuf.
+       (elf_bfd_final_link): Allocate the above, and tidy code allocating
+       other buffers.  Use elf_numsections instead of e_shnum.  Adjust
+       elf_swap_symbol_out calls.
+       (elf_link_output_sym): Swap out symbol shndx extension too.
+       (elf_link_flush_output_syms): And flush them to disk.
+       (elf_link_output_extsym): Use SHN_BAD.  Adjust elf_swap_symbol_out
+       calls.
+       (elf_gc_mark): Read symbol shndx extension, and use with
+       elf_swap_symbol_in.
+       (elf_link_input_bfd): Likewise,  Translate st_shndx for elf sections
+       > SHN_HIRESERVE too.  Use SHN_BAD.
+       (elf_reloc_symbol_deleted_p): Use symbol shndx extensions with
+       elf_swap_symbol_in.  Translate st_shndx > SHN_HIRESERVE too.
+       (elf_bfd_discard_info): Read symbol shndx extension.  Don't attempt
+       to continue after a bfd error.
+       * elf-m10200.c (mn10200_elf_relax_section): Only read local syms.
+       Stash them immediately to symtab_hdr->contents rather than later
+       in multiple places.  Clean up afterwards.  Read symbol shndx
+       extension, and use with swap_symbol_in.  Translate SHN_UNDEF,
+       SHN_ABS, SHN_COMMON and elf sections > SHN_HIRESERVE to bfd
+       sections too.  Remove dead code.
+       (mn10200_elf_relax_delete_bytes): Use symbol shndx extension
+       when swapping in symbols.  Tidy code adjusting global syms.
+       Don't swap in global syms.
+       (mn10200_elf_symbol_address_p): Likewise.  Remove extsyms param.
+       (mn10200_elf_get_relocated_section_contents): Read symbol shndx
+       extension, and use with swap_symbol_in.  Rename "size" -> "amt"
+       to maximize code in common with other files.  Translate st_shndx
+       for > SHN_HIRESERVE too.  Remove dead code.
+       * elf-m10300.c (mn10300_elf_relax_section): Only read local syms.
+       Stash them immediately to symtab_hdr->contents rather than later
+       in multiple places.  Clean up afterwards.  Read symbol shndx
+       extension, and use with swap_symbol_in.  Remove dead code.
+       (mn10300_elf_relax_delete_bytes): As for elf-m10200.c.
+       (mn10300_elf_symbol_address_p): Likewise.
+       (mn10300_elf_get_relocated_section_contents): Likewise.
+       * elf32-h8300.c (elf32_h8_relax_section): As for elf-m10300.c.
+       (elf32_h8_relax_delete_bytes): Likewise.
+       (elf32_h8_symbol_address_p): Likewise.
+       (elf32_h8_get_relocated_section_contents): Likewise.
+       * elf32-hppa.c (elf32_hppa_size_stubs): Read symbol shndx
+       extension, and use with swap_symbol_in.
+       * elf64-hppa.c (elf64_hppa_check_relocs): Likewise.
+       * elf32-i370.c (i370_elf_finish_dynamic_sections): Adjust call to
+       bfd_elf32_swap_symbol_out.
+       * elf32-m32r.c (m32r_elf_get_relocated_section_contents): Translate
+       elf sections > SHN_HIRESERVE too.
+       * elf32-m68k.c (bfd_m68k_elf32_create_embedded_relocs): Only read
+       local syms.  Read symbol shndx extension, and use with swap_symbol_in.
+       * elf32-mips.c (_bfd_mips_elf_final_write_processing): Use
+       elf_numsections rather than header e_shnum.
+       * elf32-sh.c (sh_elf_relax_section): As for elf-m10300.c.
+       (sh_elf_relax_delete_bytes): Likewise.
+       (sh_elf_get_relocated_section_contents): Likewise.  Only read local
+       symbols.
+       * elf32-v850.c (v850_elf_symbol_processing): Use an unsigned int to
+       hold section index.  Use elf_numsections rather than e_shnum.
+       Rename "index" -> "indx" to avoid shadowing warning.
+       (v850_elf_add_symbol_hook): Likewise.
+       * elf64-alpha.c (elf64_alpha_relax_section): Only read local syms.
+       Read symbol shndx extension, and use with swap_symbol_in.
+       * elf32-xstormy16.c (xstormy16_elf_relax_section): Likewise.
+       Translate SHN_COMMON and elf sections > SHN_HIRESERVE too.
+       * elfxx-ia64.c (elfNN_ia64_relax_section): Likewise.
+       (elfNN_ia64_aix_add_symbol_hook): Use elf_numsections.
+
+       * elf-m10300.c (mn10300_elf_gc_mark_hook): Remove unnecessary checks
+       before calling bfd_section_from_elf_index on local syms.
+       * elf32-arm.h (elf32_arm_gc_mark_hook): Likewise.
+       * elf32-avr.c (elf32_avr_gc_mark_hook): Likewise.
+       * elf32-cris.c (cris_elf_gc_mark_hook): Likewise.
+       * elf32-d10v.c (elf32_d10v_gc_mark_hook): Likewise.
+       * elf32-fr30.c (fr30_elf_gc_mark_hook): Likewise.
+       * elf32-hppa.c (elf32_hppa_gc_mark_hook): Likewise.
+       * elf32-i386.c (elf_i386_gc_mark_hook): Likewise.
+       * elf32-m32r.c (m32r_elf_gc_mark_hook): Likewise.
+       * elf32-m68k.c (elf_m68k_gc_mark_hook): Likewise.
+       * elf32-mcore.c (mcore_elf_gc_mark_hook): Likewise.
+       * elf32-mips.c (_bfd_mips_elf_gc_mark_hook): Likewise.
+       * elf32-openrisc.c (openrisc_elf_gc_mark_hook): Likewise.
+       * elf32-ppc.c (ppc_elf_gc_mark_hook): Likewise.
+       * elf32-s390.c (elf_s390_gc_mark_hook): Likewise.
+       * elf32-sh.c (sh_elf_gc_mark_hook): Likewise.
+       * elf32-sparc.c (elf32_sparc_gc_mark_hook): Likewise.
+       * elf32-v850.c (v850_elf_gc_mark_hook): Likewise.
+       * elf32-xstormy16.c (xstormy16_elf_gc_mark_hook): Likewise.
+       * elf64-mips.c (mips_elf64_gc_mark_hook): Likewise.
+       * elf64-mmix.c (mmix_elf_gc_mark_hook): Likewise.
+       * elf64-ppc.c (ppc64_elf_gc_mark_hook): Likewise.
+       * elf64-s390.c (elf_s390_gc_mark_hook): Likewise.
+       * elf64-x86-64.c (elf64_x86_64_gc_mark_hook): Likewise.
+
 2001-12-17  Alan Modra  <amodra@bigpond.net.au>
 
+       Hash bfd sections for fast lookup and create.
        * bfd.c (struct _bfd): Add section_htab, section_tail.
        * libbfd-in.h (_bfd_delete_bfd): Declare.
        (bfd_section_hash_newfunc): Declare.
index 0346c8d19c14c205c814fbe3f16003b2d1490d88..24ebcd9384a8aac3e6133a92ff14a81a74b5bc5e 100644 (file)
@@ -342,7 +342,7 @@ struct elf_size_info {
   void (*write_relocs)
     PARAMS ((bfd *, asection *, PTR));
   void (*swap_symbol_out)
-    PARAMS ((bfd *, const Elf_Internal_Sym *, PTR));
+    PARAMS ((bfd *, const Elf_Internal_Sym *, PTR, PTR));
   boolean (*slurp_reloc_table)
     PARAMS ((bfd *, asection *, asymbol **, boolean));
   long (*slurp_symbol_table)
@@ -394,7 +394,8 @@ enum elf_reloc_type_class {
 struct elf_reloc_cookie
 {
   Elf_Internal_Rela *rels, *rel, *relend;
-  void *locsyms;
+  PTR locsyms;
+  PTR locsym_shndx;
   bfd *abfd;
   size_t locsymcount;
   size_t extsymoff;
@@ -943,6 +944,7 @@ struct elf_obj_tdata
   struct elf_strtab_hash *strtab_ptr;
   int num_locals;
   int num_globals;
+  unsigned int num_elf_sections;       /* elf_sect_ptr size */
   int num_section_syms;
   asymbol **section_syms;              /* STT_SECTION symbols for each section */
   Elf_Internal_Shdr symtab_hdr;
@@ -953,8 +955,10 @@ struct elf_obj_tdata
   Elf_Internal_Shdr dynversym_hdr;
   Elf_Internal_Shdr dynverref_hdr;
   Elf_Internal_Shdr dynverdef_hdr;
+  Elf_Internal_Shdr symtab_shndx_hdr;
   unsigned int symtab_section, shstrtab_section;
   unsigned int strtab_section, dynsymtab_section;
+  unsigned int symtab_shndx_section;
   unsigned int dynversym_section, dynverdef_section, dynverref_section;
   file_ptr next_file_pos;
 #if 0
@@ -1083,8 +1087,10 @@ struct elf_obj_tdata
 #define elf_tdata(bfd)         ((bfd) -> tdata.elf_obj_data)
 #define elf_elfheader(bfd)     (elf_tdata(bfd) -> elf_header)
 #define elf_elfsections(bfd)   (elf_tdata(bfd) -> elf_sect_ptr)
+#define elf_numsections(bfd)   (elf_tdata(bfd) -> num_elf_sections)
 #define elf_shstrtab(bfd)      (elf_tdata(bfd) -> strtab_ptr)
 #define elf_onesymtab(bfd)     (elf_tdata(bfd) -> symtab_section)
+#define elf_symtab_shndx(bfd)  (elf_tdata(bfd) -> symtab_shndx_section)
 #define elf_dynsymtab(bfd)     (elf_tdata(bfd) -> dynsymtab_section)
 #define elf_dynversym(bfd)     (elf_tdata(bfd) -> dynversym_section)
 #define elf_dynverdef(bfd)     (elf_tdata(bfd) -> dynverdef_section)
@@ -1371,9 +1377,10 @@ extern boolean bfd_elf32_bfd_final_link
   PARAMS ((bfd *, struct bfd_link_info *));
 
 extern void bfd_elf32_swap_symbol_in
-  PARAMS ((bfd *, const Elf32_External_Sym *, Elf_Internal_Sym *));
+  PARAMS ((bfd *, const Elf32_External_Sym *, const Elf_External_Sym_Shndx *,
+          Elf_Internal_Sym *));
 extern void bfd_elf32_swap_symbol_out
-  PARAMS ((bfd *, const Elf_Internal_Sym *, PTR));
+  PARAMS ((bfd *, const Elf_Internal_Sym *, PTR, PTR));
 extern void bfd_elf32_swap_reloc_in
   PARAMS ((bfd *, const Elf32_External_Rel *, Elf_Internal_Rel *));
 extern void bfd_elf32_swap_reloc_out
@@ -1423,9 +1430,10 @@ extern boolean bfd_elf64_bfd_final_link
   PARAMS ((bfd *, struct bfd_link_info *));
 
 extern void bfd_elf64_swap_symbol_in
-  PARAMS ((bfd *, const Elf64_External_Sym *, Elf_Internal_Sym *));
+  PARAMS ((bfd *, const Elf64_External_Sym *, const Elf_External_Sym_Shndx *,
+          Elf_Internal_Sym *));
 extern void bfd_elf64_swap_symbol_out
-  PARAMS ((bfd *, const Elf_Internal_Sym *, PTR));
+  PARAMS ((bfd *, const Elf_Internal_Sym *, PTR, PTR));
 extern void bfd_elf64_swap_reloc_in
   PARAMS ((bfd *, const Elf64_External_Rel *, Elf_Internal_Rel *));
 extern void bfd_elf64_swap_reloc_out
index aebae335d714b758165cbb5231954f44c740a02e..e514934fbbc7826b84c326db4218c43ac8045935 100644 (file)
@@ -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 *, Elf32_External_Sym *, bfd_vma));
+  PARAMS ((bfd *, asection *, 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,
@@ -525,6 +525,7 @@ 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;
@@ -532,6 +533,7 @@ mn10200_elf_relax_section (abfd, sec, link_info, again)
   bfd_byte *free_contents = NULL;
   Elf32_External_Sym *extsyms = NULL;
   Elf32_External_Sym *free_extsyms = NULL;
+  Elf_External_Sym_Shndx *shndx_buf = NULL;
 
   /* Assume nothing changes.  */
   *again = false;
@@ -551,6 +553,7 @@ 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
@@ -603,29 +606,57 @@ mn10200_elf_relax_section (abfd, sec, link_info, again)
          else
            {
              /* Go get them off disk.  */
-             bfd_size_type amt = symtab_hdr->sh_size;
+             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 (extsyms, amt, abfd) != amt)
+                 || 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;
            }
        }
 
       /* 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;
          asection *sym_sec;
 
-         /* A local symbol.  */
-         bfd_elf32_swap_symbol_in (abfd,
-                                   extsyms + ELF32_R_SYM (irel->r_info),
-                                   &isym);
+         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, esym, shndx, &isym);
 
-         sym_sec = bfd_section_from_elf_index (abfd, isym.st_shndx);
+         if (isym.st_shndx == SHN_UNDEF)
+           sym_sec = bfd_und_section_ptr;
+         else if (isym.st_shndx == SHN_ABS)
+           sym_sec = bfd_abs_section_ptr;
+         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->output_section->vma
                    + sym_sec->output_offset);
@@ -692,7 +723,6 @@ mn10200_elf_relax_section (abfd, sec, link_info, again)
              elf_section_data (sec)->this_hdr.contents = contents;
              free_contents = NULL;
 
-             symtab_hdr->contents = (bfd_byte *) extsyms;
              free_extsyms = NULL;
 
              /* Fix the opcode.  */
@@ -750,7 +780,6 @@ mn10200_elf_relax_section (abfd, sec, link_info, again)
              elf_section_data (sec)->this_hdr.contents = contents;
              free_contents = NULL;
 
-             symtab_hdr->contents = (bfd_byte *) extsyms;
              free_extsyms = NULL;
 
              /* Fix the opcode.  */
@@ -836,8 +865,7 @@ 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, extsyms,
-                                           irel->r_offset + 1))
+         if (mn10200_elf_symbol_address_p (abfd, sec, irel->r_offset + 1))
            continue;
 
          /* Note that we've changed the relocs, section contents, etc.  */
@@ -847,7 +875,6 @@ mn10200_elf_relax_section (abfd, sec, link_info, again)
          elf_section_data (sec)->this_hdr.contents = contents;
          free_contents = NULL;
 
-         symtab_hdr->contents = (bfd_byte *) extsyms;
          free_extsyms = NULL;
 
          /* Reverse the condition of the first branch.  */
@@ -971,7 +998,6 @@ mn10200_elf_relax_section (abfd, sec, link_info, again)
                  elf_section_data (sec)->this_hdr.contents = contents;
                  free_contents = NULL;
 
-                 symtab_hdr->contents = (bfd_byte *) extsyms;
                  free_extsyms = NULL;
 
                  /* Fix the opcode.  */
@@ -1015,7 +1041,6 @@ mn10200_elf_relax_section (abfd, sec, link_info, again)
                  elf_section_data (sec)->this_hdr.contents = contents;
                  free_contents = NULL;
 
-                 symtab_hdr->contents = (bfd_byte *) extsyms;
                  free_extsyms = NULL;
 
                  if ((code & 0xfc) == 0x74)
@@ -1103,7 +1128,6 @@ mn10200_elf_relax_section (abfd, sec, link_info, again)
                  elf_section_data (sec)->this_hdr.contents = contents;
                  free_contents = NULL;
 
-                 symtab_hdr->contents = (bfd_byte *) extsyms;
                  free_extsyms = NULL;
 
                  /* Fix the opcode.  */
@@ -1167,7 +1191,6 @@ mn10200_elf_relax_section (abfd, sec, link_info, again)
                  elf_section_data (sec)->this_hdr.contents = contents;
                  free_contents = NULL;
 
-                 symtab_hdr->contents = (bfd_byte *) extsyms;
                  free_extsyms = NULL;
 
                  bfd_put_8 (abfd, 0xcc + (code & 0x03),
@@ -1199,10 +1222,7 @@ mn10200_elf_relax_section (abfd, sec, link_info, again)
     }
 
   if (free_relocs != NULL)
-    {
-      free (free_relocs);
-      free_relocs = NULL;
-    }
+    free (free_relocs);
 
   if (free_contents != NULL)
     {
@@ -1213,19 +1233,21 @@ mn10200_elf_relax_section (abfd, sec, link_info, again)
          /* 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)
-       free (free_extsyms);
-      else
        {
-         /* Cache the symbols for elf_link_input_bfd.  */
-         symtab_hdr->contents = (unsigned char *) extsyms;
+         symtab_hdr->contents = NULL;
+         free (free_extsyms);
        }
-      free_extsyms = NULL;
     }
 
   return true;
@@ -1235,8 +1257,17 @@ mn10200_elf_relax_section (abfd, sec, link_info, again)
     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)
-    free (free_extsyms);
+    {
+      symtab_hdr->contents = NULL;
+      free (free_extsyms);
+    }
+
   return false;
 }
 
@@ -1250,19 +1281,23 @@ 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;
-  int shndx, index;
+  unsigned int sec_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;
+  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;
 
-  shndx = _bfd_elf_section_from_bfd_section (abfd, sec);
+  sec_shndx = _bfd_elf_section_from_bfd_section (abfd, sec);
 
   contents = elf_section_data (sec)->this_hdr.contents;
 
@@ -1290,40 +1325,41 @@ 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++)
+  for (; esym < esymend; esym++, shndx = (shndx ? shndx + 1 : NULL))
     {
       Elf_Internal_Sym isym;
+      Elf_External_Sym_Shndx dummy;
 
-      bfd_elf32_swap_symbol_in (abfd, esym, &isym);
+      bfd_elf32_swap_symbol_in (abfd, esym, shndx, &isym);
 
-      if (isym.st_shndx == shndx
+      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);
+         bfd_elf32_swap_symbol_out (abfd, &isym, (PTR) esym, (PTR) &dummy);
        }
     }
 
   /* 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;
-
-      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)
+      struct elf_link_hash_entry *sym_hash = *sym_hashes;
+      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;
        }
     }
 
@@ -1333,46 +1369,53 @@ 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, extsyms, addr)
+mn10200_elf_symbol_address_p (abfd, sec, addr)
      bfd *abfd;
      asection *sec;
-     Elf32_External_Sym *extsyms;
      bfd_vma addr;
 {
   Elf_Internal_Shdr *symtab_hdr;
-  int shndx;
+  Elf_Internal_Shdr *shndx_hdr;
+  unsigned int sec_shndx;
   Elf32_External_Sym *esym, *esymend;
-  struct elf_link_hash_entry **sym_hash, **sym_hash_end;
+  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;
-  shndx = _bfd_elf_section_from_bfd_section (abfd, sec);
+  sec_shndx = _bfd_elf_section_from_bfd_section (abfd, sec);
 
   /* Examine all the symbols.  */
-  esym = extsyms;
+  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++)
+  for (; esym < esymend; esym++, shndx = (shndx ? shndx + 1 : NULL))
     {
       Elf_Internal_Sym isym;
 
-      bfd_elf32_swap_symbol_in (abfd, esym, &isym);
+      bfd_elf32_swap_symbol_in (abfd, esym, shndx, &isym);
 
-      if (isym.st_shndx == shndx
+      if (isym.st_shndx == sec_shndx
          && isym.st_value == addr)
        return true;
     }
 
-  sym_hash = elf_sym_hashes (abfd);
-  sym_hash_end = (sym_hash
-                 + (symtab_hdr->sh_size / sizeof (Elf32_External_Sym)
-                    - symtab_hdr->sh_info));
-  for (; sym_hash < sym_hash_end; sym_hash++)
+  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++)
     {
-      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)
+      struct elf_link_hash_entry *sym_hash = *sym_hashes;
+      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)
        return true;
     }
+
   return false;
 }
 
@@ -1390,11 +1433,14 @@ 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;
 
   /* We only need to handle the case of relaxing, or of having a
@@ -1407,6 +1453,7 @@ 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);
@@ -1417,19 +1464,31 @@ mn10200_elf_get_relocated_section_contents (output_bfd, link_info, link_order,
       Elf_Internal_Sym *isymp;
       asection **secpp;
       Elf32_External_Sym *esym, *esymend;
-      bfd_size_type size;
+      bfd_size_type amt;
 
       if (symtab_hdr->contents != NULL)
        external_syms = (Elf32_External_Sym *) symtab_hdr->contents;
-      else
+      else if (symtab_hdr->sh_info != 0)
        {
-         size = symtab_hdr->sh_info;
-         size *= sizeof (Elf32_External_Sym);
-         external_syms = (Elf32_External_Sym *) bfd_malloc (size);
-         if (external_syms == NULL && size != 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 (external_syms, size, input_bfd) != size)
+             || 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;
        }
 
@@ -1439,41 +1498,35 @@ mn10200_elf_get_relocated_section_contents (output_bfd, link_info, link_order,
       if (internal_relocs == NULL)
        goto error_return;
 
-      size = symtab_hdr->sh_info;
-      size *= sizeof (Elf_Internal_Sym);
-      internal_syms = (Elf_Internal_Sym *) bfd_malloc (size);
-      if (internal_syms == NULL && size != 0)
+      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;
 
-      size = symtab_hdr->sh_info;
-      size *= sizeof (asection *);
-      sections = (asection **) bfd_malloc (size);
-      if (sections == NULL && size != 0)
+      amt = symtab_hdr->sh_info;
+      amt *= sizeof (asection *);
+      sections = (asection **) bfd_malloc (amt);
+      if (sections == NULL && amt != 0)
        goto error_return;
 
-      isymp = internal_syms;
-      secpp = sections;
-      esym = external_syms;
-      esymend = esym + symtab_hdr->sh_info;
-      for (; esym < esymend; ++esym, ++isymp, ++secpp)
+      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))
        {
          asection *isec;
 
-         bfd_elf32_swap_symbol_in (input_bfd, esym, isymp);
+         bfd_elf32_swap_symbol_in (input_bfd, esym, shndx, isymp);
 
          if (isymp->st_shndx == SHN_UNDEF)
            isec = bfd_und_section_ptr;
-         else if (isymp->st_shndx > 0 && isymp->st_shndx < SHN_LORESERVE)
-           isec = bfd_section_from_elf_index (input_bfd, isymp->st_shndx);
          else if (isymp->st_shndx == SHN_ABS)
            isec = bfd_abs_section_ptr;
          else if (isymp->st_shndx == SHN_COMMON)
            isec = bfd_com_section_ptr;
          else
-           {
-             /* Who knows?  */
-             isec = NULL;
-           }
+           isec = bfd_section_from_elf_index (input_bfd, isymp->st_shndx);
 
          *secpp = isec;
        }
@@ -1485,16 +1538,14 @@ mn10200_elf_get_relocated_section_contents (output_bfd, link_info, link_order,
 
       if (sections != NULL)
        free (sections);
-      sections = NULL;
       if (internal_syms != NULL)
        free (internal_syms);
-      internal_syms = NULL;
+      if (shndx_buf != NULL)
+       free (shndx_buf);
       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;
     }
 
   return data;
@@ -1503,6 +1554,8 @@ mn10200_elf_get_relocated_section_contents (output_bfd, link_info, link_order,
   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)
index 9bec736aa3ebb4fe5def44b927d3cd554f6d2763..fb94c5127adb6a70904c73d824e8179ea9581233 100644 (file)
@@ -125,7 +125,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 *, Elf32_External_Sym *, bfd_vma));
+  PARAMS ((bfd *, asection *, bfd_vma));
 static boolean elf32_mn10300_finish_hash_table_entry
   PARAMS ((struct bfd_hash_entry *, PTR));
 static void compute_function_info
@@ -427,13 +427,7 @@ mn10300_elf_gc_mark_hook (abfd, info, rel, h, sym)
     }
   else
     {
-      if (!(elf_bad_symtab (abfd)
-           && ELF_ST_BIND (sym->st_info) != STB_LOCAL)
-         && ! ((sym->st_shndx <= 0 || sym->st_shndx >= SHN_LORESERVE)
-               && sym->st_shndx != SHN_COMMON))
-       {
-         return bfd_section_from_elf_index (abfd, sym->st_shndx);
-       }
+      return bfd_section_from_elf_index (abfd, sym->st_shndx);
     }
 
   return NULL;
@@ -803,6 +797,7 @@ 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;
@@ -810,6 +805,7 @@ mn10300_elf_relax_section (abfd, sec, link_info, again)
   bfd_byte *free_contents = NULL;
   Elf32_External_Sym *extsyms = NULL;
   Elf32_External_Sym *free_extsyms = NULL;
+  Elf_External_Sym_Shndx *shndx_buf = NULL;
   struct elf32_mn10300_link_hash_table *hash_table;
 
   /* Assume nothing changes.  */
@@ -832,20 +828,38 @@ mn10300_elf_relax_section (abfd, sec, link_info, again)
 
          /* 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
            {
-             bfd_size_type amt = symtab_hdr->sh_size;
              /* 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 (extsyms, amt, input_bfd) != amt)
+                 || 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)
                goto error_return;
            }
 
@@ -921,28 +935,33 @@ 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;
                          struct elf_link_hash_table *elftab;
                          bfd_size_type amt;
 
-                         bfd_elf32_swap_symbol_in (input_bfd,
-                                                   extsyms + r_index, &isym);
+                         esym = extsyms + r_index;
+                         shndx = shndx_buf + (shndx_buf ? r_index : 0);
+                         bfd_elf32_swap_symbol_in (input_bfd, esym, shndx,
+                                                   &isym);
 
                          if (isym.st_shndx == SHN_UNDEF)
                            sym_sec = bfd_und_section_ptr;
-                         else if (isym.st_shndx > 0
-                                  && isym.st_shndx < SHN_LORESERVE)
-                           sym_sec
-                             = bfd_section_from_elf_index (input_bfd,
-                                                           isym.st_shndx);
                          else if (isym.st_shndx == SHN_ABS)
                            sym_sec = bfd_abs_section_ptr;
                          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);
 
-                         sym_name = bfd_elf_string_from_elf_section (input_bfd,
-                                                          symtab_hdr->sh_link,
-                                                          isym.st_name);
+                         sym_name
+                           = bfd_elf_string_from_elf_section (input_bfd,
+                                                              (symtab_hdr
+                                                               ->sh_link),
+                                                              isym.st_name);
 
                          /* If it isn't a function, then we don't care
                             about it.  */
@@ -999,21 +1018,24 @@ mn10300_elf_relax_section (abfd, sec, link_info, again)
                {
 
                  Elf32_External_Sym *esym, *esymend;
-                 int idx, shndx;
+                 Elf_External_Sym_Shndx *shndx;
+                 int idx;
+                 unsigned int sec_shndx;
 
-                 shndx = _bfd_elf_section_from_bfd_section (input_bfd,
-                                                            section);
+                 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.  */
-                 esym = extsyms;
-                 esymend = esym + symtab_hdr->sh_info;
-                 for (; esym < esymend; esym++)
+                 for (esym = extsyms, esymend = esym + symtab_hdr->sh_info,
+                        shndx = shndx_buf;
+                      esym < esymend;
+                      esym++, shndx = (shndx ? shndx + 1 : NULL))
                    {
                      Elf_Internal_Sym isym;
 
-                     bfd_elf32_swap_symbol_in (input_bfd, esym, &isym);
-                     if (isym.st_shndx == shndx
+                     bfd_elf32_swap_symbol_in (input_bfd, esym, shndx, &isym);
+                     if (isym.st_shndx == sec_shndx
                          && ELF_ST_TYPE (isym.st_info) == STT_FUNC)
                        {
                          struct elf_link_hash_table *elftab;
@@ -1021,15 +1043,14 @@ mn10300_elf_relax_section (abfd, sec, link_info, again)
 
                          if (isym.st_shndx == SHN_UNDEF)
                            sym_sec = bfd_und_section_ptr;
-                         else if (isym.st_shndx > 0
-                                  && isym.st_shndx < SHN_LORESERVE)
-                           sym_sec
-                             = bfd_section_from_elf_index (input_bfd,
-                                                           isym.st_shndx);
                          else if (isym.st_shndx == SHN_ABS)
                            sym_sec = bfd_abs_section_ptr;
                          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);
 
                          sym_name = (bfd_elf_string_from_elf_section
                                      (input_bfd, symtab_hdr->sh_link,
@@ -1063,14 +1084,12 @@ mn10300_elf_relax_section (abfd, sec, link_info, again)
                    {
                      Elf_Internal_Sym isym;
 
-                     bfd_elf32_swap_symbol_in (input_bfd, esym, &isym);
                      hash = (struct elf32_mn10300_link_hash_entry *)
                               elf_sym_hashes (input_bfd)[idx];
-                     if (isym.st_shndx == shndx
-                         && ELF_ST_TYPE (isym.st_info) == STT_FUNC
-                         && (hash)->root.root.u.def.section == section
-                         && ((hash)->root.root.type == bfd_link_hash_defined
-                             || (hash)->root.root.type == bfd_link_hash_defweak))
+                     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)
                        compute_function_info (input_bfd, hash,
                                               (hash)->root.root.u.def.value,
                                               contents);
@@ -1098,6 +1117,12 @@ mn10300_elf_relax_section (abfd, sec, link_info, again)
                }
            }
 
+         if (shndx_buf != NULL)
+           {
+             free (shndx_buf);
+             shndx_buf = NULL;
+           }
+
          /* Cache or free any memory we allocated for the symbols.  */
          if (free_extsyms != NULL)
            {
@@ -1134,23 +1159,43 @@ mn10300_elf_relax_section (abfd, sec, link_info, again)
        {
          asection *section;
 
-         /* We're going to need all the symbols for each bfd.  */
+         /* 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
            {
-             bfd_size_type amt = symtab_hdr->sh_size;
              /* 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 (extsyms, amt, input_bfd) != amt)
+                 || 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.  */
@@ -1158,9 +1203,10 @@ mn10300_elf_relax_section (abfd, sec, link_info, again)
               section != NULL;
               section = section->next)
            {
-             int shndx;
+             unsigned int sec_shndx;
              Elf32_External_Sym *esym, *esymend;
-             int idx;
+             Elf_External_Sym_Shndx *shndx;
+             unsigned int idx;
 
              /* Skip non-code sections and empty sections.  */
              if ((section->flags & SEC_CODE) == 0 || section->_raw_size == 0)
@@ -1196,13 +1242,15 @@ mn10300_elf_relax_section (abfd, sec, link_info, again)
                    goto error_return;
                }
 
-             shndx = _bfd_elf_section_from_bfd_section (input_bfd, section);
+             sec_shndx = _bfd_elf_section_from_bfd_section (input_bfd,
+                                                            section);
 
              /* Now look for any function in this section which needs
                 insns deleted from its prologue.  */
-             esym = extsyms;
-             esymend = esym + symtab_hdr->sh_info;
-             for (; esym < esymend; esym++)
+             for (esym = extsyms, esymend = esym + symtab_hdr->sh_info,
+                    shndx = shndx_buf;
+                  esym < esymend;
+                  esym++, shndx = (shndx ? shndx + 1 : NULL))
                {
                  Elf_Internal_Sym isym;
                  struct elf32_mn10300_link_hash_entry *sym_hash;
@@ -1212,26 +1260,25 @@ 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, esym, &isym);
+                 bfd_elf32_swap_symbol_in (input_bfd, esym, shndx, &isym);
 
-                 if (isym.st_shndx != shndx)
+                 if (isym.st_shndx != sec_shndx)
                    continue;
 
                  if (isym.st_shndx == SHN_UNDEF)
                    sym_sec = bfd_und_section_ptr;
-                 else if (isym.st_shndx > 0 && isym.st_shndx < SHN_LORESERVE)
-                   sym_sec
-                     = bfd_section_from_elf_index (input_bfd, isym.st_shndx);
                  else if (isym.st_shndx == SHN_ABS)
                    sym_sec = bfd_abs_section_ptr;
                  else if (isym.st_shndx == SHN_COMMON)
                    sym_sec = bfd_com_section_ptr;
                  else
-                   abort ();
+                   sym_sec
+                     = 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);
+                 sym_name
+                   = bfd_elf_string_from_elf_section (input_bfd,
+                                                      symtab_hdr->sh_link,
+                                                      isym.st_name);
 
                  /* Tack on an ID so we can uniquely identify this
                     local symbol in the global hash table.  */
@@ -1251,8 +1298,8 @@ mn10300_elf_relax_section (abfd, sec, link_info, again)
                  if (sym_hash == NULL)
                    continue;
 
-                 if (! ((sym_hash)->flags & MN10300_CONVERT_CALL_TO_CALLS)
-                     && ! ((sym_hash)->flags & MN10300_DELETED_PROLOGUE_BYTES))
+                 if (! (sym_hash->flags & MN10300_CONVERT_CALL_TO_CALLS)
+                     && ! (sym_hash->flags & MN10300_DELETED_PROLOGUE_BYTES))
                    {
                      int bytes = 0;
 
@@ -1263,7 +1310,6 @@ mn10300_elf_relax_section (abfd, sec, link_info, again)
                      elf_section_data (section)->this_hdr.contents = contents;
                      free_contents = NULL;
 
-                     symtab_hdr->contents = (bfd_byte *) extsyms;
                      free_extsyms = NULL;
 
                      /* Count how many bytes we're going to delete.  */
@@ -1295,23 +1341,23 @@ mn10300_elf_relax_section (abfd, sec, link_info, again)
 
              /* Look for any global functions in this section which
                 need insns deleted from their prologues.  */
-             esym = extsyms + symtab_hdr->sh_info;
-             esymend = extsyms + (symtab_hdr->sh_size
-                                  / sizeof (Elf32_External_Sym));
-             for (idx = 0; esym < esymend; esym++, idx++)
+             for (idx = 0;
+                  idx < (symtab_hdr->sh_size / sizeof (Elf32_External_Sym)
+                         - symtab_hdr->sh_info);
+                  idx++)
                {
-                 Elf_Internal_Sym isym;
                  struct elf32_mn10300_link_hash_entry *sym_hash;
 
-                 bfd_elf32_swap_symbol_in (input_bfd, esym, &isym);
                  sym_hash = (struct elf32_mn10300_link_hash_entry *)
                               (elf_sym_hashes (input_bfd)[idx]);
-                 if (isym.st_shndx == shndx
-                     && (sym_hash)->root.root.u.def.section == section
-                     && ! ((sym_hash)->flags & MN10300_CONVERT_CALL_TO_CALLS)
-                     && ! ((sym_hash)->flags & MN10300_DELETED_PROLOGUE_BYTES))
+                 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
+                     && ! (sym_hash->flags & MN10300_CONVERT_CALL_TO_CALLS)
+                     && ! (sym_hash->flags & MN10300_DELETED_PROLOGUE_BYTES))
                    {
                      int bytes = 0;
+                     bfd_vma symval;
 
                      /* Note that we've changed things.  */
                      elf_section_data (section)->relocs = internal_relocs;
@@ -1320,7 +1366,6 @@ mn10300_elf_relax_section (abfd, sec, link_info, again)
                      elf_section_data (section)->this_hdr.contents = contents;
                      free_contents = NULL;
 
-                     symtab_hdr->contents = (bfd_byte *) extsyms;
                      free_extsyms = NULL;
 
                      /* Count how many bytes we're going to delete.  */
@@ -1338,9 +1383,10 @@ mn10300_elf_relax_section (abfd, sec, link_info, again)
                      sym_hash->flags |= MN10300_DELETED_PROLOGUE_BYTES;
 
                      /* Actually delete the bytes.  */
+                     symval = sym_hash->root.root.u.def.value;
                      if (!mn10300_elf_relax_delete_bytes (input_bfd,
                                                           section,
-                                                          (sym_hash)->root.root.u.def.value,
+                                                          symval,
                                                           bytes))
                        goto error_return;
 
@@ -1371,15 +1417,20 @@ mn10300_elf_relax_section (abfd, sec, link_info, again)
                }
            }
 
+         if (shndx_buf != NULL)
+           {
+             shndx_hdr->contents = NULL;
+             free (shndx_buf);
+             shndx_buf = NULL;
+           }
+
          /* Cache or free any memory we allocated for the symbols.  */
          if (free_extsyms != NULL)
            {
              if (! link_info->keep_memory)
-               free (free_extsyms);
-             else
                {
-                 /* Cache the symbols for elf_link_input_bfd.  */
-                 symtab_hdr->contents = (unsigned char *) extsyms;
+                 symtab_hdr->contents = NULL;
+                 free (free_extsyms);
                }
              free_extsyms = NULL;
            }
@@ -1409,6 +1460,7 @@ 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
@@ -1461,41 +1513,60 @@ mn10300_elf_relax_section (abfd, sec, link_info, again)
            extsyms = (Elf32_External_Sym *) symtab_hdr->contents;
          else
            {
-             bfd_size_type amt = symtab_hdr->sh_size;
              /* 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 (extsyms, amt, abfd) != amt)
+                 || 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;
            }
        }
 
       /* 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;
          asection *sym_sec = NULL;
          const char *sym_name;
          char *new_name;
 
          /* A local symbol.  */
-         bfd_elf32_swap_symbol_in (abfd,
-                                   extsyms + ELF32_R_SYM (irel->r_info),
-                                   &isym);
+         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, esym, shndx, &isym);
 
          if (isym.st_shndx == SHN_UNDEF)
            sym_sec = bfd_und_section_ptr;
-         else if (isym.st_shndx > 0 && isym.st_shndx < SHN_LORESERVE)
-           sym_sec = bfd_section_from_elf_index (abfd, isym.st_shndx);
          else if (isym.st_shndx == SHN_ABS)
            sym_sec = bfd_abs_section_ptr;
          else if (isym.st_shndx == SHN_COMMON)
            sym_sec = bfd_com_section_ptr;
          else
-           abort ();
+           sym_sec = bfd_section_from_elf_index (abfd, isym.st_shndx);
 
          symval = (isym.st_value
                    + sym_sec->output_section->vma
@@ -1575,7 +1646,6 @@ mn10300_elf_relax_section (abfd, sec, link_info, again)
                  elf_section_data (sec)->this_hdr.contents = contents;
                  free_contents = NULL;
 
-                 symtab_hdr->contents = (bfd_byte *) extsyms;
                  free_extsyms = NULL;
 
                  /* Fix the opcode.  */
@@ -1640,7 +1710,6 @@ mn10300_elf_relax_section (abfd, sec, link_info, again)
              elf_section_data (sec)->this_hdr.contents = contents;
              free_contents = NULL;
 
-             symtab_hdr->contents = (bfd_byte *) extsyms;
              free_extsyms = NULL;
 
              /* Fix the opcode.  */
@@ -1692,7 +1761,6 @@ mn10300_elf_relax_section (abfd, sec, link_info, again)
                  elf_section_data (sec)->this_hdr.contents = contents;
                  free_contents = NULL;
 
-                 symtab_hdr->contents = (bfd_byte *) extsyms;
                  free_extsyms = NULL;
 
                  /* Fix the opcode.  */
@@ -1755,7 +1823,6 @@ mn10300_elf_relax_section (abfd, sec, link_info, again)
              elf_section_data (sec)->this_hdr.contents = contents;
              free_contents = NULL;
 
-             symtab_hdr->contents = (bfd_byte *) extsyms;
              free_extsyms = NULL;
 
              /* Fix the opcode.  */
@@ -1840,8 +1907,7 @@ 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, extsyms,
-                                           irel->r_offset + 1))
+         if (mn10300_elf_symbol_address_p (abfd, sec, irel->r_offset + 1))
            continue;
 
          /* Note that we've changed the relocs, section contents, etc.  */
@@ -1851,7 +1917,6 @@ mn10300_elf_relax_section (abfd, sec, link_info, again)
          elf_section_data (sec)->this_hdr.contents = contents;
          free_contents = NULL;
 
-         symtab_hdr->contents = (bfd_byte *) extsyms;
          free_extsyms = NULL;
 
          /* Reverse the condition of the first branch.  */
@@ -1965,7 +2030,6 @@ mn10300_elf_relax_section (abfd, sec, link_info, again)
                          elf_section_data (sec)->this_hdr.contents = contents;
                          free_contents = NULL;
 
-                         symtab_hdr->contents = (bfd_byte *) extsyms;
                          free_extsyms = NULL;
 
                          /* Fix the opcode.  */
@@ -2041,7 +2105,6 @@ mn10300_elf_relax_section (abfd, sec, link_info, again)
                          elf_section_data (sec)->this_hdr.contents = contents;
                          free_contents = NULL;
 
-                         symtab_hdr->contents = (bfd_byte *) extsyms;
                          free_extsyms = NULL;
 
                          /* Fix the opcode.  */
@@ -2125,7 +2188,6 @@ mn10300_elf_relax_section (abfd, sec, link_info, again)
                    elf_section_data (sec)->this_hdr.contents = contents;
                    free_contents = NULL;
 
-                   symtab_hdr->contents = (bfd_byte *) extsyms;
                    free_extsyms = NULL;
 
                    /* Fix the opcode.  */
@@ -2163,7 +2225,6 @@ mn10300_elf_relax_section (abfd, sec, link_info, again)
                    elf_section_data (sec)->this_hdr.contents = contents;
                    free_contents = NULL;
 
-                   symtab_hdr->contents = (bfd_byte *) extsyms;
                    free_extsyms = NULL;
 
                    if ((code & 0xf3) == 0x81)
@@ -2218,7 +2279,6 @@ mn10300_elf_relax_section (abfd, sec, link_info, again)
                    elf_section_data (sec)->this_hdr.contents = contents;
                    free_contents = NULL;
 
-                   symtab_hdr->contents = (bfd_byte *) extsyms;
                    free_extsyms = NULL;
 
                    /* Fix the opcode.  */
@@ -2271,7 +2331,6 @@ mn10300_elf_relax_section (abfd, sec, link_info, again)
                    elf_section_data (sec)->this_hdr.contents = contents;
                    free_contents = NULL;
 
-                   symtab_hdr->contents = (bfd_byte *) extsyms;
                    free_extsyms = NULL;
 
                    if ((code & 0xfc) == 0xcc)
@@ -2353,7 +2412,6 @@ mn10300_elf_relax_section (abfd, sec, link_info, again)
                    elf_section_data (sec)->this_hdr.contents = contents;
                    free_contents = NULL;
 
-                   symtab_hdr->contents = (bfd_byte *) extsyms;
                    free_extsyms = NULL;
 
                    /* Fix the opcode.  */
@@ -2385,7 +2443,6 @@ mn10300_elf_relax_section (abfd, sec, link_info, again)
                  elf_section_data (sec)->this_hdr.contents = contents;
                  free_contents = NULL;
 
-                 symtab_hdr->contents = (bfd_byte *) extsyms;
                  free_extsyms = NULL;
 
                  /* Fix the opcode.  */
@@ -2411,10 +2468,7 @@ mn10300_elf_relax_section (abfd, sec, link_info, again)
     }
 
   if (free_relocs != NULL)
-    {
-      free (free_relocs);
-      free_relocs = NULL;
-    }
+    free (free_relocs);
 
   if (free_contents != NULL)
     {
@@ -2425,19 +2479,21 @@ mn10300_elf_relax_section (abfd, sec, link_info, again)
          /* 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)
-       free (free_extsyms);
-      else
        {
-         /* Cache the symbols for elf_link_input_bfd.  */
-         symtab_hdr->contents = (unsigned char *) extsyms;
+         symtab_hdr->contents = NULL;
+         free (free_extsyms);
        }
-      free_extsyms = NULL;
     }
 
   return true;
@@ -2447,8 +2503,17 @@ mn10300_elf_relax_section (abfd, sec, link_info, again)
     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)
-    free (free_extsyms);
+    {
+      symtab_hdr->contents = NULL;
+      free (free_extsyms);
+    }
+
   return false;
 }
 
@@ -2562,19 +2627,23 @@ 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;
-  int shndx, index;
+  unsigned int sec_shndx;
   bfd_byte *contents;
   Elf_Internal_Rela *irel, *irelend;
   Elf_Internal_Rela *irelalign;
   bfd_vma toaddr;
   Elf32_External_Sym *esym, *esymend;
-  struct elf32_mn10300_link_hash_entry *sym_hash;
+  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;
 
-  shndx = _bfd_elf_section_from_bfd_section (abfd, sec);
+  sec_shndx = _bfd_elf_section_from_bfd_section (abfd, sec);
 
   contents = elf_section_data (sec)->this_hdr.contents;
 
@@ -2602,41 +2671,41 @@ 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++)
+  for (; esym < esymend; esym++, shndx = (shndx ? shndx + 1 : NULL))
     {
       Elf_Internal_Sym isym;
+      Elf_External_Sym_Shndx dummy;
 
-      bfd_elf32_swap_symbol_in (abfd, esym, &isym);
+      bfd_elf32_swap_symbol_in (abfd, esym, shndx, &isym);
 
-      if (isym.st_shndx == shndx
+      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);
+         bfd_elf32_swap_symbol_out (abfd, &isym, (PTR) esym, (PTR) &dummy);
        }
     }
 
   /* 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;
-
-      bfd_elf32_swap_symbol_in (abfd, esym, &isym);
-      sym_hash = (struct elf32_mn10300_link_hash_entry *)
-                  (elf_sym_hashes (abfd)[index]);
-      if (isym.st_shndx == shndx
-         && ((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 == sec
-         && (sym_hash)->root.root.u.def.value > addr
-         && (sym_hash)->root.root.u.def.value < toaddr)
+      struct elf_link_hash_entry *sym_hash = *sym_hashes;
+      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.root.u.def.value -= count;
+         sym_hash->root.u.def.value -= count;
        }
     }
 
@@ -2646,46 +2715,53 @@ 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, extsyms, addr)
+mn10300_elf_symbol_address_p (abfd, sec, addr)
      bfd *abfd;
      asection *sec;
-     Elf32_External_Sym *extsyms;
      bfd_vma addr;
 {
   Elf_Internal_Shdr *symtab_hdr;
-  int shndx;
+  Elf_Internal_Shdr *shndx_hdr;
+  unsigned int sec_shndx;
   Elf32_External_Sym *esym, *esymend;
-  struct elf32_mn10300_link_hash_entry **sym_hash, **sym_hash_end;
+  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;
-  shndx = _bfd_elf_section_from_bfd_section (abfd, sec);
+  sec_shndx = _bfd_elf_section_from_bfd_section (abfd, sec);
 
   /* Examine all the symbols.  */
-  esym = extsyms;
+  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++)
+  for (; esym < esymend; esym++, shndx = (shndx ? shndx + 1 : NULL))
     {
       Elf_Internal_Sym isym;
 
-      bfd_elf32_swap_symbol_in (abfd, esym, &isym);
+      bfd_elf32_swap_symbol_in (abfd, esym, shndx, &isym);
 
-      if (isym.st_shndx == shndx
+      if (isym.st_shndx == sec_shndx
          && isym.st_value == addr)
        return true;
     }
 
-  sym_hash = (struct elf32_mn10300_link_hash_entry **) (elf_sym_hashes (abfd));
-  sym_hash_end = (sym_hash
-                 + (symtab_hdr->sh_size / sizeof (Elf32_External_Sym)
-                    - symtab_hdr->sh_info));
-  for (; sym_hash < sym_hash_end; sym_hash++)
+  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++)
     {
-      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 == sec
-         && (*sym_hash)->root.root.u.def.value == addr)
+      struct elf_link_hash_entry *sym_hash = *sym_hashes;
+      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)
        return true;
     }
+
   return false;
 }
 
@@ -2703,11 +2779,14 @@ 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;
 
   /* We only need to handle the case of relaxing, or of having a
@@ -2720,6 +2799,7 @@ 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);
@@ -2730,19 +2810,31 @@ mn10300_elf_get_relocated_section_contents (output_bfd, link_info, link_order,
       Elf_Internal_Sym *isymp;
       asection **secpp;
       Elf32_External_Sym *esym, *esymend;
-      bfd_size_type size;
+      bfd_size_type amt;
 
       if (symtab_hdr->contents != NULL)
        external_syms = (Elf32_External_Sym *) symtab_hdr->contents;
-      else
+      else if (symtab_hdr->sh_info != 0)
        {
-         size = symtab_hdr->sh_info;
-         size *= sizeof (Elf32_External_Sym);
-         external_syms = (Elf32_External_Sym *) bfd_malloc (size);
-         if (external_syms == NULL && size != 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 (external_syms, size, input_bfd) != size)
+             || 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;
        }
 
@@ -2752,41 +2844,35 @@ mn10300_elf_get_relocated_section_contents (output_bfd, link_info, link_order,
       if (internal_relocs == NULL)
        goto error_return;
 
-      size = symtab_hdr->sh_info;
-      size *= sizeof (Elf_Internal_Sym);
-      internal_syms = (Elf_Internal_Sym *) bfd_malloc (size);
-      if (internal_syms == NULL && size != 0)
+      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;
 
-      size = symtab_hdr->sh_info;
-      size *= sizeof (asection *);
-      sections = (asection **) bfd_malloc (size);
-      if (sections == NULL && size != 0)
+      amt = symtab_hdr->sh_info;
+      amt *= sizeof (asection *);
+      sections = (asection **) bfd_malloc (amt);
+      if (sections == NULL && amt != 0)
        goto error_return;
 
-      isymp = internal_syms;
-      secpp = sections;
-      esym = external_syms;
-      esymend = esym + symtab_hdr->sh_info;
-      for (; esym < esymend; ++esym, ++isymp, ++secpp)
+      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))
        {
          asection *isec;
 
-         bfd_elf32_swap_symbol_in (input_bfd, esym, isymp);
+         bfd_elf32_swap_symbol_in (input_bfd, esym, shndx, isymp);
 
          if (isymp->st_shndx == SHN_UNDEF)
            isec = bfd_und_section_ptr;
-         else if (isymp->st_shndx > 0 && isymp->st_shndx < SHN_LORESERVE)
-           isec = bfd_section_from_elf_index (input_bfd, isymp->st_shndx);
          else if (isymp->st_shndx == SHN_ABS)
            isec = bfd_abs_section_ptr;
          else if (isymp->st_shndx == SHN_COMMON)
            isec = bfd_com_section_ptr;
          else
-           {
-             /* Who knows?  */
-             isec = NULL;
-           }
+           isec = bfd_section_from_elf_index (input_bfd, isymp->st_shndx);
 
          *secpp = isec;
        }
@@ -2798,16 +2884,14 @@ mn10300_elf_get_relocated_section_contents (output_bfd, link_info, link_order,
 
       if (sections != NULL)
        free (sections);
-      sections = NULL;
       if (internal_syms != NULL)
        free (internal_syms);
-      internal_syms = NULL;
+      if (shndx_buf != NULL)
+       free (shndx_buf);
       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;
     }
 
   return data;
@@ -2816,6 +2900,8 @@ mn10300_elf_get_relocated_section_contents (output_bfd, link_info, link_order,
   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)
index 98d3cd2d9b39869fb65850ad861d8739a1f95686..cf13ad60afe57894b5f4c0e7f160a5f5a573103e 100644 (file)
--- a/bfd/elf.c
+++ b/bfd/elf.c
@@ -375,7 +375,7 @@ setup_group (abfd, hdr, newsect)
 
       /* First count the number of groups.  If we have a SHT_GROUP
         section with just a flag word (ie. sh_size is 4), ignore it.  */
-      shnum = elf_elfheader (abfd)->e_shnum;
+      shnum = elf_numsections (abfd);
       num_group = 0;
       for (i = 0; i < shnum; i++)
        {
@@ -708,11 +708,11 @@ bfd_elf_find_section (abfd, name)
   i_shdrp = elf_elfsections (abfd);
   if (i_shdrp != NULL)
     {
-      shstrtab = bfd_elf_get_str_section
-       (abfd, elf_elfheader (abfd)->e_shstrndx);
+      shstrtab = bfd_elf_get_str_section (abfd,
+                                         elf_elfheader (abfd)->e_shstrndx);
       if (shstrtab != NULL)
        {
-         max = elf_elfheader (abfd)->e_shnum;
+         max = elf_numsections (abfd);
          for (i = 1; i < max; i++)
            if (!strcmp (&shstrtab[i_shdrp[i]->sh_name], name))
              return i_shdrp[i];
@@ -1549,6 +1549,20 @@ bfd_section_from_shdr (abfd, shindex)
         section, so that objcopy can handle it.  */
       return _bfd_elf_make_section_from_shdr (abfd, hdr, name);
 
+    case SHT_SYMTAB_SHNDX:     /* Symbol section indices when >64k sections */
+      if (elf_symtab_shndx (abfd) == shindex)
+       return true;
+
+      /* Get the associated symbol table.  */
+      if (! bfd_section_from_shdr (abfd, hdr->sh_link)
+         || hdr->sh_link != elf_onesymtab (abfd))
+       return false;
+
+      elf_symtab_shndx (abfd) = shindex;
+      elf_tdata (abfd)->symtab_shndx_hdr = *hdr;
+      elf_elfsections (abfd)[shindex] = &elf_tdata (abfd)->symtab_shndx_hdr;
+      return true;
+
     case SHT_STRTAB:           /* A string table */
       if (hdr->bfd_section != NULL)
        return true;
@@ -1559,9 +1573,10 @@ bfd_section_from_shdr (abfd, shindex)
          return true;
        }
       {
-       unsigned int i;
+       unsigned int i, num_sec;
 
-       for (i = 1; i < ehdr->e_shnum; i++)
+       num_sec = elf_numsections (abfd);
+       for (i = 1; i < num_sec; i++)
          {
            Elf_Internal_Shdr *hdr2 = elf_elfsections (abfd)[i];
            if (hdr2->sh_link == shindex)
@@ -1607,9 +1622,11 @@ bfd_section_from_shdr (abfd, shindex)
       {
        asection *target_sect;
        Elf_Internal_Shdr *hdr2;
+       unsigned int num_sec = elf_numsections (abfd);
 
        /* Check for a bogus link to avoid crashing.  */
-       if (hdr->sh_link >= ehdr->e_shnum)
+       if ((hdr->sh_link >= SHN_LORESERVE && hdr->sh_link <= SHN_HIRESERVE)
+           || hdr->sh_link >= num_sec)
          {
            ((*_bfd_error_handler)
             (_("%s: invalid link %lu for reloc section %s (index %u)"),
@@ -1627,11 +1644,11 @@ bfd_section_from_shdr (abfd, shindex)
        if (elf_elfsections (abfd)[hdr->sh_link]->sh_type != SHT_SYMTAB
            && elf_elfsections (abfd)[hdr->sh_link]->sh_type != SHT_DYNSYM)
          {
-           int scan;
+           unsigned int scan;
            int found;
 
            found = 0;
-           for (scan = 1; scan < ehdr->e_shnum; scan++)
+           for (scan = 1; scan < num_sec; scan++)
              {
                if (elf_elfsections (abfd)[scan]->sh_type == SHT_SYMTAB
                    || elf_elfsections (abfd)[scan]->sh_type == SHT_DYNSYM)
@@ -1758,7 +1775,7 @@ bfd_section_from_r_symndx (abfd, cache, sec, r_symndx)
      asection *sec;
      unsigned long r_symndx;
 {
-  unsigned char esym_shndx[2];
+  unsigned char esym_shndx[4];
   unsigned int isym_shndx;
   Elf_Internal_Shdr *symtab_hdr;
   file_ptr pos;
@@ -1775,18 +1792,34 @@ bfd_section_from_r_symndx (abfd, cache, sec, r_symndx)
     {
       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);
     }
-  amt = sizeof (esym_shndx);
   if (bfd_seek (abfd, pos, SEEK_SET) != 0
       || bfd_bread ((PTR) esym_shndx, amt, abfd) != amt)
     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)
     {
       memset (cache->indx, -1, sizeof (cache->indx));
@@ -1794,7 +1827,7 @@ bfd_section_from_r_symndx (abfd, cache, sec, r_symndx)
     }
   cache->indx[ent] = r_symndx;
   cache->sec[ent] = sec;
-  if (isym_shndx > 0 && isym_shndx < SHN_LORESERVE)
+  if (isym_shndx < SHN_LORESERVE || isym_shndx > SHN_HIRESERVE)
     {
       asection *s;
       s = bfd_section_from_elf_index (abfd, isym_shndx);
@@ -1812,8 +1845,7 @@ bfd_section_from_elf_index (abfd, index)
      bfd *abfd;
      unsigned int index;
 {
-  BFD_ASSERT (index > 0 && index < SHN_LORESERVE);
-  if (index >= elf_elfheader (abfd)->e_shnum)
+  if (index >= elf_numsections (abfd))
     return NULL;
   return elf_elfsections (abfd)[index]->bfd_section;
 }
@@ -2268,18 +2300,24 @@ assign_section_numbers (abfd)
     {
       struct bfd_elf_section_data *d = elf_section_data (sec);
 
+      if (section_number == SHN_LORESERVE)
+       section_number += SHN_HIRESERVE + 1 - SHN_LORESERVE;
       d->this_idx = section_number++;
       _bfd_elf_strtab_addref (elf_shstrtab (abfd), d->this_hdr.sh_name);
       if ((sec->flags & SEC_RELOC) == 0)
        d->rel_idx = 0;
       else
        {
+         if (section_number == SHN_LORESERVE)
+           section_number += SHN_HIRESERVE + 1 - SHN_LORESERVE;
          d->rel_idx = section_number++;
          _bfd_elf_strtab_addref (elf_shstrtab (abfd), d->rel_hdr.sh_name);
        }
 
       if (d->rel_hdr2)
        {
+         if (section_number == SHN_LORESERVE)
+           section_number += SHN_HIRESERVE + 1 - SHN_LORESERVE;
          d->rel_idx2 = section_number++;
          _bfd_elf_strtab_addref (elf_shstrtab (abfd), d->rel_hdr2->sh_name);
        }
@@ -2287,21 +2325,42 @@ assign_section_numbers (abfd)
        d->rel_idx2 = 0;
     }
 
+  if (section_number == SHN_LORESERVE)
+    section_number += SHN_HIRESERVE + 1 - SHN_LORESERVE;
   t->shstrtab_section = section_number++;
   _bfd_elf_strtab_addref (elf_shstrtab (abfd), t->shstrtab_hdr.sh_name);
   elf_elfheader (abfd)->e_shstrndx = t->shstrtab_section;
 
   if (bfd_get_symcount (abfd) > 0)
     {
+      if (section_number == SHN_LORESERVE)
+       section_number += SHN_HIRESERVE + 1 - SHN_LORESERVE;
       t->symtab_section = section_number++;
       _bfd_elf_strtab_addref (elf_shstrtab (abfd), t->symtab_hdr.sh_name);
+      if (section_number > SHN_LORESERVE - 2)
+       {
+         if (section_number == SHN_LORESERVE)
+           section_number += SHN_HIRESERVE + 1 - SHN_LORESERVE;
+         t->symtab_shndx_section = section_number++;
+         t->symtab_shndx_hdr.sh_name
+           = (unsigned int) _bfd_elf_strtab_add (elf_shstrtab (abfd),
+                                                 ".symtab_shndx", false);
+         if (t->symtab_shndx_hdr.sh_name == (unsigned int) -1)
+           return false;
+       }
+      if (section_number == SHN_LORESERVE)
+       section_number += SHN_HIRESERVE + 1 - SHN_LORESERVE;
       t->strtab_section = section_number++;
       _bfd_elf_strtab_addref (elf_shstrtab (abfd), t->strtab_hdr.sh_name);
     }
 
   _bfd_elf_strtab_finalize (elf_shstrtab (abfd));
   t->shstrtab_hdr.sh_size = _bfd_elf_strtab_size (elf_shstrtab (abfd));
+
+  elf_numsections (abfd) = section_number;
   elf_elfheader (abfd)->e_shnum = section_number;
+  if (section_number > SHN_LORESERVE)
+    elf_elfheader (abfd)->e_shnum -= SHN_HIRESERVE + 1 - SHN_LORESERVE;
 
   /* Set up the list of section header pointers, in agreement with the
      indices.  */
@@ -2325,6 +2384,11 @@ assign_section_numbers (abfd)
   if (bfd_get_symcount (abfd) > 0)
     {
       i_shdrp[t->symtab_section] = &t->symtab_hdr;
+      if (elf_numsections (abfd) > SHN_LORESERVE)
+       {
+         i_shdrp[t->symtab_shndx_section] = &t->symtab_shndx_hdr;
+         t->symtab_shndx_hdr.sh_link = t->symtab_section;
+       }
       i_shdrp[t->strtab_section] = &t->strtab_hdr;
       t->symtab_hdr.sh_link = t->strtab_section;
     }
@@ -2438,9 +2502,11 @@ assign_section_numbers (abfd)
     }
 
   for (secn = 1; secn < section_number; ++secn)
-    i_shdrp[secn]->sh_name = _bfd_elf_strtab_offset (elf_shstrtab (abfd),
-                                                    i_shdrp[secn]->sh_name);
-
+    if (i_shdrp[secn] == NULL)
+      i_shdrp[secn] = i_shdrp[0];
+    else
+      i_shdrp[secn]->sh_name = _bfd_elf_strtab_offset (elf_shstrtab (abfd),
+                                                      i_shdrp[secn]->sh_name);
   return true;
 }
 
@@ -2722,6 +2788,10 @@ _bfd_elf_compute_section_file_positions (abfd, link_info)
       hdr = &elf_tdata (abfd)->symtab_hdr;
       off = _bfd_elf_assign_file_position_for_section (hdr, off, true);
 
+      hdr = &elf_tdata (abfd)->symtab_shndx_hdr;
+      if (hdr->sh_size != 0)
+       off = _bfd_elf_assign_file_position_for_section (hdr, off, true);
+
       hdr = &elf_tdata (abfd)->strtab_hdr;
       off = _bfd_elf_assign_file_position_for_section (hdr, off, true);
 
@@ -3037,7 +3107,9 @@ map_sections_to_segments (abfd)
 
   /* If there is a .eh_frame_hdr section, throw in a PT_GNU_EH_FRAME
      segment.  */
-  eh_frame_hdr = bfd_get_section_by_name (abfd, ".eh_frame_hdr");
+  eh_frame_hdr = NULL;
+  if (elf_tdata (abfd)->eh_frame_hdr)
+    eh_frame_hdr = bfd_get_section_by_name (abfd, ".eh_frame_hdr");
   if (eh_frame_hdr != NULL && (eh_frame_hdr->flags & SEC_LOAD))
     {
       amt = sizeof (struct elf_segment_map);
@@ -3617,6 +3689,7 @@ assign_file_positions_except_relocs (abfd)
   struct elf_obj_tdata * const tdata = elf_tdata (abfd);
   Elf_Internal_Ehdr * const i_ehdrp = elf_elfheader (abfd);
   Elf_Internal_Shdr ** const i_shdrpp = elf_elfsections (abfd);
+  unsigned int num_sec = elf_numsections (abfd);
   file_ptr off;
   struct elf_backend_data *bed = get_elf_backend_data (abfd);
 
@@ -3632,24 +3705,27 @@ assign_file_positions_except_relocs (abfd)
       /* We are not creating an executable, which means that we are
         not creating a program header, and that the actual order of
         the sections in the file is unimportant.  */
-      for (i = 1, hdrpp = i_shdrpp + 1; i < i_ehdrp->e_shnum; i++, hdrpp++)
+      for (i = 1, hdrpp = i_shdrpp + 1; i < num_sec; i++, hdrpp++)
        {
          Elf_Internal_Shdr *hdr;
 
          hdr = *hdrpp;
-         if (hdr->sh_type == SHT_REL || hdr->sh_type == SHT_RELA)
-           {
-             hdr->sh_offset = -1;
-             continue;
-           }
-         if (i == tdata->symtab_section
+         if (hdr->sh_type == SHT_REL
+             || hdr->sh_type == SHT_RELA
+             || i == tdata->symtab_section
+             || i == tdata->symtab_shndx_section
              || i == tdata->strtab_section)
            {
              hdr->sh_offset = -1;
-             continue;
            }
+         else
+           off = _bfd_elf_assign_file_position_for_section (hdr, off, true);
 
-         off = _bfd_elf_assign_file_position_for_section (hdr, off, true);
+         if (i == SHN_LORESERVE - 1)
+           {
+             i += SHN_HIRESERVE + 1 - SHN_LORESERVE;
+             hdrpp += SHN_HIRESERVE + 1 - SHN_LORESERVE;
+           }
        }
     }
   else
@@ -3665,7 +3741,7 @@ assign_file_positions_except_relocs (abfd)
       /* Assign file positions for the other sections.  */
 
       off = elf_tdata (abfd)->next_file_pos;
-      for (i = 1, hdrpp = i_shdrpp + 1; i < i_ehdrp->e_shnum; i++, hdrpp++)
+      for (i = 1, hdrpp = i_shdrpp + 1; i < num_sec; i++, hdrpp++)
        {
          Elf_Internal_Shdr *hdr;
 
@@ -3691,10 +3767,17 @@ assign_file_positions_except_relocs (abfd)
          else if (hdr->sh_type == SHT_REL
                   || hdr->sh_type == SHT_RELA
                   || hdr == i_shdrpp[tdata->symtab_section]
+                  || hdr == i_shdrpp[tdata->symtab_shndx_section]
                   || hdr == i_shdrpp[tdata->strtab_section])
            hdr->sh_offset = -1;
          else
            off = _bfd_elf_assign_file_position_for_section (hdr, off, true);
+
+         if (i == SHN_LORESERVE - 1)
+           {
+             i += SHN_HIRESERVE + 1 - SHN_LORESERVE;
+             hdrpp += SHN_HIRESERVE + 1 - SHN_LORESERVE;
+           }
        }
     }
 
@@ -3829,14 +3912,13 @@ _bfd_elf_assign_file_positions_for_relocs (abfd)
      bfd *abfd;
 {
   file_ptr off;
-  unsigned int i;
+  unsigned int i, num_sec;
   Elf_Internal_Shdr **shdrpp;
 
   off = elf_tdata (abfd)->next_file_pos;
 
-  for (i = 1, shdrpp = elf_elfsections (abfd) + 1;
-       i < elf_elfheader (abfd)->e_shnum;
-       i++, shdrpp++)
+  num_sec = elf_numsections (abfd);
+  for (i = 1, shdrpp = elf_elfsections (abfd) + 1; i < num_sec; i++, shdrpp++)
     {
       Elf_Internal_Shdr *shdrp;
 
@@ -3857,7 +3939,7 @@ _bfd_elf_write_object_contents (abfd)
   Elf_Internal_Ehdr *i_ehdrp;
   Elf_Internal_Shdr **i_shdrp;
   boolean failed;
-  unsigned int count;
+  unsigned int count, num_sec;
 
   if (! abfd->output_has_begun
       && ! _bfd_elf_compute_section_file_positions
@@ -3875,7 +3957,8 @@ _bfd_elf_write_object_contents (abfd)
   _bfd_elf_assign_file_positions_for_relocs (abfd);
 
   /* After writing the headers, we need to write the sections too...  */
-  for (count = 1; count < i_ehdrp->e_shnum; count++)
+  num_sec = elf_numsections (abfd);
+  for (count = 1; count < num_sec; count++)
     {
       if (bed->elf_backend_section_processing)
        (*bed->elf_backend_section_processing) (abfd, i_shdrp[count]);
@@ -3887,6 +3970,8 @@ _bfd_elf_write_object_contents (abfd)
              || bfd_bwrite (i_shdrp[count]->contents, amt, abfd) != amt)
            return false;
        }
+      if (count == SHN_LORESERVE - 1)
+       count += SHN_HIRESERVE + 1 - SHN_LORESERVE;
     }
 
   /* Write out the section header names.  */
@@ -3920,12 +4005,23 @@ _bfd_elf_section_from_bfd_section (abfd, asect)
   Elf_Internal_Shdr **i_shdrp = elf_elfsections (abfd);
   int index;
   Elf_Internal_Shdr *hdr;
-  int maxindex = elf_elfheader (abfd)->e_shnum;
+  int maxindex = elf_numsections (abfd);
 
-  for (index = 0; index < maxindex; index++)
+  if (elf_section_data (asect) != NULL
+      && elf_section_data (asect)->this_idx != 0)
+    return elf_section_data (asect)->this_idx;
+
+  if (bfd_is_abs_section (asect))
+    return SHN_ABS;
+  if (bfd_is_com_section (asect))
+    return SHN_COMMON;
+  if (bfd_is_und_section (asect))
+    return SHN_UNDEF;
+
+  for (index = 1; index < maxindex; index++)
     {
       hdr = i_shdrp[index];
-      if (hdr->bfd_section == asect)
+      if (hdr != NULL && hdr->bfd_section == asect)
        return index;
     }
 
@@ -3936,6 +4032,9 @@ _bfd_elf_section_from_bfd_section (abfd, asect)
          int retval;
 
          hdr = i_shdrp[index];
+         if (hdr == NULL)
+           continue;
+
          retval = index;
          if ((*bed->elf_backend_section_from_bfd_section)
              (abfd, hdr, asect, &retval))
@@ -3943,16 +4042,9 @@ _bfd_elf_section_from_bfd_section (abfd, asect)
        }
     }
 
-  if (bfd_is_abs_section (asect))
-    return SHN_ABS;
-  if (bfd_is_com_section (asect))
-    return SHN_COMMON;
-  if (bfd_is_und_section (asect))
-    return SHN_UNDEF;
-
   bfd_set_error (bfd_error_nonrepresentable_section);
 
-  return -1;
+  return SHN_BAD;
 }
 
 /* Given a BFD symbol, return the index in the ELF symbol table, or -1
@@ -4119,7 +4211,7 @@ copy_private_bfd_data (ibfd, obfd)
 
   /* Scan through the segments specified in the program header
      of the input BFD.  For this first scan we look for overlaps
-     in the loadable segments.  These can be created by wierd
+     in the loadable segments.  These can be created by weird
      parameters to objcopy.  */
   for (i = 0, segment = elf_tdata (ibfd)->phdr;
        i < num_segments;
@@ -4521,7 +4613,7 @@ copy_private_bfd_data (ibfd, obfd)
   elf_tdata (obfd)->segment_map = map_first;
 
   /* If we had to estimate the number of program headers that were
-     going to be needed, then check our estimate know and adjust
+     going to be needed, then check our estimate now and adjust
      the offset if necessary.  */
   if (phdr_adjust_seg != NULL)
     {
@@ -4634,10 +4726,11 @@ _bfd_elf_copy_private_section_data (ibfd, isec, obfd, osec)
    section indices; these definitions are interpreted by the
    swap_out_syms function.  */
 
-#define MAP_ONESYMTAB (SHN_LORESERVE - 1)
-#define MAP_DYNSYMTAB (SHN_LORESERVE - 2)
-#define MAP_STRTAB (SHN_LORESERVE - 3)
-#define MAP_SHSTRTAB (SHN_LORESERVE - 4)
+#define MAP_ONESYMTAB (SHN_HIOS + 1)
+#define MAP_DYNSYMTAB (SHN_HIOS + 2)
+#define MAP_STRTAB    (SHN_HIOS + 3)
+#define MAP_SHSTRTAB  (SHN_HIOS + 4)
+#define MAP_SYM_SHNDX (SHN_HIOS + 5)
 
 boolean
 _bfd_elf_copy_private_symbol_data (ibfd, isymarg, obfd, osymarg)
@@ -4670,6 +4763,8 @@ _bfd_elf_copy_private_symbol_data (ibfd, isymarg, obfd, osymarg)
        shndx = MAP_STRTAB;
       else if (shndx == elf_tdata (ibfd)->shstrtab_section)
        shndx = MAP_SHSTRTAB;
+      else if (shndx == elf_tdata (ibfd)->symtab_shndx_section)
+       shndx = MAP_SYM_SHNDX;
       osym->internal_elf_sym.st_shndx = shndx;
     }
 
@@ -4689,8 +4784,10 @@ swap_out_syms (abfd, sttp, relocatable_p)
   asymbol **syms;
   struct bfd_strtab_hash *stt;
   Elf_Internal_Shdr *symtab_hdr;
+  Elf_Internal_Shdr *symtab_shndx_hdr;
   Elf_Internal_Shdr *symstrtab_hdr;
   char *outbound_syms;
+  char *outbound_shndx;
   int idx;
   bfd_size_type amt;
 
@@ -4720,6 +4817,22 @@ swap_out_syms (abfd, sttp, relocatable_p)
     return false;
   symtab_hdr->contents = (PTR) outbound_syms;
 
+  outbound_shndx = NULL;
+  symtab_shndx_hdr = &elf_tdata (abfd)->symtab_shndx_hdr;
+  if (symtab_shndx_hdr->sh_name != 0)
+    {
+      amt = (bfd_size_type) (1 + symcount) * sizeof (Elf_External_Sym_Shndx);
+      outbound_shndx = bfd_alloc (abfd, amt);
+      if (outbound_shndx == NULL)
+       return false;
+      memset (outbound_shndx, 0, (unsigned long) amt);
+      symtab_shndx_hdr->contents = outbound_shndx;
+      symtab_shndx_hdr->sh_type = SHT_SYMTAB_SHNDX;
+      symtab_shndx_hdr->sh_size = amt;
+      symtab_shndx_hdr->sh_addralign = sizeof (Elf_External_Sym_Shndx);
+      symtab_shndx_hdr->sh_entsize = sizeof (Elf_External_Sym_Shndx);
+    }
+
   /* now generate the data (for "contents") */
   {
     /* Fill in zeroth symbol and swap it out.  */
@@ -4730,8 +4843,10 @@ swap_out_syms (abfd, sttp, relocatable_p)
     sym.st_info = 0;
     sym.st_other = 0;
     sym.st_shndx = SHN_UNDEF;
-    bed->s->swap_symbol_out (abfd, &sym, (PTR) outbound_syms);
+    bed->s->swap_symbol_out (abfd, &sym, outbound_syms, outbound_shndx);
     outbound_syms += bed->s->sizeof_sym;
+    if (outbound_shndx != NULL)
+      outbound_shndx += sizeof (Elf_External_Sym_Shndx);
   }
 
   syms = bfd_get_outsymbols (abfd);
@@ -4812,6 +4927,9 @@ swap_out_syms (abfd, sttp, relocatable_p)
                case MAP_SHSTRTAB:
                  shndx = elf_tdata (abfd)->shstrtab_section;
                  break;
+               case MAP_SYM_SHNDX:
+                 shndx = elf_tdata (abfd)->symtab_shndx_section;
+                 break;
                default:
                  break;
                }
@@ -4889,8 +5007,10 @@ swap_out_syms (abfd, sttp, relocatable_p)
       else
        sym.st_other = 0;
 
-      bed->s->swap_symbol_out (abfd, &sym, (PTR) outbound_syms);
+      bed->s->swap_symbol_out (abfd, &sym, outbound_syms, outbound_shndx);
       outbound_syms += bed->s->sizeof_sym;
+      if (outbound_shndx != NULL)
+       outbound_shndx += sizeof (Elf_External_Sym_Shndx);
     }
 
   *sttp = stt;
index 26e0b7523a8b24c20b920ee9822169601ff930af..d5cfcd428f62925f6965a1e16c8a8c316c31091b 100644 (file)
@@ -2455,14 +2455,9 @@ elf32_arm_gc_mark_hook (abfd, info, rel, h, sym)
      }
    else
      {
-       if (!(elf_bad_symtab (abfd)
-           && ELF_ST_BIND (sym->st_info) != STB_LOCAL)
-         && ! ((sym->st_shndx <= 0 || sym->st_shndx >= SHN_LORESERVE)
-                && sym->st_shndx != SHN_COMMON))
-          {
-            return bfd_section_from_elf_index (abfd, sym->st_shndx);
-          }
-      }
+       return bfd_section_from_elf_index (abfd, sym->st_shndx);
+     }
+
   return NULL;
 }
 
index 3efd24886b3e4a0e420d8f63258c3d497a02a40c..61f28e6d4e2270a9e1424eaf7e9909bc2503bdc9 100644 (file)
@@ -427,14 +427,9 @@ elf32_avr_gc_mark_hook (abfd, info, rel, h, sym)
     }
   else
     {
-      if (!(elf_bad_symtab (abfd)
-           && ELF_ST_BIND (sym->st_info) != STB_LOCAL)
-         && !((sym->st_shndx <= 0 || sym->st_shndx >= SHN_LORESERVE)
-              && sym->st_shndx != SHN_COMMON))
-       {
-         return bfd_section_from_elf_index (abfd, sym->st_shndx);
-       }
+      return bfd_section_from_elf_index (abfd, sym->st_shndx);
     }
+
   return NULL;
 }
 
index 5f7c6670c8fd6e72e89bcee0a83e8e4050dfe54c..6ee0d9cccf1190e28d01e201b28b4aa5ded55a0e 100644 (file)
@@ -1790,13 +1790,7 @@ cris_elf_gc_mark_hook (abfd, info, rel, h, sym)
     }
   else
     {
-      if (!(elf_bad_symtab (abfd)
-           && ELF_ST_BIND (sym->st_info) != STB_LOCAL)
-         && ! ((sym->st_shndx <= 0 || sym->st_shndx >= SHN_LORESERVE)
-               && sym->st_shndx != SHN_COMMON))
-       {
-         return bfd_section_from_elf_index (abfd, sym->st_shndx);
-       }
+      return bfd_section_from_elf_index (abfd, sym->st_shndx);
     }
 
   return NULL;
index 4ddda4fa576383d9efcc3b9c616350e37682eb89..11ec052a335be4f7b61a247bd5e67f24b7c86f8a 100644 (file)
@@ -272,14 +272,8 @@ elf32_d10v_gc_mark_hook (abfd, info, rel, h, sym)
      }
    else
      {
-       if (!(elf_bad_symtab (abfd)
-           && ELF_ST_BIND (sym->st_info) != STB_LOCAL)
-         && ! ((sym->st_shndx <= 0 || sym->st_shndx >= SHN_LORESERVE)
-                && sym->st_shndx != SHN_COMMON))
-          {
-            return bfd_section_from_elf_index (abfd, sym->st_shndx);
-          }
-      }
+       return bfd_section_from_elf_index (abfd, sym->st_shndx);
+     }
   return NULL;
 }
 
index 86f70efc1c78585a2f4f62fdc7c12afdf6238ce4..8e31d675223b0553e2326ed43038c468830090c1 100644 (file)
@@ -714,13 +714,7 @@ fr30_elf_gc_mark_hook (abfd, info, rel, h, sym)
     }
   else
     {
-      if (!(elf_bad_symtab (abfd)
-           && ELF_ST_BIND (sym->st_info) != STB_LOCAL)
-         && ! ((sym->st_shndx <= 0 || sym->st_shndx >= SHN_LORESERVE)
-               && sym->st_shndx != SHN_COMMON))
-       {
-         return bfd_section_from_elf_index (abfd, sym->st_shndx);
-       }
+      return bfd_section_from_elf_index (abfd, sym->st_shndx);
     }
 
   return NULL;
index 5ca695520a99deb1faf24253fb43b878fec4f566..52213ec84ecce25bab03b3deb769f0cb4e009c47 100644 (file)
@@ -42,7 +42,7 @@ static boolean elf32_h8_relax_section
 static boolean elf32_h8_relax_delete_bytes
   PARAMS ((bfd *, asection *, bfd_vma, int));
 static boolean elf32_h8_symbol_address_p
-  PARAMS ((bfd *, asection *, Elf32_External_Sym *, bfd_vma));
+  PARAMS ((bfd *, asection *, bfd_vma));
 static bfd_byte *elf32_h8_get_relocated_section_contents
   PARAMS ((bfd *, struct bfd_link_info *, struct bfd_link_order *,
           bfd_byte *, boolean, asymbol **));
@@ -690,6 +690,7 @@ 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;
@@ -697,6 +698,7 @@ elf32_h8_relax_section (abfd, sec, link_info, again)
   bfd_byte *free_contents = NULL;
   Elf32_External_Sym *extsyms = NULL;
   Elf32_External_Sym *free_extsyms = NULL;
+  Elf_External_Sym_Shndx *shndx_buf = NULL;
   static asection *last_input_section = NULL;
   static Elf_Internal_Rela *last_reloc = NULL;
 
@@ -718,6 +720,7 @@ 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
@@ -764,7 +767,7 @@ elf32_h8_relax_section (abfd, sec, link_info, again)
            }
        }
 
-      /* Read this BFD's symbols if we haven't done so already.  */
+      /* Read this BFD's local symbols if we haven't done so already.  */
       if (extsyms == NULL)
        {
          /* Get cached copy if it exists.  */
@@ -773,28 +776,46 @@ elf32_h8_relax_section (abfd, sec, link_info, again)
          else
            {
              /* Go get them off disk.  */
-             extsyms = ((Elf32_External_Sym *)
-                        bfd_malloc (symtab_hdr->sh_size));
+             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 (extsyms, symtab_hdr->sh_size, abfd)
-                     != symtab_hdr->sh_size))
+                 || 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;
            }
        }
 
       /* 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;
          asection *sym_sec;
 
          /* A local symbol.  */
-         bfd_elf32_swap_symbol_in (abfd,
-                                   extsyms + ELF32_R_SYM (irel->r_info),
-                                   &isym);
+         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, esym, shndx, &isym);
 
          sym_sec = bfd_section_from_elf_index (abfd, isym.st_shndx);
          symval = (isym.st_value
@@ -862,7 +883,6 @@ elf32_h8_relax_section (abfd, sec, link_info, again)
                elf_section_data (sec)->this_hdr.contents = contents;
                free_contents = NULL;
 
-               symtab_hdr->contents = (bfd_byte *) extsyms;
                free_extsyms = NULL;
 
                /* If the previous instruction conditionally jumped around
@@ -878,6 +898,8 @@ 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;
@@ -885,9 +907,11 @@ elf32_h8_relax_section (abfd, sec, link_info, again)
                    /* We will need to examine the symbol used by the
                       previous relocation.  */
 
-                   bfd_elf32_swap_symbol_in (abfd,
-                                             (extsyms + ELF32_R_SYM (last_reloc->r_info)),
-                                             &last_symbol);
+                   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, esym, shndx, &last_symbol);
 
                    last_sym_sec
                      = bfd_section_from_elf_index (abfd, last_symbol.st_shndx);
@@ -900,8 +924,7 @@ elf32_h8_relax_section (abfd, sec, link_info, again)
                       exists at the current location.  */
                    if (last_value == dot + 4
                        && last_reloc->r_offset + 2 == irel->r_offset
-                       && ! elf32_h8_symbol_address_p (abfd, sec,
-                                                       extsyms, dot))
+                       && ! elf32_h8_symbol_address_p (abfd, sec, dot))
                      {
                        /* We can eliminate this jump.  Twiddle the
                           previous relocation as necessary.  */
@@ -989,7 +1012,6 @@ elf32_h8_relax_section (abfd, sec, link_info, again)
                elf_section_data (sec)->this_hdr.contents = contents;
                free_contents = NULL;
 
-               symtab_hdr->contents = (bfd_byte *) extsyms;
                free_extsyms = NULL;
 
                /* Get the opcode.  */
@@ -1051,7 +1073,6 @@ elf32_h8_relax_section (abfd, sec, link_info, again)
                elf_section_data (sec)->this_hdr.contents = contents;
                free_contents = NULL;
 
-               symtab_hdr->contents = (bfd_byte *) extsyms;
                free_extsyms = NULL;
 
                /* Get the opcode.  */
@@ -1114,7 +1135,6 @@ elf32_h8_relax_section (abfd, sec, link_info, again)
                elf_section_data (sec)->this_hdr.contents = contents;
                free_contents = NULL;
 
-               symtab_hdr->contents = (bfd_byte *) extsyms;
                free_extsyms = NULL;
 
                /* Get the opcode.  */
@@ -1171,7 +1191,6 @@ elf32_h8_relax_section (abfd, sec, link_info, again)
                elf_section_data (sec)->this_hdr.contents = contents;
                free_contents = NULL;
 
-               symtab_hdr->contents = (bfd_byte *) extsyms;
                free_extsyms = NULL;
 
                /* Get the opcode.  */
@@ -1221,16 +1240,19 @@ elf32_h8_relax_section (abfd, sec, link_info, again)
       free_contents = NULL;
     }
 
+  if (shndx_buf != NULL)
+    {
+      shndx_hdr->contents = NULL;
+      free (shndx_buf);
+    }
+
   if (free_extsyms != NULL)
     {
       if (! link_info->keep_memory)
-       free (free_extsyms);
-      else
        {
-         /* Cache the symbols for elf_link_input_bfd.  */
-         symtab_hdr->contents = (unsigned char *) extsyms;
+         symtab_hdr->contents = NULL;
+         free (free_extsyms);
        }
-      free_extsyms = NULL;
     }
 
   return true;
@@ -1240,8 +1262,16 @@ elf32_h8_relax_section (abfd, sec, link_info, again)
     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)
-    free (free_extsyms);
+    {
+      symtab_hdr->contents = NULL;
+      free (free_extsyms);
+    }
   return false;
 }
 
@@ -1255,19 +1285,23 @@ 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;
-  int shndx, index;
+  unsigned int sec_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;
+  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;
 
-  shndx = _bfd_elf_section_from_bfd_section (abfd, sec);
+  sec_shndx = _bfd_elf_section_from_bfd_section (abfd, sec);
 
   contents = elf_section_data (sec)->this_hdr.contents;
 
@@ -1295,40 +1329,41 @@ 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++)
+  for (; esym < esymend; esym++, shndx = (shndx ? shndx + 1 : NULL))
     {
       Elf_Internal_Sym isym;
+      Elf_External_Sym_Shndx dummy;
 
-      bfd_elf32_swap_symbol_in (abfd, esym, &isym);
+      bfd_elf32_swap_symbol_in (abfd, esym, shndx, &isym);
 
-      if (isym.st_shndx == shndx
+      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);
+         bfd_elf32_swap_symbol_out (abfd, &isym, esym, &dummy);
        }
     }
 
   /* 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;
-
-      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)
+      struct elf_link_hash_entry *sym_hash = *sym_hashes;
+      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;
        }
     }
 
@@ -1338,46 +1373,53 @@ elf32_h8_relax_delete_bytes (abfd, sec, addr, count)
 /* Return true if a symbol exists at the given address, else return
    false.  */
 static boolean
-elf32_h8_symbol_address_p (abfd, sec, extsyms, addr)
+elf32_h8_symbol_address_p (abfd, sec, addr)
      bfd *abfd;
      asection *sec;
-     Elf32_External_Sym *extsyms;
      bfd_vma addr;
 {
   Elf_Internal_Shdr *symtab_hdr;
-  int shndx;
+  Elf_Internal_Shdr *shndx_hdr;
+  unsigned int sec_shndx;
   Elf32_External_Sym *esym, *esymend;
-  struct elf_link_hash_entry **sym_hash, **sym_hash_end;
+  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;
-  shndx = _bfd_elf_section_from_bfd_section (abfd, sec);
+  sec_shndx = _bfd_elf_section_from_bfd_section (abfd, sec);
 
   /* Examine all the symbols.  */
-  esym = extsyms;
+  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++)
+  for (; esym < esymend; esym++, shndx = (shndx ? shndx + 1 : NULL))
     {
       Elf_Internal_Sym isym;
 
-      bfd_elf32_swap_symbol_in (abfd, esym, &isym);
+      bfd_elf32_swap_symbol_in (abfd, esym, shndx, &isym);
 
-      if (isym.st_shndx == shndx
+      if (isym.st_shndx == sec_shndx
          && isym.st_value == addr)
        return true;
     }
 
-  sym_hash = elf_sym_hashes (abfd);
-  sym_hash_end = (sym_hash
-                 + (symtab_hdr->sh_size / sizeof (Elf32_External_Sym)
-                    - symtab_hdr->sh_info));
-  for (; sym_hash < sym_hash_end; sym_hash++)
+  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++)
     {
-      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)
+      struct elf_link_hash_entry *sym_hash = *sym_hashes;
+      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)
        return true;
     }
+
   return false;
 }
 
@@ -1395,11 +1437,14 @@ 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;
 
   /* We only need to handle the case of relaxing, or of having a
@@ -1412,6 +1457,7 @@ 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);
@@ -1422,20 +1468,31 @@ elf32_h8_get_relocated_section_contents (output_bfd, link_info, link_order,
       Elf_Internal_Sym *isymp;
       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
+      else if (symtab_hdr->sh_info != 0)
        {
-         bfd_size_type amt;
-
          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)
+         if (external_syms == NULL)
            goto error_return;
          if (bfd_seek (input_bfd, symtab_hdr->sh_offset, SEEK_SET) != 0
-             || bfd_bread (external_syms, amt, input_bfd) != amt)
+             || 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;
        }
 
@@ -1445,40 +1502,35 @@ elf32_h8_get_relocated_section_contents (output_bfd, link_info, link_order,
       if (internal_relocs == NULL)
        goto error_return;
 
-      internal_syms = ((Elf_Internal_Sym *)
-                      bfd_malloc ((bfd_size_type) symtab_hdr->sh_info
-                                  * sizeof (Elf_Internal_Sym)));
-      if (internal_syms == NULL && symtab_hdr->sh_info > 0)
+      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;
 
-      sections = (asection **) bfd_malloc ((bfd_size_type) symtab_hdr->sh_info
-                                          * sizeof (asection *));
-      if (sections == NULL && symtab_hdr->sh_info > 0)
+      amt = symtab_hdr->sh_info;
+      amt *= sizeof (asection *);
+      sections = (asection **) bfd_malloc (amt);
+      if (sections == NULL && amt != 0)
        goto error_return;
 
-      isymp = internal_syms;
-      secpp = sections;
-      esym = external_syms;
-      esymend = esym + symtab_hdr->sh_info;
-      for (; esym < esymend; ++esym, ++isymp, ++secpp)
+      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))
        {
          asection *isec;
 
-         bfd_elf32_swap_symbol_in (input_bfd, esym, isymp);
+         bfd_elf32_swap_symbol_in (input_bfd, esym, shndx, isymp);
 
          if (isymp->st_shndx == SHN_UNDEF)
            isec = bfd_und_section_ptr;
-         else if (isymp->st_shndx > 0 && isymp->st_shndx < SHN_LORESERVE)
-           isec = bfd_section_from_elf_index (input_bfd, isymp->st_shndx);
          else if (isymp->st_shndx == SHN_ABS)
            isec = bfd_abs_section_ptr;
          else if (isymp->st_shndx == SHN_COMMON)
            isec = bfd_com_section_ptr;
          else
-           {
-             /* Who knows?  */
-             isec = NULL;
-           }
+           isec = bfd_section_from_elf_index (input_bfd, isymp->st_shndx);
 
          *secpp = isec;
        }
@@ -1490,16 +1542,14 @@ elf32_h8_get_relocated_section_contents (output_bfd, link_info, link_order,
 
       if (sections != NULL)
        free (sections);
-      sections = NULL;
       if (internal_syms != NULL)
        free (internal_syms);
-      internal_syms = NULL;
+      if (shndx_buf != NULL)
+       free (shndx_buf);
       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;
     }
 
   return data;
@@ -1508,6 +1558,8 @@ elf32_h8_get_relocated_section_contents (output_bfd, link_info, link_order,
   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)
index 934c8e82b8a052ca35a517a8f05b84cc68c51723..5dfd6f2cf86284125a3d78395b26b321e3dc7f1c 100644 (file)
@@ -1638,13 +1638,7 @@ elf32_hppa_gc_mark_hook (abfd, info, rel, h, sym)
     }
   else
     {
-      if (!(elf_bad_symtab (abfd)
-           && ELF_ST_BIND (sym->st_info) != STB_LOCAL)
-         && ! ((sym->st_shndx <= 0 || sym->st_shndx >= SHN_LORESERVE)
-               && sym->st_shndx != SHN_COMMON))
-       {
-         return bfd_section_from_elf_index (abfd, sym->st_shndx);
-       }
+      return bfd_section_from_elf_index (abfd, sym->st_shndx);
     }
 
   return NULL;
@@ -2741,8 +2735,10 @@ elf32_hppa_size_stubs (output_bfd, stub_bfd, info, multi_subspace, group_size,
        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.  */
@@ -2756,32 +2752,50 @@ elf32_hppa_size_stubs (output_bfd, stub_bfd, info, multi_subspace, group_size,
       sec_size *= sizeof (Elf_Internal_Sym);
       local_syms = (Elf_Internal_Sym *) bfd_malloc (sec_size);
       if (local_syms == NULL)
-       {
-         goto error_ret_free_local;
-       }
+       goto error_ret_free_local;
+
       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)
-       {
-         goto error_ret_free_local;
-       }
+       goto error_ret_free_local;
 
       if (bfd_seek (input_bfd, symtab_hdr->sh_offset, SEEK_SET) != 0
-         || (bfd_bread (ext_syms, sec_size, input_bfd) != sec_size))
+         || bfd_bread ((PTR) ext_syms, sec_size, input_bfd) != sec_size)
        {
+       error_ret_free_ext_syms:
          free (ext_syms);
          goto error_ret_free_local;
        }
 
+      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.  */
-      isym = local_syms;
-      esym = ext_syms;
-      for (end_sy = esym + symtab_hdr->sh_info; esym < end_sy; esym++, isym++)
-       bfd_elf32_swap_symbol_in (input_bfd, esym, isym);
+      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, esym, shndx, isym);
 
       /* Now we can free the external symbols.  */
+      free (shndx_buf);
       free (ext_syms);
 
       if (info->shared && htab->multi_subspace)
@@ -2914,9 +2928,9 @@ elf32_hppa_size_stubs (output_bfd, stub_bfd, info, multi_subspace, group_size,
              /* Read in the external relocs.  */
              input_rel_hdr = &elf_section_data (section)->rel_hdr;
              if (bfd_seek (input_bfd, input_rel_hdr->sh_offset, SEEK_SET) != 0
-                 || bfd_bread (external_relocs,
-                              input_rel_hdr->sh_size,
-                              input_bfd) != input_rel_hdr->sh_size)
+                 || bfd_bread ((PTR) external_relocs,
+                               input_rel_hdr->sh_size,
+                               input_bfd) != input_rel_hdr->sh_size)
                {
                  free (external_relocs);
                error_ret_free_internal:
index 315689e50435bbfee6a9b0bec970ab7e55b75668..7f35bc8111f9c9071fa930e63220465a73633dc0 100644 (file)
@@ -1209,6 +1209,7 @@ i370_elf_finish_dynamic_sections (output_bfd, info)
       for (s = output_bfd->sections; s != NULL; s = s->next)
        {
          int indx, dindx;
+         Elf32_External_Sym *esym;
 
          sym.st_value = s->vma;
 
@@ -1224,10 +1225,8 @@ i370_elf_finish_dynamic_sections (output_bfd, info)
 
              sym.st_shndx = indx;
 
-             bfd_elf32_swap_symbol_out (output_bfd, &sym,
-                                        (PTR) (((Elf32_External_Sym *)
-                                                sdynsym->contents)
-                                               + dindx));
+             esym = (Elf32_External_Sym *) sdynsym->contents + dindx;
+             bfd_elf32_swap_symbol_out (output_bfd, &sym, (PTR) esym, (PTR) 0);
            }
        }
 
index 9fae870350bfbd8a87adf0780f1fe9c1fa0a6303..7d22c6ae2ccad0df1d7c0e38ec0bab8181de242a 100644 (file)
@@ -987,13 +987,7 @@ elf_i386_gc_mark_hook (abfd, info, rel, h, sym)
     }
   else
     {
-      if (!(elf_bad_symtab (abfd)
-           && ELF_ST_BIND (sym->st_info) != STB_LOCAL)
-         && ! ((sym->st_shndx <= 0 || sym->st_shndx >= SHN_LORESERVE)
-               && sym->st_shndx != SHN_COMMON))
-       {
-         return bfd_section_from_elf_index (abfd, sym->st_shndx);
-       }
+      return bfd_section_from_elf_index (abfd, sym->st_shndx);
     }
 
   return NULL;
index 214fed172f19ad97234bcfbbbaf51e37b3758dfa..4e6eca49085c6e8e8f99bbe875b38b6b3571967d 100644 (file)
@@ -1856,8 +1856,6 @@ m32r_elf_get_relocated_section_contents (output_bfd, link_info, link_order,
 
          if (isymp->st_shndx == SHN_UNDEF)
            isec = bfd_und_section_ptr;
-         else if (isymp->st_shndx > 0 && isymp->st_shndx < SHN_LORESERVE)
-           isec = bfd_section_from_elf_index (input_bfd, isymp->st_shndx);
          else if (isymp->st_shndx == SHN_ABS)
            isec = bfd_abs_section_ptr;
          else if (isymp->st_shndx == SHN_COMMON)
@@ -1865,10 +1863,7 @@ m32r_elf_get_relocated_section_contents (output_bfd, link_info, link_order,
          else if (isymp->st_shndx == SHN_M32R_SCOMMON)
            isec = &m32r_elf_scom_section;
          else
-           {
-             /* Who knows?  */
-             isec = NULL;
-           }
+           isec = bfd_section_from_elf_index (input_bfd, isymp->st_shndx);
 
          *secpp = isec;
        }
@@ -2095,14 +2090,8 @@ m32r_elf_gc_mark_hook (abfd, info, rel, h, sym)
      }
    else
      {
-       if (!(elf_bad_symtab (abfd)
-           && ELF_ST_BIND (sym->st_info) != STB_LOCAL)
-         && ! ((sym->st_shndx <= 0 || sym->st_shndx >= SHN_LORESERVE)
-                && sym->st_shndx != SHN_COMMON))
-          {
-            return bfd_section_from_elf_index (abfd, sym->st_shndx);
-          }
-      }
+       return bfd_section_from_elf_index (abfd, sym->st_shndx);
+     }
   return NULL;
 }
 
index e4b41be5904b4289adaca4d97ccb3ac28b523ddf..d0675628431a806a8fa476ed17930b5c7832a949 100644 (file)
@@ -805,13 +805,7 @@ elf_m68k_gc_mark_hook (abfd, info, rel, h, sym)
     }
   else
     {
-      if (!(elf_bad_symtab (abfd)
-           && ELF_ST_BIND (sym->st_info) != STB_LOCAL)
-         && ! ((sym->st_shndx <= 0 || sym->st_shndx >= SHN_LORESERVE)
-               && sym->st_shndx != SHN_COMMON))
-       {
-         return bfd_section_from_elf_index (abfd, sym->st_shndx);
-       }
+      return bfd_section_from_elf_index (abfd, sym->st_shndx);
     }
 
   return NULL;
@@ -2154,8 +2148,10 @@ 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_Rela *irel, *irelend;
@@ -2177,22 +2173,34 @@ bfd_m68k_elf32_create_embedded_relocs (abfd, info, datasec, relsec, errmsg)
   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, symtab_hdr->sh_size);
+       extsyms = (Elf32_External_Sym *) bfd_alloc (abfd, amt);
       else
-       extsyms = (Elf32_External_Sym *) bfd_malloc (symtab_hdr->sh_size);
+       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, symtab_hdr->sh_size, abfd)
-             != symtab_hdr->sh_size))
+         || 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
                     (abfd, datasec, (PTR) NULL, (Elf_Internal_Rela *) NULL,
@@ -2231,12 +2239,14 @@ 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.  */
-         bfd_elf32_swap_symbol_in (abfd,
-                                   extsyms + ELF32_R_SYM (irel->r_info),
-                                   &isym);
+         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, esym, shndx, &isym);
 
          targetsec = bfd_section_from_elf_index (abfd, isym.st_shndx);
        }
@@ -2262,6 +2272,8 @@ 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)
@@ -2269,6 +2281,8 @@ bfd_m68k_elf32_create_embedded_relocs (abfd, info, datasec, relsec, errmsg)
   return true;
 
 error_return:
+  if (shndx_buf != NULL)
+    free (shndx_buf);
   if (free_extsyms != NULL)
     free (free_extsyms);
   if (free_relocs != NULL)
index 8275965c9a80dbaf2b5efcdf2c41ac3fb27c10e5..90c71c8d2f0f1604e0218931cc05c4d25c625b16 100644 (file)
@@ -647,13 +647,7 @@ mcore_elf_gc_mark_hook (abfd, info, rel, h, sym)
     }
   else
     {
-      if (!(elf_bad_symtab (abfd)
-           && ELF_ST_BIND (sym->st_info) != STB_LOCAL)
-         && ! ((sym->st_shndx <= 0 || sym->st_shndx >= SHN_LORESERVE)
-               && sym->st_shndx != SHN_COMMON))
-       {
-         return bfd_section_from_elf_index (abfd, sym->st_shndx);
-       }
+      return bfd_section_from_elf_index (abfd, sym->st_shndx);
     }
 
   return NULL;
index ff758fa7869a7913512c50bd0069a9065cd45997..41c4309591493b4f8edc36a3cd4d9e645e38ebfb 100644 (file)
@@ -2955,7 +2955,7 @@ _bfd_mips_elf_final_write_processing (abfd, linker)
   /* Set the sh_info field for .gptab sections and other appropriate
      info for each special section.  */
   for (i = 1, hdrpp = elf_elfsections (abfd) + 1;
-       i < elf_elfheader (abfd)->e_shnum;
+       i < elf_numsections (abfd);
        i++, hdrpp++)
     {
       switch ((*hdrpp)->sh_type)
@@ -8539,13 +8539,7 @@ _bfd_mips_elf_gc_mark_hook (abfd, info, rel, h, sym)
     }
   else
     {
-      if (!(elf_bad_symtab (abfd)
-           && ELF_ST_BIND (sym->st_info) != STB_LOCAL)
-         && ! ((sym->st_shndx <= 0 || sym->st_shndx >= SHN_LORESERVE)
-               && sym->st_shndx != SHN_COMMON))
-       {
-         return bfd_section_from_elf_index (abfd, sym->st_shndx);
-       }
+      return bfd_section_from_elf_index (abfd, sym->st_shndx);
     }
 
   return NULL;
index 5a7b42ff61d8f7a0edd04fcb1c5043572344b083..5f603660345849bd802361f1600cbf4ecb6373a3 100644 (file)
@@ -516,13 +516,7 @@ openrisc_elf_gc_mark_hook (abfd, info, rel, h, sym)
     }
   else
     {
-      if (!(elf_bad_symtab (abfd)
-           && ELF_ST_BIND (sym->st_info) != STB_LOCAL)
-         && !((sym->st_shndx <= 0 || sym->st_shndx >= SHN_LORESERVE)
-              && sym->st_shndx != SHN_COMMON))
-       {
-         return bfd_section_from_elf_index (abfd, sym->st_shndx);
-       }
+      return bfd_section_from_elf_index (abfd, sym->st_shndx);
     }
 
   return NULL;
index e174603ce742df2be70356d0b7cf40d911e99571..15172c695a7e81ba15119ff50a278c4c9bbf38c6 100644 (file)
@@ -2477,13 +2477,7 @@ ppc_elf_gc_mark_hook (abfd, info, rel, h, sym)
     }
   else
     {
-      if (!(elf_bad_symtab (abfd)
-           && ELF_ST_BIND (sym->st_info) != STB_LOCAL)
-         && ! ((sym->st_shndx <= 0 || sym->st_shndx >= SHN_LORESERVE)
-               && sym->st_shndx != SHN_COMMON))
-       {
-         return bfd_section_from_elf_index (abfd, sym->st_shndx);
-       }
+      return bfd_section_from_elf_index (abfd, sym->st_shndx);
     }
 
   return NULL;
index af2c7ad63968aab33dc1a4b85227f717a1a99b8a..4fd706d3c974e77b4b925d1bf4c84fd65ec195b1 100644 (file)
@@ -916,13 +916,7 @@ elf_s390_gc_mark_hook (abfd, info, rel, h, sym)
     }
   else
     {
-      if (!(elf_bad_symtab (abfd)
-           && ELF_ST_BIND (sym->st_info) != STB_LOCAL)
-         && ! ((sym->st_shndx <= 0 || sym->st_shndx >= SHN_LORESERVE)
-               && sym->st_shndx != SHN_COMMON))
-       {
-         return bfd_section_from_elf_index (abfd, sym->st_shndx);
-       }
+      return bfd_section_from_elf_index (abfd, sym->st_shndx);
     }
 
   return NULL;
index 9fe9873e3ff6852fda5f46e432da6a756d0574ce..1a711916bb07f9f8feb789894fb1bc9a24b91971 100644 (file)
@@ -1023,6 +1023,7 @@ 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;
@@ -1031,6 +1032,7 @@ sh_elf_relax_section (abfd, sec, link_info, again)
   bfd_byte *free_contents = NULL;
   Elf32_External_Sym *extsyms = NULL;
   Elf32_External_Sym *free_extsyms = NULL;
+  Elf_External_Sym_Shndx *shndx_buf = NULL;
 
   *again = false;
 
@@ -1045,6 +1047,7 @@ 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,
@@ -1151,26 +1154,47 @@ sh_elf_relax_section (abfd, sec, link_info, again)
            extsyms = (Elf32_External_Sym *) symtab_hdr->contents;
          else
            {
-             extsyms = (Elf32_External_Sym *) bfd_malloc (symtab_hdr->sh_size);
+             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 (extsyms, symtab_hdr->sh_size, abfd)
-                     != symtab_hdr->sh_size))
+                 || 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;
            }
        }
 
       /* 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;
 
-         /* A local symbol.  */
-         bfd_elf32_swap_symbol_in (abfd,
-                                   extsyms + ELF32_R_SYM (irelfn->r_info),
-                                   &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, esym, shndx, &isym);
 
          if (isym.st_shndx != _bfd_elf_section_from_bfd_section (abfd, sec))
            {
@@ -1236,7 +1260,6 @@ sh_elf_relax_section (abfd, sec, link_info, again)
       elf_section_data (sec)->this_hdr.contents = contents;
       free_contents = NULL;
 
-      symtab_hdr->contents = (bfd_byte *) extsyms;
       free_extsyms = NULL;
 
       /* Replace the jsr with a bsr.  */
@@ -1362,16 +1385,12 @@ sh_elf_relax_section (abfd, sec, link_info, again)
          elf_section_data (sec)->this_hdr.contents = contents;
          free_contents = NULL;
 
-         symtab_hdr->contents = (bfd_byte *) extsyms;
          free_extsyms = NULL;
        }
     }
 
   if (free_relocs != NULL)
-    {
-      free (free_relocs);
-      free_relocs = NULL;
-    }
+    free (free_relocs);
 
   if (free_contents != NULL)
     {
@@ -1382,19 +1401,21 @@ sh_elf_relax_section (abfd, sec, link_info, again)
          /* 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)
-       free (free_extsyms);
-      else
        {
-         /* Cache the symbols for elf_link_input_bfd.  */
-         symtab_hdr->contents = (unsigned char *) extsyms;
+         symtab_hdr->contents = NULL;
+         free (free_extsyms);
        }
-      free_extsyms = NULL;
     }
 
   return true;
@@ -1404,8 +1425,17 @@ sh_elf_relax_section (abfd, sec, link_info, again)
     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)
-    free (free_extsyms);
+    {
+      symtab_hdr->contents = NULL;
+      free (free_extsyms);
+    }
+
   return false;
 }
 
@@ -1421,20 +1451,27 @@ 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;
-  int shndx, index;
+  unsigned int sec_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;
+  Elf_External_Sym_Shndx *shndx_buf, *shndx;
+  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 = _bfd_elf_section_from_bfd_section (abfd, sec);
+  shndx_hdr = &elf_tdata (abfd)->symtab_shndx_hdr;
+  shndx_buf = (Elf_External_Sym_Shndx *) shndx_hdr->contents;
+
+  sec_shndx = _bfd_elf_section_from_bfd_section (abfd, sec);
 
   contents = elf_section_data (sec)->this_hdr.contents;
 
@@ -1534,10 +1571,11 @@ 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)
            {
-             bfd_elf32_swap_symbol_in (abfd,
-                                       extsyms + ELF32_R_SYM (irel->r_info),
-                                       &sym);
-             if (sym.st_shndx == shndx
+             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, esym, shndx, &sym);
+
+             if (sym.st_shndx == sec_shndx
                  && (sym.st_value <= addr
                      || sym.st_value >= toaddr))
                {
@@ -1795,11 +1833,12 @@ sh_elf_relax_delete_bytes (abfd, sec, addr, count)
          if (ELF32_R_SYM (irelscan->r_info) >= symtab_hdr->sh_info)
            continue;
 
-         bfd_elf32_swap_symbol_in (abfd,
-                                   extsyms + ELF32_R_SYM (irelscan->r_info),
-                                   &sym);
 
-         if (sym.st_shndx == shndx
+         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, esym, shndx, &sym);
+
+         if (sym.st_shndx == sec_shndx
              && (sym.st_value <= addr
                  || sym.st_value >= toaddr))
            {
@@ -1836,40 +1875,40 @@ 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++)
+  for (; esym < esymend; esym++, shndx = (shndx ? shndx + 1 : NULL))
     {
       Elf_Internal_Sym isym;
+      Elf_External_Sym_Shndx dummy;
 
-      bfd_elf32_swap_symbol_in (abfd, esym, &isym);
+      bfd_elf32_swap_symbol_in (abfd, esym, shndx, &isym);
 
-      if (isym.st_shndx == shndx
+      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);
+         bfd_elf32_swap_symbol_out (abfd, &isym, (PTR) esym, (PTR) &dummy);
        }
     }
 
   /* 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;
-
-      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)
+      struct elf_link_hash_entry *sym_hash = *sym_hashes;
+      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;
        }
     }
 
@@ -3571,11 +3610,14 @@ 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;
 
   /* We only need to handle the case of relaxing, or of having a
@@ -3588,6 +3630,7 @@ 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);
@@ -3598,19 +3641,31 @@ sh_elf_get_relocated_section_contents (output_bfd, link_info, link_order,
       Elf_Internal_Sym *isymp;
       asection **secpp;
       Elf32_External_Sym *esym, *esymend;
-      bfd_size_type size;
+      bfd_size_type amt;
 
       if (symtab_hdr->contents != NULL)
        external_syms = (Elf32_External_Sym *) symtab_hdr->contents;
-      else
+      else if (symtab_hdr->sh_info != 0)
        {
-         size = symtab_hdr->sh_info;
-         size *= sizeof (Elf32_External_Sym);
-         external_syms = (Elf32_External_Sym *) bfd_malloc (size);
-         if (external_syms == NULL && size != 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 (external_syms, size, input_bfd) != size)
+             || 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;
        }
 
@@ -3620,41 +3675,35 @@ sh_elf_get_relocated_section_contents (output_bfd, link_info, link_order,
       if (internal_relocs == NULL)
        goto error_return;
 
-      size = symtab_hdr->sh_info;
-      size *= sizeof (Elf_Internal_Sym);
-      internal_syms = (Elf_Internal_Sym *) bfd_malloc (size);
-      if (internal_syms == NULL && symtab_hdr->sh_info > 0)
+      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;
 
-      size = symtab_hdr->sh_info;
-      size *= sizeof (asection *);
-      sections = (asection **) bfd_malloc (size);
-      if (sections == NULL && symtab_hdr->sh_info > 0)
+      amt = symtab_hdr->sh_info;
+      amt *= sizeof (asection *);
+      sections = (asection **) bfd_malloc (amt);
+      if (sections == NULL && amt != 0)
        goto error_return;
 
-      isymp = internal_syms;
-      secpp = sections;
-      esym = external_syms;
-      esymend = esym + symtab_hdr->sh_info;
-      for (; esym < esymend; ++esym, ++isymp, ++secpp)
+      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))
        {
          asection *isec;
 
-         bfd_elf32_swap_symbol_in (input_bfd, esym, isymp);
+         bfd_elf32_swap_symbol_in (input_bfd, esym, shndx, isymp);
 
          if (isymp->st_shndx == SHN_UNDEF)
            isec = bfd_und_section_ptr;
-         else if (isymp->st_shndx > 0 && isymp->st_shndx < SHN_LORESERVE)
-           isec = bfd_section_from_elf_index (input_bfd, isymp->st_shndx);
          else if (isymp->st_shndx == SHN_ABS)
            isec = bfd_abs_section_ptr;
          else if (isymp->st_shndx == SHN_COMMON)
            isec = bfd_com_section_ptr;
          else
-           {
-             /* Who knows?  */
-             isec = NULL;
-           }
+           isec = bfd_section_from_elf_index (input_bfd, isymp->st_shndx);
 
          *secpp = isec;
        }
@@ -3666,16 +3715,14 @@ sh_elf_get_relocated_section_contents (output_bfd, link_info, link_order,
 
       if (sections != NULL)
        free (sections);
-      sections = NULL;
       if (internal_syms != NULL)
        free (internal_syms);
-      internal_syms = NULL;
+      if (shndx_buf != NULL)
+       free (shndx_buf);
       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;
     }
 
   return data;
@@ -3684,6 +3731,8 @@ sh_elf_get_relocated_section_contents (output_bfd, link_info, link_order,
   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)
@@ -3726,12 +3775,9 @@ sh_elf_gc_mark_hook (abfd, info, rel, h, sym)
     }
   else
     {
-      if (!(elf_bad_symtab (abfd)
-           && ELF_ST_BIND (sym->st_info) != STB_LOCAL)
-         && ! ((sym->st_shndx <= 0 || sym->st_shndx >= SHN_LORESERVE)
-                && sym->st_shndx != SHN_COMMON))
-       return bfd_section_from_elf_index (abfd, sym->st_shndx);
+      return bfd_section_from_elf_index (abfd, sym->st_shndx);
     }
+
   return NULL;
 }
 
index d540efed9d93f210ee7f3c3378d084e7b457186c..e10cec1e73de48be3a6c66af6223a463b13629ac 100644 (file)
@@ -662,14 +662,8 @@ elf32_sparc_gc_mark_hook (abfd, info, rel, h, sym)
      }
    else
      {
-       if (!(elf_bad_symtab (abfd)
-           && ELF_ST_BIND (sym->st_info) != STB_LOCAL)
-         && ! ((sym->st_shndx <= 0 || sym->st_shndx >= SHN_LORESERVE)
-                && sym->st_shndx != SHN_COMMON))
-          {
-            return bfd_section_from_elf_index (abfd, sym->st_shndx);
-          }
-      }
+       return bfd_section_from_elf_index (abfd, sym->st_shndx);
+     }
 
   return NULL;
 }
index c873ed9a651762fdb62b7fa501f7a95b6e30b1c8..320492226fa9238d458f0051b2f3fce09b6e270c 100644 (file)
@@ -1774,14 +1774,9 @@ v850_elf_gc_mark_hook (abfd, info, rel, h, sym)
      }
    else
      {
-       if (!(elf_bad_symtab (abfd)
-           && ELF_ST_BIND (sym->st_info) != STB_LOCAL)
-         && ! ((sym->st_shndx <= 0 || sym->st_shndx >= SHN_LORESERVE)
-                && sym->st_shndx != SHN_COMMON))
-          {
-            return bfd_section_from_elf_index (abfd, sym->st_shndx);
-          }
-      }
+       return bfd_section_from_elf_index (abfd, sym->st_shndx);
+     }
+
   return NULL;
 }
 
@@ -1985,9 +1980,9 @@ v850_elf_symbol_processing (abfd, asym)
      asymbol * asym;
 {
   elf_symbol_type * elfsym = (elf_symbol_type *) asym;
-  unsigned short index;
+  unsigned int indx;
 
-  index = elfsym->internal_elf_sym.st_shndx;
+  indx = elfsym->internal_elf_sym.st_shndx;
 
   /* If the section index is an "ordinary" index, then it may
      refer to a v850 specific section created by the assembler.
@@ -1995,26 +1990,26 @@ v850_elf_symbol_processing (abfd, asym)
 
      FIXME: Should we alter the st_shndx field as well ?  */
 
-  if (index < elf_elfheader(abfd)[0].e_shnum)
-    switch (elf_elfsections(abfd)[index]->sh_type)
+  if (indx < elf_numsections (abfd))
+    switch (elf_elfsections(abfd)[indx]->sh_type)
       {
       case SHT_V850_SCOMMON:
-       index = SHN_V850_SCOMMON;
+       indx = SHN_V850_SCOMMON;
        break;
 
       case SHT_V850_TCOMMON:
-       index = SHN_V850_TCOMMON;
+       indx = SHN_V850_TCOMMON;
        break;
 
       case SHT_V850_ZCOMMON:
-       index = SHN_V850_ZCOMMON;
+       indx = SHN_V850_ZCOMMON;
        break;
 
       default:
        break;
       }
 
-  switch (index)
+  switch (indx)
     {
     case SHN_V850_SCOMMON:
       if (v850_elf_scom_section.name == NULL)
@@ -2085,7 +2080,7 @@ v850_elf_add_symbol_hook (abfd, info, sym, namep, flagsp, secp, valp)
      asection **              secp;
      bfd_vma *                valp;
 {
-  int index = sym->st_shndx;
+  unsigned int indx = sym->st_shndx;
 
   /* If the section index is an "ordinary" index, then it may
      refer to a v850 specific section created by the assembler.
@@ -2093,26 +2088,26 @@ v850_elf_add_symbol_hook (abfd, info, sym, namep, flagsp, secp, valp)
 
      FIXME: Should we alter the st_shndx field as well ?  */
 
-  if (index < elf_elfheader(abfd)[0].e_shnum)
-    switch (elf_elfsections(abfd)[index]->sh_type)
+  if (indx < elf_numsections (abfd))
+    switch (elf_elfsections(abfd)[indx]->sh_type)
       {
       case SHT_V850_SCOMMON:
-       index = SHN_V850_SCOMMON;
+       indx = SHN_V850_SCOMMON;
        break;
 
       case SHT_V850_TCOMMON:
-       index = SHN_V850_TCOMMON;
+       indx = SHN_V850_TCOMMON;
        break;
 
       case SHT_V850_ZCOMMON:
-       index = SHN_V850_ZCOMMON;
+       indx = SHN_V850_ZCOMMON;
        break;
 
       default:
        break;
       }
 
-  switch (index)
+  switch (indx)
     {
     case SHN_V850_SCOMMON:
       *secp = bfd_make_section_old_way (abfd, ".scommon");
index 5be799e957b3eaa88baf1229fd2d6a6415014b5f..5d3d171eeac3dec291bf1119641d7edb52fe18a1 100644 (file)
@@ -577,32 +577,59 @@ xstormy16_elf_relax_section (dynobj, splt, info, again)
     {
       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;
       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
        {
-         extsyms = (Elf32_External_Sym *) bfd_malloc (symtab_hdr->sh_size);
+         bfd_size_type amt;
+
+         amt = symtab_hdr->sh_info;
+         amt *= sizeof (Elf32_External_Sym);
+         extsyms = (Elf32_External_Sym *) bfd_malloc (amt);
          if (extsyms == NULL)
            return false;
          if (bfd_seek (ibfd, symtab_hdr->sh_offset, SEEK_SET) != 0
-             || (bfd_bread (extsyms, symtab_hdr->sh_size, ibfd)
-                 != symtab_hdr->sh_size))
+             || 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;
          asection *tsec;
          bfd_vma address;
@@ -610,15 +637,18 @@ xstormy16_elf_relax_section (dynobj, splt, info, again)
          if (local_plt_offsets[idx] == (bfd_vma) -1)
            continue;
 
-         bfd_elf32_swap_symbol_in (ibfd, extsyms + idx, &isym);
+         shndx = shndx_buf;
+         if (shndx != NULL)
+           shndx += idx;
+         bfd_elf32_swap_symbol_in (ibfd, extsyms + idx, shndx, &isym);
          if (isym.st_shndx == SHN_UNDEF)
            continue;
-         else if (isym.st_shndx > 0 && isym.st_shndx < SHN_LORESERVE)
-           tsec = bfd_section_from_elf_index (ibfd, isym.st_shndx);
          else if (isym.st_shndx == SHN_ABS)
            tsec = bfd_abs_section_ptr;
+         else if (isym.st_shndx == SHN_COMMON)
+           tsec = bfd_com_section_ptr;
          else
-           continue;
+           tsec = bfd_section_from_elf_index (ibfd, isym.st_shndx);
 
          address = (tsec->output_section->vma
                     + tsec->output_offset
@@ -631,7 +661,10 @@ xstormy16_elf_relax_section (dynobj, splt, info, again)
            }
        }
 
-      if (symtab_hdr->contents != extsyms)
+      if (shndx_buf != NULL)
+       free (shndx_buf);
+
+      if ((Elf32_External_Sym *) symtab_hdr->contents != extsyms)
         free (extsyms);
     }
 
@@ -1024,13 +1057,7 @@ xstormy16_elf_gc_mark_hook (abfd, info, rel, h, sym)
     }
   else
     {
-      if (!(elf_bad_symtab (abfd)
-           && ELF_ST_BIND (sym->st_info) != STB_LOCAL)
-         && ! ((sym->st_shndx <= 0 || sym->st_shndx >= SHN_LORESERVE)
-               && sym->st_shndx != SHN_COMMON))
-       {
-         return bfd_section_from_elf_index (abfd, sym->st_shndx);
-       }
+      return bfd_section_from_elf_index (abfd, sym->st_shndx);
     }
 
   return NULL;
index 81be3506cb9a6e0ab22c98344dd3e0032585dfc1..1bfe15df64d54159942db8297c2c9b1a37011a25 100644 (file)
@@ -1362,12 +1362,14 @@ 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 = NULL;
   Elf64_External_Sym *free_extsyms = NULL;
+  Elf_External_Sym_Shndx *shndx_buf = NULL;
   struct alpha_elf_got_entry **local_got_entries;
   struct alpha_relax_info info;
 
@@ -1448,17 +1450,33 @@ elf64_alpha_relax_section (abfd, sec, link_info, again)
       /* Read this BFD's symbols if we haven't done so already.  */
       if (extsyms == NULL)
        {
+         bfd_size_type amt;
+
          if (symtab_hdr->contents != NULL)
            extsyms = (Elf64_External_Sym *) symtab_hdr->contents;
          else
            {
-             extsyms = (Elf64_External_Sym *) bfd_malloc (symtab_hdr->sh_size);
+             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 (extsyms, symtab_hdr->sh_size, abfd)
-                     != symtab_hdr->sh_size))
+                 || bfd_bread ((PTR) extsyms, amt, abfd) != amt)
+               goto error_return;
+           }
+
+         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)
+               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;
            }
        }
@@ -1467,19 +1485,20 @@ elf64_alpha_relax_section (abfd, sec, link_info, again)
       if (ELF64_R_SYM (irel->r_info) < symtab_hdr->sh_info)
        {
          /* A local symbol.  */
-         bfd_elf64_swap_symbol_in (abfd,
-                                   extsyms + ELF64_R_SYM (irel->r_info),
-                                   &isym);
+         Elf64_External_Sym *esym;
+         Elf_External_Sym_Shndx *shndx;
+
+         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, esym, shndx, &isym);
          if (isym.st_shndx == SHN_UNDEF)
            info.tsec = bfd_und_section_ptr;
-         else if (isym.st_shndx > 0 && isym.st_shndx < SHN_LORESERVE)
-           info.tsec = bfd_section_from_elf_index (abfd, isym.st_shndx);
          else if (isym.st_shndx == SHN_ABS)
            info.tsec = bfd_abs_section_ptr;
          else if (isym.st_shndx == SHN_COMMON)
            info.tsec = bfd_com_section_ptr;
          else
-           continue;   /* who knows.  */
+           info.tsec = bfd_section_from_elf_index (abfd, isym.st_shndx);
 
          info.h = NULL;
          info.other = isym.st_other;
@@ -1566,6 +1585,9 @@ elf64_alpha_relax_section (abfd, sec, link_info, again)
        }
     }
 
+  if (shndx_buf != NULL)
+    free (shndx_buf);
+
   if (free_extsyms != NULL)
     {
       if (! link_info->keep_memory)
@@ -1586,6 +1608,8 @@ elf64_alpha_relax_section (abfd, sec, link_info, again)
     free (free_relocs);
   if (free_contents != NULL)
     free (free_contents);
+  if (shndx_buf != NULL)
+    free (shndx_buf);
   if (free_extsyms != NULL)
     free (free_extsyms);
   return false;
index 98d688876c8550127fb1182155f724ca763b8fa1..defd72d18a5253bea3710b090be797a966a1085c 100644 (file)
@@ -585,6 +585,7 @@ 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;
@@ -611,9 +612,10 @@ elf64_hppa_check_relocs (abfd, info, sec, relocs)
   if (info->shared && hppa_info->section_syms_bfd != abfd)
     {
       unsigned long i;
-      int highest_shndx;
+      unsigned int highest_shndx;
       Elf_Internal_Sym *local_syms, *isym;
       Elf64_External_Sym *ext_syms, *esym;
+      Elf_External_Sym_Shndx *shndx_buf, *shndx;
       bfd_size_type amt;
 
       /* We're done with the old cache of section index to section symbol
@@ -644,24 +646,49 @@ elf64_hppa_check_relocs (abfd, info, sec, relocs)
       if (bfd_seek (abfd, symtab_hdr->sh_offset, SEEK_SET) != 0
           || bfd_bread (ext_syms, amt, abfd) != amt)
         {
-         free (local_syms);
          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.  */
-      isym = local_syms;
-      esym = ext_syms;
       highest_shndx = 0;
-      for (i = 0; i < symtab_hdr->sh_info; i++, esym++, isym++)
+      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))
        {
-         bfd_elf64_swap_symbol_in (abfd, esym, isym);
+         bfd_elf64_swap_symbol_in (abfd, esym, 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
index 41071e343c371040447dfb63f89cac4a6f52d423..2be34e9e266296c40826ab0f483371833a9df853 100644 (file)
@@ -5088,13 +5088,7 @@ mips_elf64_gc_mark_hook (abfd, info, rel, h, sym)
     }
   else
     {
-      if (!(elf_bad_symtab (abfd)
-           && ELF_ST_BIND (sym->st_info) != STB_LOCAL)
-         && ! ((sym->st_shndx <= 0 || sym->st_shndx >= SHN_LORESERVE)
-               && sym->st_shndx != SHN_COMMON))
-       {
-         return bfd_section_from_elf_index (abfd, sym->st_shndx);
-       }
+      return bfd_section_from_elf_index (abfd, sym->st_shndx);
     }
 
   return NULL;
index 95cbd76f1bc4a15fd0ef53026d44a29e98a50fd8..552848ab0064fe96f446ba9acffbf8c73360d6ad 100644 (file)
@@ -1384,13 +1384,7 @@ mmix_elf_gc_mark_hook (abfd, info, rel, h, sym)
     }
   else
     {
-      if (!(elf_bad_symtab (abfd)
-           && ELF_ST_BIND (sym->st_info) != STB_LOCAL)
-         && ! ((sym->st_shndx <= 0 || sym->st_shndx >= SHN_LORESERVE)
-               && sym->st_shndx != SHN_COMMON))
-       {
-         return bfd_section_from_elf_index (abfd, sym->st_shndx);
-       }
+      return bfd_section_from_elf_index (abfd, sym->st_shndx);
     }
 
   return NULL;
index 477225469e74daaf6d1a9f80a8a033bcd9dc3ff5..1ebf1bc53b139a0718f2f23ac6234ad1658331b0 100644 (file)
@@ -2177,13 +2177,7 @@ ppc64_elf_gc_mark_hook (abfd, info, rel, h, sym)
     }
   else
     {
-      if (! (elf_bad_symtab (abfd)
-            && ELF_ST_BIND (sym->st_info) != STB_LOCAL)
-         && ! ((sym->st_shndx <= 0 || sym->st_shndx >= SHN_LORESERVE)
-               && sym->st_shndx != SHN_COMMON))
-       {
-         return bfd_section_from_elf_index (abfd, sym->st_shndx);
-       }
+      return bfd_section_from_elf_index (abfd, sym->st_shndx);
     }
 
   return NULL;
index da037fff0878e7424a6b977cf5336b2604fd72a7..0e3abf395140ca1752c0307911b936a4ab7d1f01 100644 (file)
@@ -887,13 +887,7 @@ elf_s390_gc_mark_hook (abfd, info, rel, h, sym)
     }
   else
     {
-      if (!(elf_bad_symtab (abfd)
-           && ELF_ST_BIND (sym->st_info) != STB_LOCAL)
-         && ! ((sym->st_shndx <= 0 || sym->st_shndx >= SHN_LORESERVE)
-               && sym->st_shndx != SHN_COMMON))
-       {
-         return bfd_section_from_elf_index (abfd, sym->st_shndx);
-       }
+      return bfd_section_from_elf_index (abfd, sym->st_shndx);
     }
 
   return NULL;
index 9f7fdd3dc3f645f49ba35c54168d53eacb711d74..4bbbb0871ead7bdd9677af621757aceebf3e96ad 100644 (file)
@@ -666,13 +666,7 @@ elf64_x86_64_gc_mark_hook (abfd, info, rel, h, sym)
     }
   else
     {
-      if (!(elf_bad_symtab (abfd)
-           && ELF_ST_BIND (sym->st_info) != STB_LOCAL)
-         && ! ((sym->st_shndx <= 0 || sym->st_shndx >= SHN_LORESERVE)
-               && sym->st_shndx != SHN_COMMON))
-       {
-         return bfd_section_from_elf_index (abfd, sym->st_shndx);
-       }
+      return bfd_section_from_elf_index (abfd, sym->st_shndx);
     }
 
   return NULL;
index 892ae7a332aeaf20dfdce83305ab784344bdc630..9d98bc9dfbd8ea6abc67f21d790b53906369fa73 100644 (file)
@@ -203,9 +203,10 @@ static char *elf_symbol_flags PARAMS ((flagword));
    format.  */
 
 void
-elf_swap_symbol_in (abfd, src, dst)
+elf_swap_symbol_in (abfd, src, shndx, dst)
      bfd *abfd;
      const Elf_External_Sym *src;
+     const Elf_External_Sym_Shndx *shndx;
      Elf_Internal_Sym *dst;
 {
   int signed_vma = get_elf_backend_data (abfd)->sign_extend_vma;
@@ -219,24 +220,40 @@ elf_swap_symbol_in (abfd, src, dst)
   dst->st_info = H_GET_8 (abfd, src->st_info);
   dst->st_other = H_GET_8 (abfd, src->st_other);
   dst->st_shndx = H_GET_16 (abfd, src->st_shndx);
+  if (dst->st_shndx == SHN_XINDEX)
+    {
+      if (shndx == NULL)
+       abort ();
+      dst->st_shndx = H_GET_32 (abfd, shndx->est_shndx);
+    }
 }
 
 /* Translate an ELF symbol in internal format into an ELF symbol in external
    format.  */
 
 void
-elf_swap_symbol_out (abfd, src, cdst)
+elf_swap_symbol_out (abfd, src, cdst, shndx)
      bfd *abfd;
      const Elf_Internal_Sym *src;
      PTR cdst;
+     PTR shndx;
 {
+  unsigned int tmp;
   Elf_External_Sym *dst = (Elf_External_Sym *) cdst;
   H_PUT_32 (abfd, src->st_name, dst->st_name);
   H_PUT_WORD (abfd, src->st_value, dst->st_value);
   H_PUT_WORD (abfd, src->st_size, dst->st_size);
   H_PUT_8 (abfd, src->st_info, dst->st_info);
   H_PUT_8 (abfd, src->st_other, dst->st_other);
-  H_PUT_16 (abfd, src->st_shndx, dst->st_shndx);
+  tmp = src->st_shndx;
+  if (tmp > SHN_HIRESERVE)
+    {
+      if (shndx == NULL)
+       abort ();
+      H_PUT_32 (abfd, tmp, shndx);
+      tmp = SHN_XINDEX;
+    }
+  H_PUT_16 (abfd, tmp, dst->st_shndx);
 }
 
 /* Translate an ELF file header in external format into an ELF file header in
@@ -667,14 +684,17 @@ elf_object_p (abfd)
   if (i_ehdrp->e_shnum != 0)
     {
       Elf_Internal_Shdr *shdrp;
+      unsigned int num_sec;
 
       amt = sizeof (*i_shdrp) * i_ehdrp->e_shnum;
       i_shdrp = (Elf_Internal_Shdr *) bfd_alloc (abfd, amt);
       if (!i_shdrp)
        goto got_no_match;
-      amt = sizeof (i_shdrp) * i_ehdrp->e_shnum;
-      if (i_ehdrp->e_shnum > SHN_LORESERVE)
-       amt += sizeof (i_shdrp) * (SHN_HIRESERVE + 1 - SHN_LORESERVE);
+      num_sec = i_ehdrp->e_shnum;
+      if (num_sec > SHN_LORESERVE)
+       num_sec += SHN_HIRESERVE + 1 - SHN_LORESERVE;
+      elf_numsections (abfd) = num_sec;
+      amt = sizeof (i_shdrp) * num_sec;
       elf_elfsections (abfd) = (Elf_Internal_Shdr **) bfd_alloc (abfd, amt);
       if (!elf_elfsections (abfd))
        goto got_no_match;
@@ -682,14 +702,14 @@ elf_object_p (abfd)
       memcpy (i_shdrp, &i_shdr, sizeof (*i_shdrp));
       shdrp = i_shdrp;
       shindex = 0;
-      if (i_ehdrp->e_shnum > SHN_LORESERVE)
+      if (num_sec > SHN_LORESERVE)
        {
          for ( ; shindex < SHN_LORESERVE; shindex++)
            elf_elfsections (abfd)[shindex] = shdrp++;
          for ( ; shindex < SHN_HIRESERVE + 1; shindex++)
-           elf_elfsections (abfd)[shindex] = NULL;
+           elf_elfsections (abfd)[shindex] = i_shdrp;
        }
-      for ( ; shindex < i_ehdrp->e_shnum; shindex++)
+      for ( ; shindex < num_sec; shindex++)
        elf_elfsections (abfd)[shindex] = shdrp++;
     }
 
@@ -752,6 +772,8 @@ elf_object_p (abfd)
 
   if (i_ehdrp->e_shstrndx != 0)
     {
+      unsigned int num_sec;
+
       shstrtab = bfd_elf_get_str_section (abfd, i_ehdrp->e_shstrndx);
       if (!shstrtab)
        goto got_no_match;
@@ -759,11 +781,13 @@ elf_object_p (abfd)
       /* Once all of the section headers have been read and converted, we
         can start processing them.  Note that the first section header is
         a dummy placeholder entry, so we ignore it.  */
-
-      for (shindex = 1; shindex < i_ehdrp->e_shnum; shindex++)
+      num_sec = elf_numsections (abfd);
+      for (shindex = 1; shindex < num_sec; shindex++)
        {
          if (! bfd_section_from_shdr (abfd, shindex))
            goto got_no_match;
+         if (shindex == SHN_LORESERVE - 1)
+           shindex += SHN_HIRESERVE + 1 - SHN_LORESERVE;
        }
     }
 
@@ -809,11 +833,6 @@ elf_object_p (abfd)
   bfd_default_set_arch_mach (abfd, previous_arch, previous_mach);
   bfd_set_error (bfd_error_wrong_format);
  got_no_match:
-  if (new_tdata != NULL
-      && new_tdata->elf_sect_ptr != NULL)
-    bfd_release (abfd, new_tdata->elf_sect_ptr);
-  if (i_shdrp != NULL)
-    bfd_release (abfd, i_shdrp);
   if (new_tdata != NULL)
     bfd_release (abfd, new_tdata);
   elf_tdata (abfd) = preserved_tdata;
@@ -1079,6 +1098,7 @@ elf_slurp_symbol_table (abfd, symptrs, dynamic)
   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;
   bfd_size_type amt;
 
@@ -1094,8 +1114,23 @@ 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)[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
     {
@@ -1115,7 +1150,7 @@ elf_slurp_symbol_table (abfd, symptrs, dynamic)
     }
 
   if (bfd_seek (abfd, hdr->sh_offset, SEEK_SET) != 0)
-    return -1;
+    goto error_return;
 
   symcount = hdr->sh_size / sizeof (Elf_External_Sym);
 
@@ -1126,20 +1161,20 @@ elf_slurp_symbol_table (abfd, symptrs, dynamic)
       unsigned long i;
 
       if (bfd_seek (abfd, hdr->sh_offset, SEEK_SET) != 0)
-       return -1;
+       goto error_return;
 
       amt = symcount;
       amt *= sizeof (elf_symbol_type);
       symbase = (elf_symbol_type *) bfd_zalloc (abfd, amt);
       if (symbase == (elf_symbol_type *) NULL)
-       return -1;
+       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 && symcount != 0)
+      if (x_symp == NULL)
        goto error_return;
 
       if (bfd_bread ((PTR) x_symp, amt, abfd) != amt)
@@ -1178,7 +1213,8 @@ elf_slurp_symbol_table (abfd, symptrs, dynamic)
       /* Skip first symbol, which is a null dummy.  */
       for (i = 1; i < symcount; i++)
        {
-         elf_swap_symbol_in (abfd, x_symp + i, &i_sym);
+         elf_swap_symbol_in (abfd, x_symp + i,
+                             x_shndx + (x_shndx != NULL ? 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));
@@ -1191,7 +1227,12 @@ elf_slurp_symbol_table (abfd, symptrs, dynamic)
 
          sym->symbol.value = i_sym.st_value;
 
-         if (i_sym.st_shndx > 0 && i_sym.st_shndx < SHN_LORESERVE)
+         if (i_sym.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)
            {
              sym->symbol.section = section_from_elf_index (abfd,
                                                            i_sym.st_shndx);
@@ -1216,10 +1257,6 @@ elf_slurp_symbol_table (abfd, symptrs, dynamic)
                 moment) about the alignment.  */
              sym->symbol.value = i_sym.st_size;
            }
-         else if (i_sym.st_shndx == SHN_UNDEF)
-           {
-             sym->symbol.section = bfd_und_section_ptr;
-           }
          else
            sym->symbol.section = bfd_abs_section_ptr;
 
@@ -1306,12 +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);
   return symcount;
+
 error_return:
+  if (x_shndx != NULL)
+    free (x_shndx);
   if (x_versymp != NULL)
     free (x_versymp);
   if (x_symp != NULL)
index 311774879ae3076ce9c5ff30d6383a5a4bb32fe5..13f10d2df757fc1ed9300779297b0f5082e096f6 100644 (file)
@@ -151,9 +151,12 @@ 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;
@@ -177,9 +180,15 @@ 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;
+    {
+      hdr = &elf_tdata (abfd)->symtab_hdr;
+      shndx_hdr = &elf_tdata (abfd)->symtab_shndx_hdr;
+    }
   else
-    hdr = &elf_tdata (abfd)->dynsymtab_hdr;
+    {
+      hdr = &elf_tdata (abfd)->dynsymtab_hdr;
+      shndx_hdr = NULL;
+    }
 
   symcount = hdr->sh_size / sizeof (Elf_External_Sym);
 
@@ -206,21 +215,31 @@ elf_link_is_defined_archive_symbol (abfd, symdef)
   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)
     {
-      free (buf);
-      return false;
+      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;
     }
 
   /* Scan the symbol table looking for SYMDEF.  */
   esymend = buf + extsymcount;
-  for (esym = buf;
+  for (esym = buf, shndx = shndx_buf;
        esym < esymend;
-       esym++)
+       esym++, shndx = (shndx != NULL ? shndx + 1 : NULL))
     {
       Elf_Internal_Sym sym;
       const char * name;
 
-      elf_swap_symbol_in (abfd, esym, sym);
+      elf_swap_symbol_in (abfd, esym, shndx, &sym);
 
       name = bfd_elf_string_from_elf_section (abfd, hdr->sh_link, sym.st_name);
       if (name == (const char *) NULL)
@@ -233,7 +252,11 @@ elf_link_is_defined_archive_symbol (abfd, symdef)
        }
     }
 
-  free (buf);
+ error_exit:
+  if (shndx_buf != NULL)
+    free (shndx_buf);
+  if (buf != NULL)
+    free (buf);
 
   return result;
 }
@@ -1151,10 +1174,13 @@ 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;
@@ -1271,9 +1297,15 @@ elf_link_add_object_symbols (abfd, info)
      look at .symtab for a dynamic object.  */
 
   if (! dynamic || elf_dynsymtab (abfd) == 0)
-    hdr = &elf_tdata (abfd)->symtab_hdr;
+    {
+      hdr = &elf_tdata (abfd)->symtab_hdr;
+      shndx_hdr = &elf_tdata (abfd)->symtab_shndx_hdr;
+    }
   else
-    hdr = &elf_tdata (abfd)->dynsymtab_hdr;
+    {
+      hdr = &elf_tdata (abfd)->dynsymtab_hdr;
+      shndx_hdr = NULL;
+    }
 
   if (dynamic)
     {
@@ -1320,6 +1352,14 @@ elf_link_add_object_symbols (abfd, info)
   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 *);
@@ -1596,13 +1636,23 @@ elf_link_add_object_symbols (abfd, info)
       || bfd_bread ((PTR) buf, amt, abfd) != amt)
     goto error_return;
 
+  if (shndx_hdr != NULL && shndx_hdr->sh_size != 0)
+    {
+      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)
+       goto error_return;
+    }
+
   weaks = NULL;
 
   ever = extversym != NULL ? extversym + extsymoff : NULL;
   esymend = buf + extsymcount;
-  for (esym = buf;
+  for (esym = buf, shndx = shndx_buf;
        esym < esymend;
-       esym++, sym_hash++, ever = (ever != NULL ? ever + 1 : NULL))
+       esym++, sym_hash++, ever = (ever != NULL ? ever + 1 : NULL),
+        shndx = (shndx != NULL ? shndx + 1 : NULL))
     {
       Elf_Internal_Sym sym;
       int bind;
@@ -1619,7 +1669,7 @@ elf_link_add_object_symbols (abfd, info)
 
       override = false;
 
-      elf_swap_symbol_in (abfd, esym, &sym);
+      elf_swap_symbol_in (abfd, esym, shndx, &sym);
 
       flags = BSF_NO_FLAGS;
       sec = NULL;
@@ -1650,7 +1700,7 @@ elf_link_add_object_symbols (abfd, info)
 
       if (sym.st_shndx == SHN_UNDEF)
        sec = bfd_und_section_ptr;
-      else if (sym.st_shndx > 0 && sym.st_shndx < SHN_LORESERVE)
+      else if (sym.st_shndx < SHN_LORESERVE || sym.st_shndx > SHN_HIRESERVE)
        {
          sec = section_from_elf_index (abfd, sym.st_shndx);
          if (sec == NULL)
@@ -2456,6 +2506,8 @@ elf_link_record_local_dynamic_symbol (info, input_bfd, input_indx)
   struct elf_link_hash_table *eht;
   struct elf_strtab_hash *dynstr;
   Elf_External_Sym esym;
+  Elf_External_Sym_Shndx eshndx;
+  Elf_External_Sym_Shndx *shndx;
   unsigned long dynstr_index;
   char *name;
   file_ptr pos;
@@ -2478,9 +2530,20 @@ elf_link_record_local_dynamic_symbol (info, input_bfd, input_indx)
   amt = sizeof (Elf_External_Sym);
   pos = elf_tdata (input_bfd)->symtab_hdr.sh_offset + input_indx * amt;
   if (bfd_seek (input_bfd, pos, SEEK_SET) != 0
-      || bfd_bread (&esym, amt, input_bfd) != amt)
+      || bfd_bread ((PTR) &esym, amt, input_bfd) != amt)
     return false;
-  elf_swap_symbol_in (input_bfd, &esym, &entry->isym);
+  shndx = NULL;
+  if (elf_tdata (input_bfd)->symtab_shndx_hdr.sh_size != 0)
+    {
+      amt = sizeof (Elf_External_Sym_Shndx);
+      pos = elf_tdata (input_bfd)->symtab_shndx_hdr.sh_offset;
+      pos += input_indx * amt;
+      shndx = &eshndx;
+      if (bfd_seek (input_bfd, pos, SEEK_SET) != 0
+         || bfd_bread ((PTR) shndx, amt, input_bfd) != amt)
+       return false;
+    }
+  elf_swap_symbol_in (input_bfd, &esym, shndx, &entry->isym);
 
   name = (bfd_elf_string_from_elf_section
          (input_bfd, elf_tdata (input_bfd)->symtab_hdr.sh_link,
@@ -3530,8 +3593,7 @@ NAME(bfd_elf,size_dynamic_sections) (output_bfd, soname, rpath,
          isym.st_info = 0;
          isym.st_other = 0;
          isym.st_shndx = 0;
-         elf_swap_symbol_out (output_bfd, &isym,
-                              (PTR) (Elf_External_Sym *) s->contents);
+         elf_swap_symbol_out (output_bfd, &isym, (PTR) s->contents, (PTR) 0);
        }
 
       /* Compute the size of the hashing table.  As a side effect this
@@ -4370,6 +4432,8 @@ struct elf_final_link_info
   /* Buffer large enough to hold external local symbols of any input
      BFD.  */
   Elf_External_Sym *external_syms;
+  /* And a buffer for symbol section indices.  */
+  Elf_External_Sym_Shndx *locsym_shndx;
   /* Buffer large enough to hold internal local symbols of any input
      BFD.  */
   Elf_Internal_Sym *internal_syms;
@@ -4381,6 +4445,8 @@ struct elf_final_link_info
   asection **sections;
   /* Buffer to hold swapped out symbols.  */
   Elf_External_Sym *symbuf;
+  /* And one for symbol section indices.  */
+  Elf_External_Sym_Shndx *symshndxbuf;
   /* Number of swapped out symbols in buffer.  */
   size_t symbuf_count;
   /* Number of symbols which fit in symbuf.  */
@@ -4778,6 +4844,7 @@ elf_bfd_final_link (abfd, info)
   bfd_size_type max_external_reloc_size;
   bfd_size_type max_internal_reloc_count;
   bfd_size_type max_sym_count;
+  bfd_size_type max_sym_shndx_count;
   file_ptr off;
   Elf_Internal_Sym elfsym;
   unsigned int i;
@@ -4828,10 +4895,12 @@ elf_bfd_final_link (abfd, info)
   finfo.external_relocs = NULL;
   finfo.internal_relocs = NULL;
   finfo.external_syms = NULL;
+  finfo.locsym_shndx = NULL;
   finfo.internal_syms = NULL;
   finfo.indices = NULL;
   finfo.sections = NULL;
   finfo.symbuf = NULL;
+  finfo.symshndxbuf = NULL;
   finfo.symbuf_count = 0;
 
   /* Count up the number of relocations we will output for each output
@@ -4841,6 +4910,7 @@ elf_bfd_final_link (abfd, info)
   max_external_reloc_size = 0;
   max_internal_reloc_count = 0;
   max_sym_count = 0;
+  max_sym_shndx_count = 0;
   merged = false;
   for (o = abfd->sections; o != (asection *) NULL; o = o->next)
     {
@@ -4904,6 +4974,10 @@ elf_bfd_final_link (abfd, info)
                  if (sym_count > max_sym_count)
                    max_sym_count = sym_count;
 
+                 if (sym_count > max_sym_shndx_count
+                     && elf_symtab_shndx (sec->owner) != 0)
+                   max_sym_shndx_count = sym_count;
+
                  if ((sec->flags & SEC_RELOC) != 0)
                    {
                      size_t ext_size;
@@ -5057,6 +5131,14 @@ elf_bfd_final_link (abfd, info)
   finfo.symbuf = (Elf_External_Sym *) bfd_malloc (amt);
   if (finfo.symbuf == NULL)
     goto error_return;
+  if (elf_numsections (abfd) > SHN_LORESERVE)
+    {
+      amt = finfo.symbuf_size;
+      amt *= sizeof (Elf_External_Sym_Shndx);
+      finfo.symshndxbuf = (Elf_External_Sym_Shndx *) bfd_malloc (amt);
+      if (finfo.symshndxbuf == NULL)
+       goto error_return;
+    }
 
   /* Start writing out the symbol table.  The first symbol is always a
      dummy symbol.  */
@@ -5100,7 +5182,7 @@ elf_bfd_final_link (abfd, info)
       elfsym.st_size = 0;
       elfsym.st_info = ELF_ST_INFO (STB_LOCAL, STT_SECTION);
       elfsym.st_other = 0;
-      for (i = 1; i < elf_elfheader (abfd)->e_shnum; i++)
+      for (i = 1; i < elf_numsections (abfd); i++)
        {
          o = section_from_elf_index (abfd, i);
          if (o != NULL)
@@ -5113,34 +5195,66 @@ elf_bfd_final_link (abfd, info)
          if (! elf_link_output_sym (&finfo, (const char *) NULL,
                                     &elfsym, o))
            goto error_return;
+         if (i == SHN_LORESERVE)
+           i += SHN_HIRESERVE + 1 - SHN_LORESERVE;
        }
     }
 
   /* Allocate some memory to hold information read in from the input
      files.  */
-  finfo.contents = (bfd_byte *) bfd_malloc (max_contents_size);
-  finfo.external_relocs = (PTR) bfd_malloc (max_external_reloc_size);
-  finfo.internal_relocs = ((Elf_Internal_Rela *)
-                          bfd_malloc (max_internal_reloc_count
-                                      * sizeof (Elf_Internal_Rela)
-                                      * bed->s->int_rels_per_ext_rel));
-  finfo.external_syms = ((Elf_External_Sym *)
-                        bfd_malloc (max_sym_count
-                                    * sizeof (Elf_External_Sym)));
-  finfo.internal_syms = ((Elf_Internal_Sym *)
-                        bfd_malloc (max_sym_count
-                                    * sizeof (Elf_Internal_Sym)));
-  finfo.indices = (long *) bfd_malloc (max_sym_count * sizeof (long));
-  finfo.sections = ((asection **)
-                   bfd_malloc (max_sym_count * sizeof (asection *)));
-  if ((finfo.contents == NULL && max_contents_size != 0)
-      || (finfo.external_relocs == NULL && max_external_reloc_size != 0)
-      || (finfo.internal_relocs == NULL && max_internal_reloc_count != 0)
-      || (finfo.external_syms == NULL && max_sym_count != 0)
-      || (finfo.internal_syms == NULL && max_sym_count != 0)
-      || (finfo.indices == NULL && max_sym_count != 0)
-      || (finfo.sections == NULL && max_sym_count != 0))
-    goto error_return;
+  if (max_contents_size != 0)
+    {
+      finfo.contents = (bfd_byte *) bfd_malloc (max_contents_size);
+      if (finfo.contents == NULL)
+       goto error_return;
+    }
+
+  if (max_external_reloc_size != 0)
+    {
+      finfo.external_relocs = (PTR) bfd_malloc (max_external_reloc_size);
+      if (finfo.external_relocs == NULL)
+       goto error_return;
+    }
+
+  if (max_internal_reloc_count != 0)
+    {
+      amt = max_internal_reloc_count * bed->s->int_rels_per_ext_rel;
+      amt *= sizeof (Elf_Internal_Rela);
+      finfo.internal_relocs = (Elf_Internal_Rela *) bfd_malloc (amt);
+      if (finfo.internal_relocs == NULL)
+       goto error_return;
+    }
+
+  if (max_sym_count != 0)
+    {
+      amt = max_sym_count * sizeof (Elf_External_Sym);
+      finfo.external_syms = (Elf_External_Sym *) bfd_malloc (amt);
+      if (finfo.external_syms == NULL)
+       goto error_return;
+
+      amt = max_sym_count * sizeof (Elf_Internal_Sym);
+      finfo.internal_syms = (Elf_Internal_Sym *) bfd_malloc (amt);
+      if (finfo.internal_syms == NULL)
+       goto error_return;
+
+      amt = max_sym_count * sizeof (long);
+      finfo.indices = (long *) bfd_malloc (amt);
+      if (finfo.indices == NULL)
+       goto error_return;
+
+      amt = max_sym_count * sizeof (asection *);
+      finfo.sections = (asection **) bfd_malloc (amt);
+      if (finfo.sections == NULL)
+       goto error_return;
+    }
+
+  if (max_sym_shndx_count != 0)
+    {
+      amt = max_sym_shndx_count * sizeof (Elf_External_Sym_Shndx);
+      finfo.locsym_shndx = (Elf_External_Sym_Shndx *) bfd_malloc (amt);
+      if (finfo.locsym_shndx == NULL)
+       goto error_return;
+    }
 
   /* Since ELF permits relocations to be against local symbols, we
      must have the local symbols available when we do the relocations.
@@ -5240,13 +5354,14 @@ elf_bfd_final_link (abfd, info)
          for (s = abfd->sections; s != NULL; s = s->next)
            {
              int indx;
+             Elf_External_Sym *dest;
+
              indx = elf_section_data (s)->this_idx;
              BFD_ASSERT (indx > 0);
              sym.st_shndx = indx;
              sym.st_value = s->vma;
-
-             elf_swap_symbol_out (abfd, &sym,
-                                  dynsym + elf_section_data (s)->dynindx);
+             dest = dynsym + elf_section_data (s)->dynindx;
+             elf_swap_symbol_out (abfd, &sym, (PTR) dest, (PTR) 0);
            }
 
          last_local = bfd_count_sections (abfd);
@@ -5259,6 +5374,7 @@ elf_bfd_final_link (abfd, info)
          for (e = elf_hash_table (info)->dynlocal; e ; e = e->next)
            {
              asection *s;
+             Elf_External_Sym *dest;
 
              sym.st_size = e->isym.st_size;
              sym.st_other = e->isym.st_other;
@@ -5268,7 +5384,8 @@ elf_bfd_final_link (abfd, info)
                  the original st_name with the dynstr_index.  */
               sym = e->isym;
 
-             if (e->isym.st_shndx > 0 && e->isym.st_shndx < SHN_LORESERVE)
+             if (e->isym.st_shndx < SHN_LORESERVE
+                 || e->isym.st_shndx > SHN_HIRESERVE)
                {
                  s = bfd_section_from_elf_index (e->input_bfd,
                                                  e->isym.st_shndx);
@@ -5283,7 +5400,8 @@ elf_bfd_final_link (abfd, info)
              if (last_local < e->dynindx)
                last_local = e->dynindx;
 
-             elf_swap_symbol_out (abfd, &sym, dynsym + e->dynindx);
+             dest = dynsym + e->dynindx;
+             elf_swap_symbol_out (abfd, &sym, (PTR) dest, (PTR) 0);
            }
        }
 
@@ -5473,7 +5591,7 @@ elf_bfd_final_link (abfd, info)
              else
                type = SHT_RELA;
              dyn.d_un.d_val = 0;
-             for (i = 1; i < elf_elfheader (abfd)->e_shnum; i++)
+             for (i = 1; i < elf_numsections (abfd); i++)
                {
                  Elf_Internal_Shdr *hdr;
 
@@ -5568,6 +5686,8 @@ elf_bfd_final_link (abfd, info)
     free (finfo.internal_relocs);
   if (finfo.external_syms != NULL)
     free (finfo.external_syms);
+  if (finfo.locsym_shndx != NULL)
+    free (finfo.locsym_shndx);
   if (finfo.internal_syms != NULL)
     free (finfo.internal_syms);
   if (finfo.indices != NULL)
@@ -5576,6 +5696,8 @@ elf_bfd_final_link (abfd, info)
     free (finfo.sections);
   if (finfo.symbuf != NULL)
     free (finfo.symbuf);
+  if (finfo.symshndxbuf != NULL)
+    free (finfo.symbuf);
   for (o = abfd->sections; o != NULL; o = o->next)
     {
       if ((o->flags & SEC_RELOC) != 0
@@ -5598,6 +5720,8 @@ elf_bfd_final_link (abfd, info)
     free (finfo.internal_relocs);
   if (finfo.external_syms != NULL)
     free (finfo.external_syms);
+  if (finfo.locsym_shndx != NULL)
+    free (finfo.locsym_shndx);
   if (finfo.internal_syms != NULL)
     free (finfo.internal_syms);
   if (finfo.indices != NULL)
@@ -5606,6 +5730,8 @@ elf_bfd_final_link (abfd, info)
     free (finfo.sections);
   if (finfo.symbuf != NULL)
     free (finfo.symbuf);
+  if (finfo.symshndxbuf != NULL)
+    free (finfo.symbuf);
   for (o = abfd->sections; o != NULL; o = o->next)
     {
       if ((o->flags & SEC_RELOC) != 0
@@ -5625,6 +5751,9 @@ elf_link_output_sym (finfo, name, elfsym, input_sec)
      Elf_Internal_Sym *elfsym;
      asection *input_sec;
 {
+  Elf_External_Sym *dest;
+  Elf_External_Sym_Shndx *destshndx;
+  
   boolean (*output_symbol_hook) PARAMS ((bfd *,
                                         struct bfd_link_info *info,
                                         const char *,
@@ -5658,8 +5787,11 @@ elf_link_output_sym (finfo, name, elfsym, input_sec)
        return false;
     }
 
-  elf_swap_symbol_out (finfo->output_bfd, elfsym,
-                      (PTR) (finfo->symbuf + finfo->symbuf_count));
+  dest = finfo->symbuf + finfo->symbuf_count;
+  destshndx = finfo->symshndxbuf;
+  if (destshndx != NULL)
+    destshndx += finfo->symbuf_count;
+  elf_swap_symbol_out (finfo->output_bfd, elfsym, (PTR) dest, (PTR) destshndx);
   ++finfo->symbuf_count;
 
   ++ bfd_get_symcount (finfo->output_bfd);
@@ -5675,18 +5807,31 @@ elf_link_flush_output_syms (finfo)
 {
   if (finfo->symbuf_count > 0)
     {
-      Elf_Internal_Shdr *symtab;
+      Elf_Internal_Shdr *hdr;
       file_ptr pos;
       bfd_size_type amt;
 
-      symtab = &elf_tdata (finfo->output_bfd)->symtab_hdr;
-      pos = symtab->sh_offset + symtab->sh_size;
+      hdr = &elf_tdata (finfo->output_bfd)->symtab_hdr;
+      pos = hdr->sh_offset + hdr->sh_size;
       amt = finfo->symbuf_count * sizeof (Elf_External_Sym);
       if (bfd_seek (finfo->output_bfd, pos, SEEK_SET) != 0
          || bfd_bwrite ((PTR) finfo->symbuf, amt, finfo->output_bfd) != amt)
        return false;
 
-      symtab->sh_size += finfo->symbuf_count * sizeof (Elf_External_Sym);
+      hdr->sh_size += amt;
+
+      if (finfo->symshndxbuf != NULL)
+       {
+         hdr = &elf_tdata (finfo->output_bfd)->symtab_shndx_hdr;
+         pos = hdr->sh_offset + hdr->sh_size;
+         amt = finfo->symbuf_count * sizeof (Elf_External_Sym_Shndx);
+         if (bfd_seek (finfo->output_bfd, pos, SEEK_SET) != 0
+             || (bfd_bwrite ((PTR) finfo->symshndxbuf, amt, finfo->output_bfd)
+                 != amt))
+           return false;
+
+         hdr->sh_size += amt;
+       }
 
       finfo->symbuf_count = 0;
     }
@@ -5838,7 +5983,7 @@ elf_link_output_extsym (h, data)
            sym.st_shndx =
              _bfd_elf_section_from_bfd_section (finfo->output_bfd,
                                                 input_sec->output_section);
-           if (sym.st_shndx == (unsigned short) -1)
+           if (sym.st_shndx == SHN_BAD)
              {
                (*_bfd_error_handler)
                  (_("%s: could not find output section %s for input section %s"),
@@ -5951,7 +6096,7 @@ elf_link_output_extsym (h, data)
 
       sym.st_name = h->dynstr_index;
       esym = (Elf_External_Sym *) finfo->dynsym_sec->contents + h->dynindx;
-      elf_swap_symbol_out (finfo->output_bfd, &sym, (PTR) esym);
+      elf_swap_symbol_out (finfo->output_bfd, &sym, (PTR) esym, (PTR) 0);
 
       bucketcount = elf_hash_table (finfo->info)->bucketcount;
       bucket = h->elf_hash_value % bucketcount;
@@ -6123,11 +6268,14 @@ 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 *isym;
   long *pindex;
   asection **ppsection;
@@ -6176,20 +6324,31 @@ elf_link_input_bfd (finfo, input_bfd)
        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.  */
-  esym = external_syms;
-  esymend = esym + locsymcount;
-  isym = finfo->internal_syms;
-  pindex = finfo->indices;
-  ppsection = finfo->sections;
-  for (; esym < esymend; esym++, isym++, pindex++, ppsection++)
+  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))
     {
       asection *isec;
       const char *name;
       Elf_Internal_Sym osym;
 
-      elf_swap_symbol_in (input_bfd, esym, isym);
+      elf_swap_symbol_in (input_bfd, esym, shndx, isym);
       *pindex = -1;
 
       if (elf_bad_symtab (input_bfd))
@@ -6203,7 +6362,8 @@ elf_link_input_bfd (finfo, input_bfd)
 
       if (isym->st_shndx == SHN_UNDEF)
        isec = bfd_und_section_ptr;
-      else if (isym->st_shndx > 0 && isym->st_shndx < SHN_LORESERVE)
+      else if (isym->st_shndx < SHN_LORESERVE
+              || isym->st_shndx > SHN_HIRESERVE)
        {
          isec = section_from_elf_index (input_bfd, isym->st_shndx);
          if (isec
@@ -6256,8 +6416,7 @@ elf_link_input_bfd (finfo, input_bfd)
          linker_mark is only reliable for sections that have contents.
          For the benefit of the MIPS ELF linker, we check SEC_EXCLUDE
          as well as linker_mark.  */
-      if (isym->st_shndx > 0
-         && isym->st_shndx < SHN_LORESERVE
+      if ((isym->st_shndx < SHN_LORESERVE || isym->st_shndx > SHN_HIRESERVE)
          && isec != NULL
          && ((! isec->linker_mark && (isec->flags & SEC_HAS_CONTENTS) != 0)
              || (! finfo->info->relocateable
@@ -6287,7 +6446,7 @@ elf_link_input_bfd (finfo, input_bfd)
       /* Adjust the section index for the output file.  */
       osym.st_shndx = _bfd_elf_section_from_bfd_section (output_bfd,
                                                         isec->output_section);
-      if (osym.st_shndx == (unsigned short) -1)
+      if (osym.st_shndx == SHN_BAD)
        return false;
 
       *pindex = bfd_get_symcount (output_bfd);
@@ -6629,7 +6788,7 @@ elf_link_input_bfd (finfo, input_bfd)
                          isym->st_shndx =
                            _bfd_elf_section_from_bfd_section (output_bfd,
                                                               osec);
-                         if (isym->st_shndx == (unsigned short) -1)
+                         if (isym->st_shndx == SHN_BAD)
                            return false;
 
                          isym->st_value += sec->output_offset;
@@ -7237,10 +7396,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);
 
@@ -7258,6 +7419,7 @@ 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)
@@ -7275,6 +7437,17 @@ elf_gc_mark (info, sec, gc_mark_hook)
            }
        }
 
+      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)
+           return false;
+       }
+
       /* Read the relocations.  */
       relstart = (NAME(_bfd_elf,link_read_relocs)
                  (sec->owner, sec, NULL, (Elf_Internal_Rela *) NULL,
@@ -7299,7 +7472,10 @@ elf_gc_mark (info, sec, gc_mark_hook)
 
          if (elf_bad_symtab (sec->owner))
            {
-             elf_swap_symbol_in (input_bfd, &locsyms[r_symndx], &s);
+             elf_swap_symbol_in (input_bfd,
+                                 locsyms + r_symndx,
+                                 locsym_shndx + (locsym_shndx ? r_symndx : 0),
+                                 &s);
              if (ELF_ST_BIND (s.st_info) == STB_LOCAL)
                rsec = (*gc_mark_hook) (sec->owner, info, rel, NULL, &s);
              else
@@ -7315,7 +7491,10 @@ elf_gc_mark (info, sec, gc_mark_hook)
            }
          else
            {
-             elf_swap_symbol_in (input_bfd, &locsyms[r_symndx], &s);
+             elf_swap_symbol_in (input_bfd,
+                                 locsyms + r_symndx,
+                                 locsym_shndx + (locsym_shndx ? r_symndx : 0),
+                                 &s);
              rsec = (*gc_mark_hook) (sec->owner, info, rel, NULL, &s);
            }
 
@@ -7864,7 +8043,7 @@ elf_reloc_symbol_deleted_p (offset, cookie)
      bfd_vma offset;
      PTR cookie;
 {
-  struct elf_reloc_cookie *rcookie = (struct elf_reloc_cookie *)cookie;
+  struct elf_reloc_cookie *rcookie = (struct elf_reloc_cookie *) cookie;
 
   if (rcookie->bad_symtab)
     rcookie->rel = rcookie->rels;
@@ -7881,9 +8060,16 @@ elf_reloc_symbol_deleted_p (offset, cookie)
        continue;
 
       if (rcookie->locsyms && r_symndx < rcookie->locsymcount)
-       elf_swap_symbol_in (rcookie->abfd,
-                           (Elf_External_Sym *) rcookie->locsyms + r_symndx,
-                           &isym);
+       {
+         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, lsym, lshndx, &isym);
+       }
 
       if (r_symndx >= rcookie->locsymcount
          || (rcookie->locsyms
@@ -7914,7 +8100,7 @@ elf_reloc_symbol_deleted_p (offset, cookie)
          asection *isec;
 
          /* Need to: get the symbol; get the section.  */
-         if (isym.st_shndx > 0 && isym.st_shndx < SHN_LORESERVE)
+         if (isym.st_shndx < SHN_LORESERVE || isym.st_shndx > SHN_HIRESERVE)
            {
              isec = section_from_elf_index (rcookie->abfd, isym.st_shndx);
              if (isec != NULL
@@ -7941,6 +8127,7 @@ 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;
@@ -7983,6 +8170,7 @@ 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);
@@ -8008,21 +8196,33 @@ elf_bfd_discard_info (output_bfd, info)
         {
           bfd_size_type amt = cookie.locsymcount * sizeof (Elf_External_Sym);
           cookie.locsyms = bfd_malloc (amt);
-          if (cookie.locsyms == NULL
-              || bfd_seek (abfd, symtab_hdr->sh_offset, SEEK_SET) != 0
+          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)
            {
-             /* Something is very wrong - but we can still do our job for
-                global symbols, so don't give up.  */
-             if (cookie.locsyms)
-               free (cookie.locsyms);
-             cookie.locsyms = NULL;
+           error_ret_free_loc:
+             free (cookie.locsyms);
+             return false;
             }
-         else
+        }
+
+      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)
            {
-             freesyms = cookie.locsyms;
+             free (cookie.locsym_shndx);
+             goto error_ret_free_loc;
            }
-        }
+       }
 
       if (stab)
        {
@@ -8075,7 +8275,10 @@ elf_bfd_discard_info (output_bfd, info)
            ret = true;
        }
 
-      if (freesyms)
+      if (cookie.locsym_shndx != NULL)
+       free (cookie.locsym_shndx);
+
+      if (freesyms != NULL)
        free (freesyms);
     }
 
index 6abd6909dd7cb60fd87f12b6ceab7cd6defdc4ad..8f43563c43852987d08ee946c3d0cff69ca9daab 100644 (file)
@@ -644,6 +644,7 @@ 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;
@@ -651,6 +652,7 @@ elfNN_ia64_relax_section (abfd, sec, link_info, again)
   bfd_byte *free_contents = NULL;
   ElfNN_External_Sym *extsyms;
   ElfNN_External_Sym *free_extsyms = NULL;
+  Elf_External_Sym_Shndx *shndx_buf = NULL;
   struct elfNN_ia64_link_hash_table *ia64_info;
   struct one_fixup *fixups = NULL;
   boolean changed_contents = false;
@@ -712,18 +714,34 @@ elfNN_ia64_relax_section (abfd, sec, link_info, again)
        goto error_return;
     }
 
-  /* Read this BFD's symbols.  */
+  /* Read this BFD's local symbols.  */
   if (symtab_hdr->contents != NULL)
     extsyms = (ElfNN_External_Sym *) symtab_hdr->contents;
   else
     {
-      extsyms = (ElfNN_External_Sym *) bfd_malloc (symtab_hdr->sh_size);
+      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, symtab_hdr->sh_size, abfd)
-             != symtab_hdr->sh_size))
+         || 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;
     }
 
@@ -741,20 +759,21 @@ 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.  */
-         bfd_elfNN_swap_symbol_in (abfd,
-                                   extsyms + ELFNN_R_SYM (irel->r_info),
-                                   &isym);
+         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, esym, shndx, &isym);
          if (isym.st_shndx == SHN_UNDEF)
            continue;   /* We can't do anthing with undefined symbols.  */
          else if (isym.st_shndx == SHN_ABS)
            tsec = bfd_abs_section_ptr;
          else if (isym.st_shndx == SHN_COMMON)
            tsec = bfd_com_section_ptr;
-         else if (isym.st_shndx > 0 && isym.st_shndx < SHN_LORESERVE)
-           tsec = bfd_section_from_elf_index (abfd, isym.st_shndx);
          else
-           continue;   /* who knows.  */
+           tsec = bfd_section_from_elf_index (abfd, isym.st_shndx);
 
          toff = isym.st_value;
        }
@@ -922,6 +941,9 @@ elfNN_ia64_relax_section (abfd, sec, link_info, again)
        }
     }
 
+  if (shndx_buf != NULL)
+    free (shndx_buf);
+
   if (free_extsyms != NULL)
     {
       if (! link_info->keep_memory)
@@ -941,6 +963,8 @@ elfNN_ia64_relax_section (abfd, sec, link_info, again)
     free (free_relocs);
   if (free_contents != NULL)
     free (free_contents);
+  if (shndx_buf != NULL)
+    free (shndx_buf);
   if (free_extsyms != NULL)
     free (free_extsyms);
   return false;
@@ -1225,15 +1249,15 @@ elfNN_ia64_aix_add_symbol_hook (abfd, info, sym, namep, flagsp, secp, valp)
     }
   else if (sym->st_shndx == SHN_LOOS)
     {
-      int i;
+      unsigned int i;
 
       /* SHN_AIX_SYSCALL: Treat this as any other symbol.  The special symbol
         is only relevant when compiling code for extended system calls.
         Replace the "special" section with .text, if possible.
         Note that these symbols are always assumed to be in .text. */
-      for (i = 1; i < elf_elfheader (abfd)->e_shnum; i++)
+      for (i = 1; i < elf_numsections (abfd); i++)
        {
-         asection * sec = bfd_section_from_elf_index (abfd, (unsigned) i);
+         asection * sec = bfd_section_from_elf_index (abfd, i);
 
          if (sec && strcmp (sec->name, ".text") == 0)
            {
index f08b7d2b185319b653e5441aa3d76b6283c9783e..1ddf1fadbda6925ca57dd48fcbd8c6e7c3b38b4c 100644 (file)
@@ -1,3 +1,31 @@
+2001-12-17  Alan Modra  <amodra@bigpond.net.au>
+
+       * readelf.c (symtab_shndx_hdr): New global.
+       (SECTION_HEADER_INDEX): Define.
+       (SECTION_HEADER_NUM): Define.
+       (SECTION_HEADER): Define.
+       (GET_ELF_SYMBOLS): Pass two params rather than three.
+       (get_32bit_elf_symbols): Take file and section args.  Read and
+       use SHT_SYMTAB_SHNDX.
+       (get_64bit_elf_symbols): Likewise.
+       (dump_relocations): Use SECTION_HEADER to index "section_headers".
+       (process_section_headers): Likewise.  Use SECTION_HEADER_NUM too.
+       Remember symtab_shdx_hdr.
+       (process_program_headers): Scan from index 1 for segment map.
+       (slurp_ia64_unwind_table): Use SECTION_HEADER to index
+       "section_headers".
+       (process_relocs): Likewise.  Also adjust call to GET_ELF_SYMBOLS.
+       (process_unwind): Likewise.
+       (process_version_sections): Likewise.
+       (process_symbol_table): Likewise.
+       (display_debug_info): Likewise.
+       (process_dynamic_segment): Fake up a symtab section for changed
+       GET_ELF_SYMBOLS.
+       (get_symbol_index_type): Check SHN_LOOS before SHN_LORESERVE.
+       (process_program_headers): Kill signed/unsigned warning.
+       (load_debug_str): Likewise.
+       (display_debug_info): Likewise.
+
 2001-12-13  Jakub Jelinek  <jakub@redhat.com>
 
        * readelf.c (get_segment_type): Support PT_GNU_EH_FRAME.
index 73a98b5c44b2576f7f7cc8234ca80a49d7dfc74e..cd97886a4fd6202552ea02332ea6d9d4248b2832 100644 (file)
@@ -102,6 +102,7 @@ int                 loadaddr = 0;
 Elf_Internal_Ehdr       elf_header;
 Elf_Internal_Shdr *     section_headers;
 Elf_Internal_Dyn *      dynamic_segment;
+Elf_Internal_Shdr *     symtab_shndx_hdr;
 int                    show_name;
 int                    do_dynamic;
 int                    do_syms;
@@ -202,8 +203,8 @@ static int                get_64bit_section_headers   PARAMS ((FILE *, unsigned
 static int               get_32bit_program_headers   PARAMS ((FILE *, Elf_Internal_Phdr *));
 static int               get_64bit_program_headers   PARAMS ((FILE *, Elf_Internal_Phdr *));
 static int                get_file_header             PARAMS ((FILE *));
-static Elf_Internal_Sym * get_32bit_elf_symbols       PARAMS ((FILE *, unsigned long, unsigned long));
-static Elf_Internal_Sym * get_64bit_elf_symbols       PARAMS ((FILE *, unsigned long, unsigned long));
+static Elf_Internal_Sym * get_32bit_elf_symbols       PARAMS ((FILE *, Elf_Internal_Shdr *));
+static Elf_Internal_Sym * get_64bit_elf_symbols       PARAMS ((FILE *, Elf_Internal_Shdr *));
 static const char *      get_elf_section_flags       PARAMS ((bfd_vma));
 static int *              get_dynamic_data            PARAMS ((FILE *, unsigned int));
 static int                get_32bit_dynamic_segment   PARAMS ((FILE *));
@@ -264,6 +265,22 @@ typedef int Elf32_Word;
                                 ((X)->sh_name >= string_table_length \
                                  ? "<corrupt>" : string_table + (X)->sh_name))
 
+/* Given st_shndx I, map to section_headers index.  */
+#define SECTION_HEADER_INDEX(I)                                \
+  ((I) < SHN_LORESERVE                                 \
+   ? (I)                                               \
+   : ((I) <= SHN_HIRESERVE                             \
+      ? 0                                              \
+      : (I) - (SHN_HIRESERVE + 1 - SHN_LORESERVE)))
+
+/* Reverse of the above.  */
+#define SECTION_HEADER_NUM(N)                          \
+  ((N) < SHN_LORESERVE                                 \
+   ? (N)                                               \
+   : (N) + (SHN_HIRESERVE + 1 - SHN_LORESERVE))
+
+#define SECTION_HEADER(I) (section_headers + SECTION_HEADER_INDEX (I))
+
 #define DT_VERSIONTAGIDX(tag)  (DT_VERNEEDNUM - (tag)) /* Reverse order! */
 
 #define BYTE_GET(field)        byte_get (field, sizeof (field))
@@ -284,9 +301,9 @@ typedef int Elf32_Word;
 
 #define NUM_ELEM(array)        (sizeof (array) / sizeof ((array)[0]))
 
-#define GET_ELF_SYMBOLS(file, offset, size)                    \
-  (is_32bit_elf ? get_32bit_elf_symbols (file, offset, size)   \
-   : get_64bit_elf_symbols (file, offset, size))
+#define GET_ELF_SYMBOLS(file, section)                 \
+  (is_32bit_elf ? get_32bit_elf_symbols (file, section)        \
+   : get_64bit_elf_symbols (file, section))
 
 
 static void
@@ -1042,7 +1059,7 @@ dump_relocations (file, rel_offset, rel_size, symtab, nsyms, strtab, is_rela)
 
              if (psym->st_name == 0)
                printf ("%-25.25s",
-                       SECTION_NAME (section_headers + psym->st_shndx));
+                       SECTION_NAME (SECTION_HEADER (psym->st_shndx)));
              else if (strtab == NULL)
                printf (_("<string table index %3ld>"), psym->st_name);
              else
@@ -2745,7 +2762,7 @@ process_program_headers (file)
 
       for (i = 0; i < elf_header.e_phnum; i++)
        {
-         int                 j;
+         unsigned int j;
          Elf_Internal_Shdr * section;
 
          segment = program_headers + i;
@@ -2753,7 +2770,7 @@ process_program_headers (file)
 
          printf ("   %2.2d     ", i);
 
-         for (j = 0; j < elf_header.e_shnum; j++, section ++)
+         for (j = 1; j < elf_header.e_shnum; j++, section ++)
            {
              if (section->sh_size > 0
                  /* Compare allocated sections by VMA, unallocated
@@ -2871,29 +2888,47 @@ get_64bit_section_headers (file, num)
 }
 
 static Elf_Internal_Sym *
-get_32bit_elf_symbols (file, offset, number)
+get_32bit_elf_symbols (file, section)
      FILE * file;
-     unsigned long offset;
-     unsigned long number;
+     Elf_Internal_Shdr *section;
 {
+  unsigned long number;
   Elf32_External_Sym * esyms;
+  Elf_External_Sym_Shndx *shndx;
   Elf_Internal_Sym *   isyms;
   Elf_Internal_Sym *   psym;
   unsigned int         j;
 
   esyms = ((Elf32_External_Sym *)
-          get_data (NULL, file, offset,
-                    number * sizeof (Elf32_External_Sym), _("symbols")));
+          get_data (NULL, file, section->sh_offset,
+                    section->sh_size, _("symbols")));
   if (!esyms)
     return NULL;
 
+  shndx = NULL;
+  if (symtab_shndx_hdr != NULL
+      && (symtab_shndx_hdr->sh_link
+         == (unsigned long) SECTION_HEADER_NUM (section - section_headers)))
+    {
+      shndx = ((Elf_External_Sym_Shndx *)
+              get_data (NULL, file, symtab_shndx_hdr->sh_offset,
+                        symtab_shndx_hdr->sh_size, _("symtab shndx")));
+      if (!shndx)
+       {
+         free (esyms);
+         return NULL;
+       }
+    }
+
+  number = section->sh_size / section->sh_entsize;
   isyms = (Elf_Internal_Sym *) malloc (number * sizeof (Elf_Internal_Sym));
 
   if (isyms == NULL)
     {
       error (_("Out of memory\n"));
+      if (shndx)
+       free (shndx);
       free (esyms);
-
       return NULL;
     }
 
@@ -2905,39 +2940,62 @@ get_32bit_elf_symbols (file, offset, number)
       psym->st_value = BYTE_GET (esyms[j].st_value);
       psym->st_size  = BYTE_GET (esyms[j].st_size);
       psym->st_shndx = BYTE_GET (esyms[j].st_shndx);
+      if (psym->st_shndx == SHN_XINDEX && shndx != NULL)
+       psym->st_shndx
+         = byte_get ((unsigned char *) &shndx[j], sizeof (shndx[j]));
       psym->st_info  = BYTE_GET (esyms[j].st_info);
       psym->st_other = BYTE_GET (esyms[j].st_other);
     }
 
+  if (shndx)
+    free (shndx);
   free (esyms);
 
   return isyms;
 }
 
 static Elf_Internal_Sym *
-get_64bit_elf_symbols (file, offset, number)
+get_64bit_elf_symbols (file, section)
      FILE * file;
-     unsigned long offset;
-     unsigned long number;
+     Elf_Internal_Shdr *section;
 {
+  unsigned long number;
   Elf64_External_Sym * esyms;
+  Elf_External_Sym_Shndx *shndx;
   Elf_Internal_Sym *   isyms;
   Elf_Internal_Sym *   psym;
   unsigned int         j;
 
   esyms = ((Elf64_External_Sym *)
-          get_data (NULL, file, offset,
-                    number * sizeof (Elf64_External_Sym), _("symbols")));
+          get_data (NULL, file, section->sh_offset,
+                    section->sh_size, _("symbols")));
   if (!esyms)
     return NULL;
 
+  shndx = NULL;
+  if (symtab_shndx_hdr != NULL
+      && (symtab_shndx_hdr->sh_link
+         == (unsigned long) SECTION_HEADER_NUM (section - section_headers)))
+    {
+      shndx = ((Elf_External_Sym_Shndx *)
+              get_data (NULL, file, symtab_shndx_hdr->sh_offset,
+                        symtab_shndx_hdr->sh_size, _("symtab shndx")));
+      if (!shndx)
+       {
+         free (esyms);
+         return NULL;
+       }
+    }
+
+  number = section->sh_size / section->sh_entsize;
   isyms = (Elf_Internal_Sym *) malloc (number * sizeof (Elf_Internal_Sym));
 
   if (isyms == NULL)
     {
       error (_("Out of memory\n"));
+      if (shndx)
+       free (shndx);
       free (esyms);
-
       return NULL;
     }
 
@@ -2949,10 +3007,15 @@ get_64bit_elf_symbols (file, offset, number)
       psym->st_info  = BYTE_GET (esyms[j].st_info);
       psym->st_other = BYTE_GET (esyms[j].st_other);
       psym->st_shndx = BYTE_GET (esyms[j].st_shndx);
+      if (psym->st_shndx == SHN_XINDEX && shndx != NULL)
+       psym->st_shndx
+         = byte_get ((unsigned char *) &shndx[j], sizeof (shndx[j]));
       psym->st_value = BYTE_GET8 (esyms[j].st_value);
       psym->st_size  = BYTE_GET8 (esyms[j].st_size);
     }
 
+  if (shndx)
+    free (shndx);
   free (esyms);
 
   return isyms;
@@ -3010,7 +3073,7 @@ process_section_headers (file)
      FILE * file;
 {
   Elf_Internal_Shdr * section;
-  int                 i;
+  unsigned int        i;
 
   section_headers = NULL;
 
@@ -3035,7 +3098,7 @@ process_section_headers (file)
     return 0;
 
   /* Read in the string table, so that we have names to display.  */
-  section = section_headers + elf_header.e_shstrndx;
+  section = SECTION_HEADER (elf_header.e_shstrndx);
 
   if (section->sh_size != 0)
     {
@@ -3066,8 +3129,7 @@ process_section_headers (file)
            }
 
          num_dynamic_syms = section->sh_size / section->sh_entsize;
-         dynamic_symbols =
-           GET_ELF_SYMBOLS (file, section->sh_offset, num_dynamic_syms);
+         dynamic_symbols = GET_ELF_SYMBOLS (file, section);
        }
       else if (section->sh_type == SHT_STRTAB
               && strcmp (name, ".dynstr") == 0)
@@ -3082,6 +3144,15 @@ process_section_headers (file)
                                               section->sh_size,
                                               _("dynamic strings"));
        }
+      else if (section->sh_type == SHT_SYMTAB_SHNDX)
+       {
+         if (symtab_shndx_hdr != NULL)
+           {
+             error (_("File contains multiple symtab shndx tables\n"));
+             continue;
+           }
+         symtab_shndx_hdr = section;
+       }
       else if ((do_debugging || do_debug_info || do_debug_abbrevs
                || do_debug_lines || do_debug_pubnames || do_debug_aranges
                || do_debug_frames || do_debug_macinfo || do_debug_str)
@@ -3130,8 +3201,8 @@ process_section_headers (file)
        i < elf_header.e_shnum;
        i ++, section ++)
     {
-      printf ("  [%2d] %-17.17s %-15.15s ",
-             i,
+      printf ("  [%2u] %-17.17s %-15.15s ",
+             SECTION_HEADER_NUM (i),
              SECTION_NAME (section),
              get_section_type_name (section->sh_type));
 
@@ -3330,14 +3401,14 @@ process_relocs (file)
                {
                  Elf32_Internal_Shdr * symsec;
 
-                 symsec = section_headers + section->sh_link;
+                 symsec = SECTION_HEADER (section->sh_link);
                  nsyms = symsec->sh_size / symsec->sh_entsize;
-                 symtab = GET_ELF_SYMBOLS (file, symsec->sh_offset, nsyms);
+                 symtab = GET_ELF_SYMBOLS (file, symsec);
 
                  if (symtab == NULL)
                    continue;
 
-                 strsec = section_headers + symsec->sh_link;
+                 strsec = SECTION_HEADER (symsec->sh_link);
 
                  strtab = (char *) get_data (NULL, file, strsec->sh_offset,
                                              strsec->sh_size,
@@ -3589,7 +3660,7 @@ slurp_ia64_unwind_table (file, aux, sec)
        ++relsec)
     {
       if (relsec->sh_type != SHT_RELA
-         || section_headers + relsec->sh_info != sec)
+         || SECTION_HEADER (relsec->sh_info) != sec)
        continue;
 
       if (!slurp_rela_relocs (file, relsec->sh_offset, relsec->sh_size,
@@ -3683,9 +3754,9 @@ process_unwind (file)
       if (sec->sh_type == SHT_SYMTAB)
        {
          aux.nsyms = sec->sh_size / sec->sh_entsize;
-         aux.symtab = GET_ELF_SYMBOLS (file, sec->sh_offset, aux.nsyms);
+         aux.symtab = GET_ELF_SYMBOLS (file, sec);
 
-         strsec = section_headers + sec->sh_link;
+         strsec = SECTION_HEADER (sec->sh_link);
          aux.strtab_size = strsec->sh_size;
          aux.strtab = (char *) get_data (NULL, file, strsec->sh_offset,
                                          aux.strtab_size, _("string table"));
@@ -4065,7 +4136,7 @@ process_dynamic_segment (file)
           i < dynamic_size;
           ++i, ++ entry)
        {
-         unsigned long        offset;
+         Elf32_Internal_Shdr section;
 
          if (entry->d_tag != DT_SYMTAB)
            continue;
@@ -4076,23 +4147,25 @@ process_dynamic_segment (file)
             we default to reading in the entire file (!) and
             processing that.  This is overkill, I know, but it
             should work.  */
-         offset = entry->d_un.d_val - loadaddr;
+         section.sh_offset = entry->d_un.d_val - loadaddr;
 
          if (fseek (file, 0, SEEK_END))
            error (_("Unable to seek to end of file!"));
 
+         section.sh_size = ftell (file) - section.sh_offset;
          if (is_32bit_elf)
-           num_dynamic_syms = (ftell (file) - offset) / sizeof (Elf32_External_Sym);
+           section.sh_entsize = sizeof (Elf32_External_Sym);
          else
-           num_dynamic_syms = (ftell (file) - offset) / sizeof (Elf64_External_Sym);
+           section.sh_entsize = sizeof (Elf64_External_Sym);
 
+         num_dynamic_syms = section.sh_size / section.sh_entsize;
          if (num_dynamic_syms < 1)
            {
              error (_("Unable to determine the number of symbols to load\n"));
              continue;
            }
 
-         dynamic_symbols = GET_ELF_SYMBOLS (file, offset, num_dynamic_syms);
+         dynamic_symbols = GET_ELF_SYMBOLS (file, &section);
        }
     }
 
@@ -4613,7 +4686,7 @@ process_version_sections (file)
            printf_vma (section->sh_addr);
            printf (_("  Offset: %#08lx  Link: %lx (%s)\n"),
                    (unsigned long) section->sh_offset, section->sh_link,
-                   SECTION_NAME (section_headers + section->sh_link));
+                   SECTION_NAME (SECTION_HEADER (section->sh_link)));
 
            edefs = ((Elf_External_Verdef *)
                     get_data (NULL, file, section->sh_offset,
@@ -4704,7 +4777,7 @@ process_version_sections (file)
            printf_vma (section->sh_addr);
            printf (_("  Offset: %#08lx  Link to section: %ld (%s)\n"),
                    (unsigned long) section->sh_offset, section->sh_link,
-                   SECTION_NAME (section_headers + section->sh_link));
+                   SECTION_NAME (SECTION_HEADER (section->sh_link)));
 
            eneed = ((Elf_External_Verneed *)
                     get_data (NULL, file, section->sh_offset,
@@ -4786,15 +4859,14 @@ process_version_sections (file)
            Elf_Internal_Sym *          symbols;
            Elf32_Internal_Shdr *       string_sec;
 
-           link_section = section_headers + section->sh_link;
+           link_section = SECTION_HEADER (section->sh_link);
            total = section->sh_size / section->sh_entsize;
 
            found = 1;
 
-           symbols = GET_ELF_SYMBOLS (file, link_section->sh_offset,
-                                      link_section->sh_size / link_section->sh_entsize);
+           symbols = GET_ELF_SYMBOLS (file, link_section);
 
-           string_sec = section_headers + link_section->sh_link;
+           string_sec = SECTION_HEADER (link_section->sh_link);
 
            strtab = (char *) get_data (NULL, file, string_sec->sh_offset,
                                        string_sec->sh_size,
@@ -4855,8 +4927,7 @@ process_version_sections (file)
 
                      check_def = 1;
                      check_need = 1;
-                     if (symbols [cnt + j].st_shndx >= SHN_LORESERVE
-                         || section_headers[symbols [cnt + j].st_shndx].sh_type
+                     if (SECTION_HEADER (symbols [cnt + j].st_shndx)->sh_type
                          != SHT_NOBITS)
                        {
                          if (symbols [cnt + j].st_shndx == SHN_UNDEF)
@@ -5082,10 +5153,10 @@ get_symbol_index_type (type)
     default:
       if (type >= SHN_LOPROC && type <= SHN_HIPROC)
        return "PRC";
-      else if (type >= SHN_LORESERVE && type <= SHN_HIRESERVE)
-       return "RSV";
       else if (type >= SHN_LOOS && type <= SHN_HIOS)
        return "OS ";
+      else if (type >= SHN_LORESERVE && type <= SHN_HIRESERVE)
+       return "RSV";
       else
        {
          static char buff [32];
@@ -5244,8 +5315,7 @@ process_symbol_table (file)
          else
            printf (_("   Num:    Value          Size Type    Bind   Vis      Ndx Name\n"));
 
-         symtab = GET_ELF_SYMBOLS (file, section->sh_offset,
-                                   section->sh_size / section->sh_entsize);
+         symtab = GET_ELF_SYMBOLS (file, section);
          if (symtab == NULL)
            continue;
 
@@ -5255,7 +5325,7 @@ process_symbol_table (file)
            {
              Elf32_Internal_Shdr * string_sec;
 
-             string_sec = section_headers + section->sh_link;
+             string_sec = SECTION_HEADER (section->sh_link);
 
              strtab = (char *) get_data (NULL, file, string_sec->sh_offset,
                                          string_sec->sh_size,
@@ -5293,9 +5363,8 @@ process_symbol_table (file)
 
                  vers_data = byte_get (data, 2);
 
-                 is_nobits = psym->st_shndx < SHN_LORESERVE ?
-                   (section_headers [psym->st_shndx].sh_type == SHT_NOBITS)
-                   : 0;
+                 is_nobits = (SECTION_HEADER (psym->st_shndx)->sh_type
+                              == SHT_NOBITS);
 
                  check_def = (psym->st_shndx != SHN_UNDEF);
 
@@ -6976,7 +7045,7 @@ load_debug_str (file)
      FILE * file;
 {
   Elf32_Internal_Shdr * sec;
-  int                   i;
+  unsigned int          i;
 
   /* If it is already loaded, do nothing.  */
   if (debug_str_contents != NULL)
@@ -7414,7 +7483,7 @@ display_debug_info (section, start, file)
       DWARF2_Internal_CompUnit   compunit;
       Elf32_Internal_Shdr *      relsec;
       unsigned char *            tags;
-      int                        i;
+      unsigned int               i;
       int                       level;
       unsigned long             cu_offset;
 
@@ -7437,23 +7506,22 @@ display_debug_info (section, start, file)
           relsec < section_headers + elf_header.e_shnum;
           ++relsec)
        {
-         unsigned long nrelas, nsyms;
+         unsigned long nrelas;
          Elf_Internal_Rela *rela, *rp;
          Elf32_Internal_Shdr *symsec;
          Elf_Internal_Sym *symtab;
          Elf_Internal_Sym *sym;
 
          if (relsec->sh_type != SHT_RELA
-             || section_headers + relsec->sh_info != section)
+             || SECTION_HEADER (relsec->sh_info) != section)
            continue;
 
          if (!slurp_rela_relocs (file, relsec->sh_offset, relsec->sh_size,
                                  & rela, & nrelas))
            return 0;
 
-         symsec = section_headers + relsec->sh_link;
-         nsyms = symsec->sh_size / symsec->sh_entsize;
-         symtab = GET_ELF_SYMBOLS (file, symsec->sh_offset, nsyms);
+         symsec = SECTION_HEADER (relsec->sh_link);
+         symtab = GET_ELF_SYMBOLS (file, symsec);
 
          for (rp = rela; rp < rela + nrelas; ++rp)
            {
index 4b200ab749c3ac85a7dee404cef00e8ba80eedc8..1d0675dbd039d3afe81a7e45b66fdbf58e7aa580 100644 (file)
@@ -1,3 +1,10 @@
+2001-12-17  Alan Modra  <amodra@bigpond.net.au>
+
+       * external.h (Elf_External_Sym_Shndx): Declare.
+       * internal.h (struct elf_internal_sym <st_shndx>): Make it an
+       unsigned int.
+       * common.h (SHN_BAD): Define.
+
 2001-12-11  Alan Modra  <amodra@bigpond.net.au>
 
        * common.h (SHN_XINDEX): Comment typo fix.
index 36a0b4dd81b3e0e7f861b93dc722dda3e71fffef..39ba05a0f759cdbee029a34e3f13733279b99144 100644 (file)
@@ -409,6 +409,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
 #define SHN_COMMON      0xFFF2         /* Associated symbol is in common */
 #define SHN_XINDEX      0xFFFF         /* Section index is held elsewhere */
 #define SHN_HIRESERVE   0xFFFF         /* End range of reserved indices */
+#define SHN_BAD                ((unsigned) -1) /* Used internally by bfd */
 
 /* The following constants control how a symbol may be accessed once it has
    become part of an executable or shared library.  */
index 38e6596de7d4e93e949669fe2f4198cf70b5049d..403ee622b5d1295f165d2f9ac51dac2bb132a953 100644 (file)
@@ -143,6 +143,10 @@ typedef struct {
   unsigned char        st_size[8];             /* Associated symbol size */
 } Elf64_External_Sym;
 
+typedef struct {
+  unsigned char est_shndx[4];          /* Section index */
+} Elf_External_Sym_Shndx;
+
 /* Note segments */
 
 typedef struct {
index 1e3f6a382692055bda19db7b95b608739c98e432..5d39d3ae7ce11f5fbace4decaadbf4524571345d 100644 (file)
@@ -114,7 +114,7 @@ struct elf_internal_sym {
   unsigned long        st_name;                /* Symbol name, index in string tbl */
   unsigned char        st_info;                /* Type and binding attributes */
   unsigned char        st_other;               /* Visibilty, and target specific */
-  unsigned short st_shndx;             /* Associated section index */
+  unsigned int  st_shndx;              /* Associated section index */
 };
 
 typedef struct elf_internal_sym Elf_Internal_Sym;