| Index: gdb/elfread.c
|
| diff --git a/gdb/elfread.c b/gdb/elfread.c
|
| index ca1c2a9d3ee0e21b6eccbe1a310027c3b922457c..1edfb27caa4d909a68b730ac5b0e91465acd9867 100644
|
| --- a/gdb/elfread.c
|
| +++ b/gdb/elfread.c
|
| @@ -36,11 +36,14 @@
|
| #include "demangle.h"
|
| #include "psympriv.h"
|
| #include "filenames.h"
|
| +#include "probe.h"
|
| +#include "arch-utils.h"
|
| #include "gdbtypes.h"
|
| #include "value.h"
|
| #include "infcall.h"
|
| #include "gdbthread.h"
|
| #include "regcache.h"
|
| +#include "bcache.h"
|
|
|
| extern void _initialize_elfread (void);
|
|
|
| @@ -59,6 +62,10 @@ struct elfinfo
|
| asection *mdebugsect; /* Section pointer for .mdebug section */
|
| };
|
|
|
| +/* Per-objfile data for probe info. */
|
| +
|
| +static const struct objfile_data *probe_key = NULL;
|
| +
|
| static void free_elfinfo (void *);
|
|
|
| /* Minimal symbols located at the GOT entries for .plt - that is the real
|
| @@ -141,7 +148,7 @@ elf_symfile_segments (bfd *abfd)
|
| binaries are not relocatable. */
|
| if (bfd_get_section_size (sect) > 0 && j == num_segments
|
| && (bfd_get_section_flags (abfd, sect) & SEC_LOAD) != 0)
|
| - warning (_("Loadable segment \"%s\" outside of ELF segments"),
|
| + warning (_("Loadable section \"%s\" outside of ELF segments"),
|
| bfd_section_name (abfd, sect));
|
| }
|
|
|
| @@ -238,8 +245,8 @@ elf_symtab_read (struct objfile *objfile, int type,
|
| 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 obstack. */
|
| - char *filesymname = "";
|
| + the objfile's filename cache. */
|
| + const char *filesymname = "";
|
| struct dbx_symfile_info *dbx = objfile->deprecated_sym_stab_info;
|
| int stripped = (bfd_get_symcount (objfile->obfd) == 0);
|
|
|
| @@ -265,7 +272,7 @@ elf_symtab_read (struct objfile *objfile, int type,
|
|
|
| offset = ANOFFSET (objfile->section_offsets, sym->section->index);
|
| if (type == ST_DYNAMIC
|
| - && sym->section == &bfd_und_section
|
| + && sym->section == bfd_und_section_ptr
|
| && (sym->flags & BSF_FUNCTION))
|
| {
|
| struct minimal_symbol *msym;
|
| @@ -301,6 +308,23 @@ elf_symtab_read (struct objfile *objfile, int type,
|
| if (!sect)
|
| continue;
|
|
|
| + /* On ia64-hpux, we have discovered that the system linker
|
| + adds undefined symbols with nonzero addresses that cannot
|
| + be right (their address points inside the code of another
|
| + function in the .text section). This creates problems
|
| + when trying to determine which symbol corresponds to
|
| + a given address.
|
| +
|
| + We try to detect those buggy symbols by checking which
|
| + section we think they correspond to. Normally, PLT symbols
|
| + are stored inside their own section, and the typical name
|
| + 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
|
| + && bfd_get_section_by_name (abfd, ".plt") != NULL)
|
| + continue;
|
| +
|
| symaddr += ANOFFSET (objfile->section_offsets, sect->index);
|
|
|
| msym = record_minimal_symbol
|
| @@ -327,9 +351,8 @@ elf_symtab_read (struct objfile *objfile, int type,
|
| sectinfo = NULL;
|
| }
|
| filesym = sym;
|
| - filesymname =
|
| - obsavestring ((char *) filesym->name, strlen (filesym->name),
|
| - &objfile->objfile_obstack);
|
| + filesymname = bcache (filesym->name, strlen (filesym->name) + 1,
|
| + objfile->filename_cache);
|
| }
|
| else if (sym->flags & BSF_SECTION_SYM)
|
| continue;
|
| @@ -344,7 +367,7 @@ elf_symtab_read (struct objfile *objfile, int type,
|
| symaddr = sym->value + sym->section->vma;
|
| /* Relocate all non-absolute and non-TLS symbols by the
|
| section offset. */
|
| - if (sym->section != &bfd_abs_section
|
| + if (sym->section != bfd_abs_section_ptr
|
| && !(sym->section->flags & SEC_THREAD_LOCAL))
|
| {
|
| symaddr += offset;
|
| @@ -352,7 +375,7 @@ elf_symtab_read (struct objfile *objfile, int type,
|
| /* For non-absolute symbols, use the type of the section
|
| they are relative to, to intuit text/data. Bfd provides
|
| no way of figuring this out for absolute symbols. */
|
| - if (sym->section == &bfd_abs_section)
|
| + if (sym->section == bfd_abs_section_ptr)
|
| {
|
| /* This is a hack to get the minimal symbol type
|
| right for Irix 5, which has absolute addresses
|
| @@ -494,7 +517,7 @@ elf_symtab_read (struct objfile *objfile, int type,
|
| symaddr = sym->value + sym->section->vma;
|
| /* Relocate non-absolute symbols by the
|
| section offset. */
|
| - if (sym->section != &bfd_abs_section)
|
| + if (sym->section != bfd_abs_section_ptr)
|
| symaddr += offset;
|
| sectinfo->sections[special_local_sect] = symaddr;
|
| /* The special local symbols don't go in the
|
| @@ -571,6 +594,7 @@ elf_symtab_read (struct objfile *objfile, int type,
|
| if (mtramp)
|
| {
|
| MSYMBOL_SIZE (mtramp) = MSYMBOL_SIZE (msym);
|
| + mtramp->created_by_gdb = 1;
|
| mtramp->filename = filesymname;
|
| gdbarch_elf_make_msymbol_special (gdbarch, sym, mtramp);
|
| }
|
| @@ -593,7 +617,6 @@ elf_rel_plt_read (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;
|
| - unsigned u;
|
| int plt_elf_idx;
|
| bfd_size_type reloc_count, reloc;
|
| char *string_buffer = NULL;
|
| @@ -632,7 +655,7 @@ elf_rel_plt_read (struct objfile *objfile, asymbol **dyn_symbol_table)
|
| reloc_count = relplt->size / elf_section_data (relplt)->this_hdr.sh_entsize;
|
| for (reloc = 0; reloc < reloc_count; reloc++)
|
| {
|
| - const char *name, *name_got_plt;
|
| + const char *name;
|
| struct minimal_symbol *msym;
|
| CORE_ADDR address;
|
| const size_t got_suffix_len = strlen (SYMBOL_GOT_PLT_SUFFIX);
|
| @@ -903,7 +926,7 @@ elf_gnu_ifunc_resolve_name (const char *name, CORE_ADDR *addr_p)
|
| static CORE_ADDR
|
| elf_gnu_ifunc_resolve_addr (struct gdbarch *gdbarch, CORE_ADDR pc)
|
| {
|
| - char *name_at_pc;
|
| + const char *name_at_pc;
|
| CORE_ADDR start_at_pc, address;
|
| struct type *func_func_type = builtin_type (gdbarch)->builtin_func_func;
|
| struct value *function, *address_val;
|
| @@ -978,6 +1001,9 @@ elf_gnu_ifunc_resolver_stop (struct breakpoint *b)
|
| prev_frame_id,
|
| bp_gnu_ifunc_resolver_return);
|
|
|
| + /* set_momentary_breakpoint invalidates PREV_FRAME. */
|
| + prev_frame = NULL;
|
| +
|
| /* Add new b_return to the ring list b->related_breakpoint. */
|
| gdb_assert (b_return->related_breakpoint == b_return);
|
| b_return->related_breakpoint = b->related_breakpoint;
|
| @@ -994,6 +1020,7 @@ elf_gnu_ifunc_resolver_return_stop (struct breakpoint *b)
|
| 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 value *func_func;
|
| struct value *value;
|
| CORE_ADDR resolved_address, resolved_pc;
|
| struct symtab_and_line sal;
|
| @@ -1001,14 +1028,6 @@ elf_gnu_ifunc_resolver_return_stop (struct breakpoint *b)
|
|
|
| gdb_assert (b->type == bp_gnu_ifunc_resolver_return);
|
|
|
| - value = allocate_value (value_type);
|
| - gdbarch_return_value (gdbarch, func_func_type, value_type, regcache,
|
| - value_contents_raw (value), NULL);
|
| - resolved_address = value_as_address (value);
|
| - resolved_pc = gdbarch_convert_from_func_ptr_addr (gdbarch,
|
| - resolved_address,
|
| - ¤t_target);
|
| -
|
| while (b->related_breakpoint != b)
|
| {
|
| struct breakpoint *b_next = b->related_breakpoint;
|
| @@ -1029,6 +1048,18 @@ elf_gnu_ifunc_resolver_return_stop (struct breakpoint *b)
|
| b = b_next;
|
| }
|
| gdb_assert (b->type == bp_gnu_ifunc_resolver);
|
| + gdb_assert (b->loc->next == NULL);
|
| +
|
| + func_func = allocate_value (func_func_type);
|
| + set_value_address (func_func, b->loc->related_address);
|
| +
|
| + value = allocate_value (value_type);
|
| + gdbarch_return_value (gdbarch, func_func, value_type, regcache,
|
| + value_contents_raw (value), NULL);
|
| + resolved_address = value_as_address (value);
|
| + resolved_pc = gdbarch_convert_from_func_ptr_addr (gdbarch,
|
| + resolved_address,
|
| + ¤t_target);
|
|
|
| gdb_assert (current_program_space == b->pspace || b->pspace == NULL);
|
| elf_gnu_ifunc_record_cache (b->addr_string, resolved_pc);
|
| @@ -1103,6 +1134,9 @@ static char *
|
| build_id_to_debug_filename (struct build_id *build_id)
|
| {
|
| char *link, *debugdir, *retval = NULL;
|
| + VEC (char_ptr) *debugdir_vec;
|
| + struct cleanup *back_to;
|
| + int ix;
|
|
|
| /* DEBUG_FILE_DIRECTORY/.build-id/ab/cdef */
|
| link = alloca (strlen (debug_file_directory) + (sizeof "/.build-id/" - 1) + 1
|
| @@ -1111,22 +1145,18 @@ build_id_to_debug_filename (struct build_id *build_id)
|
| /* Keep backward compatibility so that DEBUG_FILE_DIRECTORY being "" will
|
| cause "/.build-id/..." lookups. */
|
|
|
| - debugdir = debug_file_directory;
|
| - do
|
| + debugdir_vec = dirnames_to_char_ptr_vec (debug_file_directory);
|
| + back_to = make_cleanup_free_char_ptr_vec (debugdir_vec);
|
| +
|
| + for (ix = 0; VEC_iterate (char_ptr, debugdir_vec, ix, debugdir); ++ix)
|
| {
|
| - char *s, *debugdir_end;
|
| + size_t debugdir_len = strlen (debugdir);
|
| gdb_byte *data = build_id->data;
|
| size_t size = build_id->size;
|
| + char *s;
|
|
|
| - while (*debugdir == DIRNAME_SEPARATOR)
|
| - debugdir++;
|
| -
|
| - debugdir_end = strchr (debugdir, DIRNAME_SEPARATOR);
|
| - if (debugdir_end == NULL)
|
| - debugdir_end = &debugdir[strlen (debugdir)];
|
| -
|
| - memcpy (link, debugdir, debugdir_end - debugdir);
|
| - s = &link[debugdir_end - debugdir];
|
| + memcpy (link, debugdir, debugdir_len);
|
| + s = &link[debugdir_len];
|
| s += sprintf (s, "/.build-id/");
|
| if (size > 0)
|
| {
|
| @@ -1151,11 +1181,9 @@ build_id_to_debug_filename (struct build_id *build_id)
|
|
|
| if (retval != NULL)
|
| break;
|
| -
|
| - debugdir = debugdir_end;
|
| }
|
| - while (*debugdir != 0);
|
|
|
| + do_cleanups (back_to);
|
| return retval;
|
| }
|
|
|
| @@ -1223,6 +1251,13 @@ elf_symfile_read (struct objfile *objfile, int symfile_flags)
|
| asymbol **symbol_table = NULL, **dyn_symbol_table = NULL;
|
| asymbol *synthsyms;
|
|
|
| + if (symtab_create_debug)
|
| + {
|
| + fprintf_unfiltered (gdb_stdlog,
|
| + "Reading minimal symbols of objfile %s ...\n",
|
| + objfile->name);
|
| + }
|
| +
|
| init_minimal_symbol_collection ();
|
| back_to = make_cleanup_discard_minimal_symbols ();
|
|
|
| @@ -1415,6 +1450,9 @@ elf_symfile_read (struct objfile *objfile, int symfile_flags)
|
| xfree (debugfile);
|
| }
|
| }
|
| +
|
| + if (symtab_create_debug)
|
| + fprintf_unfiltered (gdb_stdlog, "Done reading minimal symbols.\n");
|
| }
|
|
|
| /* Callback to lazily read psymtabs. */
|
| @@ -1559,7 +1597,117 @@ elfstab_offset_sections (struct objfile *objfile, struct partial_symtab *pst)
|
| 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) *
|
| +elf_get_probes (struct objfile *objfile)
|
| +{
|
| + VEC (probe_p) *probes_per_objfile;
|
| +
|
| + /* Have we parsed this objfile's probes already? */
|
| + probes_per_objfile = objfile_data (objfile, probe_key);
|
| +
|
| + if (!probes_per_objfile)
|
| + {
|
| + int ix;
|
| + const struct probe_ops *probe_ops;
|
| +
|
| + /* 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_objfile, objfile);
|
| +
|
| + if (probes_per_objfile == NULL)
|
| + {
|
| + VEC_reserve (probe_p, probes_per_objfile, 1);
|
| + gdb_assert (probes_per_objfile != NULL);
|
| + }
|
| +
|
| + set_objfile_data (objfile, probe_key, probes_per_objfile);
|
| + }
|
| +
|
| + return probes_per_objfile;
|
| +}
|
| +
|
| +/* Implementation of `sym_get_probe_argument_count', as documented in
|
| + symfile.h. */
|
| +
|
| +static unsigned
|
| +elf_get_probe_argument_count (struct objfile *objfile,
|
| + struct probe *probe)
|
| +{
|
| + return probe->pops->get_probe_argument_count (probe, objfile);
|
| +}
|
| +
|
| +/* Implementation of `sym_evaluate_probe_argument', as documented in
|
| + symfile.h. */
|
| +
|
| +static struct value *
|
| +elf_evaluate_probe_argument (struct objfile *objfile,
|
| + struct probe *probe,
|
| + unsigned n)
|
| +{
|
| + return probe->pops->evaluate_probe_argument (probe, objfile, n);
|
| +}
|
| +
|
| +/* Implementation of `sym_compile_to_ax', as documented in symfile.h. */
|
| +
|
| +static void
|
| +elf_compile_to_ax (struct objfile *objfile,
|
| + struct probe *probe,
|
| + struct agent_expr *expr,
|
| + struct axs_value *value,
|
| + unsigned n)
|
| +{
|
| + probe->pops->compile_to_ax (probe, objfile, expr, value, n);
|
| +}
|
| +
|
| +/* Implementation of `sym_relocate_probe', as documented in symfile.h. */
|
| +
|
| +static void
|
| +elf_symfile_relocate_probe (struct objfile *objfile,
|
| + struct section_offsets *new_offsets,
|
| + struct section_offsets *delta)
|
| +{
|
| + int ix;
|
| + VEC (probe_p) *probes = objfile_data (objfile, probe_key);
|
| + struct probe *probe;
|
| +
|
| + for (ix = 0; VEC_iterate (probe_p, probes, ix, probe); ix++)
|
| + probe->pops->relocate (probe, ANOFFSET (delta, SECT_OFF_TEXT (objfile)));
|
| +}
|
| +
|
| +/* Helper function used to free the space allocated for storing SystemTap
|
| + probe information. */
|
| +
|
| +static void
|
| +probe_key_free (struct objfile *objfile, 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);
|
| +}
|
| +
|
|
|
| +
|
| +/* Implementation `sym_probe_fns', as documented in symfile.h. */
|
| +
|
| +static const struct sym_probe_fns elf_probe_fns =
|
| +{
|
| + elf_get_probes, /* sym_get_probes */
|
| + elf_get_probe_argument_count, /* sym_get_probe_argument_count */
|
| + elf_evaluate_probe_argument, /* sym_evaluate_probe_argument */
|
| + elf_compile_to_ax, /* sym_compile_to_ax */
|
| + elf_symfile_relocate_probe, /* sym_relocate_probe */
|
| +};
|
| +
|
| /* Register that we are able to handle ELF object file formats. */
|
|
|
| static const struct sym_fns elf_sym_fns =
|
| @@ -1574,6 +1722,7 @@ static const struct sym_fns elf_sym_fns =
|
| 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
|
| };
|
|
|
| @@ -1592,6 +1741,7 @@ static const struct sym_fns elf_sym_fns_lazy_psyms =
|
| 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
|
| };
|
|
|
| @@ -1609,6 +1759,7 @@ static const struct sym_fns elf_sym_fns_gdb_index =
|
| 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
|
| };
|
|
|
| @@ -1625,6 +1776,7 @@ static const struct gnu_ifunc_fns elf_gnu_ifunc_fns =
|
| void
|
| _initialize_elfread (void)
|
| {
|
| + probe_key = register_objfile_data_with_cleanup (NULL, probe_key_free);
|
| add_symtab_fns (&elf_sym_fns);
|
|
|
| elf_objfile_gnu_ifunc_cache_data = register_objfile_data ();
|
|
|