Thanks to visit codestin.com
Credit goes to github.com

Skip to content

[libunwind] [SEH] Implement parsing of aarch64 pdata/xdata #137949

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

mstorsjo
Copy link
Member

This is needed for forced unwind, for some testcases in libunwind/libcxxabi.

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.)

@mstorsjo mstorsjo requested a review from a team as a code owner April 30, 2025 10:46
@llvmbot
Copy link
Member

llvmbot commented Apr 30, 2025

@llvm/pr-subscribers-libunwind

Author: Martin Storsjö (mstorsjo)

Changes

This is needed for forced unwind, for some testcases in libunwind/libcxxabi.

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.)


Full diff: https://github.com/llvm/llvm-project/pull/137949.diff

1 Files Affected:

  • (modified) libunwind/src/UnwindCursor.hpp (+46)
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;

@efriedma-quic
Copy link
Collaborator

The parsing itself looks fine. I don't have any context for how this code is supposed to work, though.

@mstorsjo
Copy link
Member Author

mstorsjo commented May 1, 2025

The parsing itself looks fine. I don't have any context for how this code is supposed to work, though.

Thanks! Yeah the whole context isn't entirely clear to me as well, but roughly I think the idea is that we normally run RtlUnwindEx for unwinding an exception, but this is a case where we'd be manually unwinding the stack and calling the personality function ourself, so we need to dig it up from the xdata. In any case - this does the aarch64 equivalent of the existing x86_64 code above.

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.)
@mstorsjo mstorsjo force-pushed the libunwind-aarch64-xdata branch from 8a03c40 to 4f5614e Compare May 1, 2025 20:25
Copy link
Contributor

@cjacek cjacek left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@mstorsjo
Copy link
Member Author

mstorsjo commented May 5, 2025

@MaskRay Can you give the necessary @reviewers-libunwind approval here, given @cjacek's review?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants