[Lldb-commits] [lldb] r216409 - Add 64-bit eh_frame section CFI support.
Todd Fiala
todd.fiala at gmail.com
Mon Aug 25 14:39:30 PDT 2014
Author: tfiala
Date: Mon Aug 25 16:39:30 2014
New Revision: 216409
URL: http://llvm.org/viewvc/llvm-project?rev=216409&view=rev
Log:
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.
Modified:
lldb/trunk/source/Symbol/DWARFCallFrameInfo.cpp
Modified: lldb/trunk/source/Symbol/DWARFCallFrameInfo.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Symbol/DWARFCallFrameInfo.cpp?rev=216409&r1=216408&r2=216409&view=diff
==============================================================================
--- lldb/trunk/source/Symbol/DWARFCallFrameInfo.cpp (original)
+++ lldb/trunk/source/Symbol/DWARFCallFrameInfo.cpp Mon Aug 25 16:39:30 2014
@@ -146,9 +146,17 @@ DWARFCallFrameInfo::ParseCIE (const dw_o
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_
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_
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_
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;
More information about the lldb-commits
mailing list