diff --git a/gdb/ChangeLog b/gdb/ChangeLog index bf2811a0867..9bfb7551df2 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,31 @@ +2019-10-02 Tom Tromey + + * 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. + : 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) : + New member. + 2019-10-02 Tom Tromey * source.c (struct current_source_location): New. diff --git a/gdb/ada-lang.c b/gdb/ada-lang.c index 48a400daa7d..f7f972a9bc9 100644 --- a/gdb/ada-lang.c +++ b/gdb/ada-lang.c @@ -4724,6 +4724,15 @@ lesseq_defined_than (struct symbol *sym0, struct symbol *sym1) 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; } diff --git a/gdb/dwarf2read.c b/gdb/dwarf2read.c index f10f384f628..feac40ff95c 100644 --- a/gdb/dwarf2read.c +++ b/gdb/dwarf2read.c @@ -2138,8 +2138,10 @@ attr_value_as_address (struct attribute *attr) /* 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; @@ -2214,11 +2216,14 @@ class free_cached_comp_units /* 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; @@ -2228,7 +2233,8 @@ dwarf2_has_info (struct objfile *objfile, 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 @@ -21715,19 +21721,21 @@ new_symbol (struct die_info *die, struct type *type, struct dwarf2_cu *cu, } 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. */ diff --git a/gdb/dwarf2read.h b/gdb/dwarf2read.h index aee8742a79c..a737168b629 100644 --- a/gdb/dwarf2read.h +++ b/gdb/dwarf2read.h @@ -106,9 +106,12 @@ struct dwarf2_per_objfile { /* 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 (); @@ -208,6 +211,9 @@ struct dwarf2_per_objfile original data was compressed using 'dwz -m'. */ std::unique_ptr 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; diff --git a/gdb/elfread.c b/gdb/elfread.c index a3d17e54a2f..d2a7bcf8aa6 100644 --- a/gdb/elfread.c +++ b/gdb/elfread.c @@ -203,10 +203,16 @@ record_minimal_symbol (minimal_symbol_reader &reader, || 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. @@ -1239,7 +1245,7 @@ elf_symfile_read (struct objfile *objfile, symfile_add_flags symfile_flags) bfd_section_size (str_sect)); } - if (dwarf2_has_info (objfile, NULL)) + if (dwarf2_has_info (objfile, NULL, true)) { dw_index_kind index_kind; diff --git a/gdb/minsyms.c b/gdb/minsyms.c index 83f5d895779..c41e5c32001 100644 --- a/gdb/minsyms.c +++ b/gdb/minsyms.c @@ -519,6 +519,29 @@ iterate_over_minimal_symbols /* 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) { diff --git a/gdb/minsyms.h b/gdb/minsyms.h index ce4b83d5448..0a19f0b0962 100644 --- a/gdb/minsyms.h +++ b/gdb/minsyms.h @@ -205,6 +205,17 @@ struct bound_minimal_symbol lookup_bound_minimal_symbol (const char *); 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 diff --git a/gdb/symfile.h b/gdb/symfile.h index 642a5e223a3..cb5bed9d85c 100644 --- a/gdb/symfile.h +++ b/gdb/symfile.h @@ -585,7 +585,8 @@ struct dwarf2_debug_sections { }; 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 { diff --git a/gdb/symmisc.c b/gdb/symmisc.c index 4699fd09206..c91ad5e5f45 100644 --- a/gdb/symmisc.c +++ b/gdb/symmisc.c @@ -236,9 +236,13 @@ dump_msymbols (struct objfile *objfile, struct ui_file *outfile) 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) { diff --git a/gdb/symtab.c b/gdb/symtab.c index 7b4444c7d38..8a551f1575a 100644 --- a/gdb/symtab.c +++ b/gdb/symtab.c @@ -6261,6 +6261,50 @@ symbol_set_symtab (struct symbol *symbol, struct symtab *symtab) 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)); +} + void diff --git a/gdb/symtab.h b/gdb/symtab.h index e9024a0a739..dc65409dd24 100644 --- a/gdb/symtab.h +++ b/gdb/symtab.h @@ -454,6 +454,14 @@ extern const char *symbol_get_demangled_name 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 @@ -463,7 +471,9 @@ extern CORE_ADDR symbol_overlayed_address (CORE_ADDR, struct obj_section *); 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 @@ -671,6 +681,14 @@ struct minimal_symbol : public general_symbol_info 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. */ @@ -690,6 +708,15 @@ struct minimal_symbol : public general_symbol_info 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) @@ -708,8 +735,9 @@ struct minimal_symbol : public general_symbol_info /* 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) @@ -1112,6 +1140,14 @@ struct symbol /* 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;