[libunwind] [libunwind] [SEH] Implement parsing of aarch64 pdata/xdata (PR #137949)
via cfe-commits
cfe-commits at lists.llvm.org
Wed Apr 30 03:47:23 PDT 2025
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-libunwind
Author: Martin Storsjö (mstorsjo)
<details>
<summary>Changes</summary>
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
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;
``````````
</details>
https://github.com/llvm/llvm-project/pull/137949
More information about the cfe-commits
mailing list