[Lldb-commits] [lldb] r190812 - Fixes symbol resolution for a function with a tail call because the PC

Ashok Thirumurthi ashok.thirumurthi at intel.com
Mon Sep 16 15:00:17 PDT 2013


Author: athirumu
Date: Mon Sep 16 17:00:17 2013
New Revision: 190812

URL: http://llvm.org/viewvc/llvm-project?rev=190812&view=rev
Log:
Fixes symbol resolution for a function with a tail call because the PC
for the frame is one past the address range of the calling function.
- Lowers the fix from RegisterContextLLDB for use with disassembly
- Fixes one of three issues in the disassembly test in TestInferiorAssert.py

Also adds documentation that explains the resolution depths and interface.

Note: This change affects the resolution scope for eSymbolContextFunction
without impacting the performance of eSymbolContextSymbol.

Thanks to Matt Kopec for his review.

Modified:
    lldb/trunk/include/lldb/Core/Module.h
    lldb/trunk/source/Core/Module.cpp
    lldb/trunk/source/Plugins/Process/Utility/RegisterContextLLDB.cpp

Modified: lldb/trunk/include/lldb/Core/Module.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Core/Module.h?rev=190812&r1=190811&r2=190812&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Core/Module.h (original)
+++ lldb/trunk/include/lldb/Core/Module.h Mon Sep 16 17:00:17 2013
@@ -749,6 +749,38 @@ public:
     bool
     ResolveFileAddress (lldb::addr_t vm_addr, Address& so_addr);
 
+    //------------------------------------------------------------------
+    /// Resolve the symbol context for the given address.
+    ///
+    /// Tries to resolve the matching symbol context based on a lookup
+    /// from the current symbol vendor.  If the lazy lookup fails,
+    /// an attempt is made to parse the eh_frame section to handle 
+    /// stripped symbols.  If this fails, an attempt is made to resolve
+    /// the symbol to the previous address to handle the case of a 
+    /// function with a tail call.
+    ///
+    /// Use properties of the modified SymbolContext to inspect any
+    /// resolved target, module, compilation unit, symbol, function,
+    /// function block or line entry.  Use the return value to determine
+    /// which of these properties have been modified.
+    ///
+    /// @param[in] so_addr
+    ///     A load address to resolve.
+    ///
+    /// @param[in] resolve_scope
+    ///     The scope that should be resolved (see SymbolContext::Scope).
+    ///     A combination of flags from the enumeration SymbolContextItem
+    ///     requesting a resolution depth.  Note that the flags that are
+    ///     actually resolved may be a superset of the requested flags.
+    ///     For instance, eSymbolContextSymbol requires resolution of
+    ///     eSymbolContextModule, and eSymbolContextFunction requires
+    ///     eSymbolContextSymbol.
+    ///
+    /// @return
+    ///     The scope that has been resolved (see SymbolContext::Scope).
+    ///
+    /// @see SymbolContext::Scope
+    //------------------------------------------------------------------
     uint32_t
     ResolveSymbolContextForAddress (const Address& so_addr, uint32_t resolve_scope, SymbolContext& sc);
 

