/* Read ELF (Executable and Linking Format) object files for GDB.
- Copyright (C) 1991-2018 Free Software Foundation, Inc.
+ Copyright (C) 1991-2019 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"
#include "location.h"
#include "auxv.h"
+#include "mdebugread.h"
/* Forward declarations. */
extern const struct sym_fns elf_sym_fns_gdb_index;
asection *mdebugsect; /* Section pointer for .mdebug section */
};
+/* Type for per-BFD data. */
+
+typedef std::vector<std::unique_ptr<probe>> elfread_data;
+
/* Per-BFD data for probe info. */
-static const struct bfd_data *probe_key = NULL;
+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
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)
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;
if (sym->flags & BSF_FILE)
{
filesymname
- = (const char *) bcache (sym->name, strlen (sym->name) + 1,
- objfile->per_bfd->filename_cache);
+ = ((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
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. */
string_buffer.assign (name);
string_buffer.append (got_suffix, got_suffix + got_suffix_len);
/* 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. */
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 = MSYMBOL_LINKAGE_NAME (msym.minsym);
+ 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 = (htab_t) 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;
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 = (htab_t) objfile_data (objfile, elf_objfile_gnu_ifunc_cache_data);
+ htab = elf_objfile_gnu_ifunc_cache_data.get (objfile);
if (htab == NULL)
continue;
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 = (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);
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;
parameter. FUNCTION is the function entry address. ADDRESS may be a
function descriptor. */
- target_auxv_search (¤t_target, AT_HWCAP, &hwcap);
+ 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, 1, &hwcap_val);
+ 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 = ptid_to_global_thread_id (inferior_ptid);
+ int thread_id = inferior_thread ()->global_num;
gdb_assert (b->type == bp_gnu_ifunc_resolver);
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;
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);
b->type = bp_breakpoint;
update_breakpoint_locations (b, current_program_space,
- find_pc_line (resolved_pc, 0), {});
+ find_function_start_sal (resolved_pc, NULL, true),
+ {});
}
/* A helper function for elf_symfile_read that reads the minimal
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)
{
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);
-
/* Process the normal ELF symbol table first. */
storage_needed = bfd_get_symtab_upper_bound (objfile->obfd);
if (!debugfile.empty ())
{
- gdb_bfd_ref_ptr abfd (symfile_bfd_open (debugfile.c_str ()));
+ gdb_bfd_ref_ptr debug_bfd (symfile_bfd_open (debugfile.c_str ()));
- symbol_file_add_separate (abfd.get (), debugfile.c_str (),
+ symbol_file_add_separate (debug_bfd.get (), debugfile.c_str (),
symfile_flags, 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).
-
- 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. */
/* Implementation of `sym_get_probes', as documented in symfile.h. */
-static const std::vector<probe *> &
+static const elfread_data &
elf_get_probes (struct objfile *objfile)
{
- std::vector<probe *> *probes_per_bfd;
-
- /* Have we parsed this objfile's probes already? */
- probes_per_bfd = (std::vector<probe *> *) bfd_data (objfile->obfd, probe_key);
+ elfread_data *probes_per_bfd = probe_key.get (objfile->obfd);
if (probes_per_bfd == NULL)
{
- probes_per_bfd = new std::vector<probe *>;
+ probes_per_bfd = probe_key.emplace (objfile->obfd);
/* Here we try to gather information about all types of probes from the
objfile. */
for (const static_probe_ops *ops : all_static_probe_ops)
ops->get_probes (probes_per_bfd, objfile);
-
- set_bfd_data (objfile->obfd, probe_key, probes_per_bfd);
}
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)
-{
- std::vector<probe *> *probes = (std::vector<probe *> *) d;
-
- for (probe *p : *probes)
- delete p;
-
- delete probes;
-}
-
\f
/* Implementation `sym_probe_fns', as documented in symfile.h. */
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;
}