[Lldb-commits] [lldb] r231228 - Correctly resolve symbol names containing linker annotations

Pavel Labath labath at google.com
Wed Mar 4 02:25:22 PST 2015


Author: labath
Date: Wed Mar  4 04:25:22 2015
New Revision: 231228

URL: http://llvm.org/viewvc/llvm-project?rev=231228&view=rev
Log:
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 at VERSION), which causes issues when evaluating expressions
referencing memcpy for example (current glibc contains memcpy@@GLIBC_2.14 and
memcpy at 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

Modified:
    lldb/trunk/include/lldb/Symbol/ObjectFile.h
    lldb/trunk/include/lldb/Symbol/Symbol.h
    lldb/trunk/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp
    lldb/trunk/source/Plugins/ObjectFile/ELF/ObjectFileELF.h
    lldb/trunk/source/Symbol/Symbol.cpp
    lldb/trunk/source/Symbol/Symtab.cpp

Modified: lldb/trunk/include/lldb/Symbol/ObjectFile.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Symbol/ObjectFile.h?rev=231228&r1=231227&r2=231228&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Symbol/ObjectFile.h (original)
+++ lldb/trunk/include/lldb/Symbol/ObjectFile.h Wed Mar  4 04:25:22 2015
@@ -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:
     //------------------------------------------------------------------

Modified: lldb/trunk/include/lldb/Symbol/Symbol.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Symbol/Symbol.h?rev=231228&r1=231227&r2=231228&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Symbol/Symbol.h (original)
+++ lldb/trunk/include/lldb/Symbol/Symbol.h Wed Mar  4 04:25:22 2015
@@ -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

Modified: lldb/trunk/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp?rev=231228&r1=231227&r2=231228&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp (original)
+++ lldb/trunk/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp Wed Mar  4 04:25:22 2015
@@ -1504,6 +1504,13 @@ ObjectFileELF::GetSegmentDataByIndex(lld
     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 *sym
         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(c
                         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);

Modified: lldb/trunk/source/Plugins/ObjectFile/ELF/ObjectFileELF.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/ObjectFile/ELF/ObjectFileELF.h?rev=231228&r1=231227&r2=231228&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/ObjectFile/ELF/ObjectFileELF.h (original)
+++ lldb/trunk/source/Plugins/ObjectFile/ELF/ObjectFileELF.h Wed Mar  4 04:25:22 2015
@@ -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,

Modified: lldb/trunk/source/Symbol/Symbol.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Symbol/Symbol.cpp?rev=231228&r1=231227&r2=231228&view=diff
==============================================================================
--- lldb/trunk/source/Symbol/Symbol.cpp (original)
+++ lldb/trunk/source/Symbol/Symbol.cpp Wed Mar  4 04:25:22 2015
@@ -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();

Modified: lldb/trunk/source/Symbol/Symtab.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Symbol/Symtab.cpp?rev=231228&r1=231227&r2=231228&view=diff
==============================================================================
--- lldb/trunk/source/Symbol/Symtab.cpp (original)
+++ lldb/trunk/source/Symbol/Symtab.cpp Wed Mar  4 04:25:22 2015
@@ -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.





More information about the lldb-commits mailing list