-
Notifications
You must be signed in to change notification settings - Fork 13.4k
[libunwind] [SEH] Implement parsing of ARM pdata/xdata #137950
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
Conversation
This goes on top of #137949. |
@llvm/pr-subscribers-libunwind Author: Martin Storsjö (mstorsjo) ChangesThis 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. Full diff: https://github.com/llvm/llvm-project/pull/137950.diff 1 Files Affected:
diff --git a/libunwind/src/UnwindCursor.hpp b/libunwind/src/UnwindCursor.hpp
index ca9927edc9990..1cbed2d6f93b9 100644
--- a/libunwind/src/UnwindCursor.hpp
+++ b/libunwind/src/UnwindCursor.hpp
@@ -83,6 +83,19 @@ struct UNWIND_INFO {
uint16_t UnwindCodes[2];
};
+union UNWIND_INFO_ARM {
+ DWORD HeaderData;
+ struct {
+ DWORD FunctionLength : 18;
+ DWORD Version : 2;
+ DWORD ExceptionDataPresent : 1;
+ DWORD EpilogInHeader : 1;
+ DWORD FunctionFragment : 1;
+ DWORD EpilogCount : 5;
+ DWORD CodeWords : 4;
+ } s;
+};
+
extern "C" _Unwind_Reason_Code __libunwind_seh_personality(
int, _Unwind_Action, uint64_t, _Unwind_Exception *,
struct _Unwind_Context *);
@@ -2018,6 +2031,97 @@ 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;
+ }
+ }
+ }
+#elif defined(_LIBUNWIND_TARGET_ARM)
+ if (unwindEntry->Flag != 0) { // Packed unwind info
+ _info.end_ip = _info.start_ip + unwindEntry->FunctionLength * 2;
+ // 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 {
+ UNWIND_INFO_ARM *xdata =
+ reinterpret_cast<UNWIND_INFO_ARM *>(base + unwindEntry->UnwindData);
+ _info.end_ip = _info.start_ip + xdata->s.FunctionLength * 2;
+ // Only fill in the handler and LSDA if they're stale.
+ if (pc != getLastPC()) {
+ if (xdata->s.ExceptionDataPresent) {
+ uint32_t offset = 1; // The main xdata
+ uint32_t codeWords = xdata->s.CodeWords;
+ uint32_t epilogScopes = xdata->s.EpilogCount;
+ if (xdata->s.EpilogCount == 0 && xdata->s.CodeWords == 0) {
+ uint32_t extensionWord = reinterpret_cast<uint32_t *>(xdata)[1];
+ codeWords = (extensionWord >> 16) & 0xff;
+ epilogScopes = extensionWord & 0xffff;
+ offset++;
+ }
+ if (!xdata->s.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;
|
7254f7c
to
c027e4f
Compare
c027e4f
to
b5ed499
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
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.
b5ed499
to
fb51e2b
Compare
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.