forked from OSchip/llvm-project
Add 64-bit eh_frame section CFI support.
In practice, 64bit eh_frame is not used even for x86_64 binaries. The main reason is in eh_frame we almost always use pc-relative addressing, so addresses are within 32bits and gcc just sticks to 32bit eh_frame. I generated 64bit eh_frame for Android Java runtime and unwind successfully in gdb, and in lldb with this patch. Patch by Tong Shen. llvm-svn: 216409
This commit is contained in:
parent
4229228389
commit
1767e11594
|
@ -146,9 +146,17 @@ DWARFCallFrameInfo::ParseCIE (const dw_offset_t cie_offset)
|
|||
lldb::offset_t offset = cie_offset;
|
||||
if (m_cfi_data_initialized == false)
|
||||
GetCFIData();
|
||||
const uint32_t length = m_cfi_data.GetU32(&offset);
|
||||
const dw_offset_t cie_id = m_cfi_data.GetU32(&offset);
|
||||
const dw_offset_t end_offset = cie_offset + length + 4;
|
||||
uint32_t length = m_cfi_data.GetU32(&offset);
|
||||
dw_offset_t cie_id, end_offset;
|
||||
bool is_64bit = (length == UINT32_MAX);
|
||||
if (is_64bit) {
|
||||
length = m_cfi_data.GetU64(&offset);
|
||||
cie_id = m_cfi_data.GetU64(&offset);
|
||||
end_offset = cie_offset + length + 12;
|
||||
} else {
|
||||
cie_id = m_cfi_data.GetU32(&offset);
|
||||
end_offset = cie_offset + length + 4;
|
||||
}
|
||||
if (length > 0 && ((!m_is_eh_frame && cie_id == UINT32_MAX) || (m_is_eh_frame && cie_id == 0ul)))
|
||||
{
|
||||
size_t i;
|
||||
|
@ -337,9 +345,19 @@ DWARFCallFrameInfo::GetFDEIndex ()
|
|||
while (m_cfi_data.ValidOffsetForDataOfSize (offset, 8))
|
||||
{
|
||||
const dw_offset_t current_entry = offset;
|
||||
dw_offset_t cie_id, next_entry, cie_offset;
|
||||
uint32_t len = m_cfi_data.GetU32 (&offset);
|
||||
dw_offset_t next_entry = current_entry + len + 4;
|
||||
dw_offset_t cie_id = m_cfi_data.GetU32 (&offset);
|
||||
bool is_64bit = (len == UINT32_MAX);
|
||||
if (is_64bit) {
|
||||
len = m_cfi_data.GetU64 (&offset);
|
||||
cie_id = m_cfi_data.GetU64 (&offset);
|
||||
next_entry = current_entry + len + 12;
|
||||
cie_offset = current_entry + 12 - cie_id;
|
||||
} else {
|
||||
cie_id = m_cfi_data.GetU32 (&offset);
|
||||
next_entry = current_entry + len + 4;
|
||||
cie_offset = current_entry + 4 - cie_id;
|
||||
}
|
||||
|
||||
if (cie_id == 0 || cie_id == UINT32_MAX || len == 0)
|
||||
{
|
||||
|
@ -348,7 +366,6 @@ DWARFCallFrameInfo::GetFDEIndex ()
|
|||
continue;
|
||||
}
|
||||
|
||||
const dw_offset_t cie_offset = current_entry + 4 - cie_id;
|
||||
const CIE *cie = GetCIE (cie_offset);
|
||||
if (cie)
|
||||
{
|
||||
|
@ -388,7 +405,14 @@ DWARFCallFrameInfo::FDEToUnwindPlan (dw_offset_t dwarf_offset, Address startaddr
|
|||
GetCFIData();
|
||||
|
||||
uint32_t length = m_cfi_data.GetU32 (&offset);
|
||||
dw_offset_t cie_offset = m_cfi_data.GetU32 (&offset);
|
||||
dw_offset_t cie_offset;
|
||||
bool is_64bit = (length == UINT32_MAX);
|
||||
if (is_64bit) {
|
||||
length = m_cfi_data.GetU64 (&offset);
|
||||
cie_offset = m_cfi_data.GetU64 (&offset);
|
||||
} else {
|
||||
cie_offset = m_cfi_data.GetU32 (&offset);
|
||||
}
|
||||
|
||||
assert (cie_offset != 0 && cie_offset != UINT32_MAX);
|
||||
|
||||
|
@ -398,7 +422,7 @@ DWARFCallFrameInfo::FDEToUnwindPlan (dw_offset_t dwarf_offset, Address startaddr
|
|||
if (m_is_eh_frame)
|
||||
{
|
||||
unwind_plan.SetSourceName ("eh_frame CFI");
|
||||
cie_offset = current_entry + 4 - cie_offset;
|
||||
cie_offset = current_entry + (is_64bit ? 12 : 4) - cie_offset;
|
||||
unwind_plan.SetUnwindPlanValidAtAllInstructions (eLazyBoolNo);
|
||||
}
|
||||
else
|
||||
|
@ -415,7 +439,7 @@ DWARFCallFrameInfo::FDEToUnwindPlan (dw_offset_t dwarf_offset, Address startaddr
|
|||
const CIE *cie = GetCIE (cie_offset);
|
||||
assert (cie != nullptr);
|
||||
|
||||
const dw_offset_t end_offset = current_entry + length + 4;
|
||||
const dw_offset_t end_offset = current_entry + length + (is_64bit ? 12 : 4);
|
||||
|
||||
const lldb::addr_t pc_rel_addr = m_section_sp->GetFileAddress();
|
||||
const lldb::addr_t text_addr = LLDB_INVALID_ADDRESS;
|
||||
|
|
Loading…
Reference in New Issue