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/elfread.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/elfread.c')
-rw-r--r-- | gdb/elfread.c | 35 |
1 files changed, 10 insertions, 25 deletions
diff --git a/gdb/elfread.c b/gdb/elfread.c index 5be3118..3756fa3 100644 --- a/gdb/elfread.c +++ b/gdb/elfread.c @@ -1062,8 +1062,8 @@ elf_read_minimal_symbols (struct objfile *objfile, int symfile_flags, const struct elfinfo *ei) { bfd *synth_abfd, *abfd = objfile->obfd.get (); - long symcount = 0, dynsymcount = 0, synthcount, storage_needed; - asymbol **symbol_table = NULL, **dyn_symbol_table = NULL; + long dynsymcount = 0, synthcount; + asymbol **dyn_symbol_table = NULL; asymbol *synthsyms; symtab_create_debug_printf ("reading minimal symbols of objfile %s", @@ -1087,32 +1087,16 @@ elf_read_minimal_symbols (struct objfile *objfile, int symfile_flags, /* Process the normal ELF symbol table first. */ - storage_needed = bfd_get_symtab_upper_bound (objfile->obfd.get ()); - if (storage_needed < 0) - error (_("Can't read symbols from %s: %s"), - bfd_get_filename (objfile->obfd.get ()), - bfd_errmsg (bfd_get_error ())); + gdb::array_view<asymbol *> symbol_table + = gdb_bfd_canonicalize_symtab (objfile->obfd.get ()); - if (storage_needed > 0) - { - /* Memory gets permanently referenced from ABFD after - bfd_canonicalize_symtab so it must not get freed before ABFD gets. */ - - symbol_table = (asymbol **) bfd_alloc (abfd, storage_needed); - symcount = bfd_canonicalize_symtab (objfile->obfd.get (), symbol_table); - - if (symcount < 0) - error (_("Can't read symbols from %s: %s"), - bfd_get_filename (objfile->obfd.get ()), - bfd_errmsg (bfd_get_error ())); - - elf_symtab_read (reader, objfile, ST_REGULAR, symcount, symbol_table, - false); - } + elf_symtab_read (reader, objfile, ST_REGULAR, symbol_table.size (), + symbol_table.data (), false); /* Add the dynamic symbols. */ - storage_needed = bfd_get_dynamic_symtab_upper_bound (objfile->obfd.get ()); + long storage_needed + = bfd_get_dynamic_symtab_upper_bound (objfile->obfd.get ()); if (storage_needed > 0) { @@ -1157,7 +1141,8 @@ elf_read_minimal_symbols (struct objfile *objfile, int symfile_flags, /* Add synthetic symbols - for instance, names for any PLT entries. */ - synthcount = bfd_get_synthetic_symtab (synth_abfd, symcount, symbol_table, + synthcount = bfd_get_synthetic_symtab (synth_abfd, symbol_table.size (), + symbol_table.data (), dynsymcount, dyn_symbol_table, &synthsyms); if (synthcount > 0) |