[Lldb-commits] [lldb] r249119 - Fix several issues around .ARM.exidx section handling

Tamas Berghammer via lldb-commits lldb-commits at lists.llvm.org
Fri Oct 2 04:58:29 PDT 2015


Author: tberghammer
Date: Fri Oct  2 06:58:26 2015
New Revision: 249119

URL: http://llvm.org/viewvc/llvm-project?rev=249119&view=rev
Log:
Fix several issues around .ARM.exidx section handling

* Use .ARM.exidx as a fallback unwind plan for non-call site when the
  instruction emulation based unwind failed.
* Work around an old compiler issue where the compiler isn't sort the
  entries in .ARM.exidx based on their address.
* Fix unwind info parsing when the virtual file address >= 0x80000000
* Fix bug in unwind info parsing when neither lr nor pc is explicitly
  restored.

Differential revision: http://reviews.llvm.org/D13380

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

Modified: lldb/trunk/include/lldb/Symbol/ArmUnwindInfo.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Symbol/ArmUnwindInfo.h?rev=249119&r1=249118&r2=249119&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Symbol/ArmUnwindInfo.h (original)
+++ lldb/trunk/include/lldb/Symbol/ArmUnwindInfo.h Fri Oct  2 06:58:26 2015
@@ -43,6 +43,18 @@ public:
     GetUnwindPlan(Target &target, const Address& addr, UnwindPlan& unwind_plan);
 
 private:
+    struct ArmExidxEntry
+    {
+        ArmExidxEntry(uint32_t f, lldb::addr_t a, uint32_t d);
+
+        bool
+        operator<(const ArmExidxEntry& other) const;
+
+        uint32_t file_address;
+        lldb::addr_t address;
+        uint32_t data;
+    };
+
     const uint8_t*
     GetExceptionHandlingTableEntry(const Address& addr);
 
@@ -57,6 +69,7 @@ private:
     lldb::SectionSP m_arm_extab_sp; // .ARM.extab section
     DataExtractor m_arm_exidx_data; // .ARM.exidx section data
     DataExtractor m_arm_extab_data; // .ARM.extab section data
+    std::vector<ArmExidxEntry> m_exidx_entries;
 };
 
 } // namespace lldb_private

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=249119&r1=249118&r2=249119&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/Utility/RegisterContextLLDB.cpp (original)
+++ lldb/trunk/source/Plugins/Process/Utility/RegisterContextLLDB.cpp Fri Oct  2 06:58:26 2015
@@ -881,12 +881,12 @@ RegisterContextLLDB::GetFullUnwindPlanFo
                 // then the architecture default plan and for hand written assembly code it is often
                 // written in a way that it valid at all location what helps in the most common
                 // cases when the instruction emulation fails.
