Skip to content

Commit fb51e2b

Browse files
committed
[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.
1 parent 2e436b1 commit fb51e2b

File tree

1 file changed

+31
-6
lines changed

1 file changed

+31
-6
lines changed

libunwind/src/UnwindCursor.hpp

+31-6
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,22 @@ struct UNWIND_INFO {
8383
uint16_t UnwindCodes[2];
8484
};
8585

86+
#pragma clang diagnostic push
87+
#pragma clang diagnostic ignored "-Wgnu-anonymous-struct"
88+
union UNWIND_INFO_ARM {
89+
DWORD HeaderData;
90+
struct {
91+
DWORD FunctionLength : 18;
92+
DWORD Version : 2;
93+
DWORD ExceptionDataPresent : 1;
94+
DWORD EpilogInHeader : 1;
95+
DWORD FunctionFragment : 1;
96+
DWORD EpilogCount : 5;
97+
DWORD CodeWords : 4;
98+
};
99+
};
100+
#pragma clang diagnostic pop
101+
86102
extern "C" _Unwind_Reason_Code __libunwind_seh_personality(
87103
int, _Unwind_Action, uint64_t, _Unwind_Exception *,
88104
struct _Unwind_Context *);
@@ -2018,27 +2034,36 @@ bool UnwindCursor<A, R>::getInfoFromSEH(pint_t pc) {
20182034
_info.handler = 0;
20192035
}
20202036
}
2021-
#elif defined(_LIBUNWIND_TARGET_AARCH64)
2037+
#elif defined(_LIBUNWIND_TARGET_AARCH64) || defined(_LIBUNWIND_TARGET_ARM)
2038+
2039+
#if defined(_LIBUNWIND_TARGET_AARCH64)
2040+
#define FUNC_LENGTH_UNIT 4
2041+
#define XDATA_TYPE IMAGE_ARM64_RUNTIME_FUNCTION_ENTRY_XDATA
2042+
#else
2043+
#define FUNC_LENGTH_UNIT 2
2044+
#define XDATA_TYPE UNWIND_INFO_ARM
2045+
#endif
20222046
if (unwindEntry->Flag != 0) { // Packed unwind info
2023-
_info.end_ip = _info.start_ip + unwindEntry->FunctionLength * 4;
2047+
_info.end_ip =
2048+
_info.start_ip + unwindEntry->FunctionLength * FUNC_LENGTH_UNIT;
20242049
// Only fill in the handler and LSDA if they're stale.
20252050
if (pc != getLastPC()) {
20262051
// Packed unwind info doesn't have an exception handler.
20272052
_info.lsda = 0;
20282053
_info.handler = 0;
20292054
}
20302055
} 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;
2056+
XDATA_TYPE *xdata =
2057+
reinterpret_cast<XDATA_TYPE *>(base + unwindEntry->UnwindData);
2058+
_info.end_ip = _info.start_ip + xdata->FunctionLength * FUNC_LENGTH_UNIT;
20352059
// Only fill in the handler and LSDA if they're stale.
20362060
if (pc != getLastPC()) {
20372061
if (xdata->ExceptionDataPresent) {
20382062
uint32_t offset = 1; // The main xdata
20392063
uint32_t codeWords = xdata->CodeWords;
20402064
uint32_t epilogScopes = xdata->EpilogCount;
20412065
if (xdata->EpilogCount == 0 && xdata->CodeWords == 0) {
2066+
// The extension word has got the same layout for both ARM and ARM64
20422067
uint32_t extensionWord = reinterpret_cast<uint32_t *>(xdata)[1];
20432068
codeWords = (extensionWord >> 16) & 0xff;
20442069
epilogScopes = extensionWord & 0xffff;

0 commit comments

Comments
 (0)