[Lldb-commits] [lldb] r221788 - Add an alternative CFA type.

Justin Hibbits jrh29 at alumni.cwru.edu
Wed Nov 12 07:14:03 PST 2014


Author: jhibbits
Date: Wed Nov 12 09:14:03 2014
New Revision: 221788

URL: http://llvm.org/viewvc/llvm-project?rev=221788&view=rev
Log:
Add an alternative CFA type.

Summary:
PowerPC handles the stack chain with the current stack pointer being a pointer
to the backchain (CFA).  LLDB currently has no way of handling this, so this
adds a "CFA is dereferenced from a register" type.

Discussed with Jason Molenda, who also provided the initial patch for this.

Reviewers: jasonmolenda

Reviewed By: jasonmolenda

Subscribers: emaste, lldb-commits

Differential Revision: http://reviews.llvm.org/D6182

Modified:
    lldb/trunk/include/lldb/Symbol/UnwindPlan.h
    lldb/trunk/source/Plugins/Process/Utility/RegisterContextLLDB.cpp
    lldb/trunk/source/Plugins/Process/Utility/RegisterContextLLDB.h
    lldb/trunk/source/Symbol/UnwindPlan.cpp

Modified: lldb/trunk/include/lldb/Symbol/UnwindPlan.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Symbol/UnwindPlan.h?rev=221788&r1=221787&r2=221788&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Symbol/UnwindPlan.h (original)
+++ lldb/trunk/include/lldb/Symbol/UnwindPlan.h Wed Nov 12 09:14:03 2014
@@ -58,13 +58,13 @@ public:
                     atDWARFExpression,  // reg = deref(eval(dwarf_expr))
                     isDWARFExpression   // reg = eval(dwarf_expr)
                 };
-    
+
             RegisterLocation() : 
                 m_type(unspecified), 
                 m_location() 
             {
             }
-    
+
             bool
             operator == (const RegisterLocation& rhs) const;
     
@@ -242,6 +242,7 @@ public:
     
         Row (const UnwindPlan::Row& rhs) : 
             m_offset             (rhs.m_offset),
+            m_cfa_type           (rhs.m_cfa_type),
             m_cfa_reg_num        (rhs.m_cfa_reg_num),
             m_cfa_offset         (rhs.m_cfa_offset),
             m_register_locations (rhs.m_register_locations)
@@ -275,12 +276,50 @@ public:
             m_offset += offset;
         }
 
+        // How we can reconstruct the CFA address for this stack frame, at this location
+        enum CFAType
+        {
+            CFAIsRegisterPlusOffset,   // the CFA value in a register plus (or minus) an offset
+            CFAIsRegisterDereferenced  // the address in a register is dereferenced to get CFA value
+        };
+
+        CFAType
+        GetCFAType () const
+        {
+            return m_cfa_type;
+        }
+
+        void
+        SetCFAType (CFAType cfa_type)
+        {
+            m_cfa_type = cfa_type;
+        }
+
+        // This should be used when GetCFAType() returns CFAIsRegisterPlusOffset
         uint32_t
         GetCFARegister () const
         {
             return m_cfa_reg_num;
         }
         
