https://github.com/mstorsjo created 
https://github.com/llvm/llvm-project/pull/137950

This is generally very similar to the aarch64 case.

Contrary to aarch64, the public headers don't contain any definition of a 
struct for interpreting this data, so we provide our own.

From 8a03c40961c30bc7a73d4bb841e1811722d2f23a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Martin=20Storsj=C3=B6?= <mar...@martin.st>
Date: Tue, 18 Apr 2023 15:02:54 +0300
Subject: [PATCH 1/2] [libunwind] [SEH] Implement parsing of aarch64
 pdata/xdata

This is needed for forced unwind.

This adds an aarch64 case for extracting the LanguageHandler and
HandlerData fields from unwind info, in UnwindCursor::getInfoFromSEH,
corresponding to the existing case for x86_64.

This uses the struct IMAGE_ARM64_RUNTIME_FUNCTION_ENTRY_XDATA; this
only became available in WinSDK 10.0.19041.0 and mingw-w64 v11.0 (or
a mingw-w64 git snapshot after April 2023).

(This is only a build-time requirement though; the format for the
unwind data has been fixed since the start of Windows 10 on ARM64,
so this doesn't impose any runtime requirement.)
---
 libunwind/src/UnwindCursor.hpp | 46 ++++++++++++++++++++++++++++++++++
 1 file changed, 46 insertions(+)

diff --git a/libunwind/src/UnwindCursor.hpp b/libunwind/src/UnwindCursor.hpp
index ca9927edc9990..5c1d77ebeddaf 100644
--- a/libunwind/src/UnwindCursor.hpp
+++ b/libunwind/src/UnwindCursor.hpp
@@ -2018,6 +2018,52 @@ bool UnwindCursor<A, R>::getInfoFromSEH(pint_t pc) {
       _info.handler = 0;
     }
   }
+#elif defined(_LIBUNWIND_TARGET_AARCH64)
+  if (unwindEntry->Flag != 0) { // Packed unwind info
+    _info.end_ip = _info.start_ip + unwindEntry->FunctionLength * 4;
+    // Only fill in the handler and LSDA if they're stale.
+    if (pc != getLastPC()) {
+      // Packed unwind info doesn't have an exception handler.
+      _info.lsda = 0;
+      _info.handler = 0;
+    }
+  } else {
+    IMAGE_ARM64_RUNTIME_FUNCTION_ENTRY_XDATA *xdata =
+        reinterpret_cast<IMAGE_ARM64_RUNTIME_FUNCTION_ENTRY_XDATA *>(
+            base + unwindEntry->UnwindData);
+    _info.end_ip = _info.start_ip + xdata->FunctionLength * 4;
+    // Only fill in the handler and LSDA if they're stale.
+    if (pc != getLastPC()) {
+      if (xdata->ExceptionDataPresent) {
+        uint32_t offset = 1; // The main xdata
+        uint32_t codeWords = xdata->CodeWords;
+        uint32_t epilogScopes = xdata->EpilogCount;
+        if (xdata->EpilogCount == 0 && xdata->CodeWords == 0) {
+          uint32_t extensionWord = reinterpret_cast<uint32_t *>(xdata)[1];
+          codeWords = (extensionWord >> 16) & 0xff;
+          epilogScopes = extensionWord & 0xffff;
+          offset++;
+        }
+        if (!xdata->EpilogInHeader)
+          offset += epilogScopes;
+        offset += codeWords;
+        uint32_t *exceptionHandlerInfo =
+            reinterpret_cast<uint32_t *>(xdata) + offset;
+        _dispContext.HandlerData = &exceptionHandlerInfo[1];
+        _dispContext.LanguageHandler = reinterpret_cast<EXCEPTION_ROUTINE *>(
+            base + exceptionHandlerInfo[0]);
+        _info.lsda = reinterpret_cast<unw_word_t>(_dispContext.HandlerData);
+        if (_dispContext.LanguageHandler)
+          _info.handler =
+              reinterpret_cast<unw_word_t>(__libunwind_seh_personality);
+        else
+          _info.handler = 0;
+      } else {
+        _info.lsda = 0;
+        _info.handler = 0;
+      }
+    }
+  }
 #endif
   setLastPC(pc);
   return true;