-                UnwindPlanSP eh_frame_unwind_plan = func_unwinders_sp->GetEHFrameUnwindPlan (process->GetTarget(), m_current_offset_backed_up_one);
-                if (eh_frame_unwind_plan &&
-                    eh_frame_unwind_plan.get() != unwind_plan_sp.get() &&
-                    eh_frame_unwind_plan->GetSourceName() != unwind_plan_sp->GetSourceName())
+                UnwindPlanSP call_site_unwind_plan = func_unwinders_sp->GetUnwindPlanAtCallSite(process->GetTarget(), m_current_offset_backed_up_one);
+                if (call_site_unwind_plan &&
+                    call_site_unwind_plan.get() != unwind_plan_sp.get() &&
+                    call_site_unwind_plan->GetSourceName() != unwind_plan_sp->GetSourceName())
                 {
-                    m_fallback_unwind_plan_sp = eh_frame_unwind_plan;
+                    m_fallback_unwind_plan_sp = call_site_unwind_plan;
                 }
                 else
                 {
@@ -926,12 +926,12 @@ RegisterContextLLDB::GetFullUnwindPlanFo
         // more reliable even on non call sites then the architecture default plan and for hand
         // written assembly code it is often written in a way that it valid at all location what
         // helps in the most common cases when the instruction emulation fails.
-        UnwindPlanSP eh_frame_unwind_plan = func_unwinders_sp->GetEHFrameUnwindPlan (process->GetTarget(), m_current_offset_backed_up_one);
-        if (eh_frame_unwind_plan &&
-            eh_frame_unwind_plan.get() != unwind_plan_sp.get() &&
-            eh_frame_unwind_plan->GetSourceName() != unwind_plan_sp->GetSourceName())
+        UnwindPlanSP call_site_unwind_plan = func_unwinders_sp->GetUnwindPlanAtCallSite(process->GetTarget(), m_current_offset_backed_up_one);
+        if (call_site_unwind_plan &&
+            call_site_unwind_plan.get() != unwind_plan_sp.get() &&
+            call_site_unwind_plan->GetSourceName() != unwind_plan_sp->GetSourceName())
         {
-            m_fallback_unwind_plan_sp = eh_frame_unwind_plan;
+            m_fallback_unwind_plan_sp = call_site_unwind_plan;
         }
         else
         {

Modified: lldb/trunk/source/Symbol/ArmUnwindInfo.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Symbol/ArmUnwindInfo.cpp?rev=249119&r1=249118&r2=249119&view=diff
==============================================================================
--- lldb/trunk/source/Symbol/ArmUnwindInfo.cpp (original)
+++ lldb/trunk/source/Symbol/ArmUnwindInfo.cpp Fri Oct  2 06:58:26 2015
@@ -30,14 +30,26 @@
 using namespace lldb;
 using namespace lldb_private;
 
-namespace
+// Converts a prel31 avlue to lldb::addr_t with sign extension
+static addr_t
+Prel31ToAddr(uint32_t prel31)
 {
-    struct ArmExidxEntry
-    {
-        uint32_t address;
-        uint32_t data;
-    };
-};
+    addr_t res = prel31;
+    if (prel31 & (1<<30))
+        res |= 0xffffffff80000000ULL;
+    return res;
+}
+
+ArmUnwindInfo::ArmExidxEntry::ArmExidxEntry(uint32_t f, lldb::addr_t a, uint32_t d) :
+    file_address(f), address(a), data(d)
+{
+}
+
+bool
+ArmUnwindInfo::ArmExidxEntry::operator<(const ArmExidxEntry& other) const
+{
+    return address < other.address;
+}
 
 ArmUnwindInfo::ArmUnwindInfo(const ObjectFile& objfile,
                              SectionSP& arm_exidx,
@@ -48,6 +60,23 @@ ArmUnwindInfo::ArmUnwindInfo(const Objec
 {
     objfile.ReadSectionData(arm_exidx.get(), m_arm_exidx_data);
     objfile.ReadSectionData(arm_extab.get(), m_arm_extab_data);
+
+    addr_t exidx_base_addr = m_arm_exidx_sp->GetFileAddress();
+
+    offset_t offset = 0;
+    while (m_arm_exidx_data.ValidOffset(offset))
+    {
+        lldb::addr_t file_addr = exidx_base_addr + offset;
+        lldb::addr_t addr = exidx_base_addr +
+                            (addr_t)offset +
+                            Prel31ToAddr(m_arm_exidx_data.GetU32(&offset));
+        uint32_t data = m_arm_exidx_data.GetU32(&offset);
+        m_exidx_entries.emplace_back(file_addr, addr, data);
+    }
+
+    // Sort the entries in the exidx section. The entries should be sorted inside the section but
+    // some old compiler isn't sorted them.
+    std::sort(m_exidx_entries.begin(), m_exidx_entries.end());
 }
 
 ArmUnwindInfo::~ArmUnwindInfo()
@@ -85,7 +114,7 @@ ArmUnwindInfo::GetULEB128(const uint32_t
 bool
 ArmUnwindInfo::GetUnwindPlan(Target &target, const Address& addr, UnwindPlan& unwind_plan)
 {
-    const uint32_t* data = (const uint32_t*)GetExceptionHandlingTableEntry(addr.GetFileAddress());
+    const uint32_t* data = (const uint32_t*)GetExceptionHandlingTableEntry(addr);
     if (data == nullptr)
         return false; // No unwind information for the function
 
@@ -382,6 +411,8 @@ ArmUnwindInfo::GetUnwindPlan(Target &tar
         UnwindPlan::Row::RegisterLocation lr_location;
         if (row->GetRegisterInfo(dwarf_lr, lr_location))
             row->SetRegisterInfo(dwarf_pc, lr_location);
+        else
+            row->SetRegisterLocationToRegister(dwarf_pc, dwarf_lr, false);
     }
 
     unwind_plan.AppendRow(row);
@@ -396,38 +427,19 @@ ArmUnwindInfo::GetUnwindPlan(Target &tar
 const uint8_t*
 ArmUnwindInfo::GetExceptionHandlingTableEntry(const Address& addr)
 {
-    uint32_t file_addr = addr.GetFileAddress();
-    uint32_t exidx_base_addr = m_arm_exidx_sp->GetFileAddress();
-
-    const ArmExidxEntry* exidx_start = (const ArmExidxEntry*)m_arm_exidx_data.GetDataStart();
-    uint32_t bs_start = 0, bs_end = m_arm_exidx_data.GetByteSize() / sizeof(ArmExidxEntry);
-    while (bs_start + 1 < bs_end)
-    {
-        uint32_t mid = (bs_start + bs_end) / 2;
-        uint32_t mid_addr = exidx_base_addr + exidx_start[mid].address + mid * sizeof(ArmExidxEntry);
-        mid_addr &= 0x7fffffff;
-        if (mid_addr > file_addr)
-            bs_end = mid;
-        else
-            bs_start = mid;
-    }
-
-    uint32_t exidx_addr = exidx_base_addr +
-                          exidx_start[bs_start].address +
-                          bs_start * sizeof(ArmExidxEntry);
-    exidx_addr &= 0x7fffffff;
-    if (exidx_addr > file_addr)
+    auto it = std::upper_bound(m_exidx_entries.begin(),
+                               m_exidx_entries.end(),
+                               ArmExidxEntry{0, addr.GetFileAddress(), 0});
+    if (it == m_exidx_entries.begin())
         return nullptr;
+    --it;
 
-    if (exidx_start[bs_start].data == 0x1)
+    if (it->data == 0x1)
         return nullptr; // EXIDX_CANTUNWIND
 
-    if (exidx_start[bs_start].data & 0x80000000)
-        return (const uint8_t*)&exidx_start[bs_start].data;
+    if (it->data & 0x80000000)
+        return (const uint8_t*)&it->data;
 
-    uint32_t data_file_addr = exidx_base_addr +
-                              8 * bs_start + 4 +
-                              exidx_start[bs_start].data;
-    data_file_addr &= 0x7fffffff;
+    addr_t data_file_addr = it->file_address + 4 + Prel31ToAddr(it->data);
     return m_arm_extab_data.GetDataStart() + (data_file_addr - m_arm_extab_sp->GetFileAddress());
 }




More information about the lldb-commits mailing list