+        // This should be used when GetCFAType() is set to CFAIsRegisterPlusOffset
+        void
+        SetCFARegister (uint32_t reg_num);
+
+        // This should be used when GetCFAType() returns CFAIsRegisterPlusOffset
+        int32_t
+        GetCFAOffset () const
+        {
+            return m_cfa_offset;
+        }
+
+        // This should be used when GetCFAType() is set to CFAIsRegisterPlusOffset
+        void
+        SetCFAOffset (int32_t offset)
+        {
+            m_cfa_offset = offset;
+        }
+
         bool
         SetRegisterLocationToAtCFAPlusOffset (uint32_t reg_num, 
                                               int32_t offset, 
@@ -309,23 +348,6 @@ public:
         SetRegisterLocationToSame (uint32_t reg_num, 
                                    bool must_replace);
 
-
-
-        void
-        SetCFARegister (uint32_t reg_num);
-
-        int32_t
-        GetCFAOffset () const
-        {
-            return m_cfa_offset;
-        }
-
-        void
-        SetCFAOffset (int32_t offset)
-        {
-            m_cfa_offset = offset;
-        }
-
         void
         Clear ();
 
@@ -335,8 +357,13 @@ public:
     protected:
         typedef std::map<uint32_t, RegisterLocation> collection;
         lldb::addr_t m_offset;      // Offset into the function for this row
+
+        CFAType m_cfa_type;
+
+        // If m_cfa_type == CFAIsRegisterPlusOffset, the following ivars are used
         uint32_t m_cfa_reg_num;     // The Call Frame Address register number
         int32_t  m_cfa_offset;      // The offset from the CFA for this row
+
         collection m_register_locations;
     }; // class Row
 

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=221788&r1=221787&r2=221788&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/Utility/RegisterContextLLDB.cpp (original)
+++ lldb/trunk/source/Plugins/Process/Utility/RegisterContextLLDB.cpp Wed Nov 12 09:14:03 2014
@@ -232,7 +232,6 @@ RegisterContextLLDB::InitializeZerothFra
     m_full_unwind_plan_sp = GetFullUnwindPlanForFrame ();
 
     UnwindPlan::RowSP active_row;
-    int cfa_offset = 0;
     lldb::RegisterKind row_register_kind = eRegisterKindGeneric;
     if (m_full_unwind_plan_sp && m_full_unwind_plan_sp->PlanValidAtAddress (m_current_pc))
     {
@@ -254,18 +253,13 @@ RegisterContextLLDB::InitializeZerothFra
     }
 
 
-    addr_t cfa_regval = LLDB_INVALID_ADDRESS;
-    if (!ReadGPRValue (row_register_kind, active_row->GetCFARegister(), cfa_regval))
+    if (!ReadCFAValueForRow (row_register_kind, active_row, m_cfa))
     {
         UnwindLogMsg ("could not read CFA register for this frame.");
         m_frame_type = eNotAValidFrame;
         return;
     }
 
