diff options
author | Pavel Labath <labath@google.com> | 2015-03-04 10:25:22 +0000 |
---|---|---|
committer | Pavel Labath <labath@google.com> | 2015-03-04 10:25:22 +0000 |
commit | c6ae7eaa7b41031e87a4f807a18ee9b163409275 (patch) | |
tree | e7e37759e5dae75cdd3e613e3f22946ade4fbbe1 /lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp | |
parent | aea8461820908d143de43e4230b7483cbae50c4e (diff) | |
download | bcm5719-llvm-c6ae7eaa7b41031e87a4f807a18ee9b163409275.tar.gz bcm5719-llvm-c6ae7eaa7b41031e87a4f807a18ee9b163409275.zip |
Correctly resolve symbol names containing linker annotations
Summary:
Symbols in ELF files can be versioned, but LLDB currently does not understand these. This problem
becomes apparent once one loads glibc with debug info. Here (in the .symtab section) the versions
are embedded in the name (name@VERSION), which causes issues when evaluating expressions
referencing memcpy for example (current glibc contains memcpy@@GLIBC_2.14 and
memcpy@GLIBC_2.2.5).
This problem was not evident without debug symbols as the .dynsym section
stores the bare names and the actual versions are present in a separate section (.gnu.version_d),
which LLDB ignores. This resulted in two definitions of memcpy in the symbol table.
This patch adds support for storing annotated names to the Symbol class. If
Symbol.m_contains_linker_annotations is true then this symbol is annotated. Unannotated name can
be obtained by calling StripLinkerAnnotations on the corresponding ObjectFile. ObjectFileELF
implements this to strip @VERSION suffixes when requested. Symtab uses this function to add the
bare name as well as the annotated name to the name lookup table.
To preserve the size of the Symbol class, I had to steal one bit from the m_type field.
Test Plan:
This fixes TestExprHelpExamples.py when run with a glibc with debug symbols. Writing
an environment agnostic test case would require building a custom shared library with symbol
versions and testing symbol resolution against that, which is somewhat challenging.
Reviewers: clayborg, jingham
Subscribers: lldb-commits
Differential Revision: http://reviews.llvm.org/D8036
llvm-svn: 231228
Diffstat (limited to 'lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp')
-rw-r--r-- | lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp | 44 |
1 files changed, 38 insertions, 6 deletions
diff --git a/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp b/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp index 1b49aab0df1..1a2ef87f6d6 100644 --- a/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp +++ b/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp @@ -1504,6 +1504,13 @@ ObjectFileELF::GetSegmentDataByIndex(lldb::user_id_t id) return DataExtractor(m_data, segment_header->p_offset, segment_header->p_filesz); } +std::string +ObjectFileELF::StripLinkerSymbolAnnotations(llvm::StringRef symbol_name) const +{ + size_t pos = symbol_name.find("@"); + return symbol_name.substr(0, pos).str(); +} + //---------------------------------------------------------------------- // ParseSectionHeaders //---------------------------------------------------------------------- @@ -1897,23 +1904,46 @@ ObjectFileELF::ParseSymbols (Symtab *symtab, uint32_t flags = symbol.st_other << 8 | symbol.st_info | additional_flags; bool is_mangled = symbol_name ? (symbol_name[0] == '_' && symbol_name[1] == 'Z') : false; + llvm::StringRef symbol_ref(symbol_name); + + // Symbol names may contain @VERSION suffixes. Find those and strip them temporarily. + size_t version_pos = symbol_ref.find('@'); + bool has_suffix = version_pos != llvm::StringRef::npos; + llvm::StringRef symbol_bare = symbol_ref.substr(0, version_pos); + Mangled mangled(ConstString(symbol_bare), is_mangled); + + // Now append the suffix back to mangled and unmangled names. Only do it if the + // demangling was sucessful (string is not empty). + if (has_suffix) + { + llvm::StringRef suffix = symbol_ref.substr(version_pos); + + llvm::StringRef mangled_name = mangled.GetMangledName().GetStringRef(); + if (! mangled_name.empty()) + mangled.SetMangledName( ConstString((mangled_name + suffix).str()) ); + + llvm::StringRef demangled_name = mangled.GetDemangledName().GetStringRef(); + if (! demangled_name.empty()) + mangled.SetDemangledName( ConstString((demangled_name + suffix).str()) ); + } + Symbol dc_symbol( i + start_id, // ID is the original symbol table index. - symbol_name, // Symbol name. - is_mangled, // Is the symbol name mangled? + mangled, symbol_type, // Type of this symbol is_global, // Is this globally visible? false, // Is this symbol debug info? false, // Is this symbol a trampoline? false, // Is this symbol artificial? - symbol_section_sp, // Section in which this symbol is defined or null. - symbol_value, // Offset in section or symbol value. - symbol.st_size, // Size in bytes of this symbol. + AddressRange( + symbol_section_sp, // Section in which this symbol is defined or null. + symbol_value, // Offset in section or symbol value. + symbol.st_size), // Size in bytes of this symbol. true, // Size is valid + has_suffix, // Contains linker annotations? flags); // Symbol flags. symtab->AddSymbol(dc_symbol); } - return i; } @@ -2102,6 +2132,7 @@ ParsePLTRelocations(Symtab *symbol_table, plt_index, // Offset in section or symbol value. plt_entsize, // Size in bytes of this symbol. true, // Size is valid + false, // Contains linker annotations? 0); // Symbol flags. symbol_table->AddSymbol(jump_symbol); @@ -2443,6 +2474,7 @@ ObjectFileELF::ResolveSymbolForAddress(const Address& so_addr, bool verify_uniqu offset, // Offset in section or symbol value. range.GetByteSize(), // Size in bytes of this symbol. true, // Size is valid. + false, // Contains linker annotations? 0); // Symbol flags. if (symbol_id == m_symtab_ap->AddSymbol(eh_symbol)) return m_symtab_ap->SymbolAtIndex(symbol_id); |