diff options
author | Tom Tromey <tromey@adacore.com> | 2025-03-06 10:59:41 -0700 |
---|---|---|
committer | Tom Tromey <tromey@adacore.com> | 2025-03-24 09:47:28 -0600 |
commit | 89e59ca6dce9bc7ca88b5d6c1a073c39b8f9bcc9 (patch) | |
tree | c6ccbeba11b3ad8a2056c9a8c4b85737d503cbb4 /gdb/solib.c | |
parent | 15bbe2b14ca5b15a6e7c5c30c554fb8fd2f83e61 (diff) | |
download | binutils-89e59ca6dce9bc7ca88b5d6c1a073c39b8f9bcc9.zip binutils-89e59ca6dce9bc7ca88b5d6c1a073c39b8f9bcc9.tar.gz binutils-89e59ca6dce9bc7ca88b5d6c1a073c39b8f9bcc9.tar.bz2 |
Introduce gdb_bfd_canonicalize_symtab
bfd_canonicalize_symtab stores the symbols in the BFD, and returns
pointers to these. The ELF reader does not reuse these stored
symbols, so each call to bfd_canonicalize_symtab causes an allocation.
This interacts poorly with code like arm_pikeos_osabi_sniffer, which
searches the BFD symbol when called.
PR gdb/32758 points out a particularly pathological case: using "maint
info sections" on a program with a large number of sections (10000)
will cause 10000 calls to arm_pikeos_osabi_sniffer, allocating 20G.
I'm not sure BFD always worked this way. And, fixing BFD was an
option. However it seemed maybe better for GDB to adapt, since
adapting would mean that the fix would apply to all BFD back ends, and
not just ELF.
To that end, this patch adds a new gdb_bfd_canonicalize_symtab and
changes all callers of bfd_canonicalize_symtab to use it instead.
This new function caches the result in the per-BFD object.
I looked into having this return a view of "const asymbol *". However
both the compile module and machoread modify the returned symbols.
And while I think this is wrong, I haven't tried to fix this here.
Regression tested on x86-64 Fedora 40.
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=32758
Diffstat (limited to 'gdb/solib.c')
-rw-r--r-- | gdb/solib.c | 59 |
1 files changed, 24 insertions, 35 deletions
diff --git a/gdb/solib.c b/gdb/solib.c index 7782c8d..b1fdea9 100644 --- a/gdb/solib.c +++ b/gdb/solib.c @@ -1431,49 +1431,38 @@ CORE_ADDR gdb_bfd_lookup_symbol_from_symtab ( bfd *abfd, gdb::function_view<bool (const asymbol *)> match_sym) { - long storage_needed = bfd_get_symtab_upper_bound (abfd); CORE_ADDR symaddr = 0; + gdb::array_view<asymbol *> symbol_table + = gdb_bfd_canonicalize_symtab (abfd, false); - if (storage_needed > 0) + for (asymbol *sym : symbol_table) { - unsigned int i; - - gdb::def_vector<asymbol *> storage (storage_needed / sizeof (asymbol *)); - asymbol **symbol_table = storage.data (); - unsigned int number_of_symbols - = bfd_canonicalize_symtab (abfd, symbol_table); - - for (i = 0; i < number_of_symbols; i++) + if (match_sym (sym)) { - asymbol *sym = *symbol_table++; - - if (match_sym (sym)) + gdbarch *gdbarch = current_inferior ()->arch (); + symaddr = sym->value; + + /* Some ELF targets fiddle with addresses of symbols they + consider special. They use minimal symbols to do that + and this is needed for correct breakpoint placement, + but we do not have full data here to build a complete + minimal symbol, so just set the address and let the + targets cope with that. */ + if (bfd_get_flavour (abfd) == bfd_target_elf_flavour + && gdbarch_elf_make_msymbol_special_p (gdbarch)) { - gdbarch *gdbarch = current_inferior ()->arch (); - symaddr = sym->value; - - /* Some ELF targets fiddle with addresses of symbols they - consider special. They use minimal symbols to do that - and this is needed for correct breakpoint placement, - but we do not have full data here to build a complete - minimal symbol, so just set the address and let the - targets cope with that. */ - if (bfd_get_flavour (abfd) == bfd_target_elf_flavour - && gdbarch_elf_make_msymbol_special_p (gdbarch)) + struct minimal_symbol msym { - struct minimal_symbol msym - { - }; - - msym.set_value_address (symaddr); - gdbarch_elf_make_msymbol_special (gdbarch, sym, &msym); - symaddr = CORE_ADDR (msym.unrelocated_address ()); - } + }; - /* BFD symbols are section relative. */ - symaddr += sym->section->vma; - break; + msym.set_value_address (symaddr); + gdbarch_elf_make_msymbol_special (gdbarch, sym, &msym); + symaddr = CORE_ADDR (msym.unrelocated_address ()); } + + /* BFD symbols are section relative. */ + symaddr += sym->section->vma; + break; } } |