Hi jroelofs,

Since the personality functions do the actual unwinding on ARM, and will
also stop unwinding when they encounter a handler, we invoke
_Unwind_VRS_Interpret() directly form _Unwind_Backtrace().
    
To simplify, the logic for decoding an EHT is moved out of
unwindOneFrame() and into its own function, decode_eht_entry(). Unlike
unwindOneFrame(), which could only handle ARM's compact personality
function entries (section 6.3) decode_eht_entry() can handle the generic
entries (section 6.2).

http://reviews.llvm.org/D5112

Files:
  include/unwind.h
  src/Unwind/Unwind-EHABI.cpp
  src/Unwind/UnwindLevel1-gcc-ext.c
Index: include/unwind.h
===================================================================
--- include/unwind.h
+++ include/unwind.h
@@ -207,6 +207,7 @@
                 uint32_t discriminator,
                 _Unwind_VRS_DataRepresentation representation);
 
+extern uint32_t* decode_eht_entry(const uint32_t*, size_t*, size_t*);
 extern _Unwind_Reason_Code _Unwind_VRS_Interpret(_Unwind_Context *context,
                                                  uint32_t *data, size_t offset,
                                                  size_t len);
Index: src/Unwind/Unwind-EHABI.cpp
===================================================================
--- src/Unwind/Unwind-EHABI.cpp
+++ src/Unwind/Unwind-EHABI.cpp
@@ -167,24 +167,13 @@
     struct _Unwind_Context* context) {
   // Read the compact model EHT entry's header # 6.3
   uint32_t* unwindingData = ucbp->pr_cache.ehtp;
-  uint32_t unwindInfo = *unwindingData;
-  assert((unwindInfo & 0xf0000000) == 0x80000000 && "Must be a compact entry");
   Descriptor::Format format =
-      static_cast<Descriptor::Format>((unwindInfo & 0x0f000000) >> 24);
+      static_cast<Descriptor::Format>((*unwindingData & 0x0f000000) >> 24);
   size_t len = 0;
-  size_t startOffset = 0;
-  switch (format) {
-    case Descriptor::SU16:
-      len = 4;
-      startOffset = 1;
-      break;
-    case Descriptor::LU16:
-    case Descriptor::LU32:
-      len = 4 + 4 * ((unwindInfo & 0x00ff0000) >> 16);
-      startOffset = 2;
-      break;
-    default:
-      return _URC_FAILURE;
+  size_t off = 0;
+  unwindingData = decode_eht_entry(unwindingData, &off, &len);
+  if (unwindingData == nullptr) {
+    return _URC_FAILURE;
   }
 
   // Handle descriptors before unwinding so they are processed in the context
@@ -198,7 +187,7 @@
   if (result != _URC_CONTINUE_UNWIND)
     return result;
 
-  return _Unwind_VRS_Interpret(context, unwindingData, startOffset, len);
+  return _Unwind_VRS_Interpret(context, unwindingData, off, len);
 }
 
 // Generates mask discriminator for _Unwind_VRS_Pop, e.g. for _UVRSC_CORE /
@@ -215,6 +204,43 @@
 
 } // end anonymous namespace
 
+/**
+ * Decodes an EHT entry.
+ *
+ * @param data Pointer to EHT.
+ * @param[out] off Offset from return value (in bytes) to begin interpretation.
+ * @param[out] len Number of bytes in unwind code.
+ * @return Pointer to beginning of unwind code.
+ */
+extern "C" uint32_t*
+decode_eht_entry(const uint32_t* data, size_t* off, size_t* len) {
+  if ((*data & 0x80000000) == 0) {
+    // 6.2: Generic Model
+    *off = 1; // First byte is size data.
+    *len = (((data[1] >> 24) & 0xff) + 1) * 4;
+    data++; // Skip the first word, which is the prel31 offset.
+  } else {
+    // 6.3: ARM Compact Model
+    Descriptor::Format format =
+        static_cast<Descriptor::Format>((*data & 0x0f000000) >> 24);
+    switch (format) {
+      case Descriptor::SU16:
+        *len = 4;
+        *off = 1;
+        break;
+      case Descriptor::LU16:
+      case Descriptor::LU32:
+        *len = 4 + 4 * ((*data & 0x00ff0000) >> 16);
+        *off = 2;
+        break;
+      default:
+        return nullptr;
+    }
+  }
+
+  return const_cast<uint32_t*>(data);
+}
+
 _Unwind_Reason_Code _Unwind_VRS_Interpret(
     _Unwind_Context* context,
     uint32_t* data,
Index: src/Unwind/UnwindLevel1-gcc-ext.c
===================================================================
--- src/Unwind/UnwindLevel1-gcc-ext.c
+++ src/Unwind/UnwindLevel1-gcc-ext.c
@@ -141,6 +141,28 @@
                                  result);
       return result;
     }
+
+#if LIBCXXABI_ARM_EHABI
+    // Get the information for this frame.
+    unw_proc_info_t frameInfo;
+    if (unw_get_proc_info(&cursor, &frameInfo) != UNW_ESUCCESS) {
+      return _URC_END_OF_STACK;
+    }
+
+    struct _Unwind_Context *context = (struct _Unwind_Context *)&cursor;
+    size_t off;
+    size_t len;
+    uint32_t* unwindInfo = (uint32_t *) frameInfo.unwind_info;
+    unwindInfo = decode_eht_entry(unwindInfo, &off, &len);
+    if (unwindInfo == NULL) {
+      return _URC_FAILURE;
+    }
+
+    result = _Unwind_VRS_Interpret(context, unwindInfo, off, len);
+    if (result != _URC_CONTINUE_UNWIND) {
+      return _URC_END_OF_STACK;
+    }
+#endif // LIBCXXABI_ARM_EHABI
   }
 }
 
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits

Reply via email to