Skip to content

Commit 4f5614e

Browse files
committed
[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.)
1 parent 08f0aa4 commit 4f5614e

File tree

1 file changed

+46
-0
lines changed

1 file changed

+46
-0
lines changed

libunwind/src/UnwindCursor.hpp

+46
Original file line numberDiff line numberDiff line change
@@ -2018,6 +2018,52 @@ bool UnwindCursor<A, R>::getInfoFromSEH(pint_t pc) {
20182018
_info.handler = 0;
20192019
}
20202020
}
2021+
#elif defined(_LIBUNWIND_TARGET_AARCH64)
2022+
if (unwindEntry->Flag != 0) { // Packed unwind info
2023+
_info.end_ip = _info.start_ip + unwindEntry->FunctionLength * 4;
2024+
// Only fill in the handler and LSDA if they're stale.
2025+
if (pc != getLastPC()) {
2026+
// Packed unwind info doesn't have an exception handler.
2027+
_info.lsda = 0;
2028+
_info.handler = 0;
2029+
}
2030+
} else {
2031+
IMAGE_ARM64_RUNTIME_FUNCTION_ENTRY_XDATA *xdata =
2032+
reinterpret_cast<IMAGE_ARM64_RUNTIME_FUNCTION_ENTRY_XDATA *>(
2033+
base + unwindEntry->UnwindData);
2034+
_info.end_ip = _info.start_ip + xdata->FunctionLength * 4;
2035+
// Only fill in the handler and LSDA if they're stale.
2036+
if (pc != getLastPC()) {
2037+
if (xdata->ExceptionDataPresent) {
2038+
uint32_t offset = 1; // The main xdata
2039+
uint32_t codeWords = xdata->CodeWords;
2040+
uint32_t epilogScopes = xdata->EpilogCount;
2041+
if (xdata->EpilogCount == 0 && xdata->CodeWords == 0) {
2042+
uint32_t extensionWord = reinterpret_cast<uint32_t *>(xdata)[1];
2043+
codeWords = (extensionWord >> 16) & 0xff;
2044+
epilogScopes = extensionWord & 0xffff;
2045+
offset++;
2046+
}
2047+
if (!xdata->EpilogInHeader)
2048+
offset += epilogScopes;
2049+
offset += codeWords;
2050+
uint32_t *exceptionHandlerInfo =
2051+
reinterpret_cast<uint32_t *>(xdata) + offset;
2052+
_dispContext.HandlerData = &exceptionHandlerInfo[1];
2053+
_dispContext.LanguageHandler = reinterpret_cast<EXCEPTION_ROUTINE *>(
2054+
base + exceptionHandlerInfo[0]);
2055+
_info.lsda = reinterpret_cast<unw_word_t>(_dispContext.HandlerData);
2056+
if (exceptionHandlerInfo[0])
2057+
_info.handler =
2058+
reinterpret_cast<unw_word_t>(__libunwind_seh_personality);
2059+
else
2060+
_info.handler = 0;
2061+
} else {
2062+
_info.lsda = 0;
2063+
_info.handler = 0;
2064+
}
2065+
}
2066+
}
20212067
#endif
20222068
setLastPC(pc);
20232069
return true;

0 commit comments

Comments
 (0)