summaryrefslogtreecommitdiffstats
path: root/lldb
diff options
context:
space:
mode:
authorPavel Labath <labath@google.com>2015-03-04 10:25:22 +0000
committerPavel Labath <labath@google.com>2015-03-04 10:25:22 +0000
commitc6ae7eaa7b41031e87a4f807a18ee9b163409275 (patch)
treee7e37759e5dae75cdd3e613e3f22946ade4fbbe1 /lldb
parentaea8461820908d143de43e4230b7483cbae50c4e (diff)
downloadbcm5719-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')
-rw-r--r--lldb/include/lldb/Symbol/ObjectFile.h7
-rw-r--r--lldb/include/lldb/Symbol/Symbol.h18
-rw-r--r--lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp44
-rw-r--r--lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.h3
-rw-r--r--lldb/source/Symbol/Symbol.cpp13
-rw-r--r--lldb/source/Symbol/Symtab.cpp17
6 files changed, 89 insertions, 13 deletions
diff --git a/lldb/include/lldb/Symbol/ObjectFile.h b/lldb/include/lldb/Symbol/ObjectFile.h
index 8bcf92de42e..ff00ac26e67 100644
--- a/lldb/include/lldb/Symbol/ObjectFile.h
+++ b/lldb/include/lldb/Symbol/ObjectFile.h
@@ -836,6 +836,13 @@ public:
{
return m_memory_addr != LLDB_INVALID_ADDRESS;
}
+
+ // Strip linker annotations (such as @@VERSION) from symbol names.
+ virtual std::string
+ StripLinkerSymbolAnnotations(llvm::StringRef symbol_name) const
+ {
+ return symbol_name.str();
+ }
protected:
//------------------------------------------------------------------
diff --git a/lldb/include/lldb/Symbol/Symbol.h b/lldb/include/lldb/Symbol/Symbol.h
index ed2ae3ed8e7..6e14dfff044 100644
--- a/lldb/include/lldb/Symbol/Symbol.h
+++ b/lldb/include/lldb/Symbol/Symbol.h
@@ -39,11 +39,11 @@ public:
lldb::addr_t value,
lldb::addr_t size,
bool size_is_valid,
+ bool contains_linker_annotations,
uint32_t flags);
Symbol (uint32_t symID,
- const char *name,
- bool name_is_mangled,
+ const Mangled &mangled,
lldb::SymbolType type,
bool external,
bool is_debug,
@@ -51,6 +51,7 @@ public:
bool is_artificial,
const AddressRange &range,
bool size_is_valid,
+ bool contains_linker_annotations,
uint32_t flags);
Symbol (const Symbol& rhs);
@@ -272,6 +273,16 @@ public:
m_demangled_is_synthesized = b;
}
+ bool
+ ContainsLinkerAnnotations() const
+ {
+ return m_contains_linker_annotations;
+ }
+ void
+ SetContainsLinkerAnnotations(bool b)
+ {
+ m_contains_linker_annotations = b;
+ }
//------------------------------------------------------------------
/// @copydoc SymbolContextScope::CalculateSymbolContext(SymbolContext*)
///
@@ -325,7 +336,8 @@ protected:
m_size_is_synthesized:1,// non-zero if this symbol's size was calculated using a delta between this symbol and the next
m_size_is_valid:1,
m_demangled_is_synthesized:1, // The demangled name was created should not be used for expressions or other lookups
- m_type:8;
+ m_contains_linker_annotations:1, // The symbol name contains linker annotations, which are optional when doing name lookups
+ m_type:7;
Mangled m_mangled; // uniqued symbol name/mangled name pair
AddressRange m_addr_range; // Contains the value, or the section offset address when the value is an address in a section, and the size (if any)
uint32_t m_flags; // A copy of the flags from the original symbol table, the ObjectFile plug-in can interpret these
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);
diff --git a/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.h b/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.h
index b10dfb532cd..f264478dfcc 100644
--- a/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.h
+++ b/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.h
@@ -187,6 +187,9 @@ public:
lldb_private::DataExtractor
GetSegmentDataByIndex(lldb::user_id_t id);
+ std::string
+ StripLinkerSymbolAnnotations(llvm::StringRef symbol_name) const override;
+
private:
ObjectFileELF(const lldb::ModuleSP &module_sp,
lldb::DataBufferSP& data_sp,
diff --git a/lldb/source/Symbol/Symbol.cpp b/lldb/source/Symbol/Symbol.cpp
index da2208412b3..4a1ae8197b8 100644
--- a/lldb/source/Symbol/Symbol.cpp
+++ b/lldb/source/Symbol/Symbol.cpp
@@ -36,6 +36,7 @@ Symbol::Symbol() :
m_size_is_synthesized (false),
m_size_is_valid (false),
m_demangled_is_synthesized (false),
+ m_contains_linker_annotations (false),
m_type (eSymbolTypeInvalid),
m_mangled (),
m_addr_range (),
@@ -57,6 +58,7 @@ Symbol::Symbol
addr_t offset,
addr_t size,
bool size_is_valid,
+ bool contains_linker_annotations,
uint32_t flags
) :
SymbolContextScope (),
@@ -70,6 +72,7 @@ Symbol::Symbol
m_size_is_synthesized (false),
m_size_is_valid (size_is_valid || size > 0),
m_demangled_is_synthesized (false),
+ m_contains_linker_annotations (contains_linker_annotations),
m_type (type),
m_mangled (ConstString(name), name_is_mangled),
m_addr_range (section_sp, offset, size),
@@ -80,8 +83,7 @@ Symbol::Symbol
Symbol::Symbol
(
uint32_t symID,
- const char *name,
- bool name_is_mangled,
+ const Mangled &mangled,
SymbolType type,
bool external,
bool is_debug,
@@ -89,6 +91,7 @@ Symbol::Symbol
bool is_artificial,
const AddressRange &range,
bool size_is_valid,
+ bool contains_linker_annotations,
uint32_t flags
) :
SymbolContextScope (),
@@ -102,8 +105,9 @@ Symbol::Symbol
m_size_is_synthesized (false),
m_size_is_valid (size_is_valid || range.GetByteSize() > 0),
m_demangled_is_synthesized (false),
+ m_contains_linker_annotations (contains_linker_annotations),
m_type (type),
- m_mangled (ConstString(name), name_is_mangled),
+ m_mangled (mangled),
m_addr_range (range),
m_flags (flags)
{
@@ -121,6 +125,7 @@ Symbol::Symbol(const Symbol& rhs):
m_size_is_synthesized (false),
m_size_is_valid (rhs.m_size_is_valid),
m_demangled_is_synthesized (rhs.m_demangled_is_synthesized),
+ m_contains_linker_annotations (rhs.m_contains_linker_annotations),
m_type (rhs.m_type),
m_mangled (rhs.m_mangled),
m_addr_range (rhs.m_addr_range),
@@ -144,6 +149,7 @@ Symbol::operator= (const Symbol& rhs)
m_size_is_synthesized = rhs.m_size_is_sibling;
m_size_is_valid = rhs.m_size_is_valid;
m_demangled_is_synthesized = rhs.m_demangled_is_synthesized;
+ m_contains_linker_annotations = rhs.m_contains_linker_annotations;
m_type = rhs.m_type;
m_mangled = rhs.m_mangled;
m_addr_range = rhs.m_addr_range;
@@ -166,6 +172,7 @@ Symbol::Clear()
m_size_is_synthesized = false;
m_size_is_valid = false;
m_demangled_is_synthesized = false;
+ m_contains_linker_annotations = false;
m_type = eSymbolTypeInvalid;
m_flags = 0;
m_addr_range.Clear();
diff --git a/lldb/source/Symbol/Symtab.cpp b/lldb/source/Symbol/Symtab.cpp
index e2bf984c5cc..96622d7c652 100644
--- a/lldb/source/Symbol/Symtab.cpp
+++ b/lldb/source/Symbol/Symtab.cpp
@@ -313,6 +313,13 @@ Symtab::InitNameIndexes()
if (entry.cstring && entry.cstring[0])
{
m_name_to_index.Append (entry);
+
+ if (symbol->ContainsLinkerAnnotations()) {
+ // If the symbol has linker annotations, also add the version without the
+ // annotations.
+ entry.cstring = ConstString(m_objfile->StripLinkerSymbolAnnotations(entry.cstring)).GetCString();
+ m_name_to_index.Append (entry);
+ }
const SymbolType symbol_type = symbol->GetType();
if (symbol_type == eSymbolTypeCode || symbol_type == eSymbolTypeResolver)
@@ -372,8 +379,16 @@ Symtab::InitNameIndexes()
}
entry.cstring = mangled.GetDemangledName().GetCString();
- if (entry.cstring && entry.cstring[0])
+ if (entry.cstring && entry.cstring[0]) {
m_name_to_index.Append (entry);
+
+ if (symbol->ContainsLinkerAnnotations()) {
+ // If the symbol has linker annotations, also add the version without the
+ // annotations.
+ entry.cstring = ConstString(m_objfile->StripLinkerSymbolAnnotations(entry.cstring)).GetCString();
+ m_name_to_index.Append (entry);
+ }
+ }
// If the demangled name turns out to be an ObjC name, and
// is a category name, add the version without categories to the index too.
OpenPOWER on IntegriCloud