[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