summaryrefslogtreecommitdiffstats
path: root/lldb/source/Symbol/ArmUnwindInfo.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lldb/source/Symbol/ArmUnwindInfo.cpp')
-rw-r--r--lldb/source/Symbol/ArmUnwindInfo.cpp696
1 files changed, 311 insertions, 385 deletions
diff --git a/lldb/source/Symbol/ArmUnwindInfo.cpp b/lldb/source/Symbol/ArmUnwindInfo.cpp
index 95207cbe320..19951498c1d 100644
--- a/lldb/source/Symbol/ArmUnwindInfo.cpp
+++ b/lldb/source/Symbol/ArmUnwindInfo.cpp
@@ -9,13 +9,13 @@
#include <vector>
+#include "Utility/ARM_DWARF_Registers.h"
#include "lldb/Core/Module.h"
#include "lldb/Core/Section.h"
#include "lldb/Host/Endian.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
@@ -31,415 +31,341 @@ using namespace lldb;
using namespace lldb_private;
// Converts a prel31 avlue to lldb::addr_t with sign extension
-static addr_t
-Prel31ToAddr(uint32_t prel31)
-{
- addr_t res = prel31;
- if (prel31 & (1<<30))
- res |= 0xffffffff80000000ULL;
- return res;
+static addr_t Prel31ToAddr(uint32_t prel31) {
+ 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)
-{
-}
+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;
+bool ArmUnwindInfo::ArmExidxEntry::operator<(const ArmExidxEntry &other) const {
+ return address < other.address;
}
-ArmUnwindInfo::ArmUnwindInfo(const ObjectFile& objfile,
- SectionSP& arm_exidx,
- SectionSP& arm_extab) :
- m_byte_order(objfile.GetByteOrder()),
- 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);
-
- 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(const ObjectFile &objfile, SectionSP &arm_exidx,
+ SectionSP &arm_extab)
+ : m_byte_order(objfile.GetByteOrder()), 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);
+
+ 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()
-{
-}
+ArmUnwindInfo::~ArmUnwindInfo() {}
// Read a byte from the unwind instruction stream with the given offset.
-// Custom function is required because have to red in order of significance within their containing
+// Custom function is required because have to red in order of significance
+// within their containing
// word (most significant byte first) and in increasing word address order.
-uint8_t
-ArmUnwindInfo::GetByteAtOffset(const uint32_t* data, uint16_t offset) const
-{
- uint32_t value = data[offset / 4];
- if (m_byte_order != endian::InlHostByteOrder())
- value = llvm::ByteSwap_32(value);
- return (value >> ((3 - (offset % 4)) * 8)) & 0xff;
+uint8_t ArmUnwindInfo::GetByteAtOffset(const uint32_t *data,
+ uint16_t offset) const {
+ uint32_t value = data[offset / 4];
+ if (m_byte_order != endian::InlHostByteOrder())
+ value = llvm::ByteSwap_32(value);
+ return (value >> ((3 - (offset % 4)) * 8)) & 0xff;
}
-uint64_t
-ArmUnwindInfo::GetULEB128(const uint32_t* data, uint16_t& offset, uint16_t max_offset) const
-{
- uint64_t result = 0;
- uint8_t shift = 0;
- while (offset < max_offset)
- {
- uint8_t byte = GetByteAtOffset(data, offset++);
- result |= (uint64_t)(byte & 0x7f) << shift;
- if ((byte & 0x80) == 0)
- break;
- shift += 7;
- }
- return result;
+uint64_t ArmUnwindInfo::GetULEB128(const uint32_t *data, uint16_t &offset,
+ uint16_t max_offset) const {
+ uint64_t result = 0;
+ uint8_t shift = 0;
+ while (offset < max_offset) {
+ uint8_t byte = GetByteAtOffset(data, offset++);
+ result |= (uint64_t)(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);
- 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;
+bool ArmUnwindInfo::GetUnwindPlan(Target &target, const Address &addr,
+ UnwindPlan &unwind_plan) {
+ const uint32_t *data = (const uint32_t *)GetExceptionHandlingTableEntry(addr);
+ 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;
}
-
- 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 = GetByteAtOffset(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 = GetByteAtOffset(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 = GetByteAtOffset(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 = GetByteAtOffset(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 {
+ 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 = GetByteAtOffset(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 = GetByteAtOffset(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&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;
- }
+ }
+ } 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 = GetByteAtOffset(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 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 = GetByteAtOffset(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 = GetByteAtOffset(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);
- else
- row->SetRegisterLocationToRegister(dwarf_pc, dwarf_lr, false);
+ } 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 = GetByteAtOffset(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 = GetByteAtOffset(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 = GetByteAtOffset(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);
+ else
+ row->SetRegisterLocationToRegister(dwarf_pc, dwarf_lr, false);
+ }
- unwind_plan.AppendRow(row);
- unwind_plan.SetSourceName ("ARM.exidx unwind info");
- unwind_plan.SetSourcedFromCompiler (eLazyBoolYes);
- unwind_plan.SetUnwindPlanValidAtAllInstructions (eLazyBoolNo);
- unwind_plan.SetRegisterKind (eRegisterKindDWARF);
+ 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;
+ return true;
}
-const uint8_t*
-ArmUnwindInfo::GetExceptionHandlingTableEntry(const Address& 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;
+const uint8_t *
+ArmUnwindInfo::GetExceptionHandlingTableEntry(const Address &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 (it->data == 0x1)
- return nullptr; // EXIDX_CANTUNWIND
+ if (it->data == 0x1)
+ return nullptr; // EXIDX_CANTUNWIND
- if (it->data & 0x80000000)
- return (const uint8_t*)&it->data;
+ if (it->data & 0x80000000)
+ return (const uint8_t *)&it->data;
- 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());
+ 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());
}
OpenPOWER on IntegriCloud