+2019-10-02 Tom Tromey <tromey@adacore.com>
+
+ * symmisc.c (dump_msymbols): Don't use MSYMBOL_VALUE_ADDRESS.
+ * ada-lang.c (lesseq_defined_than): Handle
+ LOC_STATIC.
+ * dwarf2read.c (dwarf2_per_objfile): Add can_copy
+ parameter.
+ (dwarf2_has_info): Likewise.
+ (new_symbol): Set maybe_copied on symbol when
+ appropriate.
+ * dwarf2read.h (dwarf2_per_objfile): Add can_copy
+ parameter.
+ <can_copy>: New member.
+ * elfread.c (record_minimal_symbol): Set maybe_copied
+ on symbol when appropriate.
+ (elf_symfile_read): Update call to dwarf2_has_info.
+ * minsyms.c (lookup_minimal_symbol_linkage): New
+ function.
+ * minsyms.h (lookup_minimal_symbol_linkage): Declare.
+ * symtab.c (get_symbol_address, get_msymbol_address):
+ New functions.
+ * symtab.h (get_symbol_address, get_msymbol_address):
+ Declare.
+ (SYMBOL_VALUE_ADDRESS, MSYMBOL_VALUE_ADDRESS): Handle
+ maybe_copied.
+ (struct symbol, struct minimal_symbol) <maybe_copied>:
+ New member.
+
2019-10-02 Tom Tromey <tromey@adacore.com>
* source.c (struct current_source_location): New.
case LOC_CONST:
return SYMBOL_VALUE (sym0) == SYMBOL_VALUE (sym1)
&& equiv_types (SYMBOL_TYPE (sym0), SYMBOL_TYPE (sym1));
+
+ case LOC_STATIC:
+ {
+ const char *name0 = SYMBOL_LINKAGE_NAME (sym0);
+ const char *name1 = SYMBOL_LINKAGE_NAME (sym1);
+ return (strcmp (name0, name1) == 0
+ && SYMBOL_VALUE_ADDRESS (sym0) == SYMBOL_VALUE_ADDRESS (sym1));
+ }
+
default:
return 0;
}
/* See declaration. */
dwarf2_per_objfile::dwarf2_per_objfile (struct objfile *objfile_,
- const dwarf2_debug_sections *names)
- : objfile (objfile_)
+ const dwarf2_debug_sections *names,
+ bool can_copy_)
+ : objfile (objfile_),
+ can_copy (can_copy_)
{
if (names == NULL)
names = &dwarf2_elf_names;
/* Try to locate the sections we need for DWARF 2 debugging
information and return true if we have enough to do something.
NAMES points to the dwarf2 section names, or is NULL if the standard
- ELF names are used. */
+ ELF names are used. CAN_COPY is true for formats where symbol
+ interposition is possible and so symbol values must follow copy
+ relocation rules. */
int
dwarf2_has_info (struct objfile *objfile,
- const struct dwarf2_debug_sections *names)
+ const struct dwarf2_debug_sections *names,
+ bool can_copy)
{
if (objfile->flags & OBJF_READNEVER)
return 0;
if (dwarf2_per_objfile == NULL)
dwarf2_per_objfile = dwarf2_objfile_data_key.emplace (objfile, objfile,
- names);
+ names,
+ can_copy);
return (!dwarf2_per_objfile->info.is_virtual
&& dwarf2_per_objfile->info.s.section != NULL
}
else if (attr2 && (DW_UNSND (attr2) != 0))
{
- /* Workaround gfortran PR debug/40040 - it uses
- DW_AT_location for variables in -fPIC libraries which may
- get overriden by other libraries/executable and get
- a different address. Resolve it by the minimal symbol
- which may come from inferior's executable using copy
- relocation. Make this workaround only for gfortran as for
- other compilers GDB cannot guess the minimal symbol
- Fortran mangling kind. */
- if (cu->language == language_fortran && die->parent
- && die->parent->tag == DW_TAG_module
- && cu->producer
- && startswith (cu->producer, "GNU Fortran"))
- SYMBOL_ACLASS_INDEX (sym) = LOC_UNRESOLVED;
+ if (SYMBOL_CLASS (sym) == LOC_STATIC
+ && (objfile->flags & OBJF_MAINLINE) == 0
+ && dwarf2_per_objfile->can_copy)
+ {
+ /* A global static variable might be subject to
+ copy relocation. We first check for a local
+ minsym, though, because maybe the symbol was
+ marked hidden, in which case this would not
+ apply. */
+ bound_minimal_symbol found
+ = (lookup_minimal_symbol_linkage
+ (SYMBOL_LINKAGE_NAME (sym), objfile));
+ if (found.minsym != nullptr)
+ sym->maybe_copied = 1;
+ }
/* A variable with DW_AT_external is never static,
but it may be block-scoped. */
{
/* Construct a dwarf2_per_objfile for OBJFILE. NAMES points to the
dwarf2 section names, or is NULL if the standard ELF names are
- used. */
+ used. CAN_COPY is true for formats where symbol
+ interposition is possible and so symbol values must follow copy
+ relocation rules. */
dwarf2_per_objfile (struct objfile *objfile,
- const dwarf2_debug_sections *names);
+ const dwarf2_debug_sections *names,
+ bool can_copy);
~dwarf2_per_objfile ();
original data was compressed using 'dwz -m'. */
std::unique_ptr<struct dwz_file> dwz_file;
+ /* Whether copy relocations are supported by this object format. */
+ bool can_copy;
+
/* A flag indicating whether this objfile has a section loaded at a
VMA of 0. */
bool has_section_at_zero = false;
|| ms_type == mst_text_gnu_ifunc)
address = gdbarch_addr_bits_remove (gdbarch, address);
- return reader.record_full (name, name_len, copy_name, address,
- ms_type,
- gdb_bfd_section_index (objfile->obfd,
- bfd_section));
+ struct minimal_symbol *result
+ = reader.record_full (name, name_len, 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.
bfd_section_size (str_sect));
}
- if (dwarf2_has_info (objfile, NULL))
+ if (dwarf2_has_info (objfile, NULL, true))
{
dw_index_kind index_kind;
/* See minsyms.h. */
+bound_minimal_symbol
+lookup_minimal_symbol_linkage (const char *name, struct objfile *objf)
+{
+ unsigned int hash = msymbol_hash (name) % MINIMAL_SYMBOL_HASH_SIZE;
+
+ for (objfile *objfile : objf->separate_debug_objfiles ())
+ {
+ for (minimal_symbol *msymbol = objfile->per_bfd->msymbol_hash[hash];
+ msymbol != NULL;
+ msymbol = msymbol->hash_next)
+ {
+ if (strcmp (MSYMBOL_LINKAGE_NAME (msymbol), name) == 0
+ && (MSYMBOL_TYPE (msymbol) == mst_data
+ || MSYMBOL_TYPE (msymbol) == mst_bss))
+ return {msymbol, objfile};
+ }
+ }
+
+ return {};
+}
+
+/* See minsyms.h. */
+
struct bound_minimal_symbol
lookup_minimal_symbol_text (const char *name, struct objfile *objf)
{
struct bound_minimal_symbol lookup_minimal_symbol_text (const char *,
struct objfile *);
+/* Look through the minimal symbols in OBJF (and its separate debug
+ objfiles) for a global (not file-local) minsym whose linkage name
+ is NAME. This is somewhat similar to lookup_minimal_symbol_text,
+ only data symbols (not text symbols) are considered, and a non-NULL
+ objfile is not accepted. Returns a bound minimal symbol that
+ matches, or an "empty" bound minimal symbol otherwise. */
+
+extern struct bound_minimal_symbol lookup_minimal_symbol_linkage
+ (const char *name, struct objfile *objf)
+ ATTRIBUTE_NONNULL (1) ATTRIBUTE_NONNULL (2);
+
/* Look through all the current minimal symbol tables and find the
first minimal symbol that matches NAME and PC. If OBJF is non-NULL,
limit the search to that objfile. Returns a pointer to the minimal
};
extern int dwarf2_has_info (struct objfile *,
- const struct dwarf2_debug_sections *);
+ const struct dwarf2_debug_sections *,
+ bool = false);
/* Dwarf2 sections that can be accessed by dwarf2_get_section_info. */
enum dwarf2_section_enum {
break;
}
fprintf_filtered (outfile, "[%2d] %c ", index, ms_type);
- fputs_filtered (paddress (gdbarch, MSYMBOL_VALUE_ADDRESS (objfile,
- msymbol)),
- outfile);
+
+ /* Use the relocated address as shown in the symbol here -- do
+ not try to respect copy relocations. */
+ CORE_ADDR addr = (msymbol->value.address
+ + ANOFFSET (objfile->section_offsets,
+ msymbol->section));
+ fputs_filtered (paddress (gdbarch, addr), outfile);
fprintf_filtered (outfile, " %s", MSYMBOL_LINKAGE_NAME (msymbol));
if (section)
{
symbol->owner.symtab = symtab;
}
+/* See symtab.h. */
+
+CORE_ADDR
+get_symbol_address (const struct symbol *sym)
+{
+ gdb_assert (sym->maybe_copied);
+ gdb_assert (SYMBOL_CLASS (sym) == LOC_STATIC);
+
+ const char *linkage_name = SYMBOL_LINKAGE_NAME (sym);
+
+ for (objfile *objfile : current_program_space->objfiles ())
+ {
+ bound_minimal_symbol minsym
+ = lookup_minimal_symbol_linkage (linkage_name, objfile);
+ if (minsym.minsym != nullptr)
+ return BMSYMBOL_VALUE_ADDRESS (minsym);
+ }
+ return sym->ginfo.value.address;
+}
+
+/* See symtab.h. */
+
+CORE_ADDR
+get_msymbol_address (struct objfile *objf, const struct minimal_symbol *minsym)
+{
+ gdb_assert (minsym->maybe_copied);
+ gdb_assert ((objf->flags & OBJF_MAINLINE) == 0);
+
+ const char *linkage_name = MSYMBOL_LINKAGE_NAME (minsym);
+
+ for (objfile *objfile : current_program_space->objfiles ())
+ {
+ if ((objfile->flags & OBJF_MAINLINE) != 0)
+ {
+ bound_minimal_symbol found
+ = lookup_minimal_symbol_linkage (linkage_name, objfile);
+ if (found.minsym != nullptr)
+ return BMSYMBOL_VALUE_ADDRESS (found);
+ }
+ }
+ return (minsym->value.address
+ + ANOFFSET (objf->section_offsets, minsym->section));
+}
+
\f
void
extern CORE_ADDR symbol_overlayed_address (CORE_ADDR, struct obj_section *);
+/* Return the address of SYM. The MAYBE_COPIED flag must be set on
+ SYM. If SYM appears in the main program's minimal symbols, then
+ that minsym's address is returned; otherwise, SYM's address is
+ returned. This should generally only be used via the
+ SYMBOL_VALUE_ADDRESS macro. */
+
+extern CORE_ADDR get_symbol_address (const struct symbol *sym);
+
/* Note that all the following SYMBOL_* macros are used with the
SYMBOL argument being either a partial symbol or
a full symbol. Both types have a ginfo field. In particular
field only, instead of the SYMBOL parameter. */
#define SYMBOL_VALUE(symbol) (symbol)->ginfo.value.ivalue
-#define SYMBOL_VALUE_ADDRESS(symbol) ((symbol)->ginfo.value.address + 0)
+#define SYMBOL_VALUE_ADDRESS(symbol) \
+ (((symbol)->maybe_copied) ? get_symbol_address (symbol) \
+ : ((symbol)->ginfo.value.address))
#define SET_SYMBOL_VALUE_ADDRESS(symbol, new_value) \
((symbol)->ginfo.value.address = (new_value))
#define SYMBOL_VALUE_BYTES(symbol) (symbol)->ginfo.value.bytes
the object file format may not carry that piece of information. */
unsigned int has_size : 1;
+ /* For data symbols only, if this is set, then the symbol might be
+ subject to copy relocation. In this case, a minimal symbol
+ matching the symbol's linkage name is first looked for in the
+ main objfile. If found, then that address is used; otherwise the
+ address in this symbol is used. */
+
+ unsigned maybe_copied : 1;
+
/* Minimal symbols with the same hash key are kept on a linked
list. This is the link. */
bool text_p () const;
};
+/* Return the address of MINSYM, which comes from OBJF. The
+ MAYBE_COPIED flag must be set on MINSYM. If MINSYM appears in the
+ main program's minimal symbols, then that minsym's address is
+ returned; otherwise, MINSYM's address is returned. This should
+ generally only be used via the MSYMBOL_VALUE_ADDRESS macro. */
+
+extern CORE_ADDR get_msymbol_address (struct objfile *objf,
+ const struct minimal_symbol *minsym);
+
#define MSYMBOL_TARGET_FLAG_1(msymbol) (msymbol)->target_flag_1
#define MSYMBOL_TARGET_FLAG_2(msymbol) (msymbol)->target_flag_2
#define MSYMBOL_SIZE(msymbol) ((msymbol)->size + 0)
/* The relocated address of the minimal symbol, using the section
offsets from OBJFILE. */
#define MSYMBOL_VALUE_ADDRESS(objfile, symbol) \
- ((symbol)->value.address \
- + ANOFFSET ((objfile)->section_offsets, ((symbol)->section)))
+ (((symbol)->maybe_copied) ? get_msymbol_address (objfile, symbol) \
+ : ((symbol)->value.address \
+ + ANOFFSET ((objfile)->section_offsets, ((symbol)->section))))
/* For a bound minsym, we can easily compute the address directly. */
#define BMSYMBOL_VALUE_ADDRESS(symbol) \
MSYMBOL_VALUE_ADDRESS ((symbol).objfile, (symbol).minsym)
/* Whether this is an inlined function (class LOC_BLOCK only). */
unsigned is_inlined : 1;
+ /* For LOC_STATIC only, if this is set, then the symbol might be
+ subject to copy relocation. In this case, a minimal symbol
+ matching the symbol's linkage name is first looked for in the
+ main objfile. If found, then that address is used; otherwise the
+ address in this symbol is used. */
+
+ unsigned maybe_copied : 1;
+
/* The concrete type of this symbol. */
ENUM_BITFIELD (symbol_subclass_kind) subclass : 2;