[Lldb-commits] [lldb] r248903 - Add support for .ARM.exidx unwind information
Tamas Berghammer via lldb-commits
lldb-commits at lists.llvm.org
Wed Sep 30 06:50:14 PDT 2015
Author: tberghammer
Date: Wed Sep 30 08:50:14 2015
New Revision: 248903
URL: http://llvm.org/viewvc/llvm-project?rev=248903&view=rev
Log:
Add support for .ARM.exidx unwind information
.ARM.exidx/.ARM.extab sections contain unwind information used on ARM
architecture from unwinding from an exception.
Differential revision: http://reviews.llvm.org/D13245
Added:
lldb/trunk/include/lldb/Symbol/ArmUnwindInfo.h
lldb/trunk/source/Symbol/ArmUnwindInfo.cpp
Modified:
lldb/trunk/include/lldb/Symbol/FuncUnwinders.h
lldb/trunk/include/lldb/Symbol/UnwindTable.h
lldb/trunk/include/lldb/lldb-enumerations.h
lldb/trunk/include/lldb/lldb-forward.h
lldb/trunk/source/Commands/CommandObjectTarget.cpp
lldb/trunk/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp
lldb/trunk/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp
lldb/trunk/source/Plugins/Process/Utility/RegisterContextLLDB.cpp
lldb/trunk/source/Symbol/CMakeLists.txt
lldb/trunk/source/Symbol/FuncUnwinders.cpp
lldb/trunk/source/Symbol/ObjectFile.cpp
lldb/trunk/source/Symbol/UnwindTable.cpp
lldb/trunk/source/Utility/ConvertEnum.cpp
Added: lldb/trunk/include/lldb/Symbol/ArmUnwindInfo.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Symbol/ArmUnwindInfo.h?rev=248903&view=auto
==============================================================================
--- lldb/trunk/include/lldb/Symbol/ArmUnwindInfo.h (added)
+++ lldb/trunk/include/lldb/Symbol/ArmUnwindInfo.h Wed Sep 30 08:50:14 2015
@@ -0,0 +1,55 @@
+//===-- ArmUnwindInfo.h -----------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_ArmUnwindInfo_h_
+#define liblldb_ArmUnwindInfo_h_
+
+#include <vector>
+
+#include "lldb/Core/DataExtractor.h"
+#include "lldb/Core/RangeMap.h"
+#include "lldb/Host/Mutex.h"
+#include "lldb/Symbol/ObjectFile.h"
+#include "lldb/lldb-private.h"
+
+/*
+ * Unwind information reader and parser for the ARM exception handling ABI
+ *
+ * Implemented based on:
+ * Exception Handling ABI for the ARM Architecture
+ * Document number: ARM IHI 0038A (current through ABI r2.09)
+ * Date of Issue: 25th January 2007, reissued 30th November 2012
+ * http://infocenter.arm.com/help/topic/com.arm.doc.ihi0038a/IHI0038A_ehabi.pdf
+ */
+
+namespace lldb_private {
+
+class ArmUnwindInfo
+{
+public:
+ ArmUnwindInfo (ObjectFile& objfile, lldb::SectionSP& arm_exidx, lldb::SectionSP& arm_extab);
+ ~ArmUnwindInfo();
+
+ bool
+ GetUnwindPlan (Target &target, const Address& addr, UnwindPlan& unwind_plan);
+
+private:
+ const uint8_t*
+ GetExceptionHandlingTableEntry(const Address& addr);
+
+ lldb::SectionSP m_arm_exidx_sp; // .ARM.exidx section
+ 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
+};
+
+} // namespace lldb_private
+
+#endif // liblldb_ArmUnwindInfo_h_
Modified: lldb/trunk/include/lldb/Symbol/FuncUnwinders.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Symbol/FuncUnwinders.h?rev=248903&r1=248902&r2=248903&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Symbol/FuncUnwinders.h (original)
+++ lldb/trunk/include/lldb/Symbol/FuncUnwinders.h Wed Sep 30 08:50:14 2015
@@ -103,6 +103,9 @@ public:
GetCompactUnwindUnwindPlan (Target &target, int current_offset);
lldb::UnwindPlanSP
+ GetArmUnwindUnwindPlan (Target &target, int current_offset);
+
+ lldb::UnwindPlanSP
GetArchDefaultUnwindPlan (Thread &thread);
lldb::UnwindPlanSP
@@ -122,6 +125,7 @@ private:
lldb::UnwindPlanSP m_unwind_plan_eh_frame_sp;
lldb::UnwindPlanSP m_unwind_plan_eh_frame_augmented_sp; // augmented by assembly inspection so it's valid everywhere
std::vector<lldb::UnwindPlanSP> m_unwind_plan_compact_unwind;
+ lldb::UnwindPlanSP m_unwind_plan_arm_unwind_sp;
lldb::UnwindPlanSP m_unwind_plan_fast_sp;
lldb::UnwindPlanSP m_unwind_plan_arch_default_sp;
lldb::UnwindPlanSP m_unwind_plan_arch_default_at_func_entry_sp;
@@ -132,6 +136,7 @@ private:
m_tried_unwind_plan_eh_frame:1,
m_tried_unwind_plan_eh_frame_augmented:1,
m_tried_unwind_plan_compact_unwind:1,
+ m_tried_unwind_plan_arm_unwind:1,
m_tried_unwind_fast:1,
m_tried_unwind_arch_default:1,
m_tried_unwind_arch_default_at_func_entry:1;
Modified: lldb/trunk/include/lldb/Symbol/UnwindTable.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Symbol/UnwindTable.h?rev=248903&r1=248902&r2=248903&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Symbol/UnwindTable.h (original)
+++ lldb/trunk/include/lldb/Symbol/UnwindTable.h Wed Sep 30 08:50:14 2015
@@ -34,6 +34,9 @@ public:
lldb_private::CompactUnwindInfo *
GetCompactUnwindInfo ();
+ ArmUnwindInfo *
+ GetArmUnwindInfo ();
+
lldb::FuncUnwindersSP
GetFuncUnwindersContainingAddress (const Address& addr, SymbolContext &sc);
@@ -65,9 +68,10 @@ private:
bool m_initialized; // delay some initialization until ObjectFile is set up
Mutex m_mutex;
- DWARFCallFrameInfo* m_eh_frame;
- CompactUnwindInfo *m_compact_unwind;
-
+ std::unique_ptr<DWARFCallFrameInfo> m_eh_frame_up;
+ std::unique_ptr<CompactUnwindInfo> m_compact_unwind_up;
+ std::unique_ptr<ArmUnwindInfo> m_arm_unwind_up;
+
DISALLOW_COPY_AND_ASSIGN (UnwindTable);
};
Modified: lldb/trunk/include/lldb/lldb-enumerations.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/lldb-enumerations.h?rev=248903&r1=248902&r2=248903&view=diff
==============================================================================
--- lldb/trunk/include/lldb/lldb-enumerations.h (original)
+++ lldb/trunk/include/lldb/lldb-enumerations.h Wed Sep 30 08:50:14 2015
@@ -616,6 +616,8 @@ namespace lldb {
eSectionTypeELFRelocationEntries, // Elf SHT_REL or SHT_REL section
eSectionTypeELFDynamicLinkInfo, // Elf SHT_DYNAMIC section
eSectionTypeEHFrame,
+ eSectionTypeARMexidx,
+ eSectionTypeARMextab,
eSectionTypeCompactUnwind, // compact unwind section in Mach-O, __TEXT,__unwind_info
eSectionTypeGoSymtab,
eSectionTypeOther
Modified: lldb/trunk/include/lldb/lldb-forward.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/lldb-forward.h?rev=248903&r1=248902&r2=248903&view=diff
==============================================================================
--- lldb/trunk/include/lldb/lldb-forward.h (original)
+++ lldb/trunk/include/lldb/lldb-forward.h Wed Sep 30 08:50:14 2015
@@ -25,6 +25,7 @@ class AddressImpl;
class AddressRange;
class AddressResolver;
class ArchSpec;
+class ArmUnwindInfo;
class Args;
class ASTResultSynthesizer;
class ASTStructExtractor;
Modified: lldb/trunk/source/Commands/CommandObjectTarget.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Commands/CommandObjectTarget.cpp?rev=248903&r1=248902&r2=248903&view=diff
==============================================================================
--- lldb/trunk/source/Commands/CommandObjectTarget.cpp (original)
+++ lldb/trunk/source/Commands/CommandObjectTarget.cpp Wed Sep 30 08:50:14 2015
@@ -3819,6 +3819,14 @@ protected:
result.GetOutputStream().Printf("\n");
}
+ UnwindPlanSP arm_unwind_sp = func_unwinders_sp->GetArmUnwindUnwindPlan(*target, 0);
+ if (arm_unwind_sp)
+ {
+ result.GetOutputStream().Printf("ARM.exidx unwind UnwindPlan:\n");
+ arm_unwind_sp->Dump(result.GetOutputStream(), thread.get(), LLDB_INVALID_ADDRESS);
+ result.GetOutputStream().Printf("\n");
+ }
+
UnwindPlanSP compact_unwind_sp = func_unwinders_sp->GetCompactUnwindUnwindPlan(*target, 0);
if (compact_unwind_sp)
{
Modified: lldb/trunk/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp?rev=248903&r1=248902&r2=248903&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp (original)
+++ lldb/trunk/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp Wed Sep 30 08:50:14 2015
@@ -1720,6 +1720,8 @@ ObjectFileELF::CreateSections(SectionLis
static ConstString g_sect_name_dwarf_debug_str_dwo (".debug_str.dwo");
static ConstString g_sect_name_dwarf_debug_str_offsets_dwo (".debug_str_offsets.dwo");
static ConstString g_sect_name_eh_frame (".eh_frame");
+ static ConstString g_sect_name_arm_exidx (".ARM.exidx");
+ static ConstString g_sect_name_arm_extab (".ARM.extab");
static ConstString g_sect_name_go_symtab (".gosymtab");
SectionType sect_type = eSectionTypeOther;
@@ -1773,6 +1775,8 @@ ObjectFileELF::CreateSections(SectionLis
else if (name == g_sect_name_dwarf_debug_str_dwo) sect_type = eSectionTypeDWARFDebugStr;
else if (name == g_sect_name_dwarf_debug_str_offsets_dwo) sect_type = eSectionTypeDWARFDebugStrOffsets;
else if (name == g_sect_name_eh_frame) sect_type = eSectionTypeEHFrame;
+ else if (name == g_sect_name_arm_exidx) sect_type = eSectionTypeARMexidx;
+ else if (name == g_sect_name_arm_extab) sect_type = eSectionTypeARMextab;
else if (name == g_sect_name_go_symtab) sect_type = eSectionTypeGoSymtab;
switch (header.sh_type)
Modified: lldb/trunk/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp?rev=248903&r1=248902&r2=248903&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp (original)
+++ lldb/trunk/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp Wed Sep 30 08:50:14 2015
@@ -1342,6 +1342,8 @@ ObjectFileMachO::GetAddressClass (lldb::
return eAddressClassDebug;
case eSectionTypeEHFrame:
+ case eSectionTypeARMexidx:
+ case eSectionTypeARMextab:
case eSectionTypeCompactUnwind:
return eAddressClassRuntime;
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=248903&r1=248902&r2=248903&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/Utility/RegisterContextLLDB.cpp (original)
+++ lldb/trunk/source/Plugins/Process/Utility/RegisterContextLLDB.cpp Wed Sep 30 08:50:14 2015
@@ -17,6 +17,7 @@
#include "lldb/Core/RegisterValue.h"
#include "lldb/Core/Value.h"
#include "lldb/Expression/DWARFExpression.h"
+#include "lldb/Symbol/ArmUnwindInfo.h"
#include "lldb/Symbol/DWARFCallFrameInfo.h"
#include "lldb/Symbol/FuncUnwinders.h"
#include "lldb/Symbol/Function.h"
@@ -794,24 +795,38 @@ RegisterContextLLDB::GetFullUnwindPlanFo
func_unwinders_sp = pc_module_sp->GetObjectFile()->GetUnwindTable().GetFuncUnwindersContainingAddress (m_current_pc, m_sym_ctx);
}
- // No FuncUnwinders available for this pc (i.e. a stripped function symbol and -fomit-frame-pointer).
- // Try using the eh_frame information relative to the current PC,
- // and finally fall back on the architectural default unwind.
+ // No FuncUnwinders available for this pc (stripped function symbols, lldb could not augment its
+ // function table with another source, like LC_FUNCTION_STARTS or eh_frame in ObjectFileMachO).
+ // See if eh_frame or the .ARM.exidx tables have unwind information for this address, else fall
+ // back to the architectural default unwind.
if (!func_unwinders_sp)
{
- DWARFCallFrameInfo *eh_frame = pc_module_sp && pc_module_sp->GetObjectFile() ?
- pc_module_sp->GetObjectFile()->GetUnwindTable().GetEHFrameInfo() : nullptr;
-
m_frame_type = eNormalFrame;
- if (eh_frame && m_current_pc.IsValid())
+
+ if (!pc_module_sp || !pc_module_sp->GetObjectFile() || !m_current_pc.IsValid())
+ return arch_default_unwind_plan_sp;
+
+ // Even with -fomit-frame-pointer, we can try eh_frame to get back on track.
+ DWARFCallFrameInfo *eh_frame = pc_module_sp->GetObjectFile()->GetUnwindTable().GetEHFrameInfo();
+ if (eh_frame)
{
unwind_plan_sp.reset (new UnwindPlan (lldb::eRegisterKindGeneric));
- // Even with -fomit-frame-pointer, we can try eh_frame to get back on track.
if (eh_frame->GetUnwindPlan (m_current_pc, *unwind_plan_sp))
return unwind_plan_sp;
else
unwind_plan_sp.reset();
}
+
+ ArmUnwindInfo *arm_exidx = pc_module_sp->GetObjectFile()->GetUnwindTable().GetArmUnwindInfo();
+ if (arm_exidx)
+ {
+ unwind_plan_sp.reset (new UnwindPlan (lldb::eRegisterKindGeneric));
+ if (arm_exidx->GetUnwindPlan (exe_ctx.GetTargetRef(), m_current_pc, *unwind_plan_sp))
+ return unwind_plan_sp;
+ else
+ unwind_plan_sp.reset();
+ }
+
return arch_default_unwind_plan_sp;
}
Added: lldb/trunk/source/Symbol/ArmUnwindInfo.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Symbol/ArmUnwindInfo.cpp?rev=248903&view=auto
==============================================================================
--- lldb/trunk/source/Symbol/ArmUnwindInfo.cpp (added)
+++ lldb/trunk/source/Symbol/ArmUnwindInfo.cpp Wed Sep 30 08:50:14 2015
@@ -0,0 +1,425 @@
+//===-- ArmUnwindInfo.cpp ---------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include <vector>
+
+#include "lldb/Core/Module.h"
+#include "lldb/Core/Section.h"
+#include "lldb/Symbol/ArmUnwindInfo.h"
+#include "lldb/Symbol/SymbolVendor.h"
+#include "lldb/Symbol/UnwindPlan.h"
+#include "Utility/ARM_DWARF_Registers.h"
+
+/*
+ * Unwind information reader and parser for the ARM exception handling ABI
+ *
+ * Implemented based on:
+ * Exception Handling ABI for the ARM Architecture
+ * Document number: ARM IHI 0038A (current through ABI r2.09)
+ * Date of Issue: 25th January 2007, reissued 30th November 2012
+ * http://infocenter.arm.com/help/topic/com.arm.doc.ihi0038a/IHI0038A_ehabi.pdf
+ */
+
+using namespace lldb;
+using namespace lldb_private;
+
+namespace
+{
+ struct ArmExidxEntry
+ {
+ uint32_t address;
+ uint32_t data;
+ };
+};
+
+ArmUnwindInfo::ArmUnwindInfo(ObjectFile& objfile, SectionSP& arm_exidx, SectionSP& arm_extab) :
+ m_arm_exidx_sp(arm_exidx),
+ m_arm_extab_sp(arm_extab)
+{
+ objfile.ReadSectionData(arm_exidx.get(), m_arm_exidx_data);
+ objfile.ReadSectionData(arm_extab.get(), m_arm_extab_data);
+}
+
+ArmUnwindInfo::~ArmUnwindInfo()
+{
+}
+
+static uint8_t
+GetNextByte(const uint32_t* data, uint16_t offset)
+{
+ data += offset / 4;
+ offset = offset % 4;
+ return (data[0] >> ((3 - offset) * 8)) & 0xff;
+}
+
+static uint64_t
+GetULEB128(const uint32_t* data, uint16_t& offset, uint16_t max_offset)
+{
+ uint64_t result = 0;
+ uint8_t shift = 0;
+ while (offset < max_offset)
+ {
+ uint8_t byte = GetNextByte(data, offset++);
+ result |= (byte & 0x7f) << shift;
+ if ((byte & 0x80) == 0)
+ break;
+ shift += 7;
+ }
+ return result;
+}
+
+bool
+ArmUnwindInfo::GetUnwindPlan(Target &target, const Address& addr, UnwindPlan& unwind_plan)
+{
+ const uint32_t* data = (const uint32_t*)GetExceptionHandlingTableEntry(addr.GetFileAddress());
+ if (data == nullptr)
+ return false; // No unwind information for the function
+
+ if (data[0] == 0x1)
+ return false; // EXIDX_CANTUNWIND
+
+ uint16_t byte_count = 0;
+ uint16_t byte_offset = 0;
+ if (data[0] & 0x80000000)
+ {
+ switch ((data[0] >> 24) & 0x0f)
+ {
+ case 0:
+ byte_count = 4;
+ byte_offset = 1;
+ break;
+ case 1:
+ case 2:
+ byte_count = 4 * ((data[0] >> 16) & 0xff) + 4;
+ byte_offset = 2;
+ break;
+ default:
+ // Unhandled personality routine index
+ return false;
+ }
+ }
+ else
+ {
+ byte_count = 4 * ((data[1] >> 24) & 0xff) + 8;
+ byte_offset = 5;
+ }
+
+ uint8_t vsp_reg = dwarf_sp;
+ int32_t vsp = 0;
+ std::vector<std::pair<uint32_t, int32_t>> register_offsets; // register -> (offset from vsp_reg)
+
+ while (byte_offset < byte_count)
+ {
+ uint8_t byte1 = GetNextByte(data, byte_offset++);
+ if ((byte1&0xc0) == 0x00)
+ {
+ // 00xxxxxx
+ // vsp = vsp + (xxxxxx << 2) + 4. Covers range 0x04-0x100 inclusive
+ vsp += ((byte1 & 0x3f) << 2) + 4;
+ }
+ else if ((byte1&0xc0) == 0x40)
+ {
+ // 01xxxxxx
+ // vsp = vsp â (xxxxxx << 2) - 4. Covers range 0x04-0x100 inclusive
+ vsp -= ((byte1 & 0x3f) << 2) + 4;
+ }
+ else if ((byte1&0xf0) == 0x80)
+ {
+ if (byte_offset >= byte_count)
+ return false;
+
+ uint8_t byte2 = GetNextByte(data, byte_offset++);
+ if (byte1 == 0x80 && byte2 == 0)
+ {
+ // 10000000 00000000
+ // Refuse to unwind (for example, out of a cleanup) (see remark a)
+ return false;
+ }
+ else
+ {
+ // 1000iiii iiiiiiii (i not all 0)
+ // Pop up to 12 integer registers under masks {r15-r12}, {r11-r4} (see remark b)
+ uint16_t regs = ((byte1&0x0f) << 8) | byte2;
+ for (uint8_t i = 0; i < 12; ++i)
+ {
+ if (regs & (1<<i))
+ {
+ register_offsets.emplace_back(dwarf_r4 + i, vsp);
+ vsp += 4;
+ }
+ }
+ }
+ }
+ else if ((byte1&0xff) == 0x9d)
+ {
+ // 10011101
+ // Reserved as prefix for ARM register to register moves
+ return false;
+ }
+ else if ((byte1&0xff) == 0x9f)
+ {
+ // 10011111
+ // Reserved as prefix for Intel Wireless MMX register to register moves
+ return false;
+ }
+ else if ((byte1&0xf0) == 0x90)
+ {
+ // 1001nnnn (nnnn != 13,15)
+ // Set vsp = r[nnnn]
+ vsp_reg = dwarf_r0 + (byte1&0x0f);
+ }
+ else if ((byte1&0xf8) == 0xa0)
+ {
+ // 10100nnn
+ // Pop r4-r[4+nnn]
+ uint8_t n = byte1&0x7;
+ for (uint8_t i = 0; i <= n; ++i)
+ {
+ register_offsets.emplace_back(dwarf_r4 + i, vsp);
+ vsp += 4;
+ }
+ }
+ else if ((byte1&0xf8) == 0xa8)
+ {
+ // 10101nnn
+ // Pop r4-r[4+nnn], r14
+ uint8_t n = byte1&0x7;
+ for (uint8_t i = 0; i <= n; ++i)
+ {
+ register_offsets.emplace_back(dwarf_r4 + i, vsp);
+ vsp += 4;
+ }
+
+ register_offsets.emplace_back(dwarf_lr, vsp);
+ vsp += 4;
+ }
+ else if ((byte1&0xff) == 0xb0)
+ {
+ // 10110000
+ // Finish (see remark c)
+ break;
+ }
+ else if ((byte1&0xff) == 0xb1)
+ {
+ if (byte_offset >= byte_count)
+ return false;
+
+ uint8_t byte2 = GetNextByte(data, byte_offset++);
+ if ((byte2&0xff) == 0x00)
+ {
+ // 10110001 00000000
+ // Spare (see remark f)
+ return false;
+ }
+ else if ((byte2&0xf0) == 0x00)
+ {
+ // 10110001 0000iiii (i not all 0)
+ // Pop integer registers under mask {r3, r2, r1, r0}
+ for (uint8_t i = 0; i < 4; ++i)
+ {
+ if (byte2 & (1<<i))
+ {
+ register_offsets.emplace_back(dwarf_r0 + i, vsp);
+ vsp += 4;
+ }
+ }
+ }
+ else
+ {
+ // 10110001 xxxxyyyy
+ // Spare (xxxx != 0000)
+ return false;
+ }
+ }
+ else if ((byte1&0xff) == 0xb2)
+ {
+ // 10110010 uleb128
+ // vsp = vsp + 0x204+ (uleb128 << 2)
+ uint64_t uleb128 = GetULEB128(data, byte_offset, byte_count);
+ vsp += 0x204 + (uleb128 << 2);
+ }
+ else if ((byte1&0xff) == 0xb3)
+ {
+ // 10110011 sssscccc
+ // Pop VFP double-precision registers D[ssss]-D[ssss+cccc] saved (as if) by FSTMFDX (see remark d)
+ if (byte_offset >= byte_count)
+ return false;
+
+ uint8_t byte2 = GetNextByte(data, byte_offset++);
+ uint8_t s = (byte2&0xf0) >> 4;
+ uint8_t c = (byte2&0x0f) >> 0;
+ for (uint8_t i = 0; i <= c; ++i)
+ {
+ register_offsets.emplace_back(dwarf_d0 + s + i, vsp);
+ vsp += 8;
+ }
+ vsp += 4;
+ }
+ else if ((byte1&0xfc) == 0xb4)
+ {
+ // 101101nn
+ // Spare (was Pop FPA)
+ return false;
+ }
+ else if ((byte1&0xf8) == 0xb8)
+ {
+ // 10111nnn
+ // Pop VFP double-precision registers D[8]-D[8+nnn] saved (as if) by FSTMFDX (see remark d)
+ uint8_t n = byte1&0x07;
+ for (uint8_t i = 0; i <= n; ++i)
+ {
+ register_offsets.emplace_back(dwarf_d8 + i, vsp);
+ vsp += 8;
+ }
+ vsp += 4;
+ }
+ else if ((byte1&0xf8) == 0xc0)
+ {
+ // 11000nnn (nnn != 6,7)
+ // Intel Wireless MMX pop wR[10]-wR[10+nnn]
+
+ // 11000110 sssscccc
+ // Intel Wireless MMX pop wR[ssss]-wR[ssss+cccc] (see remark e)
+
+ // 11000111 00000000
+ // Spare
+
+ // 11000111 0000iiii
+ // Intel Wireless MMX pop wCGR registers under mask {wCGR3,2,1,0}
+
+ // 11000111 xxxxyyyy
+ // Spare (xxxx != 0000)
+
+ return false;
+ }
+ else if ((byte1&0xff) == 0xc8)
+ {
+ // 11001000 sssscccc
+ // Pop VFP double precision registers D[16+ssss]-D[16+ssss+cccc] saved (as if) by FSTMFDD (see remarks d,e)
+ if (byte_offset >= byte_count)
+ return false;
+
+ uint8_t byte2 = GetNextByte(data, byte_offset++);
+ uint8_t s = (byte2&0xf0) >> 4;
+ uint8_t c = (byte2&0x0f) >> 0;
+ for (uint8_t i = 0; i <= c; ++i)
+ {
+ register_offsets.emplace_back(dwarf_d16 + s + i, vsp);
+ vsp += 8;
+ }
+ }
+ else if ((byte1&0xff) == 0xc9)
+ {
+ // 11001001 sssscccc
+ // Pop VFP double precision registers D[ssss]-D[ssss+cccc] saved (as if) by FSTMFDD (see remark d)
+ if (byte_offset >= byte_count)
+ return false;
+
+ uint8_t byte2 = GetNextByte(data, byte_offset++);
+ uint8_t s = (byte2&0xf0) >> 4;
+ uint8_t c = (byte2&0x0f) >> 0;
+ for (uint8_t i = 0; i <= c; ++i)
+ {
+ register_offsets.emplace_back(dwarf_d0 + s + i, vsp);
+ vsp += 8;
+ }
+ }
+ else if ((byte1&0xf8) == 0xc8)
+ {
+ // 11001yyy
+ // Spare (yyy != 000, 001)
+ return false;
+ }
+ else if ((byte1&0xf8) == 0xc0)
+ {
+ // 11010nnn
+ // Pop VFP double-precision registers D[8]-D[8+nnn] saved (as if) by FSTMFDD (see remark d)
+ uint8_t n = byte1&0x07;
+ for (uint8_t i = 0; i <= n; ++i)
+ {
+ register_offsets.emplace_back(dwarf_d8 + i, vsp);
+ vsp += 8;
+ }
+ }
+ else if ((byte1&0xc0) == 0xc0)
+ {
+ // 11xxxyyy Spare (xxx != 000, 001, 010)
+ return false;
+ }
+ else
+ {
+ return false;
+ }
+ }
+
+ UnwindPlan::RowSP row = std::make_shared<UnwindPlan::Row>();
+ row->SetOffset(0);
+ row->GetCFAValue().SetIsRegisterPlusOffset(vsp_reg, vsp);
+
+ bool have_location_for_pc = false;
+ for (const auto& offset : register_offsets)
+ {
+ have_location_for_pc |= offset.first == dwarf_pc;
+ row->SetRegisterLocationToAtCFAPlusOffset(offset.first, offset.second - vsp, true);
+ }
+
+ if (!have_location_for_pc)
+ {
+ UnwindPlan::Row::RegisterLocation lr_location;
+ if (row->GetRegisterInfo(dwarf_lr, lr_location))
+ row->SetRegisterInfo(dwarf_pc, lr_location);
+ }
+
+ unwind_plan.AppendRow(row);
+ unwind_plan.SetSourceName ("ARM.exidx unwind info");
+ unwind_plan.SetSourcedFromCompiler (eLazyBoolYes);
+ unwind_plan.SetUnwindPlanValidAtAllInstructions (eLazyBoolNo);
+ unwind_plan.SetRegisterKind (eRegisterKindDWARF);
+
+ return true;
+}
+
+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)
+ return nullptr;
+
+ if (exidx_start[bs_start].data == 0x1)
+ return nullptr; // EXIDX_CANTUNWIND
+
+ if (exidx_start[bs_start].data & 0x80000000)
+ return (const uint8_t*)&exidx_start[bs_start].data;
+
+ uint32_t data_file_addr = exidx_base_addr +
+ 8 * bs_start + 4 +
+ exidx_start[bs_start].data;
+ data_file_addr &= 0x7fffffff;
+ return m_arm_extab_data.GetDataStart() + (data_file_addr - m_arm_extab_sp->GetFileAddress());
+}
Modified: lldb/trunk/source/Symbol/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Symbol/CMakeLists.txt?rev=248903&r1=248902&r2=248903&view=diff
==============================================================================
--- lldb/trunk/source/Symbol/CMakeLists.txt (original)
+++ lldb/trunk/source/Symbol/CMakeLists.txt Wed Sep 30 08:50:14 2015
@@ -1,4 +1,5 @@
add_lldb_library(lldbSymbol
+ ArmUnwindInfo.cpp
Block.cpp
ClangASTContext.cpp
ClangASTImporter.cpp
Modified: lldb/trunk/source/Symbol/FuncUnwinders.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Symbol/FuncUnwinders.cpp?rev=248903&r1=248902&r2=248903&view=diff
==============================================================================
--- lldb/trunk/source/Symbol/FuncUnwinders.cpp (original)
+++ lldb/trunk/source/Symbol/FuncUnwinders.cpp Wed Sep 30 08:50:14 2015
@@ -10,6 +10,7 @@
#include "lldb/Core/AddressRange.h"
#include "lldb/Core/Address.h"
#include "lldb/Symbol/FuncUnwinders.h"
+#include "lldb/Symbol/ArmUnwindInfo.h"
#include "lldb/Symbol/DWARFCallFrameInfo.h"
#include "lldb/Symbol/CompactUnwindInfo.h"
#include "lldb/Symbol/ObjectFile.h"
@@ -37,6 +38,7 @@ FuncUnwinders::FuncUnwinders (UnwindTabl
m_unwind_plan_eh_frame_sp (),
m_unwind_plan_eh_frame_augmented_sp (),
m_unwind_plan_compact_unwind (),
+ m_unwind_plan_arm_unwind_sp (),
m_unwind_plan_fast_sp (),
m_unwind_plan_arch_default_sp (),
m_unwind_plan_arch_default_at_func_entry_sp (),
@@ -44,6 +46,7 @@ FuncUnwinders::FuncUnwinders (UnwindTabl
m_tried_unwind_plan_eh_frame (false),
m_tried_unwind_plan_eh_frame_augmented (false),
m_tried_unwind_plan_compact_unwind (false),
+ m_tried_unwind_plan_arm_unwind (false),
m_tried_unwind_fast (false),
m_tried_unwind_arch_default (false),
m_tried_unwind_arch_default_at_func_entry (false),
@@ -65,12 +68,18 @@ FuncUnwinders::GetUnwindPlanAtCallSite (
Mutex::Locker locker (m_mutex);
UnwindPlanSP unwind_plan_sp = GetEHFrameUnwindPlan (target, current_offset);
- if (unwind_plan_sp.get() == nullptr)
- {
- unwind_plan_sp = GetCompactUnwindUnwindPlan (target, current_offset);
- }
+ if (unwind_plan_sp)
+ return unwind_plan_sp;
+
+ unwind_plan_sp = GetCompactUnwindUnwindPlan (target, current_offset);
+ if (unwind_plan_sp)
+ return unwind_plan_sp;
+
+ unwind_plan_sp = GetArmUnwindUnwindPlan (target, current_offset);
+ if (unwind_plan_sp)
+ return unwind_plan_sp;
- return unwind_plan_sp;
+ return nullptr;
}
UnwindPlanSP
@@ -127,6 +136,30 @@ FuncUnwinders::GetEHFrameUnwindPlan (Tar
}
UnwindPlanSP
+FuncUnwinders::GetArmUnwindUnwindPlan (Target &target, int current_offset)
+{
+ if (m_unwind_plan_arm_unwind_sp.get() || m_tried_unwind_plan_arm_unwind)
+ return m_unwind_plan_arm_unwind_sp;
+
+ Mutex::Locker lock (m_mutex);
+ m_tried_unwind_plan_arm_unwind = true;
+ if (m_range.GetBaseAddress().IsValid())
+ {
+ Address current_pc (m_range.GetBaseAddress ());
+ if (current_offset != -1)
+ current_pc.SetOffset (current_pc.GetOffset() + current_offset);
+ ArmUnwindInfo *arm_unwind_info = m_unwind_table.GetArmUnwindInfo();
+ if (arm_unwind_info)
+ {
+ m_unwind_plan_arm_unwind_sp.reset (new UnwindPlan (lldb::eRegisterKindGeneric));
+ if (!arm_unwind_info->GetUnwindPlan (target, current_pc, *m_unwind_plan_arm_unwind_sp))
+ m_unwind_plan_arm_unwind_sp.reset();
+ }
+ }
+ return m_unwind_plan_arm_unwind_sp;
+}
+
+UnwindPlanSP
FuncUnwinders::GetEHFrameAugmentedUnwindPlan (Target &target, Thread &thread, int current_offset)
{
if (m_unwind_plan_eh_frame_augmented_sp.get() || m_tried_unwind_plan_eh_frame_augmented)
Modified: lldb/trunk/source/Symbol/ObjectFile.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Symbol/ObjectFile.cpp?rev=248903&r1=248902&r2=248903&view=diff
==============================================================================
--- lldb/trunk/source/Symbol/ObjectFile.cpp (original)
+++ lldb/trunk/source/Symbol/ObjectFile.cpp Wed Sep 30 08:50:14 2015
@@ -373,6 +373,8 @@ ObjectFile::GetAddressClass (addr_t file
case eSectionTypeDWARFAppleObjC:
return eAddressClassDebug;
case eSectionTypeEHFrame:
+ case eSectionTypeARMexidx:
+ case eSectionTypeARMextab:
case eSectionTypeCompactUnwind:
return eAddressClassRuntime;
case eSectionTypeELFSymbolTable:
Modified: lldb/trunk/source/Symbol/UnwindTable.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Symbol/UnwindTable.cpp?rev=248903&r1=248902&r2=248903&view=diff
==============================================================================
--- lldb/trunk/source/Symbol/UnwindTable.cpp (original)
+++ lldb/trunk/source/Symbol/UnwindTable.cpp Wed Sep 30 08:50:14 2015
@@ -17,6 +17,7 @@
#include "lldb/Symbol/FuncUnwinders.h"
#include "lldb/Symbol/SymbolContext.h"
#include "lldb/Symbol/DWARFCallFrameInfo.h"
+#include "lldb/Symbol/ArmUnwindInfo.h"
#include "lldb/Symbol/CompactUnwindInfo.h"
// There is one UnwindTable object per ObjectFile.
@@ -31,8 +32,9 @@ UnwindTable::UnwindTable (ObjectFile& ob
m_unwinds (),
m_initialized (false),
m_mutex (),
- m_eh_frame (nullptr),
- m_compact_unwind (nullptr)
+ m_eh_frame_up (),
+ m_compact_unwind_up (),
+ m_arm_unwind_up ()
{
}
@@ -56,12 +58,21 @@ UnwindTable::Initialize ()
SectionSP sect = sl->FindSectionByType (eSectionTypeEHFrame, true);
if (sect.get())
{
- m_eh_frame = new DWARFCallFrameInfo(m_object_file, sect, eRegisterKindEHFrame, true);
+ m_eh_frame_up.reset(new DWARFCallFrameInfo(m_object_file, sect, eRegisterKindEHFrame, true));
}
sect = sl->FindSectionByType (eSectionTypeCompactUnwind, true);
if (sect.get())
{
- m_compact_unwind = new CompactUnwindInfo(m_object_file, sect);
+ m_compact_unwind_up.reset(new CompactUnwindInfo(m_object_file, sect));
+ }
+ sect = sl->FindSectionByType (eSectionTypeARMexidx, true);
+ if (sect.get())
+ {
+ SectionSP sect_extab = sl->FindSectionByType (eSectionTypeARMextab, true);
+ if (sect_extab.get())
+ {
+ m_arm_unwind_up.reset(new ArmUnwindInfo(m_object_file, sect, sect_extab));
+ }
}
}
@@ -70,8 +81,6 @@ UnwindTable::Initialize ()
UnwindTable::~UnwindTable ()
{
- if (m_eh_frame)
- delete m_eh_frame;
}
FuncUnwindersSP
@@ -102,7 +111,7 @@ UnwindTable::GetFuncUnwindersContainingA
if (!sc.GetAddressRange(eSymbolContextFunction | eSymbolContextSymbol, 0, false, range) || !range.GetBaseAddress().IsValid())
{
// Does the eh_frame unwind info has a function bounds for this addr?
- if (m_eh_frame == nullptr || !m_eh_frame->GetAddressRange (addr, range))
+ if (m_eh_frame_up == nullptr || !m_eh_frame_up->GetAddressRange (addr, range))
{
return no_unwind_found;
}
@@ -129,7 +138,7 @@ UnwindTable::GetUncachedFuncUnwindersCon
if (!sc.GetAddressRange(eSymbolContextFunction | eSymbolContextSymbol, 0, false, range) || !range.GetBaseAddress().IsValid())
{
// Does the eh_frame unwind info has a function bounds for this addr?
- if (m_eh_frame == nullptr || !m_eh_frame->GetAddressRange (addr, range))
+ if (m_eh_frame_up == nullptr || !m_eh_frame_up->GetAddressRange (addr, range))
{
return no_unwind_found;
}
@@ -158,14 +167,21 @@ DWARFCallFrameInfo *
UnwindTable::GetEHFrameInfo ()
{
Initialize();
- return m_eh_frame;
+ return m_eh_frame_up.get();
}
CompactUnwindInfo *
UnwindTable::GetCompactUnwindInfo ()
{
Initialize();
- return m_compact_unwind;
+ return m_compact_unwind_up.get();
+}
+
+ArmUnwindInfo *
+UnwindTable::GetArmUnwindInfo ()
+{
+ Initialize();
+ return m_arm_unwind_up.get();
}
bool
Modified: lldb/trunk/source/Utility/ConvertEnum.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Utility/ConvertEnum.cpp?rev=248903&r1=248902&r2=248903&view=diff
==============================================================================
--- lldb/trunk/source/Utility/ConvertEnum.cpp (original)
+++ lldb/trunk/source/Utility/ConvertEnum.cpp Wed Sep 30 08:50:14 2015
@@ -105,6 +105,10 @@ lldb_private::GetSectionTypeAsCString(ll
return "apple-objc";
case eSectionTypeEHFrame:
return "eh-frame";
+ case eSectionTypeARMexidx:
+ return "ARM.exidx";
+ case eSectionTypeARMextab:
+ return "ARM.extab";
case eSectionTypeCompactUnwind:
return "compact-unwind";
case eSectionTypeGoSymtab:
More information about the lldb-commits
mailing list