From 7254f7c4d8b07420c873b6729fac273f71efe38a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Martin=20Storsj=C3=B6?= <mar...@martin.st>
Date: Tue, 18 Apr 2023 23:28:20 +0300
Subject: [PATCH 2/2] [libunwind] [SEH] Implement parsing of ARM pdata/xdata

This is generally very similar to the aarch64 case.

Contrary to aarch64, the public headers don't contain any definition
of a struct for interpreting this data, so we provide our own.
---
 libunwind/src/UnwindCursor.hpp | 58 ++++++++++++++++++++++++++++++++++
 1 file changed, 58 insertions(+)

diff --git a/libunwind/src/UnwindCursor.hpp b/libunwind/src/UnwindCursor.hpp
index 5c1d77ebeddaf..1cbed2d6f93b9 100644
--- a/libunwind/src/UnwindCursor.hpp
+++ b/libunwind/src/UnwindCursor.hpp
@@ -83,6 +83,19 @@ struct UNWIND_INFO {
   uint16_t UnwindCodes[2];
 };
 
+union UNWIND_INFO_ARM {
+  DWORD HeaderData;
+  struct {
+    DWORD FunctionLength : 18;
+    DWORD Version : 2;
+    DWORD ExceptionDataPresent : 1;
+    DWORD EpilogInHeader : 1;
+    DWORD FunctionFragment : 1;
+    DWORD EpilogCount : 5;
+    DWORD CodeWords : 4;
+  } s;
+};
+
 extern "C" _Unwind_Reason_Code __libunwind_seh_personality(
     int, _Unwind_Action, uint64_t, _Unwind_Exception *,
     struct _Unwind_Context *);
@@ -2064,6 +2077,51 @@ bool UnwindCursor<A, R>::getInfoFromSEH(pint_t pc) {
       }
     }
   }
+#elif defined(_LIBUNWIND_TARGET_ARM)
+  if (unwindEntry->Flag != 0) { // Packed unwind info
+    _info.end_ip = _info.start_ip + unwindEntry->FunctionLength * 2;
+    // Only fill in the handler and LSDA if they're stale.
+    if (pc != getLastPC()) {
+      // Packed unwind info doesn't have an exception handler.
+      _info.lsda = 0;
+      _info.handler = 0;
+    }
+  } else {
+    UNWIND_INFO_ARM *xdata =
+        reinterpret_cast<UNWIND_INFO_ARM *>(base + unwindEntry->UnwindData);
+    _info.end_ip = _info.start_ip + xdata->s.FunctionLength * 2;
+    // Only fill in the handler and LSDA if they're stale.
+    if (pc != getLastPC()) {
+      if (xdata->s.ExceptionDataPresent) {
+        uint32_t offset = 1; // The main xdata
+        uint32_t codeWords = xdata->s.CodeWords;
+        uint32_t epilogScopes = xdata->s.EpilogCount;
+        if (xdata->s.EpilogCount == 0 && xdata->s.CodeWords == 0) {
+          uint32_t extensionWord = reinterpret_cast<uint32_t *>(xdata)[1];
+          codeWords = (extensionWord >> 16) & 0xff;
+          epilogScopes = extensionWord & 0xffff;
+          offset++;
+        }
+        if (!xdata->s.EpilogInHeader)
+          offset += epilogScopes;
+        offset += codeWords;
+        uint32_t *exceptionHandlerInfo =
+            reinterpret_cast<uint32_t *>(xdata) + offset;
+        _dispContext.HandlerData = &exceptionHandlerInfo[1];
+        _dispContext.LanguageHandler = reinterpret_cast<EXCEPTION_ROUTINE *>(
+            base + exceptionHandlerInfo[0]);
+        _info.lsda = reinterpret_cast<unw_word_t>(_dispContext.HandlerData);
+        if (_dispContext.LanguageHandler)
+          _info.handler =
+              reinterpret_cast<unw_word_t>(__libunwind_seh_personality);
+        else
+          _info.handler = 0;
+      } else {
+        _info.lsda = 0;
+        _info.handler = 0;
+      }
+    }
+  }
 #endif
   setLastPC(pc);
   return true;

_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to