diff options
Diffstat (limited to 'gdb/elfread.c')
-rw-r--r-- | gdb/elfread.c | 194 |
1 files changed, 152 insertions, 42 deletions
diff --git a/gdb/elfread.c b/gdb/elfread.c index 7a6a8ca..ae74978 100644 --- a/gdb/elfread.c +++ b/gdb/elfread.c @@ -1,6 +1,6 @@ /* Read ELF (Executable and Linking Format) object files for GDB. - Copyright (C) 1991-2024 Free Software Foundation, Inc. + Copyright (C) 1991-2025 Free Software Foundation, Inc. Written by Fred Fish at Cygnus Support. @@ -29,8 +29,6 @@ #include "symfile.h" #include "objfiles.h" #include "stabsread.h" -#include "demangle.h" -#include "filenames.h" #include "probe.h" #include "arch-utils.h" #include "gdbtypes.h" @@ -39,16 +37,15 @@ #include "gdbthread.h" #include "inferior.h" #include "regcache.h" -#include "bcache.h" #include "gdb_bfd.h" #include "location.h" #include "auxv.h" #include "mdebugread.h" #include "ctfread.h" #include <string_view> -#include "gdbsupport/scoped_fd.h" #include "dwarf2/public.h" #include "cli/cli-cmds.h" +#include "gdb-stabs.h" /* Whether ctf should always be read, or only if no dwarf is present. */ static bool always_read_ctf; @@ -595,7 +592,7 @@ elf_rel_plt_read (minimal_symbol_reader &reader, std::string string_buffer; /* Does ADDRESS reside in SECTION of OBFD? */ - auto within_section = [obfd] (asection *section, CORE_ADDR address) + auto within_section = [] (asection *section, CORE_ADDR address) { if (section == NULL) return false; @@ -615,6 +612,8 @@ elf_rel_plt_read (minimal_symbol_reader &reader, const size_t got_suffix_len = strlen (SYMBOL_GOT_PLT_SUFFIX); name = bfd_asymbol_name (*relplt->relocation[reloc].sym_ptr_ptr); + if (!name) + continue; address = relplt->relocation[reloc].address; asection *msym_section; @@ -694,13 +693,12 @@ elf_gnu_ifunc_cache_eq (const void *a_voidp, const void *b_voidp) static int elf_gnu_ifunc_record_cache (const char *name, CORE_ADDR addr) { - struct bound_minimal_symbol msym; struct objfile *objfile; htab_t htab; struct elf_gnu_ifunc_cache entry_local, *entry_p; void **slot; - msym = lookup_minimal_symbol_by_pc (addr); + bound_minimal_symbol msym = lookup_minimal_symbol_by_pc (addr); if (msym.minsym == NULL) return 0; if (msym.value_address () != addr) @@ -843,9 +841,10 @@ elf_gnu_ifunc_resolve_by_got (const char *name, CORE_ADDR *addr_p) CORE_ADDR pointer_address, addr; asection *plt; gdb_byte *buf = (gdb_byte *) alloca (ptr_size); - bound_minimal_symbol msym; - msym = lookup_minimal_symbol (name_got_plt, NULL, objfile); + bound_minimal_symbol msym + = lookup_minimal_symbol (current_program_space, name_got_plt, + objfile); if (msym.minsym == NULL) return 0; if (msym.minsym->type () != mst_slot_got_plt) @@ -899,7 +898,7 @@ elf_gnu_ifunc_resolve_name (const char *name, CORE_ADDR *addr_p) return false; } -/* Call STT_GNU_IFUNC - a function returning addresss of a real function to +/* Call STT_GNU_IFUNC - a function returning address of a real function to call. PC is theSTT_GNU_IFUNC resolving function entry. The value returned is the entry point of the resolved STT_GNU_IFUNC target function to call. */ @@ -977,7 +976,7 @@ elf_gnu_ifunc_resolver_stop (code_breakpoint *b) if (b_return == b) { /* No need to call find_pc_line for symbols resolving as this is only - a helper breakpointer never shown to the user. */ + a helper breakpoint never shown to the user. */ symtab_and_line sal; sal.pspace = current_inferior ()->pspace; @@ -1063,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", @@ -1088,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 ())); - - if (storage_needed > 0) - { - /* Memory gets permanently referenced from ABFD after - bfd_canonicalize_symtab so it must not get freed before ABFD gets. */ + gdb::array_view<asymbol *> symbol_table + = gdb_bfd_canonicalize_symtab (objfile->obfd.get ()); - 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) { @@ -1158,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) @@ -1225,6 +1209,134 @@ elf_symfile_read_dwarf2 (struct objfile *objfile, return has_dwarf2; } +/* find_text_range --- find start and end of loadable code sections + + The find_text_range function finds the shortest address range that + encloses all sections containing executable code, and stores it in + objfile's text_addr and text_size members. + + dbx_symfile_read will use this to finish off the partial symbol + table, in some cases. */ + +static void +find_text_range (bfd * sym_bfd, struct objfile *objfile) +{ + asection *sec; + int found_any = 0; + CORE_ADDR start = 0; + CORE_ADDR end = 0; + + for (sec = sym_bfd->sections; sec; sec = sec->next) + if (bfd_section_flags (sec) & SEC_CODE) + { + CORE_ADDR sec_start = bfd_section_vma (sec); + CORE_ADDR sec_end = sec_start + bfd_section_size (sec); + + if (found_any) + { + if (sec_start < start) + start = sec_start; + if (sec_end > end) + end = sec_end; + } + else + { + start = sec_start; + end = sec_end; + } + + found_any = 1; + } + + if (!found_any) + error (_("Can't find any code sections in symbol file")); + + DBX_TEXT_ADDR (objfile) = start; + DBX_TEXT_SIZE (objfile) = end - start; +} + +/* Scan and build partial symbols for an ELF symbol file. + This ELF file has already been processed to get its minimal symbols. + + This routine is the equivalent of dbx_symfile_init and dbx_symfile_read + rolled into one. + + OBJFILE is the object file we are reading symbols from. + ADDR is the address relative to which the symbols are (e.g. + the base address of the text segment). + STABSECT is the BFD section information for the .stab section. + STABSTROFFSET and STABSTRSIZE define the location in OBJFILE where the + .stabstr section exists. + + This routine is mostly copied from dbx_symfile_init and dbx_symfile_read, + adjusted for elf details. */ + +void +elfstab_build_psymtabs (struct objfile *objfile, asection *stabsect, + file_ptr stabstroffset, unsigned int stabstrsize) +{ + int val; + bfd *sym_bfd = objfile->obfd.get (); + const char *name = bfd_get_filename (sym_bfd); + + stabsread_new_init (); + + /* Allocate struct to keep track of stab reading. */ + dbx_objfile_data_key.emplace (objfile); + dbx_symfile_info *key = dbx_objfile_data_key.get (objfile); + + /* Find the first and last text address. dbx_symfile_read seems to + want this. */ + find_text_range (sym_bfd, objfile); + +#define ELF_STABS_SYMBOL_SIZE 12 /* XXX FIXME XXX */ + DBX_SYMBOL_SIZE (objfile) = ELF_STABS_SYMBOL_SIZE; + DBX_SYMCOUNT (objfile) + = bfd_section_size (stabsect) / DBX_SYMBOL_SIZE (objfile); + DBX_STRINGTAB_SIZE (objfile) = stabstrsize; + DBX_SYMTAB_OFFSET (objfile) = stabsect->filepos; + DBX_STAB_SECTION (objfile) = stabsect; + + if (stabstrsize > bfd_get_size (sym_bfd)) + error (_("ridiculous string table size: %d bytes"), stabstrsize); + DBX_STRINGTAB (objfile) = (char *) + obstack_alloc (&objfile->objfile_obstack, stabstrsize + 1); + OBJSTAT (objfile, sz_strtab += stabstrsize + 1); + + /* Now read in the string table in one big gulp. */ + + val = bfd_seek (sym_bfd, stabstroffset, SEEK_SET); + if (val < 0) + perror_with_name (name); + val = bfd_read (DBX_STRINGTAB (objfile), stabstrsize, sym_bfd); + if (val != stabstrsize) + perror_with_name (name); + + stabsread_new_init (); + free_header_files (); + init_header_files (); + + key->ctx.processing_acc_compilation = 1; + + key->ctx.symbuf_read = 0; + key->ctx.symbuf_left = bfd_section_size (stabsect); + + scoped_restore restore_stabs_data = make_scoped_restore (&key->ctx.stabs_data); + gdb::unique_xmalloc_ptr<gdb_byte> data_holder; + + key->ctx.stabs_data = symfile_relocate_debug_section (objfile, stabsect, NULL); + if (key->ctx.stabs_data) + data_holder.reset (key->ctx.stabs_data); + + /* In an elf file, we've already installed the minimal symbols that came + from the elf (non-stab) symbol table, so always act like an + incremental load here. dbx_symfile_read should not generate any new + minimal symbols, since we will have already read the ELF dynamic symbol + table and normal symbol entries won't be in the ".stab" section; but in + case it does, it will install them itself. */ + read_stabs_symtab (objfile, 0); +} + /* Scan and build partial symbols for a symbol file. We have been initialized by a call to elf_symfile_init, which currently does nothing. @@ -1401,9 +1513,7 @@ static const struct gnu_ifunc_fns elf_gnu_ifunc_fns = elf_gnu_ifunc_resolver_return_stop }; -void _initialize_elfread (); -void -_initialize_elfread () +INIT_GDB_FILE (elfread) { add_symtab_fns (bfd_target_elf_flavour, &elf_sym_fns); @@ -1416,8 +1526,8 @@ Set whether CTF is always read."), _("\ Show whether CTF is always read."), _("\ -When off, CTF is only read if DWARF is not present. When on, CTF is read\ - regardless of whether DWARF is present."), +When off, CTF is only read if DWARF is not present. When on, CTF is read\n\ +regardless of whether DWARF is present."), nullptr /* set_func */, nullptr /* show_func */, &setlist, &showlist); } |