[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