diff options
author | Martin Storsjö <martin@martin.st> | 2025-05-09 11:08:38 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2025-05-09 11:08:38 +0300 |
commit | 2e436b15d30689c4525da3c8d4467a1c70e509f5 (patch) | |
tree | 109eda2ebd11168558f1b203269c992a3a0d49ee | |
parent | 9d5a5424f0356bd6ee01c751dd6957299783b41b (diff) | |
download | llvm-2e436b15d30689c4525da3c8d4467a1c70e509f5.zip llvm-2e436b15d30689c4525da3c8d4467a1c70e509f5.tar.gz llvm-2e436b15d30689c4525da3c8d4467a1c70e509f5.tar.bz2 |
[libunwind] [SEH] Implement parsing of aarch64 pdata/xdata (#137949)
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.)
-rw-r--r-- | libunwind/src/UnwindCursor.hpp | 46 |
1 files changed, 46 insertions, 0 deletions
diff --git a/libunwind/src/UnwindCursor.hpp b/libunwind/src/UnwindCursor.hpp index ca9927e..240752e 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 (exceptionHandlerInfo[0]) + _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; |