/* Read ELF (Executable and Linking Format) object files for GDB.
- Copyright (C) 1991-2020 Free Software Foundation, Inc.
+ Copyright (C) 1991-2022 Free Software Foundation, Inc.
Written by Fred Fish at Cygnus Support.
#include "symfile.h"
#include "objfiles.h"
#include "stabsread.h"
-#include "complaints.h"
#include "demangle.h"
#include "psympriv.h"
#include "filenames.h"
#include "gdbsupport/gdb_string_view.h"
#include "gdbsupport/scoped_fd.h"
#include "debuginfod-support.h"
-
-/* Forward declarations. */
-extern const struct sym_fns elf_sym_fns_gdb_index;
-extern const struct sym_fns elf_sym_fns_debug_names;
-extern const struct sym_fns elf_sym_fns_lazy_psyms;
+#include "dwarf2/public.h"
/* The struct elfinfo is available only during ELF symbol table and
psymtab reading. It is destroyed at the completion of psymtab-reading.
/* Locate the segments in ABFD. */
-static struct symfile_segment_data *
+static symfile_segment_data_up
elf_symfile_segments (bfd *abfd)
{
Elf_Internal_Phdr *phdrs, **segments;
long phdrs_size;
int num_phdrs, num_segments, num_sections, i;
asection *sect;
- struct symfile_segment_data *data;
phdrs_size = bfd_get_elf_phdr_upper_bound (abfd);
if (phdrs_size == -1)
if (num_segments == 0)
return NULL;
- data = XCNEW (struct symfile_segment_data);
- data->num_segments = num_segments;
- data->segment_bases = XCNEWVEC (CORE_ADDR, num_segments);
- data->segment_sizes = XCNEWVEC (CORE_ADDR, num_segments);
+ symfile_segment_data_up data (new symfile_segment_data);
+ data->segments.reserve (num_segments);
for (i = 0; i < num_segments; i++)
- {
- data->segment_bases[i] = segments[i]->p_vaddr;
- data->segment_sizes[i] = segments[i]->p_memsz;
- }
+ data->segments.emplace_back (segments[i]->p_vaddr, segments[i]->p_memsz);
num_sections = bfd_count_sections (abfd);
- data->segment_info = XCNEWVEC (int, num_sections);
+
+ /* All elements are initialized to 0 (map to no segment). */
+ data->segment_info.resize (num_sections);
for (i = 0, sect = abfd->sections; sect != NULL; i++, sect = sect->next)
{
RealView) use SHT_NOBITS for uninitialized data. Since it is
uninitialized, it doesn't need a program header. Such
binaries are not relocatable. */
- if (bfd_section_size (sect) > 0 && j == num_segments
+
+ /* Exclude debuginfo files from this warning, too, since those
+ are often not strictly compliant with the standard. See, e.g.,
+ ld/24717 for more discussion. */
+ if (!is_debuginfo_file (abfd)
+ && bfd_section_size (sect) > 0 && j == num_segments
&& (bfd_section_flags (sect) & SEC_LOAD) != 0)
- warning (_("Loadable section \"%s\" outside of ELF segments"),
- bfd_section_name (sect));
+ warning (_("Loadable section \"%s\" outside of ELF segments\n in %s"),
+ bfd_section_name (sect), bfd_get_filename (abfd));
}
return data;
-kingdon). */
static void
-elf_locate_sections (bfd *ignore_abfd, asection *sectp, void *eip)
+elf_locate_sections (asection *sectp, struct elfinfo *ei)
{
- struct elfinfo *ei;
-
- ei = (struct elfinfo *) eip;
if (strcmp (sectp->name, ".stab") == 0)
{
ei->stabsect = sectp;
enum minimal_symbol_type ms_type,
asection *bfd_section, struct objfile *objfile)
{
- struct gdbarch *gdbarch = get_objfile_arch (objfile);
+ struct gdbarch *gdbarch = objfile->arch ();
if (ms_type == mst_text || ms_type == mst_file_text
|| ms_type == mst_text_gnu_ifunc)
long number_of_symbols, asymbol **symbol_table,
bool copy_names)
{
- struct gdbarch *gdbarch = get_objfile_arch (objfile);
+ struct gdbarch *gdbarch = objfile->arch ();
asymbol *sym;
long i;
CORE_ADDR symaddr;
continue;
}
+ elf_symbol_type *elf_sym = (elf_symbol_type *) sym;
+
/* Skip "special" symbols, e.g. ARM mapping symbols. These are
symbols which do not correspond to objects in the symbol table,
but have some other target-specific meaning. */
if (type == ST_DYNAMIC && !stripped)
continue;
if (sym->flags & BSF_FILE)
- {
- filesymname
- = ((const char *) objfile->per_bfd->filename_cache.insert
- (sym->name, strlen (sym->name) + 1));
- }
+ filesymname = objfile->intern (sym->name);
else if (sym->flags & BSF_SECTION_SYM)
continue;
else if (sym->flags & (BSF_GLOBAL | BSF_LOCAL | BSF_WEAK
NOTE: uweigand-20071112: Synthetic symbols do not
have an ELF-private part, so do not touch those. */
unsigned int shndx = type == ST_SYNTHETIC ? 0 :
- ((elf_symbol_type *) sym)->internal_elf_sym.st_shndx;
+ elf_sym->internal_elf_sym.st_shndx;
switch (shndx)
{
if (type != ST_SYNTHETIC)
{
/* Pass symbol size field in via BFD. FIXME!!! */
- elf_symbol_type *elf_sym = (elf_symbol_type *) sym;
SET_MSYMBOL_SIZE (msym, elf_sym->internal_elf_sym.st_size);
}
if (msym != NULL)
{
const char *atsign = strchr (sym->name, '@');
-
- if (atsign != NULL && atsign[1] == '@' && atsign > sym->name)
- {
- int len = atsign - sym->name;
-
- record_minimal_symbol (reader,
- gdb::string_view (sym->name, len),
- true, symaddr, ms_type, sym->section,
- objfile);
- }
- }
-
- /* For @plt symbols, also record a trampoline to the
- destination symbol. The @plt symbol will be used in
- disassembly, and the trampoline will be used when we are
- trying to find the target. */
- if (msym && ms_type == mst_text && type == ST_SYNTHETIC)
- {
- int len = strlen (sym->name);
-
- if (len > 4 && strcmp (sym->name + len - 4, "@plt") == 0)
+ bool is_at_symbol = atsign != nullptr && atsign > sym->name;
+ bool is_plt = is_at_symbol && strcmp (atsign, "@plt") == 0;
+ int len = is_at_symbol ? atsign - sym->name : 0;
+
+ if (is_at_symbol
+ && !is_plt
+ && (elf_sym->version & VERSYM_HIDDEN) == 0)
+ record_minimal_symbol (reader,
+ gdb::string_view (sym->name, len),
+ true, symaddr, ms_type, sym->section,
+ objfile);
+ else if (is_plt)
{
- struct minimal_symbol *mtramp;
-
- mtramp = record_minimal_symbol
- (reader, gdb::string_view (sym->name, len - 4), true,
- symaddr, mst_solib_trampoline, sym->section, objfile);
- if (mtramp)
+ /* For @plt symbols, also record a trampoline to the
+ destination symbol. The @plt symbol will be used
+ in disassembly, and the trampoline will be used
+ when we are trying to find the target. */
+ if (ms_type == mst_text && type == ST_SYNTHETIC)
{
- SET_MSYMBOL_SIZE (mtramp, MSYMBOL_SIZE (msym));
- mtramp->created_by_gdb = 1;
- mtramp->filename = filesymname;
- if (elf_make_msymbol_special_p)
- gdbarch_elf_make_msymbol_special (gdbarch,
- sym, mtramp);
+ struct minimal_symbol *mtramp;
+
+ mtramp = record_minimal_symbol
+ (reader, gdb::string_view (sym->name, len), true,
+ symaddr, mst_solib_trampoline, sym->section, objfile);
+ if (mtramp)
+ {
+ SET_MSYMBOL_SIZE (mtramp, MSYMBOL_SIZE (msym));
+ mtramp->created_by_gdb = 1;
+ mtramp->filename = filesymname;
+ if (elf_make_msymbol_special_p)
+ gdbarch_elf_make_msymbol_special (gdbarch,
+ sym, mtramp);
+ }
}
}
}
const struct elf_backend_data *bed = get_elf_backend_data (obfd);
asection *relplt, *got_plt;
bfd_size_type reloc_count, reloc;
- struct gdbarch *gdbarch = get_objfile_arch (objfile);
+ struct gdbarch *gdbarch = objfile->arch ();
struct type *ptr_type = builtin_type (gdbarch)->builtin_data_ptr;
size_t ptr_size = TYPE_LENGTH (ptr_type);
{
struct elf_gnu_ifunc_cache *entry_found_p
= (struct elf_gnu_ifunc_cache *) *slot;
- struct gdbarch *gdbarch = get_objfile_arch (objfile);
+ struct gdbarch *gdbarch = objfile->arch ();
if (entry_found_p->addr != addr)
{
for (objfile *objfile : current_program_space->objfiles ())
{
bfd *obfd = objfile->obfd;
- struct gdbarch *gdbarch = get_objfile_arch (objfile);
+ struct gdbarch *gdbarch = objfile->arch ();
struct type *ptr_type = builtin_type (gdbarch)->builtin_data_ptr;
size_t ptr_size = TYPE_LENGTH (ptr_type);
CORE_ADDR pointer_address, addr;
if (target_read_memory (pointer_address, buf, ptr_size) != 0)
continue;
addr = extract_typed_address (buf, ptr_type);
- addr = gdbarch_convert_from_func_ptr_addr (gdbarch, addr,
- current_top_target ());
+ addr = gdbarch_convert_from_func_ptr_addr
+ (gdbarch, addr, current_inferior ()->top_target ());
addr = gdbarch_addr_bits_remove (gdbarch, addr);
if (elf_gnu_ifunc_record_cache (name, addr))
parameter. FUNCTION is the function entry address. ADDRESS may be a
function descriptor. */
- target_auxv_search (current_top_target (), AT_HWCAP, &hwcap);
+ target_auxv_search (current_inferior ()->top_target (), AT_HWCAP, &hwcap);
hwcap_val = value_from_longest (builtin_type (gdbarch)
->builtin_unsigned_long, hwcap);
address_val = call_function_by_hand (function, NULL, hwcap_val);
address = value_as_address (address_val);
- address = gdbarch_convert_from_func_ptr_addr (gdbarch, address, current_top_target ());
+ address = gdbarch_convert_from_func_ptr_addr
+ (gdbarch, address, current_inferior ()->top_target ());
address = gdbarch_addr_bits_remove (gdbarch, address);
if (name_at_pc)
value = allocate_value (value_type);
gdbarch_return_value (gdbarch, func_func, value_type, regcache,
- value_contents_raw (value), NULL);
+ value_contents_raw (value).data (), NULL);
resolved_address = value_as_address (value);
- resolved_pc = gdbarch_convert_from_func_ptr_addr (gdbarch,
- resolved_address,
- current_top_target ());
+ resolved_pc = gdbarch_convert_from_func_ptr_addr
+ (gdbarch, resolved_address, current_inferior ()->top_target ());
resolved_pc = gdbarch_addr_bits_remove (gdbarch, resolved_pc);
gdb_assert (current_program_space == b->pspace || b->pspace == NULL);
memset ((char *) &ei, 0, sizeof (ei));
if (!(objfile->flags & OBJF_READNEVER))
- bfd_map_over_sections (abfd, elf_locate_sections, (void *) & ei);
+ {
+ for (asection *sect : gdb_bfd_sections (abfd))
+ elf_locate_sections (sect, &ei);
+ }
elf_read_minimal_symbols (objfile, symfile_flags, &ei);
const struct ecoff_debug_swap *swap;
/* .mdebug section, presumably holding ECOFF debugging
- information. */
+ information. */
swap = get_elf_backend_data (abfd)->elf_backend_ecoff_debug_swap;
if (swap)
elfmdebug_build_psymtabs (objfile, swap, ei.mdebugsect);
asection *str_sect;
/* Stab sections have an associated string table that looks like
- a separate section. */
+ a separate section. */
str_sect = bfd_get_section_by_name (abfd, ".stabstr");
/* FIXME should probably warn about a stab section without a stabstr. */
}
if (dwarf2_has_info (objfile, NULL, true))
- {
- dw_index_kind index_kind;
-
- /* elf_sym_fns_gdb_index cannot handle simultaneous non-DWARF
- debug information present in OBJFILE. If there is such debug
- info present never use an index. */
- if (!objfile_has_partial_symbols (objfile)
- && dwarf2_initialize_objfile (objfile, &index_kind))
- {
- switch (index_kind)
- {
- case dw_index_kind::GDB_INDEX:
- objfile_set_sym_fns (objfile, &elf_sym_fns_gdb_index);
- break;
- case dw_index_kind::DEBUG_NAMES:
- objfile_set_sym_fns (objfile, &elf_sym_fns_debug_names);
- break;
- }
- }
- else
- {
- /* It is ok to do this even if the stabs reader made some
- partial symbols, because OBJF_PSYMTABS_READ has not been
- set, and so our lazy reader function will still be called
- when needed. */
- objfile_set_sym_fns (objfile, &elf_sym_fns_lazy_psyms);
- }
- }
+ dwarf2_initialize_objfile (objfile);
/* If the file has its own symbol tables it has no separate debug
info. `.dynsym'/`.symtab' go to MSYMBOLS, `.debug_info' goes to
SYMTABS/PSYMTABS. `.gnu_debuglink' may no longer be present with
`.note.gnu.build-id'.
- .gnu_debugdata is !objfile_has_partial_symbols because it contains only
+ .gnu_debugdata is !objfile::has_partial_symbols because it contains only
.symtab, not .debug_* section. But if we already added .gnu_debugdata as
an objfile via find_separate_debug_file_in_section there was no separate
debug info available. Therefore do not attempt to search for another one,
objfile->separate_debug_objfile->separate_debug_objfile GDB guarantees to
be NULL and we would possibly violate it. */
- else if (!objfile_has_partial_symbols (objfile)
+ else if (!objfile->has_partial_symbols ()
&& objfile->separate_debug_objfile == NULL
&& objfile->separate_debug_objfile_backlink == NULL)
{
}
}
-/* Callback to lazily read psymtabs. */
-
-static void
-read_psyms (struct objfile *objfile)
-{
- if (dwarf2_has_info (objfile, NULL))
- dwarf2_build_psymtabs (objfile);
-}
-
/* Initialize anything that needs initializing when a completely new symbol
file is specified (not just adding some symbols from another file, e.g. a
shared library). */
elf_new_init, /* init anything gbl to entire symtab */
elf_symfile_init, /* read initial info, setup for sym_read() */
elf_symfile_read, /* read a symbol file into symtab */
- NULL, /* sym_read_psymbols */
- elf_symfile_finish, /* finished with file, cleanup */
- default_symfile_offsets, /* Translate ext. to int. relocation */
- elf_symfile_segments, /* Get segment information from a file. */
- NULL,
- default_symfile_relocate, /* Relocate a debug section. */
- &elf_probe_fns, /* sym_probe_fns */
- &psym_functions
-};
-
-/* The same as elf_sym_fns, but not registered and lazily reads
- psymbols. */
-
-const struct sym_fns elf_sym_fns_lazy_psyms =
-{
- elf_new_init, /* init anything gbl to entire symtab */
- elf_symfile_init, /* read initial info, setup for sym_read() */
- elf_symfile_read, /* read a symbol file into symtab */
- read_psyms, /* sym_read_psymbols */
- elf_symfile_finish, /* finished with file, cleanup */
- default_symfile_offsets, /* Translate ext. to int. relocation */
- elf_symfile_segments, /* Get segment information from a file. */
- NULL,
- default_symfile_relocate, /* Relocate a debug section. */
- &elf_probe_fns, /* sym_probe_fns */
- &psym_functions
-};
-
-/* The same as elf_sym_fns, but not registered and uses the
- DWARF-specific GNU index rather than psymtab. */
-const struct sym_fns elf_sym_fns_gdb_index =
-{
- elf_new_init, /* init anything gbl to entire symab */
- elf_symfile_init, /* read initial info, setup for sym_red() */
- elf_symfile_read, /* read a symbol file into symtab */
- NULL, /* sym_read_psymbols */
- elf_symfile_finish, /* finished with file, cleanup */
- default_symfile_offsets, /* Translate ext. to int. relocation */
- elf_symfile_segments, /* Get segment information from a file. */
- NULL,
- default_symfile_relocate, /* Relocate a debug section. */
- &elf_probe_fns, /* sym_probe_fns */
- &dwarf2_gdb_index_functions
-};
-
-/* The same as elf_sym_fns, but not registered and uses the
- DWARF-specific .debug_names index rather than psymtab. */
-const struct sym_fns elf_sym_fns_debug_names =
-{
- elf_new_init, /* init anything gbl to entire symab */
- elf_symfile_init, /* read initial info, setup for sym_red() */
- elf_symfile_read, /* read a symbol file into symtab */
- NULL, /* sym_read_psymbols */
elf_symfile_finish, /* finished with file, cleanup */
default_symfile_offsets, /* Translate ext. to int. relocation */
elf_symfile_segments, /* Get segment information from a file. */
NULL,
default_symfile_relocate, /* Relocate a debug section. */
&elf_probe_fns, /* sym_probe_fns */
- &dwarf2_debug_names_functions
};
/* STT_GNU_IFUNC resolver vector to be installed to gnu_ifunc_fns_p. */