Modified: lldb/trunk/source/Core/Module.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Core/Module.cpp?rev=190812&r1=190811&r2=190812&view=diff
==============================================================================
--- lldb/trunk/source/Core/Module.cpp (original)
+++ lldb/trunk/source/Core/Module.cpp Mon Sep 16 17:00:17 2013
@@ -468,6 +468,10 @@ Module::ResolveSymbolContextForAddress (
         sc.module_sp = shared_from_this();
         resolved_flags |= eSymbolContextModule;
 
+        SymbolVendor* sym_vendor = GetSymbolVendor();
+        if (!sym_vendor)
+            return resolved_flags;
+
         // Resolve the compile unit, function, block, line table or line
         // entry if requested.
         if (resolve_scope & eSymbolContextCompUnit    ||
@@ -475,25 +479,51 @@ Module::ResolveSymbolContextForAddress (
             resolve_scope & eSymbolContextBlock       ||
             resolve_scope & eSymbolContextLineEntry   )
         {
-            SymbolVendor *symbols = GetSymbolVendor ();
-            if (symbols)
-                resolved_flags |= symbols->ResolveSymbolContext (so_addr, resolve_scope, sc);
+            resolved_flags |= sym_vendor->ResolveSymbolContext (so_addr, resolve_scope, sc);
         }
 
         // Resolve the symbol if requested, but don't re-look it up if we've already found it.
         if (resolve_scope & eSymbolContextSymbol && !(resolved_flags & eSymbolContextSymbol))
         {
-            SymbolVendor* sym_vendor = GetSymbolVendor();
-            if (sym_vendor)
+            Symtab *symtab = sym_vendor->GetSymtab();
+            if (symtab && so_addr.IsSectionOffset())
             {
-                Symtab *symtab = sym_vendor->GetSymtab();
-                if (symtab)
+                sc.symbol = symtab->FindSymbolContainingFileAddress(so_addr.GetFileAddress());
+                if (sc.symbol)
+                    resolved_flags |= eSymbolContextSymbol;
+            }
+        }
+
+        // For function symbols, so_addr may be off by one.  This is a convention consistent
+        // with FDE row indices in eh_frame sections, but requires extra logic here to permit
+        // symbol lookup for disassembly and unwind.
+        if (resolve_scope & eSymbolContextSymbol && !(resolved_flags & eSymbolContextSymbol) &&
+            resolve_scope & eSymbolContextFunction && !(resolved_flags & eSymbolContextFunction) &&
+            so_addr.GetOffset() > 0)
+        {
+            Address previous_addr = so_addr;
+            previous_addr.SetOffset(so_addr.GetOffset() - 1);
+
+            const uint32_t flags = sym_vendor->ResolveSymbolContext (previous_addr, resolve_scope, sc);
+            if (flags & eSymbolContextSymbol)
+            {
+                AddressRange addr_range;
+                if (sc.GetAddressRange (eSymbolContextFunction | eSymbolContextSymbol, 0, false, addr_range))
                 {
-                    if (so_addr.IsSectionOffset())
+                    if (addr_range.GetBaseAddress().GetSection() == so_addr.GetSection())
+                    {
+                        // If the requested address is one past the address range of a function (i.e. a tail call),
+                        // or the decremented address is the start of a function (i.e. some forms of trampoline),
+                        // indicate that the symbol has been resolved.
+                        if (so_addr.GetOffset() == addr_range.GetBaseAddress().GetOffset() ||
+                            so_addr.GetOffset() == addr_range.GetBaseAddress().GetOffset() + addr_range.GetByteSize())
+                        {
+                            resolved_flags |= flags;
+                        }
+                    }
+                    else
                     {
-                        sc.symbol = symtab->FindSymbolContainingFileAddress(so_addr.GetFileAddress());
-                        if (sc.symbol)
-                            resolved_flags |= eSymbolContextSymbol;
+                        sc.symbol = nullptr; // Don't trust the symbol if the sections didn't match.
                     }
                 }
             }

Modified: lldb/trunk/source/Plugins/Process/Utility/RegisterContextLLDB.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Utility/RegisterContextLLDB.cpp?rev=190812&r1=190811&r2=190812&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/Utility/RegisterContextLLDB.cpp (original)
+++ lldb/trunk/source/Plugins/Process/Utility/RegisterContextLLDB.cpp Mon Sep 16 17:00:17 2013
@@ -387,35 +387,18 @@ RegisterContextLLDB::InitializeNonZeroth
     if (m_sym_ctx_valid == false)
        decr_pc_and_recompute_addr_range = true;
 
-    // Or if we're in the middle of the stack (and not "above" an asynchronous event like sigtramp),
-    // and our "current" pc is the start of a function...
+    // Or if we're in the middle of the stack (and not "above" an asynchronous event like sigtramp), and
+    // our "current" pc is the start of a function or our "current" pc is one past the end of a function...
     if (m_sym_ctx_valid
         && GetNextFrame()->m_frame_type != eSigtrampFrame
         && GetNextFrame()->m_frame_type != eDebuggerFrame
         && addr_range.GetBaseAddress().IsValid()
-        && addr_range.GetBaseAddress().GetSection() == m_current_pc.GetSection()
-        && addr_range.GetBaseAddress().GetOffset() == m_current_pc.GetOffset())
+        && addr_range.GetBaseAddress().GetSection() == m_current_pc.GetSection())
     {
-        decr_pc_and_recompute_addr_range = true;
-    }
-
-    // We need to back up the pc by 1 byte and re-search for the Symbol to handle the case where the "saved pc"
-    // value is pointing to the next function, e.g. if a function ends with a CALL instruction.
-    // FIXME this may need to be an architectural-dependent behavior; if so we'll need to add a member function
-    // to the ABI plugin and consult that.
-    if (decr_pc_and_recompute_addr_range)
-    {
-        Address temporary_pc(m_current_pc);
-        temporary_pc.SetOffset(m_current_pc.GetOffset() - 1);
-        m_sym_ctx.Clear(false);
-        m_sym_ctx_valid = false;
-        if ((pc_module_sp->ResolveSymbolContextForAddress (temporary_pc, eSymbolContextFunction| eSymbolContextSymbol, m_sym_ctx) & eSymbolContextSymbol) == eSymbolContextSymbol)
-        {
-            m_sym_ctx_valid = true;
-        }
-        if (!m_sym_ctx.GetAddressRange (eSymbolContextFunction | eSymbolContextSymbol, 0, false,  addr_range))
+        if (addr_range.GetBaseAddress().GetOffset() == m_current_pc.GetOffset() ||
+            addr_range.GetBaseAddress().GetOffset() + addr_range.GetByteSize() == m_current_pc.GetOffset())
         {
-            m_sym_ctx_valid = false;
+            decr_pc_and_recompute_addr_range = true;
         }
     }
 





More information about the lldb-commits mailing list