-    cfa_offset = active_row->GetCFAOffset ();
-    m_cfa = cfa_regval + cfa_offset;
-
-    UnwindLogMsg ("cfa_regval = 0x%16.16" PRIx64 " (cfa_regval = 0x%16.16" PRIx64 ", cfa_offset = %i)", m_cfa, cfa_regval, cfa_offset);
     UnwindLogMsg ("initialized frame current pc is 0x%" PRIx64 " cfa is 0x%" PRIx64 " using %s UnwindPlan",
             (uint64_t) m_current_pc.GetLoadAddress (exe_ctx.GetTargetPtr()),
             (uint64_t) m_cfa,
@@ -378,14 +372,11 @@ RegisterContextLLDB::InitializeNonZeroth
             m_all_registers_available = false;
             m_current_offset = -1;
             m_current_offset_backed_up_one = -1;
-            addr_t cfa_regval = LLDB_INVALID_ADDRESS;
             RegisterKind row_register_kind = m_full_unwind_plan_sp->GetRegisterKind ();
             UnwindPlan::RowSP row = m_full_unwind_plan_sp->GetRowForFunctionOffset(0);
             if (row.get())
             {
-                uint32_t cfa_regnum = row->GetCFARegister();
-                int cfa_offset = row->GetCFAOffset();
-                if (!ReadGPRValue (row_register_kind, cfa_regnum, cfa_regval))
+                if (!ReadCFAValueForRow (row_register_kind, row, m_cfa))
                 {
                     UnwindLogMsg ("failed to get cfa value");
                     if (m_frame_type != eSkipFrame)   // don't override eSkipFrame
@@ -394,19 +385,18 @@ RegisterContextLLDB::InitializeNonZeroth
                     }
                     return;
                 }
-                m_cfa = cfa_regval + cfa_offset;
 
                 // A couple of sanity checks..
-                if (cfa_regval == LLDB_INVALID_ADDRESS || cfa_regval == 0 || cfa_regval == 1)
+                if (m_cfa == LLDB_INVALID_ADDRESS || m_cfa == 0 || m_cfa == 1)
                 {
                     UnwindLogMsg ("could not find a valid cfa address");
                     m_frame_type = eNotAValidFrame;
                     return;
                 }
 
-                // cfa_regval should point into the stack memory; if we can query memory region permissions,
+                // m_cfa should point into the stack memory; if we can query memory region permissions,
                 // see if the memory is allocated & readable.
-                if (process->GetLoadAddressPermissions(cfa_regval, permissions)
+                if (process->GetLoadAddressPermissions(m_cfa, permissions)
                     && (permissions & ePermissionsReadable) == 0)
                 {
                     m_frame_type = eNotAValidFrame;
@@ -600,8 +590,7 @@ RegisterContextLLDB::InitializeNonZeroth
         return;
     }
 
-    addr_t cfa_regval = LLDB_INVALID_ADDRESS;
-    if (!ReadGPRValue (row_register_kind, active_row->GetCFARegister(), cfa_regval))
+    if (!ReadCFAValueForRow (row_register_kind, active_row, m_cfa))
     {
         UnwindLogMsg ("failed to get cfa reg %d/%d", row_register_kind, active_row->GetCFARegister());
         m_frame_type = eNotAValidFrame;
@@ -609,12 +598,11 @@ RegisterContextLLDB::InitializeNonZeroth
     }
 
     cfa_offset = active_row->GetCFAOffset ();
-    m_cfa = cfa_regval + cfa_offset;
 
-    UnwindLogMsg ("cfa_regval = 0x%16.16" PRIx64 " (cfa_regval = 0x%16.16" PRIx64 ", cfa_offset = %i)", m_cfa, cfa_regval, cfa_offset);
+    UnwindLogMsg ("m_cfa = 0x%16.16" PRIx64 " (cfa_offset = %i)", m_cfa, cfa_offset);
 
     // A couple of sanity checks..
-    if (cfa_regval == LLDB_INVALID_ADDRESS || cfa_regval == 0 || cfa_regval == 1)
+    if (m_cfa == LLDB_INVALID_ADDRESS || m_cfa == (addr_t)cfa_offset || m_cfa == (addr_t)cfa_offset + 1)
     {
         UnwindLogMsg ("could not find a valid cfa address");
         m_frame_type = eNotAValidFrame;
@@ -1478,11 +1466,8 @@ RegisterContextLLDB::TryFallbackUnwindPl
     {
         m_registers.clear();
         m_full_unwind_plan_sp = m_fallback_unwind_plan_sp;
-        addr_t cfa_regval = LLDB_INVALID_ADDRESS;
-        if (ReadGPRValue (m_fallback_unwind_plan_sp->GetRegisterKind(), active_row->GetCFARegister(), cfa_regval))
-        {
-            m_cfa = cfa_regval + active_row->GetCFAOffset ();
-        }
+        m_cfa = LLDB_INVALID_ADDRESS;
+        ReadCFAValueForRow(m_fallback_unwind_plan_sp->GetRegisterKind(), active_row, m_cfa);
 
         UnwindLogMsg ("trying to unwind from this function with the UnwindPlan '%s' because UnwindPlan '%s' failed.", 
                       m_fallback_unwind_plan_sp->GetSourceName().GetCString(),
@@ -1493,6 +1478,38 @@ RegisterContextLLDB::TryFallbackUnwindPl
     return true;
 }
 
+bool
+RegisterContextLLDB::ReadCFAValueForRow (lldb::RegisterKind row_register_kind,
+                                         const UnwindPlan::RowSP &row,
+                                         addr_t &value)
+{
+    uint32_t cfa_regnum = row->GetCFARegister();
+    RegisterValue reg_value;
+    addr_t tmp;
+
+    value = LLDB_INVALID_ADDRESS;
+
+    if (ReadGPRValue (row_register_kind, cfa_regnum, value))
+    {
+        if (row->GetCFAType() == UnwindPlan::Row::CFAIsRegisterDereferenced)
+        {
+            const RegisterInfo *reg_info = GetRegisterInfoAtIndex(cfa_regnum);
+            RegisterValue reg_value;
+            tmp = value;
+            Error error = ReadRegisterValueFromMemory(reg_info,
+                                                      value,
+                                                      reg_info->byte_size,
+                                                      reg_value);
+            value = reg_value.GetAsUInt64();
+            UnwindLogMsg("dereferenced address: 0x%16.16" PRIx64 " yields: %lx", tmp, value);
+            return error.Success();
+        }
+        value = value + row->GetCFAOffset ();
+        return true;
+    }
+    return false;
+}
+
 // Retrieve a general purpose register value for THIS frame, as saved by the NEXT frame, i.e. the frame that
 // this frame called.  e.g.
 //

Modified: lldb/trunk/source/Plugins/Process/Utility/RegisterContextLLDB.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Utility/RegisterContextLLDB.h?rev=221788&r1=221787&r2=221788&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/Utility/RegisterContextLLDB.h (original)
+++ lldb/trunk/source/Plugins/Process/Utility/RegisterContextLLDB.h Wed Nov 12 09:14:03 2014
@@ -333,6 +333,10 @@ private:
     bool
     ReadGPRValue (lldb::RegisterKind register_kind, uint32_t regnum, lldb::addr_t &value);
 
+    // Get the CFA register for a given frame.
+    bool
+    ReadCFAValueForRow (lldb::RegisterKind register_kind, const UnwindPlan::RowSP &row, lldb::addr_t &value);
+
     lldb::UnwindPlanSP
     GetFastUnwindPlanForFrame ();
 

Modified: lldb/trunk/source/Symbol/UnwindPlan.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Symbol/UnwindPlan.cpp?rev=221788&r1=221787&r2=221788&view=diff
==============================================================================
--- lldb/trunk/source/Symbol/UnwindPlan.cpp (original)
+++ lldb/trunk/source/Symbol/UnwindPlan.cpp Wed Nov 12 09:14:03 2014
@@ -153,6 +153,7 @@ UnwindPlan::Row::RegisterLocation::Dump
 void
 UnwindPlan::Row::Clear ()
 {
+    m_cfa_type = CFAIsRegisterPlusOffset;
     m_offset = 0;
     m_cfa_reg_num = LLDB_INVALID_REGNUM;
     m_cfa_offset = 0;
@@ -189,10 +190,11 @@ UnwindPlan::Row::Dump (Stream& s, const
 }
 
 UnwindPlan::Row::Row() :
-    m_offset(0),
-    m_cfa_reg_num(LLDB_INVALID_REGNUM),
-    m_cfa_offset(0),
-    m_register_locations()
+    m_offset (0),
+    m_cfa_type (CFAIsRegisterPlusOffset),
+    m_cfa_reg_num (LLDB_INVALID_REGNUM),
+    m_cfa_offset (0),
+    m_register_locations ()
 {
 }
 
@@ -301,6 +303,23 @@ UnwindPlan::Row::operator == (const Unwi
 {
     if (m_offset != rhs.m_offset || m_cfa_reg_num != rhs.m_cfa_reg_num || m_cfa_offset != rhs.m_cfa_offset)
         return false;
+
+    if (m_cfa_type != rhs.m_cfa_type)
+        return false;
+
+    if (m_cfa_type == CFAIsRegisterPlusOffset)
+    {
+        if (m_cfa_reg_num != rhs.m_cfa_reg_num)
+            return false;
+        if (m_cfa_offset != rhs.m_cfa_offset)
+            return false;
+    }
+    if (m_cfa_type == CFAIsRegisterDereferenced)
+    {
+        if (m_cfa_reg_num != rhs.m_cfa_reg_num)
+            return false;
+    }
+
     return m_register_locations == rhs.m_register_locations;
 }
 





More information about the lldb-commits mailing list