/* Read ELF (Executable and Linking Format) object files for GDB.
- Copyright (C) 1991-2014 Free Software Foundation, Inc.
+ Copyright (C) 1991-2020 Free Software Foundation, Inc.
Written by Fred Fish at Cygnus Support.
#include "symtab.h"
#include "symfile.h"
#include "objfiles.h"
-#include "buildsym.h"
#include "stabsread.h"
-#include "gdb-stabs.h"
#include "complaints.h"
#include "demangle.h"
#include "psympriv.h"
#include "value.h"
#include "infcall.h"
#include "gdbthread.h"
+#include "inferior.h"
#include "regcache.h"
#include "bcache.h"
#include "gdb_bfd.h"
#include "build-id.h"
-
-extern void _initialize_elfread (void);
+#include "location.h"
+#include "auxv.h"
+#include "mdebugread.h"
+#include "ctfread.h"
+#include "gdbsupport/gdb_string_view.h"
/* Forward declarations. */
-static const struct sym_fns elf_sym_fns_gdb_index;
-static const struct sym_fns elf_sym_fns_lazy_psyms;
+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;
/* The struct elfinfo is available only during ELF symbol table and
psymtab reading. It is destroyed at the completion of psymtab-reading.
{
asection *stabsect; /* Section pointer for .stab section */
asection *mdebugsect; /* Section pointer for .mdebug section */
+ asection *ctfsect; /* Section pointer for .ctf section */
};
-/* Per-BFD data for probe info. */
+/* Type for per-BFD data. */
-static const struct bfd_data *probe_key = NULL;
+typedef std::vector<std::unique_ptr<probe>> elfread_data;
+
+/* Per-BFD data for probe info. */
-static void free_elfinfo (void *);
+static const struct bfd_key<elfread_data> probe_key;
/* Minimal symbols located at the GOT entries for .plt - that is the real
pointer where the given entry will jump to. It gets updated by the real
if (phdrs_size == -1)
return NULL;
- phdrs = alloca (phdrs_size);
+ phdrs = (Elf_Internal_Phdr *) alloca (phdrs_size);
num_phdrs = bfd_get_elf_phdrs (abfd, phdrs);
if (num_phdrs == -1)
return NULL;
num_segments = 0;
- segments = alloca (sizeof (Elf_Internal_Phdr *) * num_phdrs);
+ segments = XALLOCAVEC (Elf_Internal_Phdr *, num_phdrs);
for (i = 0; i < num_phdrs; i++)
if (phdrs[i].p_type == PT_LOAD)
segments[num_segments++] = &phdrs[i];
for (i = 0, sect = abfd->sections; sect != NULL; i++, sect = sect->next)
{
int j;
- CORE_ADDR vma;
- if ((bfd_get_section_flags (abfd, sect) & SEC_ALLOC) == 0)
+ if ((bfd_section_flags (sect) & SEC_ALLOC) == 0)
continue;
- vma = bfd_get_section_vma (abfd, sect);
+ Elf_Internal_Shdr *this_hdr = &elf_section_data (sect)->this_hdr;
for (j = 0; j < num_segments; j++)
- if (segments[j]->p_memsz > 0
- && vma >= segments[j]->p_vaddr
- && (vma - segments[j]->p_vaddr) < segments[j]->p_memsz)
+ if (ELF_SECTION_IN_SEGMENT (this_hdr, segments[j]))
{
data->segment_info[i] = j + 1;
break;
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_get_section_size (sect) > 0 && j == num_segments
- && (bfd_get_section_flags (abfd, sect) & SEC_LOAD) != 0)
+ if (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 (abfd, sect));
+ bfd_section_name (sect));
}
return data;
{
ei->mdebugsect = sectp;
}
+ else if (strcmp (sectp->name, ".ctf") == 0)
+ {
+ ei->ctfsect = sectp;
+ }
}
static struct minimal_symbol *
-record_minimal_symbol (const char *name, int name_len, int copy_name,
+record_minimal_symbol (minimal_symbol_reader &reader,
+ gdb::string_view name, bool copy_name,
CORE_ADDR address,
enum minimal_symbol_type ms_type,
asection *bfd_section, struct objfile *objfile)
|| ms_type == mst_text_gnu_ifunc)
address = gdbarch_addr_bits_remove (gdbarch, address);
- return prim_record_minimal_symbol_full (name, name_len, copy_name, address,
- ms_type,
- gdb_bfd_section_index (objfile->obfd,
- bfd_section),
- objfile);
+ struct minimal_symbol *result
+ = reader.record_full (name, copy_name, address,
+ ms_type,
+ gdb_bfd_section_index (objfile->obfd,
+ bfd_section));
+ if ((objfile->flags & OBJF_MAINLINE) == 0
+ && (ms_type == mst_data || ms_type == mst_bss))
+ result->maybe_copied = 1;
+
+ return result;
}
/* Read the symbol table of an ELF file.
#define ST_SYNTHETIC 2
static void
-elf_symtab_read (struct objfile *objfile, int type,
+elf_symtab_read (minimal_symbol_reader &reader,
+ struct objfile *objfile, int type,
long number_of_symbols, asymbol **symbol_table,
- int copy_names)
+ bool copy_names)
{
struct gdbarch *gdbarch = get_objfile_arch (objfile);
asymbol *sym;
long i;
CORE_ADDR symaddr;
- CORE_ADDR offset;
enum minimal_symbol_type ms_type;
- /* If sectinfo is nonNULL, it contains section info that should end up
- filed in the objfile. */
- struct stab_section_info *sectinfo = NULL;
- /* If filesym is nonzero, it points to a file symbol, but we haven't
- seen any section info for it yet. */
- asymbol *filesym = 0;
- /* Name of filesym. This is either a constant string or is saved on
- the objfile's filename cache. */
+ /* Name of the last file symbol. This is either a constant string or is
+ saved on the objfile's filename cache. */
const char *filesymname = "";
- struct dbx_symfile_info *dbx = DBX_SYMFILE_INFO (objfile);
int stripped = (bfd_get_symcount (objfile->obfd) == 0);
int elf_make_msymbol_special_p
= gdbarch_elf_make_msymbol_special_p (gdbarch);
continue;
}
- offset = ANOFFSET (objfile->section_offsets,
- gdb_bfd_section_index (objfile->obfd, sym->section));
if (type == ST_DYNAMIC
&& sym->section == bfd_und_section_ptr
&& (sym->flags & BSF_FUNCTION))
covers the stub's address. */
for (sect = abfd->sections; sect != NULL; sect = sect->next)
{
- if ((bfd_get_section_flags (abfd, sect) & SEC_ALLOC) == 0)
+ if ((bfd_section_flags (sect) & SEC_ALLOC) == 0)
continue;
- if (symaddr >= bfd_get_section_vma (abfd, sect)
- && symaddr < bfd_get_section_vma (abfd, sect)
- + bfd_get_section_size (sect))
+ if (symaddr >= bfd_section_vma (sect)
+ && symaddr < bfd_section_vma (sect)
+ + bfd_section_size (sect))
break;
}
if (!sect)
for that section is ".plt". So, if there is a ".plt"
section, and yet the section name of our symbol does not
start with ".plt", we ignore that symbol. */
- if (strncmp (sect->name, ".plt", 4) != 0
+ if (!startswith (sect->name, ".plt")
&& bfd_get_section_by_name (abfd, ".plt") != NULL)
continue;
msym = record_minimal_symbol
- (sym->name, strlen (sym->name), copy_names,
+ (reader, sym->name, copy_names,
symaddr, mst_solib_trampoline, sect, objfile);
if (msym != NULL)
{
continue;
if (sym->flags & BSF_FILE)
{
- /* STT_FILE debugging symbol that helps stabs-in-elf debugging.
- Chain any old one onto the objfile; remember new sym. */
- if (sectinfo != NULL)
- {
- sectinfo->next = dbx->stab_section_info;
- dbx->stab_section_info = sectinfo;
- sectinfo = NULL;
- }
- filesym = sym;
- filesymname = bcache (filesym->name, strlen (filesym->name) + 1,
- objfile->per_bfd->filename_cache);
+ filesymname
+ = ((const char *) objfile->per_bfd->filename_cache.insert
+ (sym->name, strlen (sym->name) + 1));
}
else if (sym->flags & BSF_SECTION_SYM)
continue;
{
if (sym->flags & (BSF_GLOBAL | BSF_WEAK | BSF_GNU_UNIQUE))
{
- if (sym->section->flags & SEC_LOAD)
+ if (sym->flags & BSF_GNU_INDIRECT_FUNCTION)
+ {
+ ms_type = mst_data_gnu_ifunc;
+ }
+ else if (sym->section->flags & SEC_LOAD)
{
ms_type = mst_data;
}
}
else if (sym->flags & BSF_LOCAL)
{
- /* Named Local variable in a Data section.
- Check its name for stabs-in-elf. */
- int special_local_sect;
-
- if (strcmp ("Bbss.bss", sym->name) == 0)
- special_local_sect = SECT_OFF_BSS (objfile);
- else if (strcmp ("Ddata.data", sym->name) == 0)
- special_local_sect = SECT_OFF_DATA (objfile);
- else if (strcmp ("Drodata.rodata", sym->name) == 0)
- special_local_sect = SECT_OFF_RODATA (objfile);
- else
- special_local_sect = -1;
- if (special_local_sect >= 0)
- {
- /* Found a special local symbol. Allocate a
- sectinfo, if needed, and fill it in. */
- if (sectinfo == NULL)
- {
- int max_index;
- size_t size;
-
- max_index = SECT_OFF_BSS (objfile);
- if (objfile->sect_index_data > max_index)
- max_index = objfile->sect_index_data;
- if (objfile->sect_index_rodata > max_index)
- max_index = objfile->sect_index_rodata;
-
- /* max_index is the largest index we'll
- use into this array, so we must
- allocate max_index+1 elements for it.
- However, 'struct stab_section_info'
- already includes one element, so we
- need to allocate max_index aadditional
- elements. */
- size = (sizeof (struct stab_section_info)
- + (sizeof (CORE_ADDR) * max_index));
- sectinfo = (struct stab_section_info *)
- xmalloc (size);
- memset (sectinfo, 0, size);
- sectinfo->num_sections = max_index;
- if (filesym == NULL)
- {
- complaint (&symfile_complaints,
- _("elf/stab section information %s "
- "without a preceding file symbol"),
- sym->name);
- }
- else
- {
- sectinfo->filename =
- (char *) filesym->name;
- }
- }
- if (sectinfo->sections[special_local_sect] != 0)
- complaint (&symfile_complaints,
- _("duplicated elf/stab section "
- "information for %s"),
- sectinfo->filename);
- /* BFD symbols are section relative. */
- symaddr = sym->value + sym->section->vma;
- /* Relocate non-absolute symbols by the
- section offset. */
- if (sym->section != bfd_abs_section_ptr)
- symaddr += offset;
- sectinfo->sections[special_local_sect] = symaddr;
- /* The special local symbols don't go in the
- minimal symbol table, so ignore this one. */
- continue;
- }
- /* Not a special stabs-in-elf symbol, do regular
- symbol processing. */
if (sym->section->flags & SEC_LOAD)
{
ms_type = mst_file_data;
continue; /* Skip this symbol. */
}
msym = record_minimal_symbol
- (sym->name, strlen (sym->name), copy_names, symaddr,
+ (reader, sym->name, copy_names, symaddr,
ms_type, sym->section, objfile);
if (msym)
{
int len = atsign - sym->name;
- record_minimal_symbol (sym->name, len, 1, symaddr,
- ms_type, sym->section, objfile);
+ record_minimal_symbol (reader,
+ gdb::string_view (sym->name, len),
+ true, symaddr, ms_type, sym->section,
+ objfile);
}
}
{
struct minimal_symbol *mtramp;
- mtramp = record_minimal_symbol (sym->name, len - 4, 1,
- symaddr,
- mst_solib_trampoline,
- sym->section, objfile);
+ mtramp = record_minimal_symbol
+ (reader, gdb::string_view (sym->name, len - 4), true,
+ symaddr, mst_solib_trampoline, sym->section, objfile);
if (mtramp)
{
SET_MSYMBOL_SIZE (mtramp, MSYMBOL_SIZE (msym));
DYN_SYMBOL_TABLE is no longer easily available for OBJFILE. */
static void
-elf_rel_plt_read (struct objfile *objfile, asymbol **dyn_symbol_table)
+elf_rel_plt_read (minimal_symbol_reader &reader,
+ struct objfile *objfile, asymbol **dyn_symbol_table)
{
bfd *obfd = objfile->obfd;
const struct elf_backend_data *bed = get_elf_backend_data (obfd);
- asection *plt, *relplt, *got_plt;
- int plt_elf_idx;
+ asection *relplt, *got_plt;
bfd_size_type reloc_count, reloc;
- char *string_buffer = NULL;
- size_t string_buffer_size = 0;
- struct cleanup *back_to;
struct gdbarch *gdbarch = get_objfile_arch (objfile);
struct type *ptr_type = builtin_type (gdbarch)->builtin_data_ptr;
size_t ptr_size = TYPE_LENGTH (ptr_type);
if (objfile->separate_debug_objfile_backlink)
return;
- plt = bfd_get_section_by_name (obfd, ".plt");
- if (plt == NULL)
- return;
- plt_elf_idx = elf_section_data (plt)->this_idx;
-
got_plt = bfd_get_section_by_name (obfd, ".got.plt");
if (got_plt == NULL)
{
return;
}
+ /* Depending on system, we may find jump slots in a relocation
+ section for either .got.plt or .plt. */
+ asection *plt = bfd_get_section_by_name (obfd, ".plt");
+ int plt_elf_idx = (plt != NULL) ? elf_section_data (plt)->this_idx : -1;
+
+ int got_plt_elf_idx = elf_section_data (got_plt)->this_idx;
+
/* This search algorithm is from _bfd_elf_canonicalize_dynamic_reloc. */
for (relplt = obfd->sections; relplt != NULL; relplt = relplt->next)
- if (elf_section_data (relplt)->this_hdr.sh_info == plt_elf_idx
- && (elf_section_data (relplt)->this_hdr.sh_type == SHT_REL
- || elf_section_data (relplt)->this_hdr.sh_type == SHT_RELA))
- break;
+ {
+ const auto &this_hdr = elf_section_data (relplt)->this_hdr;
+
+ if (this_hdr.sh_type == SHT_REL || this_hdr.sh_type == SHT_RELA)
+ {
+ if (this_hdr.sh_info == plt_elf_idx
+ || this_hdr.sh_info == got_plt_elf_idx)
+ break;
+ }
+ }
if (relplt == NULL)
return;
if (! bed->s->slurp_reloc_table (obfd, relplt, dyn_symbol_table, TRUE))
return;
- back_to = make_cleanup (free_current_contents, &string_buffer);
+ std::string string_buffer;
+
+ /* Does ADDRESS reside in SECTION of OBFD? */
+ auto within_section = [obfd] (asection *section, CORE_ADDR address)
+ {
+ if (section == NULL)
+ return false;
+
+ return (bfd_section_vma (section) <= address
+ && (address < bfd_section_vma (section)
+ + bfd_section_size (section)));
+ };
reloc_count = relplt->size / elf_section_data (relplt)->this_hdr.sh_entsize;
for (reloc = 0; reloc < reloc_count; reloc++)
const char *name;
struct minimal_symbol *msym;
CORE_ADDR address;
+ const char *got_suffix = SYMBOL_GOT_PLT_SUFFIX;
const size_t got_suffix_len = strlen (SYMBOL_GOT_PLT_SUFFIX);
- size_t name_len;
name = bfd_asymbol_name (*relplt->relocation[reloc].sym_ptr_ptr);
- name_len = strlen (name);
address = relplt->relocation[reloc].address;
- /* Does the pointer reside in the .got.plt section? */
- if (!(bfd_get_section_vma (obfd, got_plt) <= address
- && address < bfd_get_section_vma (obfd, got_plt)
- + bfd_get_section_size (got_plt)))
+ asection *msym_section;
+
+ /* Does the pointer reside in either the .got.plt or .plt
+ sections? */
+ if (within_section (got_plt, address))
+ msym_section = got_plt;
+ else if (within_section (plt, address))
+ msym_section = plt;
+ else
continue;
- /* We cannot check if NAME is a reference to mst_text_gnu_ifunc as in
- OBJFILE the symbol is undefined and the objfile having NAME defined
- may not yet have been loaded. */
+ /* We cannot check if NAME is a reference to
+ mst_text_gnu_ifunc/mst_data_gnu_ifunc as in OBJFILE the
+ symbol is undefined and the objfile having NAME defined may
+ not yet have been loaded. */
- if (string_buffer_size < name_len + got_suffix_len + 1)
- {
- string_buffer_size = 2 * (name_len + got_suffix_len);
- string_buffer = xrealloc (string_buffer, string_buffer_size);
- }
- memcpy (string_buffer, name, name_len);
- memcpy (&string_buffer[name_len], SYMBOL_GOT_PLT_SUFFIX,
- got_suffix_len + 1);
+ string_buffer.assign (name);
+ string_buffer.append (got_suffix, got_suffix + got_suffix_len);
- msym = record_minimal_symbol (string_buffer, name_len + got_suffix_len,
- 1, address, mst_slot_got_plt, got_plt,
- objfile);
+ msym = record_minimal_symbol (reader, string_buffer,
+ true, address, mst_slot_got_plt,
+ msym_section, objfile);
if (msym)
SET_MSYMBOL_SIZE (msym, ptr_size);
}
-
- do_cleanups (back_to);
}
/* The data pointer is htab_t for gnu_ifunc_record_cache_unchecked. */
-static const struct objfile_data *elf_objfile_gnu_ifunc_cache_data;
+static const struct objfile_key<htab, htab_deleter>
+ elf_objfile_gnu_ifunc_cache_data;
/* Map function names to CORE_ADDR in elf_objfile_gnu_ifunc_cache_data. */
static hashval_t
elf_gnu_ifunc_cache_hash (const void *a_voidp)
{
- const struct elf_gnu_ifunc_cache *a = a_voidp;
+ const struct elf_gnu_ifunc_cache *a
+ = (const struct elf_gnu_ifunc_cache *) a_voidp;
return htab_hash_string (a->name);
}
static int
elf_gnu_ifunc_cache_eq (const void *a_voidp, const void *b_voidp)
{
- const struct elf_gnu_ifunc_cache *a = a_voidp;
- const struct elf_gnu_ifunc_cache *b = b_voidp;
+ const struct elf_gnu_ifunc_cache *a
+ = (const struct elf_gnu_ifunc_cache *) a_voidp;
+ const struct elf_gnu_ifunc_cache *b
+ = (const struct elf_gnu_ifunc_cache *) b_voidp;
return strcmp (a->name, b->name) == 0;
}
elf_gnu_ifunc_record_cache (const char *name, CORE_ADDR addr)
{
struct bound_minimal_symbol msym;
- asection *sect;
struct objfile *objfile;
htab_t htab;
struct elf_gnu_ifunc_cache entry_local, *entry_p;
return 0;
if (BMSYMBOL_VALUE_ADDRESS (msym) != addr)
return 0;
- /* minimal symbols have always SYMBOL_OBJ_SECTION non-NULL. */
- sect = MSYMBOL_OBJ_SECTION (msym.objfile, msym.minsym)->the_bfd_section;
objfile = msym.objfile;
/* If .plt jumps back to .plt the symbol is still deferred for later
- resolution and it has no use for GDB. Besides ".text" this symbol can
- reside also in ".opd" for ppc64 function descriptor. */
- if (strcmp (bfd_get_section_name (objfile->obfd, sect), ".plt") == 0)
+ resolution and it has no use for GDB. */
+ const char *target_name = msym.minsym->linkage_name ();
+ size_t len = strlen (target_name);
+
+ /* Note we check the symbol's name instead of checking whether the
+ symbol is in the .plt section because some systems have @plt
+ symbols in the .text section. */
+ if (len > 4 && strcmp (target_name + len - 4, "@plt") == 0)
return 0;
- htab = objfile_data (objfile, elf_objfile_gnu_ifunc_cache_data);
+ htab = elf_objfile_gnu_ifunc_cache_data.get (objfile);
if (htab == NULL)
{
- htab = htab_create_alloc_ex (1, elf_gnu_ifunc_cache_hash,
- elf_gnu_ifunc_cache_eq,
- NULL, &objfile->objfile_obstack,
- hashtab_obstack_allocate,
- dummy_obstack_deallocate);
- set_objfile_data (objfile, elf_objfile_gnu_ifunc_cache_data, htab);
+ htab = htab_create_alloc (1, elf_gnu_ifunc_cache_hash,
+ elf_gnu_ifunc_cache_eq,
+ NULL, xcalloc, xfree);
+ elf_objfile_gnu_ifunc_cache_data.set (objfile, htab);
}
entry_local.addr = addr;
obstack_grow (&objfile->objfile_obstack, &entry_local,
offsetof (struct elf_gnu_ifunc_cache, name));
obstack_grow_str0 (&objfile->objfile_obstack, name);
- entry_p = obstack_finish (&objfile->objfile_obstack);
+ entry_p
+ = (struct elf_gnu_ifunc_cache *) obstack_finish (&objfile->objfile_obstack);
slot = htab_find_slot (htab, entry_p, INSERT);
if (*slot != NULL)
{
- struct elf_gnu_ifunc_cache *entry_found_p = *slot;
+ struct elf_gnu_ifunc_cache *entry_found_p
+ = (struct elf_gnu_ifunc_cache *) *slot;
struct gdbarch *gdbarch = get_objfile_arch (objfile);
if (entry_found_p->addr != addr)
static int
elf_gnu_ifunc_resolve_by_cache (const char *name, CORE_ADDR *addr_p)
{
- struct objfile *objfile;
-
- ALL_PSPACE_OBJFILES (current_program_space, objfile)
+ for (objfile *objfile : current_program_space->objfiles ())
{
htab_t htab;
struct elf_gnu_ifunc_cache *entry_p;
void **slot;
- htab = objfile_data (objfile, elf_objfile_gnu_ifunc_cache_data);
+ htab = elf_objfile_gnu_ifunc_cache_data.get (objfile);
if (htab == NULL)
continue;
- entry_p = alloca (sizeof (*entry_p) + strlen (name));
+ entry_p = ((struct elf_gnu_ifunc_cache *)
+ alloca (sizeof (*entry_p) + strlen (name)));
strcpy (entry_p->name, name);
slot = htab_find_slot (htab, entry_p, NO_INSERT);
if (slot == NULL)
continue;
- entry_p = *slot;
+ entry_p = (struct elf_gnu_ifunc_cache *) *slot;
gdb_assert (entry_p != NULL);
if (addr_p)
elf_gnu_ifunc_resolve_by_got (const char *name, CORE_ADDR *addr_p)
{
char *name_got_plt;
- struct objfile *objfile;
const size_t got_suffix_len = strlen (SYMBOL_GOT_PLT_SUFFIX);
- name_got_plt = alloca (strlen (name) + got_suffix_len + 1);
+ name_got_plt = (char *) alloca (strlen (name) + got_suffix_len + 1);
sprintf (name_got_plt, "%s" SYMBOL_GOT_PLT_SUFFIX, name);
- ALL_PSPACE_OBJFILES (current_program_space, objfile)
+ for (objfile *objfile : current_program_space->objfiles ())
{
bfd *obfd = objfile->obfd;
struct gdbarch *gdbarch = get_objfile_arch (objfile);
size_t ptr_size = TYPE_LENGTH (ptr_type);
CORE_ADDR pointer_address, addr;
asection *plt;
- gdb_byte *buf = alloca (ptr_size);
+ gdb_byte *buf = (gdb_byte *) alloca (ptr_size);
struct bound_minimal_symbol msym;
msym = lookup_minimal_symbol (name_got_plt, NULL, objfile);
continue;
addr = extract_typed_address (buf, ptr_type);
addr = gdbarch_convert_from_func_ptr_addr (gdbarch, addr,
- ¤t_target);
+ current_top_target ());
addr = gdbarch_addr_bits_remove (gdbarch, addr);
- if (addr_p)
- *addr_p = addr;
if (elf_gnu_ifunc_record_cache (name, addr))
- return 1;
+ {
+ if (addr_p != NULL)
+ *addr_p = addr;
+ return 1;
+ }
}
return 0;
/* Try to find the target resolved function entry address of a STT_GNU_IFUNC
function NAME. If the address is found it is stored to *ADDR_P (if ADDR_P
- is not NULL) and the function returns 1. It returns 0 otherwise.
+ is not NULL) and the function returns true. It returns false otherwise.
Both the elf_objfile_gnu_ifunc_cache_data hash table and
SYMBOL_GOT_PLT_SUFFIX locations are searched by this function. */
-static int
+static bool
elf_gnu_ifunc_resolve_name (const char *name, CORE_ADDR *addr_p)
{
if (elf_gnu_ifunc_resolve_by_cache (name, addr_p))
- return 1;
+ return true;
if (elf_gnu_ifunc_resolve_by_got (name, addr_p))
- return 1;
+ return true;
- return 0;
+ return false;
}
/* Call STT_GNU_IFUNC - a function returning addresss of a real function to
CORE_ADDR start_at_pc, address;
struct type *func_func_type = builtin_type (gdbarch)->builtin_func_func;
struct value *function, *address_val;
+ CORE_ADDR hwcap = 0;
+ struct value *hwcap_val;
/* Try first any non-intrusive methods without an inferior call. */
name_at_pc = NULL;
function = allocate_value (func_func_type);
+ VALUE_LVAL (function) = lval_memory;
set_value_address (function, pc);
- /* STT_GNU_IFUNC resolver functions have no parameters. FUNCTION is the
- function entry address. ADDRESS may be a function descriptor. */
+ /* STT_GNU_IFUNC resolver functions usually receive the HWCAP vector as
+ parameter. FUNCTION is the function entry address. ADDRESS may be a
+ function descriptor. */
- address_val = call_function_by_hand (function, 0, NULL);
+ target_auxv_search (current_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,
- ¤t_target);
+ address = gdbarch_convert_from_func_ptr_addr (gdbarch, address, current_top_target ());
address = gdbarch_addr_bits_remove (gdbarch, address);
if (name_at_pc)
struct frame_info *prev_frame = get_prev_frame (get_current_frame ());
struct frame_id prev_frame_id = get_stack_frame_id (prev_frame);
CORE_ADDR prev_pc = get_frame_pc (prev_frame);
- int thread_id = pid_to_thread_id (inferior_ptid);
+ int thread_id = inferior_thread ()->global_num;
gdb_assert (b->type == bp_gnu_ifunc_resolver);
if (b_return == b)
{
- struct symtab_and_line sal;
-
/* No need to call find_pc_line for symbols resolving as this is only
a helper breakpointer never shown to the user. */
- init_sal (&sal);
+ symtab_and_line sal;
sal.pspace = current_inferior ()->pspace;
sal.pc = prev_pc;
sal.section = find_pc_overlay (sal.pc);
sal.explicit_pc = 1;
- b_return = set_momentary_breakpoint (get_frame_arch (prev_frame), sal,
- prev_frame_id,
- bp_gnu_ifunc_resolver_return);
+ b_return
+ = set_momentary_breakpoint (get_frame_arch (prev_frame), sal,
+ prev_frame_id,
+ bp_gnu_ifunc_resolver_return).release ();
/* set_momentary_breakpoint invalidates PREV_FRAME. */
prev_frame = NULL;
static void
elf_gnu_ifunc_resolver_return_stop (struct breakpoint *b)
{
+ thread_info *thread = inferior_thread ();
struct gdbarch *gdbarch = get_frame_arch (get_current_frame ());
struct type *func_func_type = builtin_type (gdbarch)->builtin_func_func;
struct type *value_type = TYPE_TARGET_TYPE (func_func_type);
- struct regcache *regcache = get_thread_regcache (inferior_ptid);
+ struct regcache *regcache = get_thread_regcache (thread);
struct value *func_func;
struct value *value;
CORE_ADDR resolved_address, resolved_pc;
- struct symtab_and_line sal;
- struct symtabs_and_lines sals, sals_end;
gdb_assert (b->type == bp_gnu_ifunc_resolver_return);
gdb_assert (b->loc->next == NULL);
func_func = allocate_value (func_func_type);
+ VALUE_LVAL (func_func) = lval_memory;
set_value_address (func_func, b->loc->related_address);
value = allocate_value (value_type);
resolved_address = value_as_address (value);
resolved_pc = gdbarch_convert_from_func_ptr_addr (gdbarch,
resolved_address,
- ¤t_target);
+ current_top_target ());
resolved_pc = gdbarch_addr_bits_remove (gdbarch, resolved_pc);
gdb_assert (current_program_space == b->pspace || b->pspace == NULL);
- elf_gnu_ifunc_record_cache (b->addr_string, resolved_pc);
-
- sal = find_pc_line (resolved_pc, 0);
- sals.nelts = 1;
- sals.sals = &sal;
- sals_end.nelts = 0;
+ elf_gnu_ifunc_record_cache (event_location_to_string (b->location.get ()),
+ resolved_pc);
b->type = bp_breakpoint;
- update_breakpoint_locations (b, sals, sals_end);
+ update_breakpoint_locations (b, current_program_space,
+ find_function_start_sal (resolved_pc, NULL, true),
+ {});
}
/* A helper function for elf_symfile_read that reads the minimal
const struct elfinfo *ei)
{
bfd *synth_abfd, *abfd = objfile->obfd;
- struct cleanup *back_to;
long symcount = 0, dynsymcount = 0, synthcount, storage_needed;
asymbol **symbol_table = NULL, **dyn_symbol_table = NULL;
asymbol *synthsyms;
- struct dbx_symfile_info *dbx;
if (symtab_create_debug)
{
go away once all types of symbols are in the per-BFD object. */
if (objfile->per_bfd->minsyms_read
&& ei->stabsect == NULL
- && ei->mdebugsect == NULL)
+ && ei->mdebugsect == NULL
+ && ei->ctfsect == NULL)
{
if (symtab_create_debug)
fprintf_unfiltered (gdb_stdlog,
return;
}
- init_minimal_symbol_collection ();
- back_to = make_cleanup_discard_minimal_symbols ();
+ minimal_symbol_reader reader (objfile);
- /* Allocate struct to keep track of the symfile. */
- dbx = XCNEW (struct dbx_symfile_info);
- set_objfile_data (objfile, dbx_objfile_data_key, dbx);
- make_cleanup (free_elfinfo, (void *) objfile);
-
- /* Process the normal ELF symbol table first. This may write some
- chain of info into the dbx_symfile_info of the objfile, which can
- later be used by elfstab_offset_sections. */
+ /* Process the normal ELF symbol table first. */
storage_needed = bfd_get_symtab_upper_bound (objfile->obfd);
if (storage_needed < 0)
if (storage_needed > 0)
{
- symbol_table = (asymbol **) xmalloc (storage_needed);
- make_cleanup (xfree, symbol_table);
+ /* 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, symbol_table);
if (symcount < 0)
bfd_get_filename (objfile->obfd),
bfd_errmsg (bfd_get_error ()));
- elf_symtab_read (objfile, ST_REGULAR, symcount, symbol_table, 0);
+ elf_symtab_read (reader, objfile, ST_REGULAR, symcount, symbol_table,
+ false);
}
/* Add the dynamic symbols. */
done by _bfd_elf_get_synthetic_symtab which is all a bfd
implementation detail, though. */
- dyn_symbol_table = bfd_alloc (abfd, storage_needed);
+ dyn_symbol_table = (asymbol **) bfd_alloc (abfd, storage_needed);
dynsymcount = bfd_canonicalize_dynamic_symtab (objfile->obfd,
dyn_symbol_table);
bfd_get_filename (objfile->obfd),
bfd_errmsg (bfd_get_error ()));
- elf_symtab_read (objfile, ST_DYNAMIC, dynsymcount, dyn_symbol_table, 0);
+ elf_symtab_read (reader, objfile, ST_DYNAMIC, dynsymcount,
+ dyn_symbol_table, false);
- elf_rel_plt_read (objfile, dyn_symbol_table);
+ elf_rel_plt_read (reader, objfile, dyn_symbol_table);
}
/* Contrary to binutils --strip-debug/--only-keep-debug the strip command from
&synthsyms);
if (synthcount > 0)
{
- asymbol **synth_symbol_table;
long i;
- make_cleanup (xfree, synthsyms);
- synth_symbol_table = xmalloc (sizeof (asymbol *) * synthcount);
+ std::unique_ptr<asymbol *[]>
+ synth_symbol_table (new asymbol *[synthcount]);
for (i = 0; i < synthcount; i++)
synth_symbol_table[i] = synthsyms + i;
- make_cleanup (xfree, synth_symbol_table);
- elf_symtab_read (objfile, ST_SYNTHETIC, synthcount,
- synth_symbol_table, 1);
+ elf_symtab_read (reader, objfile, ST_SYNTHETIC, synthcount,
+ synth_symbol_table.get (), true);
+
+ xfree (synthsyms);
+ synthsyms = NULL;
}
/* Install any minimal symbols that have been collected as the current
responsibility to install them. "mdebug" appears to be the only one
which will do this. */
- install_minimal_symbols (objfile);
- do_cleanups (back_to);
+ reader.install ();
if (symtab_create_debug)
fprintf_unfiltered (gdb_stdlog, "Done reading minimal symbols.\n");
capability even for files compiled without -g. */
static void
-elf_symfile_read (struct objfile *objfile, int symfile_flags)
+elf_symfile_read (struct objfile *objfile, symfile_add_flags symfile_flags)
{
bfd *abfd = objfile->obfd;
struct elfinfo ei;
+ bool has_dwarf2 = true;
memset ((char *) &ei, 0, sizeof (ei));
- bfd_map_over_sections (abfd, elf_locate_sections, (void *) & ei);
+ if (!(objfile->flags & OBJF_READNEVER))
+ bfd_map_over_sections (abfd, elf_locate_sections, (void *) & ei);
elf_read_minimal_symbols (objfile, symfile_flags, &ei);
elfstab_build_psymtabs (objfile,
ei.stabsect,
str_sect->filepos,
- bfd_section_size (abfd, str_sect));
+ bfd_section_size (str_sect));
}
- if (dwarf2_has_info (objfile, NULL))
+ if (dwarf2_has_info (objfile, NULL, true))
{
- /* elf_sym_fns_gdb_index cannot handle simultaneous non-DWARF debug
- information present in OBJFILE. If there is such debug info present
- never use .gdb_index. */
+ 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))
- objfile_set_sym_fns (objfile, &elf_sym_fns_gdb_index);
+ && 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
&& objfile->separate_debug_objfile == NULL
&& objfile->separate_debug_objfile_backlink == NULL)
{
- char *debugfile;
+ std::string debugfile = find_separate_debug_file_by_buildid (objfile);
- debugfile = find_separate_debug_file_by_buildid (objfile);
-
- if (debugfile == NULL)
+ if (debugfile.empty ())
debugfile = find_separate_debug_file_by_debuglink (objfile);
- if (debugfile)
+ if (!debugfile.empty ())
{
- struct cleanup *cleanup = make_cleanup (xfree, debugfile);
- bfd *abfd = symfile_bfd_open (debugfile);
+ gdb_bfd_ref_ptr debug_bfd (symfile_bfd_open (debugfile.c_str ()));
- make_cleanup_bfd_unref (abfd);
- symbol_file_add_separate (abfd, debugfile, symfile_flags, objfile);
- do_cleanups (cleanup);
+ symbol_file_add_separate (debug_bfd.get (), debugfile.c_str (),
+ symfile_flags, objfile);
}
+ else
+ has_dwarf2 = false;
+ }
+
+ /* Read the CTF section only if there is no DWARF info. */
+ if (!has_dwarf2 && ei.ctfsect)
+ {
+ elfctf_build_psymtabs (objfile);
}
}
dwarf2_build_psymtabs (objfile);
}
-/* This cleans up the objfile's dbx symfile info, and the chain of
- stab_section_info's, that might be dangling from it. */
-
-static void
-free_elfinfo (void *objp)
-{
- struct objfile *objfile = (struct objfile *) objp;
- struct dbx_symfile_info *dbxinfo = DBX_SYMFILE_INFO (objfile);
- struct stab_section_info *ssi, *nssi;
-
- ssi = dbxinfo->stab_section_info;
- while (ssi)
- {
- nssi = ssi->next;
- xfree (ssi);
- ssi = nssi;
- }
-
- dbxinfo->stab_section_info = 0; /* Just say No mo info about this. */
-}
-
-
/* 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).
-
- We reinitialize buildsym, since we may be reading stabs from an ELF
- file. */
+ shared library). */
static void
elf_new_init (struct objfile *ignore)
{
- stabsread_new_init ();
- buildsym_new_init ();
}
/* Perform any local cleanups required when we are done with a particular
static void
elf_symfile_finish (struct objfile *objfile)
{
- dwarf2_free_objfile (objfile);
}
/* ELF specific initialization routine for reading symbols. */
objfile->flags |= OBJF_REORDERED;
}
-/* When handling an ELF file that contains Sun STABS debug info,
- some of the debug info is relative to the particular chunk of the
- section that was generated in its individual .o file. E.g.
- offsets to static variables are relative to the start of the data
- segment *for that module before linking*. This information is
- painfully squirreled away in the ELF symbol table as local symbols
- with wierd names. Go get 'em when needed. */
-
-void
-elfstab_offset_sections (struct objfile *objfile, struct partial_symtab *pst)
-{
- const char *filename = pst->filename;
- struct dbx_symfile_info *dbx = DBX_SYMFILE_INFO (objfile);
- struct stab_section_info *maybe = dbx->stab_section_info;
- struct stab_section_info *questionable = 0;
- int i;
-
- /* The ELF symbol info doesn't include path names, so strip the path
- (if any) from the psymtab filename. */
- filename = lbasename (filename);
-
- /* FIXME: This linear search could speed up significantly
- if it was chained in the right order to match how we search it,
- and if we unchained when we found a match. */
- for (; maybe; maybe = maybe->next)
- {
- if (filename[0] == maybe->filename[0]
- && filename_cmp (filename, maybe->filename) == 0)
- {
- /* We found a match. But there might be several source files
- (from different directories) with the same name. */
- if (0 == maybe->found)
- break;
- questionable = maybe; /* Might use it later. */
- }
- }
-
- if (maybe == 0 && questionable != 0)
- {
- complaint (&symfile_complaints,
- _("elf/stab section information questionable for %s"),
- filename);
- maybe = questionable;
- }
-
- if (maybe)
- {
- /* Found it! Allocate a new psymtab struct, and fill it in. */
- maybe->found++;
- pst->section_offsets = (struct section_offsets *)
- obstack_alloc (&objfile->objfile_obstack,
- SIZEOF_N_SECTION_OFFSETS (objfile->num_sections));
- for (i = 0; i < maybe->num_sections; i++)
- (pst->section_offsets)->offsets[i] = maybe->sections[i];
- return;
- }
-
- /* We were unable to find any offsets for this file. Complain. */
- if (dbx->stab_section_info) /* If there *is* any info, */
- complaint (&symfile_complaints,
- _("elf/stab section information missing for %s"), filename);
-}
-
/* Implementation of `sym_get_probes', as documented in symfile.h. */
-static VEC (probe_p) *
+static const elfread_data &
elf_get_probes (struct objfile *objfile)
{
- VEC (probe_p) *probes_per_bfd;
-
- /* Have we parsed this objfile's probes already? */
- probes_per_bfd = bfd_data (objfile->obfd, probe_key);
+ elfread_data *probes_per_bfd = probe_key.get (objfile->obfd);
- if (!probes_per_bfd)
+ if (probes_per_bfd == NULL)
{
- int ix;
- const struct probe_ops *probe_ops;
+ probes_per_bfd = probe_key.emplace (objfile->obfd);
/* Here we try to gather information about all types of probes from the
objfile. */
- for (ix = 0; VEC_iterate (probe_ops_cp, all_probe_ops, ix, probe_ops);
- ix++)
- probe_ops->get_probes (&probes_per_bfd, objfile);
-
- if (probes_per_bfd == NULL)
- {
- VEC_reserve (probe_p, probes_per_bfd, 1);
- gdb_assert (probes_per_bfd != NULL);
- }
-
- set_bfd_data (objfile->obfd, probe_key, probes_per_bfd);
+ for (const static_probe_ops *ops : all_static_probe_ops)
+ ops->get_probes (probes_per_bfd, objfile);
}
- return probes_per_bfd;
-}
-
-/* Helper function used to free the space allocated for storing SystemTap
- probe information. */
-
-static void
-probe_key_free (bfd *abfd, void *d)
-{
- int ix;
- VEC (probe_p) *probes = d;
- struct probe *probe;
-
- for (ix = 0; VEC_iterate (probe_p, probes, ix, probe); ix++)
- probe->pops->destroy (probe);
-
- VEC_free (probe_p, probes);
+ return *probes_per_bfd;
}
\f
/* The same as elf_sym_fns, but not registered and lazily reads
psymbols. */
-static const struct sym_fns elf_sym_fns_lazy_psyms =
+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() */
/* The same as elf_sym_fns, but not registered and uses the
DWARF-specific GNU index rather than psymtab. */
-static const struct sym_fns elf_sym_fns_gdb_index =
+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. relocatin */
+ 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. */
&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. */
static const struct gnu_ifunc_fns elf_gnu_ifunc_fns =
void
_initialize_elfread (void)
{
- probe_key = register_bfd_data_with_cleanup (NULL, probe_key_free);
add_symtab_fns (bfd_target_elf_flavour, &elf_sym_fns);
- elf_objfile_gnu_ifunc_cache_data = register_objfile_data ();
gnu_ifunc_fns_p = &elf_gnu_ifunc_fns;
}