Index: lldb/trunk/include/lldb/Symbol/ArmUnwindInfo.h =================================================================== --- lldb/trunk/include/lldb/Symbol/ArmUnwindInfo.h +++ lldb/trunk/include/lldb/Symbol/ArmUnwindInfo.h @@ -43,6 +43,18 @@ 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 @@ 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 m_exidx_entries; }; } // namespace lldb_private Index: lldb/trunk/source/Plugins/Process/Utility/RegisterContextLLDB.cpp =================================================================== --- lldb/trunk/source/Plugins/Process/Utility/RegisterContextLLDB.cpp +++ lldb/trunk/source/Plugins/Process/Utility/RegisterContextLLDB.cpp @@ -881,12 +881,12 @@ // 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 @@ // 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 { Index: lldb/trunk/source/Symbol/ArmUnwindInfo.cpp =================================================================== --- lldb/trunk/source/Symbol/ArmUnwindInfo.cpp +++ lldb/trunk/source/Symbol/ArmUnwindInfo.cpp @@ -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 @@ { 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 @@ 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 @@ 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 @@ 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()); }