[PATCH] elf: Cache full internal symbol table for relocatable input
H.J. Lu
hjl.tools@gmail.com
Fri Oct 10 23:18:50 GMT 2025
Add bfd_elf_get_elf_syms_cached to cache internal symbol table for
relocatable input and use the internal symbol table cache for both local
and global symbols to avoid swapping in the same symbol table repeatedly
for --gc-sections. This improves linker --gc-sections speed by ~2x for
PR ld/33530.
elf_link_input_bfd is updated to not to pass preallocated buffers to
bfd_elf_get_elf_syms_cache.
Data to link the 3.1GB clang executable in LLVM 21 debug build on
Linux/x86-64 with 32GB RAM is:
before after improvement
user 48.29 46.45 3.8%
system 7.82 5.47 30%
total 56.1 51.92 7%
maximum set(GB) 10.5 10.7 -0.2%
page faults 2535779 2509896 0.1%
and data to link the 308M cc1plus executable in GCC 16 stage 1 build is:
before after improvement
user 3.56 3.49 0.2%
system 0.66 0.58 12%
total 4.22 4.07 0.3%
maximum set(MB) 969 992 -2.4%
page faults 992692 1016732 0.1%
bfd/
PR ld/33530
* elf-bfd.h (elf_obj_tdata): Add symtab.
(bfd_elf_get_elf_syms): Remove the Elf_External_Sym_Shndx pointer
argument.
(bfd_elf_get_elf_syms_cached): New function.
(bfd_elf_free_symtab): Likewise.
* elf-eh-frame.c (adjust_eh_frame_local_symbols): Changed to
return void.
(_bfd_elf_discard_section_eh_frame): Updated. Don't cache
internal symbol table in symtab_hdr.
* elf-m10200.c (mn10200_elf_relax_section): Drop the last argument
to bfd_elf_get_elf_syms.
(mn10200_elf_get_relocated_section_contents): Likewise.
* elf-m10300.c (mn10300_elf_check_relocs): Likewise.
(mn10300_elf_relax_section): Likewise.
(mn10300_elf_get_relocated_section_contents): Likewise.
* elf.c (bfd_elf_get_elf_syms): Drop the Elf_External_Sym_Shndx
pointer argument. Renamed to ...
(bfd_elf_get_elf_syms_cached): This. Cache internal symbol
table.
(bfd_elf_get_elf_syms): Call bfd_elf_get_elf_syms_cached.
(group_signature): Call bfd_elf_get_elf_syms_cached instead of
bfd_elf_get_elf_syms.
(bfd_sym_from_r_symndx): Likewise.
(_bfd_elf_free_cached_info): Free internal symbol table cache.
* elf32-arc.c (arc_elf_relax_section): Likewise.
* elf32-arm.c (cmse_scan): Likewise.
(elf32_arm_size_stubs): Likewise.
(bfd_elf32_arm_init_maps): Likewise.
* elf32-avr.c (elf32_avr_relax_delete_bytes): Likewise.
(retrieve_local_syms): Likewise.
(elf32_avr_relax_section): Likewise.
(elf32_avr_get_relocated_section_contents): Likewise.
(get_local_syms): Likewise.
* elf32-bfin.c (bfd_bfin_elf32_create_embedded_relocs): Likewise.
* elf32-cr16.c (elf32_cr16_get_relocated_section_contents):
Likewise.
(elf32_cr16_relax_section): Likewise.
(bfd_cr16_elf32_create_embedded_relocs): Likewise.
* elf32-crx.c (elf32_crx_get_relocated_section_contents):
Likewise.
(elf32_crx_relax_section): Likewise.
* elf32-csky.c (elf32_csky_size_stubs): Likewise.
* elf32-epiphany.c (epiphany_elf_relax_section): Likewise.
* elf32-ft32.c (elf32_ft32_relax_delete_bytes): Likewise.
(elf32_ft32_relax_is_branch_target): Likewise.
(ft32_elf_relax_section): Likewise.
* elf32-h8300.c (elf32_h8_relax_section): Likewise.
(elf32_h8_get_relocated_section_contents): Likewise.
* elf32-hppa.c (get_local_syms): Likewise.
* elf32-ip2k.c (ip2k_elf_relax_section): Likewise.
* elf32-m32c.c (dump_symtab): Likewise.
(m32c_elf_relax_plt_section): Likewise.
(m32c_elf_relax_section): Likewise.
* elf32-m68hc11.c (m68hc11_elf_relax_section): Likewise.
* elf32-m68hc1x.c (elf32_m68hc11_size_stubs): Likewise.
* elf32-m68k.c (bfd_m68k_elf32_create_embedded_relocs): Likewise.
* elf32-metag.c (get_local_syms): Likewise.
* elf32-microblaze.c (microblaze_elf_relax_section): Likewise.
* elf32-msp430.c (msp430_elf_relax_section): Likewise.
* elf32-nds32.c (nds32_elf_relax_delete_blanks): Likewise.
(nds32_get_local_syms): Likewise.
* elf32-ppc.c (get_sym_h): Likewise.
(ppc_elf_late_size_sections): Likewise.
* elf32-pru.c (pru_elf_relax_delete_bytes): Likewise.
(pru_elf32_relax_section): Likewise.
* elf32-rl78.c (rl78_elf_relax_plt_section): Likewise.
(rl78_elf_relax_section): Likewise.
* elf32-rx.c (elf32_rx_relax_section): Likewise.
(rx_dump_symtab): Likewise.
* elf32-sh.c (sh_elf_relax_section): Likewise.
(sh_elf_get_relocated_section_contents): Likewise.
* elf32-spu.c (get_sym_h): Likewise.
(discover_functions): Likewise.
* elf32-v850.c (v850_elf_relax_section): Likewise.
* elf32-xstormy16.c (xstormy16_elf_relax_section): Likewise.
* elf32-xtensa.c (retrieve_local_syms): Likewise.
* elf64-alpha.c (elf64_alpha_relax_section): Likewise.
* elf64-hppa.c (elf64_hppa_check_relocs): Likewise.
* elf64-ia64-vms.c (elf64_ia64_relax_section): Likewise.
(elf64_vms_link_add_object_symbols): Likewise.
* elf64-mmix.c (mmix_elf_relax_section): Likewise.
* elf64-ppc.c (opd_entry_value): Likewise.
(get_sym_h): Likewise.
(ppc64_elf_late_size_sections): Likewise.
(ppc64_elf_layout_multitoc): Likewise.
(got_and_plt_relr_for_local_syms): Likewise.
* elfcode.h (elf_slurp_symbol_table): Call
bfd_elf_get_elf_syms_cached instead of bfd_elf_get_elf_syms.
Don't free internal symbol buffer.
* elflink.c (bfd_elf_link_record_local_dynamic_symbol): Call
bfd_elf_get_elf_syms_cached instead of bfd_elf_get_elf_syms.
(elf_link_is_defined_archive_symbol): Likewise. Free internal
symbol table cache.
(elf_link_add_object_symbols): Call bfd_elf_get_elf_syms_cached
instead of bfd_elf_get_elf_syms. Free internal symbol table
cache if it has been changed.
(bfd_elf_match_symbols_in_sections): Call
bfd_elf_get_elf_syms_cached instead of bfd_elf_get_elf_syms.
Don't free the internal symbol table.
(elf_final_link_info): Remove external_syms, locsym_shndx and
internal_syms.
(elf_link_check_versioned_symbol): Call
bfd_elf_get_elf_syms_cached instead of bfd_elf_get_elf_syms.
(elf_link_input_bfd): Likewise. Don't pass pre-allocated
buffer to bfd_elf_get_elf_syms_cached.
(elf_final_link_free): Updated.
(bfd_elf_final_link): Don't set flinfo.external_syms,
flinfo.internal_syms nor flinfo.locsym_shndx.
(init_reloc_cookie): Remove the keep_memory argument. Don't
cache internal symbol table in symtab_hdr.
(fini_reloc_cookie): Removed.
(init_reloc_cookie_for_section): Don't call fini_reloc_cookie on
error.
(_bfd_elf_gc_mark): Replace fini_reloc_cookie_for_section with
fini_reloc_cookie_rels.
(bfd_elf_gc_sections): Likewise. Free the internal symbol table
cache.
(bfd_elf_discard_info): Replace fini_reloc_cookie_for_section with
fini_reloc_cookie_rels. Don't call fini_reloc_cookie.
(bfd_elf_parse_eh_frame_entries): Updated.
* elfnn-aarch64.c (_bfd_aarch64_add_call_stub_entries): Likewise.
(bfd_elfNN_aarch64_init_maps): Likewise.
* elfnn-ia64.c (elfNN_ia64_relax_section): Likewise.
* elfnn-kvx.c (elfNN_kvx_size_stubs): Likewise.
* elfnn-loongarch.c (_bfd_riscv_relax_section): Likewise.
* elfxx-mips.c (_bfd_mips_elf_relax_section): Likewise.
* elfxx-x86.c (_bfd_x86_elf_link_relax_section): Don't use
use symtab_hdr->contents for internal symbol table. Set
keep_symtab if the symbol table has been updated.
libctf/
PR ld/33530
* ctf-open-bfd.c (ctf_bfdopen_ctfsect): Call
bfd_elf_get_elf_syms_cached instead of bfd_elf_get_elf_syms.
Free internal symbol table cache.
Signed-off-by: H.J. Lu <hjl.tools@gmail.com>
---
bfd/elf-bfd.h | 19 ++++-
bfd/elf-eh-frame.c | 17 +----
bfd/elf-m10200.c | 4 +-
bfd/elf-m10300.c | 10 +--
bfd/elf.c | 167 +++++++++++++++++++++++++++++++----------
bfd/elf32-arc.c | 2 +-
bfd/elf32-arm.c | 7 +-
bfd/elf32-avr.c | 12 +--
bfd/elf32-bfin.c | 2 +-
bfd/elf32-cr16.c | 6 +-
bfd/elf32-crx.c | 4 +-
bfd/elf32-csky.c | 2 +-
bfd/elf32-epiphany.c | 2 +-
bfd/elf32-ft32.c | 6 +-
bfd/elf32-h8300.c | 4 +-
bfd/elf32-hppa.c | 2 +-
bfd/elf32-ip2k.c | 2 +-
bfd/elf32-m32c.c | 8 +-
bfd/elf32-m68hc11.c | 2 +-
bfd/elf32-m68hc1x.c | 2 +-
bfd/elf32-m68k.c | 2 +-
bfd/elf32-metag.c | 2 +-
bfd/elf32-microblaze.c | 2 +-
bfd/elf32-msp430.c | 4 +-
bfd/elf32-nds32.c | 4 +-
bfd/elf32-ppc.c | 4 +-
bfd/elf32-pru.c | 4 +-
bfd/elf32-rl78.c | 4 +-
bfd/elf32-rx.c | 4 +-
bfd/elf32-sh.c | 4 +-
bfd/elf32-spu.c | 4 +-
bfd/elf32-v850.c | 2 +-
bfd/elf32-xstormy16.c | 2 +-
bfd/elf32-xtensa.c | 2 +-
bfd/elf64-alpha.c | 2 +-
bfd/elf64-hppa.c | 2 +-
bfd/elf64-ia64-vms.c | 4 +-
bfd/elf64-mmix.c | 2 +-
bfd/elf64-ppc.c | 12 +--
bfd/elfcode.h | 10 +--
bfd/elflink.c | 162 +++++++++++----------------------------
bfd/elfnn-aarch64.c | 4 +-
bfd/elfnn-ia64.c | 2 +-
bfd/elfnn-kvx.c | 2 +-
bfd/elfnn-loongarch.c | 2 +-
bfd/elfnn-riscv.c | 2 +-
bfd/elfxx-mips.c | 2 +-
bfd/elfxx-x86.c | 22 ++++--
libctf/ctf-open-bfd.c | 6 +-
49 files changed, 293 insertions(+), 267 deletions(-)
diff --git a/bfd/elf-bfd.h b/bfd/elf-bfd.h
index 5d19529d972..b0bd8f4d589 100644
--- a/bfd/elf-bfd.h
+++ b/bfd/elf-bfd.h
@@ -2165,6 +2165,11 @@ struct elf_obj_tdata
/* Symbol buffer. */
void *symbuf;
+ /* A pointer to the full internal symbol table of input relocatable
+ SHT_SYMTAB if not NULL. Don't use symtab_hdr->contents since not
+ all backends use it to only cache local symbols. */
+ Elf_Internal_Sym *symtab;
+
/* List of GNU properties. Will be updated by setup_gnu_properties
after all input GNU properties are merged for output. */
elf_property_list *properties;
@@ -2297,8 +2302,9 @@ extern unsigned int _bfd_elf_section_from_bfd_section
extern char *bfd_elf_string_from_elf_section
(bfd *, unsigned, unsigned);
extern Elf_Internal_Sym *bfd_elf_get_elf_syms
- (bfd *, Elf_Internal_Shdr *, size_t, size_t, Elf_Internal_Sym *, void *,
- Elf_External_Sym_Shndx *);
+ (bfd *, Elf_Internal_Shdr *, size_t, size_t, Elf_Internal_Sym *, void *);
+extern Elf_Internal_Sym *bfd_elf_get_elf_syms_cached
+ (bfd *, Elf_Internal_Shdr *, size_t, size_t, Elf_Internal_Sym *, void *);
extern char * bfd_elf_get_str_section (bfd *, unsigned int);
extern const char *bfd_elf_sym_name
(bfd *, Elf_Internal_Shdr *, Elf_Internal_Sym *, asection *);
@@ -3333,6 +3339,15 @@ bfd_section_is_ctf (const asection *sec)
return startswith (name, ".ctf") && (name[4] == 0 || name[4] == '.');
}
+/* Free ELF symbol table cache. */
+
+static inline void
+bfd_elf_free_symtab (bfd *abfd)
+{
+ free (elf_tdata (abfd)->symtab);
+ elf_tdata (abfd)->symtab = NULL;
+}
+
#ifdef __cplusplus
}
#endif
diff --git a/bfd/elf-eh-frame.c b/bfd/elf-eh-frame.c
index 4eda3c991bb..bd2c85291fb 100644
--- a/bfd/elf-eh-frame.c
+++ b/bfd/elf-eh-frame.c
@@ -1448,12 +1448,10 @@ _bfd_elf_adjust_eh_frame_global_symbol (struct elf_link_hash_entry *h,
/* The same for all local symbols defined in .eh_frame. Returns true
if any symbol was changed. */
-static int
+static void
adjust_eh_frame_local_symbols (const asection *sec,
struct elf_reloc_cookie *cookie)
{
- int adjusted = 0;
-
if (cookie->locsymcount > 1)
{
unsigned int shndx = elf_section_data (sec)->this_idx;
@@ -1467,13 +1465,9 @@ adjust_eh_frame_local_symbols (const asection *sec,
bfd_signed_vma delta = offset_adjust (sym->st_value, sec);
if (delta != 0)
- {
- adjusted = 1;
- sym->st_value += delta;
- }
+ sym->st_value += delta;
}
}
- return adjusted;
}
/* This function is called for each input file before the .eh_frame
@@ -1611,11 +1605,8 @@ _bfd_elf_discard_section_eh_frame
if (sec->size != sec->rawsize)
changed = 1;
- if (changed && adjust_eh_frame_local_symbols (sec, cookie))
- {
- Elf_Internal_Shdr *symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
- symtab_hdr->contents = (unsigned char *) cookie->locsyms;
- }
+ if (changed)
+ adjust_eh_frame_local_symbols (sec, cookie);
return changed;
}
diff --git a/bfd/elf-m10200.c b/bfd/elf-m10200.c
index ca9a92e1221..4da86774ee2 100644
--- a/bfd/elf-m10200.c
+++ b/bfd/elf-m10200.c
@@ -627,7 +627,7 @@ mn10200_elf_relax_section (bfd *abfd,
if (isymbuf == NULL)
isymbuf = bfd_elf_get_elf_syms (abfd, symtab_hdr,
symtab_hdr->sh_info, 0,
- NULL, NULL, NULL);
+ NULL, NULL);
if (isymbuf == NULL)
goto error_return;
}
@@ -1321,7 +1321,7 @@ mn10200_elf_get_relocated_section_contents (bfd *output_bfd,
if (isymbuf == NULL)
isymbuf = bfd_elf_get_elf_syms (input_bfd, symtab_hdr,
symtab_hdr->sh_info, 0,
- NULL, NULL, NULL);
+ NULL, NULL);
if (isymbuf == NULL)
goto error_return;
}
diff --git a/bfd/elf-m10300.c b/bfd/elf-m10300.c
index b381bb9037c..373290cbe4a 100644
--- a/bfd/elf-m10300.c
+++ b/bfd/elf-m10300.c
@@ -1328,7 +1328,7 @@ mn10300_elf_check_relocs (bfd *abfd,
if (isymbuf == NULL)
isymbuf = bfd_elf_get_elf_syms (abfd, symtab_hdr,
symtab_hdr->sh_info, 0,
- NULL, NULL, NULL);
+ NULL, NULL);
if (isymbuf)
{
isym = isymbuf + r_symndx;
@@ -2676,7 +2676,7 @@ mn10300_elf_relax_section (bfd *abfd,
if (isymbuf == NULL)
isymbuf = bfd_elf_get_elf_syms (input_bfd, symtab_hdr,
symtab_hdr->sh_info, 0,
- NULL, NULL, NULL);
+ NULL, NULL);
if (isymbuf == NULL)
goto error_return;
}
@@ -3019,7 +3019,7 @@ mn10300_elf_relax_section (bfd *abfd,
if (isymbuf == NULL)
isymbuf = bfd_elf_get_elf_syms (input_bfd, symtab_hdr,
symtab_hdr->sh_info, 0,
- NULL, NULL, NULL);
+ NULL, NULL);
if (isymbuf == NULL)
goto error_return;
}
@@ -3347,7 +3347,7 @@ mn10300_elf_relax_section (bfd *abfd,
if (isymbuf == NULL)
isymbuf = bfd_elf_get_elf_syms (abfd, symtab_hdr,
symtab_hdr->sh_info, 0,
- NULL, NULL, NULL);
+ NULL, NULL);
if (isymbuf == NULL)
goto error_return;
}
@@ -4463,7 +4463,7 @@ mn10300_elf_get_relocated_section_contents (bfd *output_bfd,
if (isymbuf == NULL)
isymbuf = bfd_elf_get_elf_syms (input_bfd, symtab_hdr,
symtab_hdr->sh_info, 0,
- NULL, NULL, NULL);
+ NULL, NULL);
if (isymbuf == NULL)
goto error_return;
}
diff --git a/bfd/elf.c b/bfd/elf.c
index bde7414ee21..472fb5da55e 100644
--- a/bfd/elf.c
+++ b/bfd/elf.c
@@ -428,21 +428,20 @@ bfd_elf_string_from_elf_section (bfd *abfd,
}
/* Read and convert symbols to internal format.
- SYMCOUNT specifies the number of symbols to read, starting from
- symbol SYMOFFSET. If any of INTSYM_BUF, EXTSYM_BUF or EXTSHNDX_BUF
+ PARTIAL_SYMCOUNT specifies the number of symbols to read, starting
+ from symbol PARTIAL_SYMOFFSET. If INTSYM_BUF or PARTIAL_EXTSYM_BUF
are non-NULL, they are used to store the internal symbols, external
- symbols, and symbol section index extensions, respectively.
- Returns a pointer to the internal symbol buffer (malloced if necessary)
- or NULL if there were no symbols or some kind of problem. */
+ symbols, and symbol section index extensions, respectively. Returns
+ a pointer to the internal symbol cache or NULL if there were no
+ symbols or some kind of problem. */
Elf_Internal_Sym *
-bfd_elf_get_elf_syms (bfd *ibfd,
- Elf_Internal_Shdr *symtab_hdr,
- size_t symcount,
- size_t symoffset,
- Elf_Internal_Sym *intsym_buf,
- void *extsym_buf,
- Elf_External_Sym_Shndx *extshndx_buf)
+bfd_elf_get_elf_syms_cached (bfd *ibfd,
+ Elf_Internal_Shdr *symtab_hdr,
+ size_t partial_symcount,
+ size_t partial_symoffset,
+ Elf_Internal_Sym *intsym_buf,
+ void *partial_extsym_buf)
{
Elf_Internal_Shdr *shndx_hdr;
void *alloc_ext;
@@ -455,7 +454,12 @@ bfd_elf_get_elf_syms (bfd *ibfd,
const struct elf_backend_data *bed;
size_t extsym_size;
size_t amt;
- file_ptr pos;
+ file_ptr pos = 0;
+ size_t symcount = partial_symcount;
+ size_t symoffset = partial_symoffset;
+ void *extsym_buf = NULL;
+ Elf_External_Sym_Shndx *extshndx_buf = NULL;
+ bool cache_symtab = false;
if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour)
abort ();
@@ -474,6 +478,25 @@ bfd_elf_get_elf_syms (bfd *ibfd,
return elf_tdata (ibfd)->dt_symtab + symoffset;
}
+ if (elf_tdata (ibfd)->symtab != NULL)
+ {
+ /* Since extsym_buf isn't cached, free the symbol table cache and
+ re-read the symbol table. */
+ if (partial_extsym_buf != NULL)
+ bfd_elf_free_symtab (ibfd);
+ else
+ {
+ if (intsym_buf != NULL)
+ {
+ memcpy (intsym_buf, elf_tdata (ibfd)->symtab + symoffset,
+ symcount * sizeof (*intsym_buf));
+ return intsym_buf;
+ }
+ else
+ return elf_tdata (ibfd)->symtab + symoffset;
+ }
+ }
+
/* Normal syms might have section extension entries. */
shndx_hdr = NULL;
if (elf_symtab_shndx_list (ibfd) != NULL)
@@ -506,19 +529,31 @@ bfd_elf_get_elf_syms (bfd *ibfd,
}
}
+ if (elf_elfheader (ibfd)->e_type == ET_REL
+ && symtab_hdr->sh_entsize != 0)
+ {
+ symcount = symtab_hdr->sh_size / symtab_hdr->sh_entsize;
+ symoffset = 0;
+ cache_symtab = true;
+ }
+
/* Read the symbols. */
alloc_ext = NULL;
alloc_extshndx = NULL;
alloc_intsym = NULL;
bed = get_elf_backend_data (ibfd);
extsym_size = bed->s->sizeof_sym;
- if (_bfd_mul_overflow (symcount, extsym_size, &amt))
+ size_t extsym_buf_size;
+ if (_bfd_mul_overflow (symcount, extsym_size, &extsym_buf_size))
{
bfd_set_error (bfd_error_file_too_big);
return NULL;
}
- pos = symtab_hdr->sh_offset + symoffset * extsym_size;
- size_t alloc_ext_size = amt;
+ if (cache_symtab)
+ pos = symtab_hdr->sh_offset;
+ else
+ pos = symtab_hdr->sh_offset + symoffset * extsym_size;
+ size_t alloc_ext_size = extsym_buf_size;
if (bfd_seek (ibfd, pos, SEEK_SET) != 0
|| !_bfd_mmap_read_temporary (&extsym_buf, &alloc_ext_size,
&alloc_ext, ibfd, false))
@@ -551,22 +586,24 @@ bfd_elf_get_elf_syms (bfd *ibfd,
}
}
- if (intsym_buf == NULL)
+ if (_bfd_mul_overflow (symcount, sizeof (Elf_Internal_Sym), &amt))
{
- if (_bfd_mul_overflow (symcount, sizeof (Elf_Internal_Sym), &amt))
- {
- bfd_set_error (bfd_error_file_too_big);
- goto out1;
- }
- alloc_intsym = (Elf_Internal_Sym *) bfd_malloc (amt);
- intsym_buf = alloc_intsym;
- if (intsym_buf == NULL)
- goto out1;
+ bfd_set_error (bfd_error_file_too_big);
+ goto out1;
+ }
+ alloc_intsym = (Elf_Internal_Sym *) bfd_malloc (amt);
+ if (alloc_intsym == NULL)
+ {
+ intsym_buf = NULL;
+ goto out1;
}
+ if (intsym_buf == NULL)
+ intsym_buf = alloc_intsym;
+
/* Convert the symbols to internal form. */
- isymend = intsym_buf + symcount;
- for (esym = (const bfd_byte *) extsym_buf, isym = intsym_buf,
+ isymend = alloc_intsym + symcount;
+ for (esym = (const bfd_byte *) extsym_buf, isym = alloc_intsym,
shndx = extshndx_buf;
isym < isymend;
esym += extsym_size, isym++, shndx = shndx != NULL ? shndx + 1 : NULL)
@@ -590,7 +627,9 @@ bfd_elf_get_elf_syms (bfd *ibfd,
{
/* xgettext:c-format */
_bfd_error_handler (_("%pB symbol number %lu uses unsupported binding of %u"),
- ibfd, (unsigned long) (isym - intsym_buf), bind);
+ ibfd,
+ (unsigned long) (isym - alloc_intsym),
+ bind);
free (alloc_intsym);
intsym_buf = NULL;
goto out1;
@@ -602,18 +641,72 @@ bfd_elf_get_elf_syms (bfd *ibfd,
{
/* xgettext:c-format */
_bfd_error_handler (_("%pB symbol number %lu uses unsupported type of %u"),
- ibfd, (unsigned long) (isym - intsym_buf), t);
+ ibfd,
+ (unsigned long) (isym - alloc_intsym),
+ t);
free (alloc_intsym);
intsym_buf = NULL;
goto out1;
}
}
+ /* Copy external symbol table before external symbol table buffer
+ is released by _bfd_munmap_temporary. */
+ if (intsym_buf != NULL && partial_extsym_buf != NULL)
+ memcpy (partial_extsym_buf,
+ extsym_buf + partial_symoffset * extsym_size,
+ partial_symcount * extsym_size);
+
out1:
_bfd_munmap_temporary (alloc_extshndx, alloc_extshndx_size);
out2:
_bfd_munmap_temporary (alloc_ext, alloc_ext_size);
+ if (intsym_buf == NULL || !cache_symtab)
+ return intsym_buf;
+
+ elf_tdata (ibfd)->symtab = alloc_intsym;
+ if (intsym_buf != alloc_intsym)
+ {
+ memcpy (intsym_buf, alloc_intsym + partial_symoffset,
+ partial_symcount * sizeof (*intsym_buf));
+ return intsym_buf;
+ }
+ else
+ return alloc_intsym + partial_symoffset;
+}
+
+/* Read and convert symbols to internal format.
+ PARTIAL_SYMCOUNT specifies the number of symbols to read, starting
+ from symbol PARTIAL_SYMOFFSET. If INTSYM_BUF or PARTIAL_EXTSYM_BUF
+ are non-NULL, they are used to store the internal symbols, external
+ symbols, and symbol section index extensions, respectively. Returns
+ a pointer to the internal symbol buffer (malloced if necessary) or
+ NULL if there were no symbols or some kind of problem. */
+
+Elf_Internal_Sym *
+bfd_elf_get_elf_syms (bfd *ibfd,
+ Elf_Internal_Shdr *symtab_hdr,
+ size_t partial_symcount,
+ size_t partial_symoffset,
+ Elf_Internal_Sym *intsym_buf,
+ void *partial_extsym_buf)
+{
+ Elf_Internal_Sym *isym
+ = bfd_elf_get_elf_syms_cached (ibfd, symtab_hdr, partial_symcount,
+ partial_symoffset, intsym_buf,
+ partial_extsym_buf);
+ if (isym == NULL
+ || intsym_buf != NULL
+ || partial_symcount == 0
+ || elf_use_dt_symtab_p (ibfd))
+ return isym;
+
+ size_t amt = partial_symcount * sizeof (*intsym_buf);
+ intsym_buf = bfd_malloc (amt);
+ if (intsym_buf != NULL)
+ memcpy (intsym_buf, isym, amt);
+ bfd_elf_free_symtab (ibfd);
return intsym_buf;
}
@@ -659,8 +752,6 @@ static const char *
group_signature (bfd *abfd, Elf_Internal_Shdr *ghdr)
{
Elf_Internal_Shdr *hdr;
- unsigned char esym[sizeof (Elf64_External_Sym)];
- Elf_External_Sym_Shndx eshndx;
Elf_Internal_Sym isym;
/* First we need to ensure the symbol table is available. Make sure
@@ -674,8 +765,8 @@ group_signature (bfd *abfd, Elf_Internal_Shdr *ghdr)
/* Go read the symbol. */
hdr = &elf_tdata (abfd)->symtab_hdr;
- if (bfd_elf_get_elf_syms (abfd, hdr, 1, ghdr->sh_info,
- &isym, esym, &eshndx) == NULL)
+ if (bfd_elf_get_elf_syms_cached (abfd, hdr, 1, ghdr->sh_info,
+ &isym, NULL) == NULL)
return NULL;
return bfd_elf_sym_name_raw (abfd, hdr, &isym);
@@ -3029,12 +3120,10 @@ bfd_sym_from_r_symndx (struct sym_cache *cache,
if (cache->abfd != abfd || cache->indx[ent] != r_symndx)
{
Elf_Internal_Shdr *symtab_hdr;
- unsigned char esym[sizeof (Elf64_External_Sym)];
- Elf_External_Sym_Shndx eshndx;
symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
- if (bfd_elf_get_elf_syms (abfd, symtab_hdr, 1, r_symndx,
- &cache->sym[ent], esym, &eshndx) == NULL)
+ if (bfd_elf_get_elf_syms_cached (abfd, symtab_hdr, 1, r_symndx,
+ &cache->sym[ent], NULL) == NULL)
return NULL;
if (cache->abfd != abfd)
@@ -10241,6 +10330,8 @@ _bfd_elf_free_cached_info (bfd *abfd)
}
free (tdata->symtab_hdr.contents);
tdata->symtab_hdr.contents = NULL;
+ free (tdata->symtab);
+ tdata->symtab = NULL;
}
return _bfd_generic_bfd_free_cached_info (abfd);
diff --git a/bfd/elf32-arc.c b/bfd/elf32-arc.c
index ebfe4dcc26a..ed1dd56a59f 100644
--- a/bfd/elf32-arc.c
+++ b/bfd/elf32-arc.c
@@ -3037,7 +3037,7 @@ arc_elf_relax_section (bfd *abfd, asection *sec,
if (isymbuf == NULL)
isymbuf = bfd_elf_get_elf_syms (abfd, symtab_hdr,
symtab_hdr->sh_info, 0,
- NULL, NULL, NULL);
+ NULL, NULL);
if (isymbuf == NULL)
goto error_return;
}
diff --git a/bfd/elf32-arm.c b/bfd/elf32-arm.c
index ae3dc246be0..627c03eb507 100644
--- a/bfd/elf32-arm.c
+++ b/bfd/elf32-arm.c
@@ -5928,7 +5928,7 @@ cmse_scan (bfd *input_bfd, struct elf32_arm_link_hash_table *htab,
local_syms = (Elf_Internal_Sym *) symtab_hdr->contents;
if (local_syms == NULL)
local_syms = bfd_elf_get_elf_syms (input_bfd, symtab_hdr,
- symtab_hdr->sh_info, 0, NULL, NULL,
+ symtab_hdr->sh_info, 0, NULL,
NULL);
if (symtab_hdr->sh_info && local_syms == NULL)
return false;
@@ -6611,7 +6611,7 @@ elf32_arm_size_stubs (bfd *output_bfd,
local_syms
= bfd_elf_get_elf_syms (input_bfd, symtab_hdr,
symtab_hdr->sh_info, 0,
- NULL, NULL, NULL);
+ NULL, NULL);
if (local_syms == NULL)
goto error_ret_free_internal;
}
@@ -7966,8 +7966,7 @@ bfd_elf32_arm_init_maps (bfd *abfd)
/* Obtain a buffer full of symbols for this BFD. The hdr->sh_info field
should contain the number of local symbols, which should come before any
global symbols. Mapping symbols are always local. */
- isymbuf = bfd_elf_get_elf_syms (abfd, hdr, localsyms, 0, NULL, NULL,
- NULL);
+ isymbuf = bfd_elf_get_elf_syms (abfd, hdr, localsyms, 0, NULL, NULL);
/* No internal symbols read? Skip this BFD. */
if (isymbuf == NULL)
diff --git a/bfd/elf32-avr.c b/bfd/elf32-avr.c
index 6653e4d72f6..28e41914bd0 100644
--- a/bfd/elf32-avr.c
+++ b/bfd/elf32-avr.c
@@ -2064,7 +2064,7 @@ elf32_avr_relax_delete_bytes (bfd *abfd,
if (isymbuf == NULL)
isymbuf = bfd_elf_get_elf_syms (abfd, symtab_hdr,
symtab_hdr->sh_info, 0,
- NULL, NULL, NULL);
+ NULL, NULL);
if (isymbuf == NULL)
return false;
}
@@ -2197,7 +2197,7 @@ retrieve_local_syms (bfd *input_bfd)
isymbuf = (Elf_Internal_Sym *) symtab_hdr->contents;
if (isymbuf == NULL && locsymcount != 0)
isymbuf = bfd_elf_get_elf_syms (input_bfd, symtab_hdr, locsymcount, 0,
- NULL, NULL, NULL);
+ NULL, NULL);
/* Save the symbols for this input file so they won't be read again. */
if (isymbuf && isymbuf != (Elf_Internal_Sym *) symtab_hdr->contents)
@@ -2569,7 +2569,7 @@ elf32_avr_relax_section (bfd *abfd,
if (isymbuf == NULL)
isymbuf = bfd_elf_get_elf_syms (abfd, symtab_hdr,
symtab_hdr->sh_info, 0,
- NULL, NULL, NULL);
+ NULL, NULL);
if (isymbuf == NULL)
goto error_return;
}
@@ -3008,7 +3008,7 @@ elf32_avr_relax_section (bfd *abfd,
(abfd,
symtab_hdr,
symtab_hdr->sh_info, 0,
- NULL, NULL, NULL);
+ NULL, NULL);
if (isymbuf == NULL)
break;
}
@@ -3241,7 +3241,7 @@ elf32_avr_get_relocated_section_contents (bfd *output_bfd,
if (isymbuf == NULL)
isymbuf = bfd_elf_get_elf_syms (input_bfd, symtab_hdr,
symtab_hdr->sh_info, 0,
- NULL, NULL, NULL);
+ NULL, NULL);
if (isymbuf == NULL)
goto error_return;
}
@@ -3590,7 +3590,7 @@ get_local_syms (bfd *input_bfd, struct bfd_link_info *info)
{
local_syms = bfd_elf_get_elf_syms (input_bfd, symtab_hdr,
symtab_hdr->sh_info, 0,
- NULL, NULL, NULL);
+ NULL, NULL);
/* Cache them for elf_link_input_bfd. */
symtab_hdr->contents = (unsigned char *) local_syms;
}
diff --git a/bfd/elf32-bfin.c b/bfd/elf32-bfin.c
index 7ed1285f4c2..8b74a9f3039 100644
--- a/bfd/elf32-bfin.c
+++ b/bfd/elf32-bfin.c
@@ -5351,7 +5351,7 @@ bfd_bfin_elf32_create_embedded_relocs (bfd *abfd,
if (isymbuf == NULL)
isymbuf = bfd_elf_get_elf_syms (abfd, symtab_hdr,
symtab_hdr->sh_info, 0,
- NULL, NULL, NULL);
+ NULL, NULL);
if (isymbuf == NULL)
goto error_return;
}
diff --git a/bfd/elf32-cr16.c b/bfd/elf32-cr16.c
index 31d1ba41c17..3fc4b4adfa1 100644
--- a/bfd/elf32-cr16.c
+++ b/bfd/elf32-cr16.c
@@ -1511,7 +1511,7 @@ elf32_cr16_get_relocated_section_contents (bfd *output_bfd,
if (isymbuf == NULL)
isymbuf = bfd_elf_get_elf_syms (input_bfd, symtab_hdr,
symtab_hdr->sh_info, 0,
- NULL, NULL, NULL);
+ NULL, NULL);
if (isymbuf == NULL)
goto error_return;
}
@@ -1765,7 +1765,7 @@ elf32_cr16_relax_section (bfd *abfd, asection *sec,
if (isymbuf == NULL)
isymbuf = bfd_elf_get_elf_syms (abfd, symtab_hdr,
symtab_hdr->sh_info, 0,
- NULL, NULL, NULL);
+ NULL, NULL);
if (isymbuf == NULL)
goto error_return;
}
@@ -2739,7 +2739,7 @@ bfd_cr16_elf32_create_embedded_relocs (bfd *abfd,
if (isymbuf == NULL)
isymbuf = bfd_elf_get_elf_syms (abfd, symtab_hdr,
symtab_hdr->sh_info, 0,
- NULL, NULL, NULL);
+ NULL, NULL);
if (isymbuf == NULL)
goto error_return;
}
diff --git a/bfd/elf32-crx.c b/bfd/elf32-crx.c
index d2bc1f7ba72..03c20aab6cb 100644
--- a/bfd/elf32-crx.c
+++ b/bfd/elf32-crx.c
@@ -772,7 +772,7 @@ elf32_crx_get_relocated_section_contents (bfd *output_bfd,
if (isymbuf == NULL)
isymbuf = bfd_elf_get_elf_syms (input_bfd, symtab_hdr,
symtab_hdr->sh_info, 0,
- NULL, NULL, NULL);
+ NULL, NULL);
if (isymbuf == NULL)
goto error_return;
}
@@ -1021,7 +1021,7 @@ elf32_crx_relax_section (bfd *abfd, asection *sec,
if (isymbuf == NULL)
isymbuf = bfd_elf_get_elf_syms (abfd, symtab_hdr,
symtab_hdr->sh_info, 0,
- NULL, NULL, NULL);
+ NULL, NULL);
if (isymbuf == NULL)
goto error_return;
}
diff --git a/bfd/elf32-csky.c b/bfd/elf32-csky.c
index 40781a0e1bb..cc93602f5b0 100644
--- a/bfd/elf32-csky.c
+++ b/bfd/elf32-csky.c
@@ -3543,7 +3543,7 @@ elf32_csky_size_stubs (bfd *output_bfd,
bfd_elf_get_elf_syms (input_bfd,
symtab_hdr,
symtab_hdr->sh_info,
- 0, NULL, NULL, NULL);
+ 0, NULL, NULL);
if (local_syms == NULL)
goto error_ret_free_internal;
}
diff --git a/bfd/elf32-epiphany.c b/bfd/elf32-epiphany.c
index ea60ce4dc72..bace4943dea 100644
--- a/bfd/elf32-epiphany.c
+++ b/bfd/elf32-epiphany.c
@@ -259,7 +259,7 @@ epiphany_elf_relax_section (bfd *abfd, asection *sec,
if (isymbuf == NULL)
isymbuf = bfd_elf_get_elf_syms (abfd, symtab_hdr,
symtab_hdr->sh_info, 0,
- NULL, NULL, NULL);
+ NULL, NULL);
if (isymbuf == NULL)
goto error_return;
}
diff --git a/bfd/elf32-ft32.c b/bfd/elf32-ft32.c
index 6ca175533da..ee9294def64 100644
--- a/bfd/elf32-ft32.c
+++ b/bfd/elf32-ft32.c
@@ -837,7 +837,7 @@ elf32_ft32_relax_delete_bytes (struct bfd_link_info *link_info, bfd * abfd,
if (isymbuf == NULL)
isymbuf = bfd_elf_get_elf_syms (abfd, symtab_hdr,
symtab_hdr->sh_info, 0,
- NULL, NULL, NULL);
+ NULL, NULL);
if (isymbuf == NULL)
return false;
}
@@ -995,7 +995,7 @@ elf32_ft32_relax_is_branch_target (struct bfd_link_info *link_info,
if (isymbuf == NULL)
isymbuf = bfd_elf_get_elf_syms (abfd, symtab_hdr,
symtab_hdr->sh_info, 0,
- NULL, NULL, NULL);
+ NULL, NULL);
if (isymbuf == NULL)
return false;
}
@@ -1119,7 +1119,7 @@ ft32_elf_relax_section (bfd *abfd,
if (isymbuf == NULL)
isymbuf = bfd_elf_get_elf_syms (abfd, symtab_hdr,
symtab_hdr->sh_info, 0,
- NULL, NULL, NULL);
+ NULL, NULL);
if (isymbuf == NULL)
goto error_return;
symtab_hdr->contents = (unsigned char *) isymbuf;
diff --git a/bfd/elf32-h8300.c b/bfd/elf32-h8300.c
index e183577fca4..4bd20f9c433 100644
--- a/bfd/elf32-h8300.c
+++ b/bfd/elf32-h8300.c
@@ -778,7 +778,7 @@ elf32_h8_relax_section (bfd *abfd, asection *sec,
if (isymbuf == NULL)
isymbuf = bfd_elf_get_elf_syms (abfd, symtab_hdr,
symtab_hdr->sh_info, 0,
- NULL, NULL, NULL);
+ NULL, NULL);
if (isymbuf == NULL)
goto error_return;
}
@@ -1654,7 +1654,7 @@ elf32_h8_get_relocated_section_contents (bfd *output_bfd,
if (isymbuf == NULL)
isymbuf = bfd_elf_get_elf_syms (input_bfd, symtab_hdr,
symtab_hdr->sh_info, 0,
- NULL, NULL, NULL);
+ NULL, NULL);
if (isymbuf == NULL)
goto error_return;
}
diff --git a/bfd/elf32-hppa.c b/bfd/elf32-hppa.c
index 2f463e12829..085b10b8ea9 100644
--- a/bfd/elf32-hppa.c
+++ b/bfd/elf32-hppa.c
@@ -2506,7 +2506,7 @@ get_local_syms (bfd *output_bfd, bfd *input_bfd, struct bfd_link_info *info)
{
local_syms = bfd_elf_get_elf_syms (input_bfd, symtab_hdr,
symtab_hdr->sh_info, 0,
- NULL, NULL, NULL);
+ NULL, NULL);
/* Cache them for elf_link_input_bfd. */
symtab_hdr->contents = (unsigned char *) local_syms;
}
diff --git a/bfd/elf32-ip2k.c b/bfd/elf32-ip2k.c
index 5c28a06f318..71de071e1ec 100644
--- a/bfd/elf32-ip2k.c
+++ b/bfd/elf32-ip2k.c
@@ -1130,7 +1130,7 @@ ip2k_elf_relax_section (bfd *abfd,
if (isymbuf == NULL)
isymbuf = bfd_elf_get_elf_syms (abfd, symtab_hdr,
symtab_hdr->sh_info, 0,
- NULL, NULL, NULL);
+ NULL, NULL);
if (isymbuf == NULL)
goto error_return;
}
diff --git a/bfd/elf32-m32c.c b/bfd/elf32-m32c.c
index 8f6881bcb0b..bf24f487c44 100644
--- a/bfd/elf32-m32c.c
+++ b/bfd/elf32-m32c.c
@@ -980,7 +980,7 @@ dump_symtab (bfd * abfd, void *internal_syms, void *external_syms)
if (free_internal)
isymbuf = bfd_elf_get_elf_syms (abfd, symtab_hdr,
symtab_hdr->sh_info, 0,
- internal_syms, external_syms, NULL);
+ internal_syms, external_syms);
else
isymbuf = internal_syms;
isymend = isymbuf + locsymcount;
@@ -1191,7 +1191,7 @@ m32c_elf_relax_plt_section (asection *splt,
if (isymbuf == NULL)
isymbuf = bfd_elf_get_elf_syms (ibfd, symtab_hdr,
symtab_hdr->sh_info, 0,
- NULL, NULL, NULL);
+ NULL, NULL);
if (isymbuf == NULL)
return false;
}
@@ -1488,7 +1488,9 @@ m32c_elf_relax_section (bfd *abfd,
}
else
{
- intsyms = bfd_elf_get_elf_syms (abfd, symtab_hdr, symtab_hdr->sh_info, 0, NULL, NULL, NULL);
+ intsyms = bfd_elf_get_elf_syms (abfd, symtab_hdr,
+ symtab_hdr->sh_info, 0, NULL,
+ NULL);
symtab_hdr->contents = (bfd_byte *) intsyms;
}
diff --git a/bfd/elf32-m68hc11.c b/bfd/elf32-m68hc11.c
index f70716d66a2..b4e0a3220ac 100644
--- a/bfd/elf32-m68hc11.c
+++ b/bfd/elf32-m68hc11.c
@@ -823,7 +823,7 @@ m68hc11_elf_relax_section (bfd *abfd, asection *sec,
if (isymbuf == NULL)
isymbuf = bfd_elf_get_elf_syms (abfd, symtab_hdr,
symtab_hdr->sh_info, 0,
- NULL, NULL, NULL);
+ NULL, NULL);
if (isymbuf == NULL)
goto error_return;
}
diff --git a/bfd/elf32-m68hc1x.c b/bfd/elf32-m68hc1x.c
index 7e8e0383717..9c1bac23549 100644
--- a/bfd/elf32-m68hc1x.c
+++ b/bfd/elf32-m68hc1x.c
@@ -375,7 +375,7 @@ elf32_m68hc11_size_stubs (bfd *output_bfd, bfd *stub_bfd,
{
local_syms = bfd_elf_get_elf_syms (input_bfd, symtab_hdr,
symtab_hdr->sh_info, 0,
- NULL, NULL, NULL);
+ NULL, NULL);
/* Cache them for elf_link_input_bfd. */
symtab_hdr->contents = (unsigned char *) local_syms;
}
diff --git a/bfd/elf32-m68k.c b/bfd/elf32-m68k.c
index 44ef102ea60..728da0754ab 100644
--- a/bfd/elf32-m68k.c
+++ b/bfd/elf32-m68k.c
@@ -4439,7 +4439,7 @@ bfd_m68k_elf32_create_embedded_relocs (bfd *abfd, struct bfd_link_info *info,
if (isymbuf == NULL)
isymbuf = bfd_elf_get_elf_syms (abfd, symtab_hdr,
symtab_hdr->sh_info, 0,
- NULL, NULL, NULL);
+ NULL, NULL);
if (isymbuf == NULL)
goto error_return;
}
diff --git a/bfd/elf32-metag.c b/bfd/elf32-metag.c
index 916f3e15c72..f754af6e3be 100644
--- a/bfd/elf32-metag.c
+++ b/bfd/elf32-metag.c
@@ -3604,7 +3604,7 @@ get_local_syms (bfd *output_bfd ATTRIBUTE_UNUSED, bfd *input_bfd,
{
local_syms = bfd_elf_get_elf_syms (input_bfd, symtab_hdr,
symtab_hdr->sh_info, 0,
- NULL, NULL, NULL);
+ NULL, NULL);
/* Cache them for elf_link_input_bfd. */
symtab_hdr->contents = (unsigned char *) local_syms;
}
diff --git a/bfd/elf32-microblaze.c b/bfd/elf32-microblaze.c
index db7ed465779..3a526391676 100644
--- a/bfd/elf32-microblaze.c
+++ b/bfd/elf32-microblaze.c
@@ -1801,7 +1801,7 @@ microblaze_elf_relax_section (bfd *abfd,
symcount = symtab_hdr->sh_size / sizeof (Elf32_External_Sym);
if (isymbuf == NULL)
isymbuf = bfd_elf_get_elf_syms (abfd, symtab_hdr, symcount,
- 0, NULL, NULL, NULL);
+ 0, NULL, NULL);
BFD_ASSERT (isymbuf != NULL);
internal_relocs = _bfd_elf_link_read_relocs (abfd, sec, NULL, NULL, link_info->keep_memory);
diff --git a/bfd/elf32-msp430.c b/bfd/elf32-msp430.c
index 3b356bfe4e2..5250f13a8b9 100644
--- a/bfd/elf32-msp430.c
+++ b/bfd/elf32-msp430.c
@@ -2071,7 +2071,7 @@ msp430_elf_relax_section (bfd * abfd, asection * sec,
if (isymbuf == NULL)
isymbuf = bfd_elf_get_elf_syms (abfd, symtab_hdr,
symtab_hdr->sh_info, 0,
- NULL, NULL, NULL);
+ NULL, NULL);
if (isymbuf == NULL)
goto error_return;
}
@@ -2295,7 +2295,7 @@ msp430_elf_relax_section (bfd * abfd, asection * sec,
if (isymbuf == NULL)
isymbuf = bfd_elf_get_elf_syms (abfd, symtab_hdr,
symtab_hdr->sh_info, 0,
- NULL, NULL, NULL);
+ NULL, NULL);
if (isymbuf == NULL)
goto error_return;
}
diff --git a/bfd/elf32-nds32.c b/bfd/elf32-nds32.c
index e22b58c4ea8..b15626349a8 100644
--- a/bfd/elf32-nds32.c
+++ b/bfd/elf32-nds32.c
@@ -9225,7 +9225,7 @@ nds32_elf_relax_delete_blanks (bfd *abfd, asection *sec,
if (isym == NULL)
{
isym = bfd_elf_get_elf_syms (abfd, symtab_hdr,
- symtab_hdr->sh_info, 0, NULL, NULL, NULL);
+ symtab_hdr->sh_info, 0, NULL, NULL);
symtab_hdr->contents = (bfd_byte *) isym;
}
@@ -9533,7 +9533,7 @@ nds32_get_local_syms (bfd *abfd, asection *sec ATTRIBUTE_UNUSED,
{
*isymbuf_p = bfd_elf_get_elf_syms (abfd, symtab_hdr,
symtab_hdr->sh_info, 0,
- NULL, NULL, NULL);
+ NULL, NULL);
if (*isymbuf_p == NULL)
return false;
}
diff --git a/bfd/elf32-ppc.c b/bfd/elf32-ppc.c
index a3adcf8430e..e77e77fd687 100644
--- a/bfd/elf32-ppc.c
+++ b/bfd/elf32-ppc.c
@@ -4114,7 +4114,7 @@ get_sym_h (struct elf_link_hash_entry **hp,
if (locsyms == NULL)
locsyms = bfd_elf_get_elf_syms (ibfd, symtab_hdr,
symtab_hdr->sh_info,
- 0, NULL, NULL, NULL);
+ 0, NULL, NULL);
if (locsyms == NULL)
return false;
*locsymsp = locsyms;
@@ -5570,7 +5570,7 @@ ppc_elf_late_size_sections (bfd *output_bfd,
if (local_syms == NULL && locsymcount != 0)
{
local_syms = bfd_elf_get_elf_syms (ibfd, symtab_hdr, locsymcount,
- 0, NULL, NULL, NULL);
+ 0, NULL, NULL);
if (local_syms == NULL)
return false;
}
diff --git a/bfd/elf32-pru.c b/bfd/elf32-pru.c
index 45a86be3ccf..e0d9eb507e2 100644
--- a/bfd/elf32-pru.c
+++ b/bfd/elf32-pru.c
@@ -1215,7 +1215,7 @@ pru_elf_relax_delete_bytes (bfd *abfd,
if (isymbuf == NULL)
isymbuf = bfd_elf_get_elf_syms (abfd, symtab_hdr,
symtab_hdr->sh_info, 0,
- NULL, NULL, NULL);
+ NULL, NULL);
if (isymbuf == NULL)
return false;
}
@@ -1393,7 +1393,7 @@ pru_elf32_relax_section (bfd *abfd, asection *sec,
if (isymbuf == NULL)
isymbuf = bfd_elf_get_elf_syms (abfd, symtab_hdr,
symtab_hdr->sh_info, 0,
- NULL, NULL, NULL);
+ NULL, NULL);
if (isymbuf == NULL)
goto error_return;
}
diff --git a/bfd/elf32-rl78.c b/bfd/elf32-rl78.c
index e2ea6b1d15f..3608008c977 100644
--- a/bfd/elf32-rl78.c
+++ b/bfd/elf32-rl78.c
@@ -1573,7 +1573,7 @@ rl78_elf_relax_plt_section (bfd *dynobj,
if (isymbuf == NULL)
isymbuf = bfd_elf_get_elf_syms (ibfd, symtab_hdr,
symtab_hdr->sh_info, 0,
- NULL, NULL, NULL);
+ NULL, NULL);
if (isymbuf == NULL)
return false;
}
@@ -2137,7 +2137,7 @@ rl78_elf_relax_section (bfd *abfd,
intsyms = (Elf_Internal_Sym *) symtab_hdr->contents;
else
{
- intsyms = bfd_elf_get_elf_syms (abfd, symtab_hdr, symtab_hdr->sh_info, 0, NULL, NULL, NULL);
+ intsyms = bfd_elf_get_elf_syms (abfd, symtab_hdr, symtab_hdr->sh_info, 0, NULL, NULL);
symtab_hdr->contents = (bfd_byte *) intsyms;
}
diff --git a/bfd/elf32-rx.c b/bfd/elf32-rx.c
index d8a2236a233..e18eab7bbda 100644
--- a/bfd/elf32-rx.c
+++ b/bfd/elf32-rx.c
@@ -2070,7 +2070,7 @@ elf32_rx_relax_section (bfd *abfd,
intsyms = (Elf_Internal_Sym *) symtab_hdr->contents;
else
{
- intsyms = bfd_elf_get_elf_syms (abfd, symtab_hdr, symtab_hdr->sh_info, 0, NULL, NULL, NULL);
+ intsyms = bfd_elf_get_elf_syms (abfd, symtab_hdr, symtab_hdr->sh_info, 0, NULL, NULL);
symtab_hdr->contents = (bfd_byte *) intsyms;
}
@@ -3362,7 +3362,7 @@ rx_dump_symtab (bfd * abfd, void * internal_syms, void * external_syms)
if (!internal_syms)
isymbuf = bfd_elf_get_elf_syms (abfd, symtab_hdr,
symtab_hdr->sh_info, 0,
- internal_syms, external_syms, NULL);
+ internal_syms, external_syms);
else
isymbuf = internal_syms;
isymend = isymbuf + locsymcount;
diff --git a/bfd/elf32-sh.c b/bfd/elf32-sh.c
index e078e41b675..022799f389b 100644
--- a/bfd/elf32-sh.c
+++ b/bfd/elf32-sh.c
@@ -577,7 +577,7 @@ sh_elf_relax_section (bfd *abfd, asection *sec,
if (isymbuf == NULL)
isymbuf = bfd_elf_get_elf_syms (abfd, symtab_hdr,
symtab_hdr->sh_info, 0,
- NULL, NULL, NULL);
+ NULL, NULL);
if (isymbuf == NULL)
goto error_return;
}
@@ -5118,7 +5118,7 @@ sh_elf_get_relocated_section_contents (bfd *output_bfd,
if (isymbuf == NULL)
isymbuf = bfd_elf_get_elf_syms (input_bfd, symtab_hdr,
symtab_hdr->sh_info, 0,
- NULL, NULL, NULL);
+ NULL, NULL);
if (isymbuf == NULL)
goto error_return;
}
diff --git a/bfd/elf32-spu.c b/bfd/elf32-spu.c
index de051e48185..eb1ce1c9a12 100644
--- a/bfd/elf32-spu.c
+++ b/bfd/elf32-spu.c
@@ -538,7 +538,7 @@ get_sym_h (struct elf_link_hash_entry **hp,
if (locsyms == NULL)
locsyms = bfd_elf_get_elf_syms (ibfd, symtab_hdr,
symtab_hdr->sh_info,
- 0, NULL, NULL, NULL);
+ 0, NULL, NULL);
if (locsyms == NULL)
return false;
*locsymsp = locsyms;
@@ -3018,7 +3018,7 @@ discover_functions (struct bfd_link_info *info)
free (symtab_hdr->contents);
symtab_hdr->contents = NULL;
syms = bfd_elf_get_elf_syms (ibfd, symtab_hdr, symcount, 0,
- NULL, NULL, NULL);
+ NULL, NULL);
symtab_hdr->contents = (void *) syms;
if (syms == NULL)
return false;
diff --git a/bfd/elf32-v850.c b/bfd/elf32-v850.c
index 27744814691..4d96cf9fbce 100644
--- a/bfd/elf32-v850.c
+++ b/bfd/elf32-v850.c
@@ -3548,7 +3548,7 @@ v850_elf_relax_section (bfd *abfd,
if (isymbuf == NULL)
isymbuf = bfd_elf_get_elf_syms (abfd, symtab_hdr,
symtab_hdr->sh_info, 0,
- NULL, NULL, NULL);
+ NULL, NULL);
if (isymbuf == NULL)
goto error_return;
}
diff --git a/bfd/elf32-xstormy16.c b/bfd/elf32-xstormy16.c
index 5cee2f389eb..ae043319206 100644
--- a/bfd/elf32-xstormy16.c
+++ b/bfd/elf32-xstormy16.c
@@ -627,7 +627,7 @@ xstormy16_elf_relax_section (bfd *dynobj,
if (isymbuf == NULL)
isymbuf = bfd_elf_get_elf_syms (ibfd, symtab_hdr,
symtab_hdr->sh_info, 0,
- NULL, NULL, NULL);
+ NULL, NULL);
if (isymbuf == NULL)
return false;
}
diff --git a/bfd/elf32-xtensa.c b/bfd/elf32-xtensa.c
index b21676df36a..c554740f357 100644
--- a/bfd/elf32-xtensa.c
+++ b/bfd/elf32-xtensa.c
@@ -6831,7 +6831,7 @@ retrieve_local_syms (bfd *input_bfd)
isymbuf = (Elf_Internal_Sym *) symtab_hdr->contents;
if (isymbuf == NULL && locsymcount != 0)
isymbuf = bfd_elf_get_elf_syms (input_bfd, symtab_hdr, locsymcount, 0,
- NULL, NULL, NULL);
+ NULL, NULL);
/* Save the symbols for this input file so they won't be read again. */
if (isymbuf && isymbuf != (Elf_Internal_Sym *) symtab_hdr->contents)
diff --git a/bfd/elf64-alpha.c b/bfd/elf64-alpha.c
index b13c99e4958..2b9eede314d 100644
--- a/bfd/elf64-alpha.c
+++ b/bfd/elf64-alpha.c
@@ -3814,7 +3814,7 @@ elf64_alpha_relax_section (bfd *abfd, asection *sec,
if (isymbuf == NULL)
isymbuf = bfd_elf_get_elf_syms (abfd, symtab_hdr,
symtab_hdr->sh_info, 0,
- NULL, NULL, NULL);
+ NULL, NULL);
if (isymbuf == NULL)
goto error_return;
}
diff --git a/bfd/elf64-hppa.c b/bfd/elf64-hppa.c
index 05bb7f125b7..8cd2d918d8b 100644
--- a/bfd/elf64-hppa.c
+++ b/bfd/elf64-hppa.c
@@ -560,7 +560,7 @@ elf64_hppa_check_relocs (bfd *abfd,
if (local_syms == NULL)
local_syms = bfd_elf_get_elf_syms (abfd, symtab_hdr,
symtab_hdr->sh_info, 0,
- NULL, NULL, NULL);
+ NULL, NULL);
if (local_syms == NULL)
return false;
}
diff --git a/bfd/elf64-ia64-vms.c b/bfd/elf64-ia64-vms.c
index 822b263ae2c..f6d00fc1826 100644
--- a/bfd/elf64-ia64-vms.c
+++ b/bfd/elf64-ia64-vms.c
@@ -467,7 +467,7 @@ elf64_ia64_relax_section (bfd *abfd, asection *sec,
if (isymbuf == NULL)
isymbuf = bfd_elf_get_elf_syms (abfd, symtab_hdr,
symtab_hdr->sh_info, 0,
- NULL, NULL, NULL);
+ NULL, NULL);
if (isymbuf == 0)
goto error_return;
}
@@ -4896,7 +4896,7 @@ elf64_vms_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info)
if (extsymcount != 0)
{
isymbuf = bfd_elf_get_elf_syms (abfd, hdr, extsymcount, extsymoff,
- NULL, NULL, NULL);
+ NULL, NULL);
if (isymbuf == NULL)
goto error_return;
diff --git a/bfd/elf64-mmix.c b/bfd/elf64-mmix.c
index bb8350718a2..642b2cdb9bb 100644
--- a/bfd/elf64-mmix.c
+++ b/bfd/elf64-mmix.c
@@ -2640,7 +2640,7 @@ mmix_elf_relax_section (bfd *abfd,
if (isymbuf == NULL)
isymbuf = bfd_elf_get_elf_syms (abfd, symtab_hdr,
symtab_hdr->sh_info, 0,
- NULL, NULL, NULL);
+ NULL, NULL);
if (isymbuf == 0)
goto error_return;
}
diff --git a/bfd/elf64-ppc.c b/bfd/elf64-ppc.c
index fdda9e0bbb3..ee15d6f0639 100644
--- a/bfd/elf64-ppc.c
+++ b/bfd/elf64-ppc.c
@@ -5666,7 +5666,7 @@ opd_entry_value (asection *opd_sec,
size_t symcnt = symtab_hdr->sh_info;
sym = bfd_elf_get_elf_syms (opd_bfd, symtab_hdr,
symcnt, 0,
- NULL, NULL, NULL);
+ NULL, NULL);
if (sym == NULL)
break;
symtab_hdr->contents = (bfd_byte *) sym;
@@ -5677,7 +5677,7 @@ opd_entry_value (asection *opd_sec,
{
sym = bfd_elf_get_elf_syms (opd_bfd, symtab_hdr,
1, symndx,
- NULL, NULL, NULL);
+ NULL, NULL);
if (sym == NULL)
break;
}
@@ -6987,7 +6987,7 @@ get_sym_h (struct elf_link_hash_entry **hp,
if (locsyms == NULL)
locsyms = bfd_elf_get_elf_syms (ibfd, symtab_hdr,
symtab_hdr->sh_info,
- 0, NULL, NULL, NULL);
+ 0, NULL, NULL);
if (locsyms == NULL)
return false;
*locsymsp = locsyms;
@@ -10325,7 +10325,7 @@ ppc64_elf_late_size_sections (bfd *output_bfd,
if (local_syms == NULL && locsymcount != 0)
{
local_syms = bfd_elf_get_elf_syms (ibfd, symtab_hdr, locsymcount,
- 0, NULL, NULL, NULL);
+ 0, NULL, NULL);
if (local_syms == NULL)
return false;
}
@@ -12921,7 +12921,7 @@ ppc64_elf_layout_multitoc (struct bfd_link_info *info)
if (local_syms == NULL && locsymcount != 0)
{
local_syms = bfd_elf_get_elf_syms (ibfd, symtab_hdr, locsymcount,
- 0, NULL, NULL, NULL);
+ 0, NULL, NULL);
if (local_syms == NULL)
return false;
}
@@ -13591,7 +13591,7 @@ got_and_plt_relr_for_local_syms (struct bfd_link_info *info)
if (local_syms == NULL && locsymcount != 0)
{
local_syms = bfd_elf_get_elf_syms (ibfd, symtab_hdr, locsymcount,
- 0, NULL, NULL, NULL);
+ 0, NULL, NULL);
if (local_syms == NULL)
return false;
}
diff --git a/bfd/elfcode.h b/bfd/elfcode.h
index 5224a1abee6..f8176294bc9 100644
--- a/bfd/elfcode.h
+++ b/bfd/elfcode.h
@@ -1302,8 +1302,8 @@ elf_slurp_symbol_table (bfd *abfd, asymbol **symptrs, bool dynamic)
{
size_t i;
- isymbuf = bfd_elf_get_elf_syms (abfd, hdr, symcount, 0,
- NULL, NULL, NULL);
+ isymbuf = bfd_elf_get_elf_syms_cached (abfd, hdr, symcount, 0,
+ NULL, NULL);
if (isymbuf == NULL)
return -1;
@@ -1523,16 +1523,10 @@ elf_slurp_symbol_table (bfd *abfd, asymbol **symptrs, bool dynamic)
}
free (xverbuf);
- if (hdr->contents != (unsigned char *) isymbuf
- && !elf_use_dt_symtab_p (abfd))
- free (isymbuf);
return symcount;
error_return:
free (xverbuf);
- if (hdr->contents != (unsigned char *) isymbuf
- && !elf_use_dt_symtab_p (abfd))
- free (isymbuf);
return -1;
}
diff --git a/bfd/elflink.c b/bfd/elflink.c
index 3f3ea2cce51..0ab843a4924 100644
--- a/bfd/elflink.c
+++ b/bfd/elflink.c
@@ -851,8 +851,6 @@ bfd_elf_link_record_local_dynamic_symbol (struct bfd_link_info *info,
struct elf_strtab_hash *dynstr;
size_t dynstr_index;
char *name;
- Elf_External_Sym_Shndx eshndx;
- char esym[sizeof (Elf64_External_Sym)];
if (! is_elf_hash_table (info->hash))
return 0;
@@ -868,8 +866,9 @@ bfd_elf_link_record_local_dynamic_symbol (struct bfd_link_info *info,
return 0;
/* Go find the symbol, so that we can find it's name. */
- if (!bfd_elf_get_elf_syms (input_bfd, &elf_tdata (input_bfd)->symtab_hdr,
- 1, input_indx, &entry->isym, esym, &eshndx))
+ if (!bfd_elf_get_elf_syms_cached (input_bfd,
+ &elf_tdata (input_bfd)->symtab_hdr,
+ 1, input_indx, &entry->isym, NULL))
{
bfd_release (input_bfd, entry);
return 0;
@@ -3744,8 +3743,8 @@ elf_link_is_defined_archive_symbol (bfd * abfd, carsym * symdef)
return false;
/* Read in the symbol table. */
- isymbuf = bfd_elf_get_elf_syms (abfd, hdr, extsymcount, extsymoff,
- NULL, NULL, NULL);
+ isymbuf = bfd_elf_get_elf_syms_cached (abfd, hdr, extsymcount,
+ extsymoff, NULL, NULL);
if (isymbuf == NULL)
return false;
@@ -3767,7 +3766,7 @@ elf_link_is_defined_archive_symbol (bfd * abfd, carsym * symdef)
}
}
- free (isymbuf);
+ bfd_elf_free_symtab (abfd);
return result;
}
@@ -4829,8 +4828,8 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info)
sym_hash = elf_sym_hashes (abfd);
if (extsymcount != 0)
{
- isymbuf = bfd_elf_get_elf_syms (abfd, hdr, extsymcount, extsymoff,
- NULL, NULL, NULL);
+ isymbuf = bfd_elf_get_elf_syms_cached (abfd, hdr, extsymcount,
+ extsymoff, NULL, NULL);
if (isymbuf == NULL)
goto error_return;
@@ -4977,6 +4976,8 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info)
(_("%pB: plugin needed to handle lto object"), abfd);
}
+ bool symtab_changed = false;
+
for (isym = isymbuf, isymend = PTR_ADD (isymbuf, extsymcount);
isym < isymend;
isym++, sym_hash++, ever = (ever != NULL ? ever + 1 : NULL))
@@ -5013,6 +5014,7 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info)
{
/* Treat common symbol as undefined for --no-define-common. */
isym->st_shndx = SHN_UNDEF;
+ symtab_changed = true;
common = false;
}
discarded = false;
@@ -5086,6 +5088,7 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info)
sec = bfd_und_section_ptr;
discarded = true;
isym->st_shndx = SHN_UNDEF;
+ symtab_changed = true;
}
else if ((abfd->flags & (EXEC_P | DYNAMIC)) != 0)
value -= sec->vma;
@@ -5814,8 +5817,10 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info)
free (extversym);
extversym = NULL;
- free (isymbuf);
- isymbuf = NULL;
+
+ /* Free internal symbol table cache if it has been changed. */
+ if (symtab_changed)
+ bfd_elf_free_symtab (abfd);
if ((elf_dyn_lib_class (abfd) & DYN_AS_NEEDED) != 0)
{
@@ -6167,7 +6172,7 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info)
free (nondeflt_vers);
free (extversym);
error_free_sym:
- free (isymbuf);
+ bfd_elf_free_symtab (abfd);
error_return:
return false;
}
@@ -8808,8 +8813,8 @@ bfd_elf_match_symbols_in_sections (asection *sec1, asection *sec2,
if (ssymbuf1 == NULL)
{
- isymbuf1 = bfd_elf_get_elf_syms (bfd1, hdr1, symcount1, 0,
- NULL, NULL, NULL);
+ isymbuf1 = bfd_elf_get_elf_syms_cached (bfd1, hdr1, symcount1,
+ 0, NULL, NULL);
if (isymbuf1 == NULL)
goto done;
@@ -8822,8 +8827,8 @@ bfd_elf_match_symbols_in_sections (asection *sec1, asection *sec2,
if (ssymbuf1 == NULL || ssymbuf2 == NULL)
{
- isymbuf2 = bfd_elf_get_elf_syms (bfd2, hdr2, symcount2, 0,
- NULL, NULL, NULL);
+ isymbuf2 = bfd_elf_get_elf_syms_cached (bfd2, hdr2, symcount2,
+ 0, NULL, NULL);
if (isymbuf2 == NULL)
goto done;
@@ -9013,8 +9018,6 @@ bfd_elf_match_symbols_in_sections (asection *sec1, asection *sec2,
done:
free (symtable1);
free (symtable2);
- free (isymbuf1);
- free (isymbuf2);
return result;
}
@@ -9056,14 +9059,6 @@ struct elf_final_link_info
void *external_relocs;
/* Buffer large enough to hold internal relocs of any section. */
Elf_Internal_Rela *internal_relocs;
- /* Buffer large enough to hold external local symbols of any input
- BFD. */
- bfd_byte *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;
/* Array large enough to hold a symbol index for each local symbol
of any input BFD. */
long *indices;
@@ -10665,8 +10660,8 @@ elf_link_check_versioned_symbol (struct bfd_link_info *info,
if (extsymcount == 0)
continue;
- isymbuf = bfd_elf_get_elf_syms (input, hdr, extsymcount, extsymoff,
- NULL, NULL, NULL);
+ isymbuf = bfd_elf_get_elf_syms_cached (input, hdr, extsymcount,
+ extsymoff, NULL, NULL);
if (isymbuf == NULL)
return false;
@@ -11410,7 +11405,7 @@ elf_link_input_bfd (struct elf_final_link_info *flinfo, bfd *input_bfd)
Elf_Internal_Shdr *symtab_hdr;
size_t locsymcount;
size_t extsymoff;
- Elf_Internal_Sym *isymbuf;
+ Elf_Internal_Sym *isymbuf = NULL;
Elf_Internal_Sym *isym;
Elf_Internal_Sym *isymend;
long *pindex;
@@ -11459,10 +11454,8 @@ elf_link_input_bfd (struct elf_final_link_info *flinfo, bfd *input_bfd)
isymbuf = (Elf_Internal_Sym *) symtab_hdr->contents;
if (isymbuf == NULL && locsymcount != 0)
{
- isymbuf = bfd_elf_get_elf_syms (input_bfd, symtab_hdr, locsymcount, 0,
- flinfo->internal_syms,
- flinfo->external_syms,
- flinfo->locsym_shndx);
+ isymbuf = bfd_elf_get_elf_syms_cached (input_bfd, symtab_hdr,
+ locsymcount, 0, NULL, NULL);
if (isymbuf == NULL)
return false;
}
@@ -12632,9 +12625,6 @@ elf_final_link_free (bfd *obfd, struct elf_final_link_info *flinfo)
free (flinfo->contents);
free (flinfo->external_relocs);
free (flinfo->internal_relocs);
- free (flinfo->external_syms);
- free (flinfo->locsym_shndx);
- free (flinfo->internal_syms);
free (flinfo->indices);
free (flinfo->sections);
if (flinfo->symshndxbuf != (Elf_External_Sym_Shndx *) -1)
@@ -12663,7 +12653,6 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *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;
Elf_Internal_Sym elfsym;
unsigned int i;
Elf_Internal_Shdr *symtab_hdr;
@@ -12792,7 +12781,6 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info)
}
max_internal_reloc_count = 0;
max_sym_count = 0;
- max_sym_shndx_count = 0;
merged = false;
for (o = abfd->sections; o != NULL; o = o->next)
{
@@ -12854,10 +12842,6 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info)
if (sym_count > max_sym_count)
max_sym_count = sym_count;
- if (sym_count > max_sym_shndx_count
- && elf_symtab_shndx_list (sec->owner) != NULL)
- max_sym_shndx_count = sym_count;
-
esdi = elf_section_data (sec);
if (esdi->this_hdr.sh_type == SHT_REL
@@ -13118,16 +13102,6 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info)
if (max_sym_count != 0)
{
- amt = max_sym_count * bed->s->sizeof_sym;
- flinfo.external_syms = (bfd_byte *) bfd_malloc (amt);
- if (flinfo.external_syms == NULL)
- goto error_return;
-
- amt = max_sym_count * sizeof (Elf_Internal_Sym);
- flinfo.internal_syms = (Elf_Internal_Sym *) bfd_malloc (amt);
- if (flinfo.internal_syms == NULL)
- goto error_return;
-
amt = max_sym_count * sizeof (long);
flinfo.indices = (long int *) bfd_malloc (amt);
if (flinfo.indices == NULL)
@@ -13139,14 +13113,6 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info)
goto error_return;
}
- if (max_sym_shndx_count != 0)
- {
- amt = max_sym_shndx_count * sizeof (Elf_External_Sym_Shndx);
- flinfo.locsym_shndx = (Elf_External_Sym_Shndx *) bfd_malloc (amt);
- if (flinfo.locsym_shndx == NULL)
- goto error_return;
- }
-
if (htab->tls_sec)
{
bfd_vma base, end = 0; /* Both bytes. */
@@ -13890,8 +13856,7 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info)
static bool
init_reloc_cookie (struct elf_reloc_cookie *cookie,
- struct bfd_link_info *info, bfd *abfd,
- bool keep_memory)
+ struct bfd_link_info *info, bfd *abfd)
{
Elf_Internal_Shdr *symtab_hdr;
const struct elf_backend_data *bed;
@@ -13918,39 +13883,20 @@ init_reloc_cookie (struct elf_reloc_cookie *cookie,
else
cookie->r_sym_shift = 32;
- cookie->locsyms = (Elf_Internal_Sym *) symtab_hdr->contents;
- if (cookie->locsyms == NULL && cookie->locsymcount != 0)
+ if (cookie->locsymcount != 0)
{
- cookie->locsyms = bfd_elf_get_elf_syms (abfd, symtab_hdr,
- cookie->locsymcount, 0,
- NULL, NULL, NULL);
+ cookie->locsyms = bfd_elf_get_elf_syms_cached (abfd, symtab_hdr,
+ cookie->locsymcount,
+ 0, NULL, NULL);
if (cookie->locsyms == NULL)
{
info->callbacks->einfo (_("%P%X: can not read symbols: %E\n"));
return false;
}
- if (keep_memory || _bfd_elf_link_keep_memory (info))
- {
- symtab_hdr->contents = (bfd_byte *) cookie->locsyms;
- info->cache_size += (cookie->locsymcount
- * sizeof (Elf_Internal_Sym));
- }
}
return true;
}
-/* Free the memory allocated by init_reloc_cookie, if appropriate. */
-
-static void
-fini_reloc_cookie (struct elf_reloc_cookie *cookie, bfd *abfd)
-{
- Elf_Internal_Shdr *symtab_hdr;
-
- symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
- if (symtab_hdr->contents != (unsigned char *) cookie->locsyms)
- free (cookie->locsyms);
-}
-
/* Initialize the relocation information in COOKIE for input section SEC
of input bfd ABFD. */
@@ -13996,28 +13942,9 @@ init_reloc_cookie_for_section (struct elf_reloc_cookie *cookie,
struct bfd_link_info *info,
asection *sec, bool keep_memory)
{
- if (!init_reloc_cookie (cookie, info, sec->owner, keep_memory))
- goto error1;
- if (!init_reloc_cookie_rels (cookie, info, sec->owner, sec,
- keep_memory))
- goto error2;
- return true;
-
- error2:
- fini_reloc_cookie (cookie, sec->owner);
- error1:
- return false;
-}
-
-/* Free the memory allocated by init_reloc_cookie_for_section,
- if appropriate. */
-
-static void
-fini_reloc_cookie_for_section (struct elf_reloc_cookie *cookie,
- asection *sec)
-{
- fini_reloc_cookie_rels (cookie, sec);
- fini_reloc_cookie (cookie, sec->owner);
+ return (init_reloc_cookie (cookie, info, sec->owner)
+ && init_reloc_cookie_rels (cookie, info, sec->owner, sec,
+ keep_memory));
}
/* Garbage collect unused sections. */
@@ -14209,7 +14136,7 @@ _bfd_elf_gc_mark (struct bfd_link_info *info,
ret = false;
break;
}
- fini_reloc_cookie_for_section (&cookie, sec);
+ fini_reloc_cookie_rels (&cookie, sec);
}
}
@@ -14231,7 +14158,7 @@ _bfd_elf_gc_mark (struct bfd_link_info *info,
if (!_bfd_elf_gc_mark_fdes (info, sec, eh_frame,
gc_mark_hook, &cookie))
ret = false;
- fini_reloc_cookie_for_section (&cookie, eh_frame);
+ fini_reloc_cookie_rels (&cookie, eh_frame);
}
}
@@ -14665,7 +14592,7 @@ bfd_elf_parse_eh_frame_entries (bfd *abfd ATTRIBUTE_UNUSED,
if (sec == NULL || sec->sec_info_type == SEC_INFO_TYPE_JUST_SYMS)
continue;
- if (!init_reloc_cookie (&cookie, info, ibfd, false))
+ if (!init_reloc_cookie (&cookie, info, ibfd))
return false;
for (sec = ibfd->sections; sec; sec = sec->next)
@@ -14724,7 +14651,7 @@ bfd_elf_gc_sections (bfd *abfd, struct bfd_link_info *info)
if (elf_section_data (sec)->sec_info
&& (sec->flags & SEC_LINKER_CREATED) == 0)
elf_eh_frame_section (sub) = sec;
- fini_reloc_cookie_for_section (&cookie, sec);
+ fini_reloc_cookie_rels (&cookie, sec);
sec = bfd_get_next_section_by_name (NULL, sec);
}
}
@@ -14784,6 +14711,9 @@ bfd_elf_gc_sections (bfd *abfd, struct bfd_link_info *info)
if (!_bfd_elf_gc_mark (info, o, gc_mark_hook))
return false;
}
+
+ if (!_bfd_elf_link_keep_memory (info))
+ bfd_elf_free_symtab (sub);
}
/* Allow the backend to mark additional target specific sections. */
@@ -15239,7 +15169,7 @@ bfd_elf_discard_info (bfd *output_bfd, struct bfd_link_info *info)
&cookie))
changed = 1;
- fini_reloc_cookie_for_section (&cookie, i);
+ fini_reloc_cookie_rels (&cookie, i);
}
}
@@ -15274,7 +15204,7 @@ bfd_elf_discard_info (bfd *output_bfd, struct bfd_link_info *info)
changed = 1;
}
- fini_reloc_cookie_for_section (&cookie, i);
+ fini_reloc_cookie_rels (&cookie, i);
}
eh_alignment = ((1 << o->alignment_power)
@@ -15339,7 +15269,7 @@ bfd_elf_discard_info (bfd *output_bfd, struct bfd_link_info *info)
changed = 1;
}
}
- fini_reloc_cookie_for_section (&cookie, i);
+ fini_reloc_cookie_rels (&cookie, i);
}
/* Update the reference to the output .sframe section. Used to
determine later if PT_GNU_SFRAME segment is to be generated. */
@@ -15362,13 +15292,11 @@ bfd_elf_discard_info (bfd *output_bfd, struct bfd_link_info *info)
if (bed->elf_backend_discard_info != NULL)
{
- if (!init_reloc_cookie (&cookie, info, abfd, false))
+ if (!init_reloc_cookie (&cookie, info, abfd))
return -1;
if ((*bed->elf_backend_discard_info) (abfd, &cookie, info))
changed = 1;
-
- fini_reloc_cookie (&cookie, abfd);
}
}
diff --git a/bfd/elfnn-aarch64.c b/bfd/elfnn-aarch64.c
index 3c3c2899674..553ba27b604 100644
--- a/bfd/elfnn-aarch64.c
+++ b/bfd/elfnn-aarch64.c
@@ -4471,7 +4471,7 @@ _bfd_aarch64_add_call_stub_entries (bool *stub_changed, bfd *output_bfd,
local_syms
= bfd_elf_get_elf_syms (input_bfd, symtab_hdr,
symtab_hdr->sh_info, 0,
- NULL, NULL, NULL);
+ NULL, NULL);
if (local_syms == NULL)
goto error_ret_free_internal;
}
@@ -4934,7 +4934,7 @@ bfd_elfNN_aarch64_init_maps (bfd *abfd)
/* Obtain a buffer full of symbols for this BFD. The hdr->sh_info field
should contain the number of local symbols, which should come before any
global symbols. Mapping symbols are always local. */
- isymbuf = bfd_elf_get_elf_syms (abfd, hdr, localsyms, 0, NULL, NULL, NULL);
+ isymbuf = bfd_elf_get_elf_syms (abfd, hdr, localsyms, 0, NULL, NULL);
/* No internal symbols read? Skip this BFD. */
if (isymbuf == NULL)
diff --git a/bfd/elfnn-ia64.c b/bfd/elfnn-ia64.c
index 528b1dcdcc3..48fce2380cd 100644
--- a/bfd/elfnn-ia64.c
+++ b/bfd/elfnn-ia64.c
@@ -468,7 +468,7 @@ elfNN_ia64_relax_section (bfd *abfd, asection *sec,
if (isymbuf == NULL)
isymbuf = bfd_elf_get_elf_syms (abfd, symtab_hdr,
symtab_hdr->sh_info, 0,
- NULL, NULL, NULL);
+ NULL, NULL);
if (isymbuf == 0)
goto error_return;
}
diff --git a/bfd/elfnn-kvx.c b/bfd/elfnn-kvx.c
index 3b44db57421..8e75b400570 100644
--- a/bfd/elfnn-kvx.c
+++ b/bfd/elfnn-kvx.c
@@ -1404,7 +1404,7 @@ elfNN_kvx_size_stubs (bfd *output_bfd,
local_syms
= bfd_elf_get_elf_syms (input_bfd, symtab_hdr,
symtab_hdr->sh_info, 0,
- NULL, NULL, NULL);
+ NULL, NULL);
if (local_syms == NULL)
goto error_ret_free_internal;
}
diff --git a/bfd/elfnn-loongarch.c b/bfd/elfnn-loongarch.c
index 53cdb783859..10a4f99add7 100644
--- a/bfd/elfnn-loongarch.c
+++ b/bfd/elfnn-loongarch.c
@@ -5792,7 +5792,7 @@ loongarch_elf_relax_section (bfd *abfd, asection *sec,
&& !(symtab_hdr->contents =
(unsigned char *) bfd_elf_get_elf_syms (abfd, symtab_hdr,
symtab_hdr->sh_info,
- 0, NULL, NULL, NULL)))
+ 0, NULL, NULL)))
return true;
/* Estimate the maximum alignment for all output sections once time
diff --git a/bfd/elfnn-riscv.c b/bfd/elfnn-riscv.c
index 09cf7076733..d1ab410a94f 100644
--- a/bfd/elfnn-riscv.c
+++ b/bfd/elfnn-riscv.c
@@ -5492,7 +5492,7 @@ _bfd_riscv_relax_section (bfd *abfd, asection *sec,
&& !(symtab_hdr->contents =
(unsigned char *) bfd_elf_get_elf_syms (abfd, symtab_hdr,
symtab_hdr->sh_info,
- 0, NULL, NULL, NULL)))
+ 0, NULL, NULL)))
goto fail;
/* Get the value of the symbol referred to by the reloc. */
diff --git a/bfd/elfxx-mips.c b/bfd/elfxx-mips.c
index 00ef0663728..44c58362dda 100644
--- a/bfd/elfxx-mips.c
+++ b/bfd/elfxx-mips.c
@@ -14136,7 +14136,7 @@ _bfd_mips_elf_relax_section (bfd *abfd, asection *sec,
if (isymbuf == NULL)
isymbuf = bfd_elf_get_elf_syms (abfd, symtab_hdr,
symtab_hdr->sh_info, 0,
- NULL, NULL, NULL);
+ NULL, NULL);
if (isymbuf == NULL)
goto error_return;
}
diff --git a/bfd/elfxx-x86.c b/bfd/elfxx-x86.c
index 140e86888a6..3f397f5cf70 100644
--- a/bfd/elfxx-x86.c
+++ b/bfd/elfxx-x86.c
@@ -1157,9 +1157,10 @@ _bfd_x86_elf_link_relax_section (bfd *abfd ATTRIBUTE_UNUSED,
isymbuf = (Elf_Internal_Sym *) symtab_hdr->contents;
if (isymbuf == NULL)
{
- isymbuf = bfd_elf_get_elf_syms (abfd, symtab_hdr,
- symtab_hdr->sh_info,
- 0, NULL, NULL, NULL);
+ isymbuf
+ = bfd_elf_get_elf_syms_cached (abfd, symtab_hdr,
+ symtab_hdr->sh_info,
+ 0, NULL, NULL);
if (isymbuf == NULL)
goto error_return;
}
@@ -1345,13 +1346,18 @@ _bfd_x86_elf_link_relax_section (bfd *abfd ATTRIBUTE_UNUSED,
return_status = true;
error_return:
- if ((unsigned char *) isymbuf != symtab_hdr->contents)
+ if (keep_symbuf && (unsigned char *) isymbuf != symtab_hdr->contents)
{
- /* Cache the symbol buffer if it must be kept. */
- if (keep_symbuf)
- symtab_hdr->contents = (unsigned char *) isymbuf;
+ /* Cache the symbol buffer if it has been changed. */
+ size_t amt = symtab_hdr->sh_info * sizeof (*isymbuf);
+ void *buffer = bfd_malloc (amt);
+ if (buffer == NULL)
+ return_status = false;
else
- free (isymbuf);
+ {
+ memcpy (buffer, isymbuf, amt);
+ symtab_hdr->contents = buffer;
+ }
}
if (elf_section_data (input_section)->relocs != internal_relocs)
free (internal_relocs);
diff --git a/libctf/ctf-open-bfd.c b/libctf/ctf-open-bfd.c
index 7241de70709..2ec91ffb0bf 100644
--- a/libctf/ctf-open-bfd.c
+++ b/libctf/ctf-open-bfd.c
@@ -145,9 +145,9 @@ ctf_bfdopen_ctfsect (struct bfd *abfd _libctf_unused_,
goto err;
}
- isymbuf = bfd_elf_get_elf_syms (abfd, symhdr, symcount, 0,
- NULL, symtab, NULL);
- free (isymbuf);
+ isymbuf = bfd_elf_get_elf_syms_cached (abfd, symhdr, symcount, 0,
+ NULL, symtab);
+ bfd_elf_free_symtab (abfd);
if (isymbuf == NULL)
{
bfderrstr = N_("cannot read symbol table");
--
2.51.0
More information about the Binutils
mailing list