[PATCH v3] Cygwin: SEH: Fix crash and handle second unwind phase on AArch64
Igor Podgainoi
Igor.Podgainoi@arm.com
Tue Mar 31 12:11:52 GMT 2026
This patch adds the SEH_CODE macro (defined in cygtls.h) and refactors
the TRY_HANDLER_DATA metadata, fixing code styling and allowing it to
be used on both AArch64 and x86_64 architectures.
It also makes modifications to the exception handler responsible for the
__try and __except blocks.
The first change to the handler fixes a bug where the existing
exception context record is reused as an unwind context record, which
fails with a crash on Windows on Arm (AArch64). The fix is to create a
new record instead, while leaving the original one intact.
The second change adds an additional condition for cases when the
handler is called again in the second phase of unwinding on certain
platforms such as Windows on Arm (AArch64). In this case, the value
ExceptionContinueSearch is simply returned without making any changes.
Tests fixed on AArch64:
winsup.api/ltp/access03.exe
winsup.api/ltp/access05.exe
winsup.api/ltp/chdir04.exe
winsup.api/ltp/mkdir01.exe
winsup.api/ltp/rename08.exe
winsup.api/ltp/rmdir05.exe
winsup.api/ltp/stat03.exe
winsup.api/ltp/stat06.exe
winsup.api/ltp/symlink01.exe
winsup.api/ltp/symlink03.exe
winsup.api/ltp/times02.exe
winsup.api/ltp/unlink07.exe
Signed-off-by: Igor Podgainoi <igor.podgainoi@arm.com>
---
v3:
- Rebased on top of current main
- Improved the code style (if condition braces and TRY_HANDLER_DATA)
winsup/cygwin/exceptions.cc | 10 +++++++---
winsup/cygwin/local_includes/cygtls.h | 27 ++++++++++++++++-----------
2 files changed, 23 insertions(+), 14 deletions(-)
diff --git a/winsup/cygwin/exceptions.cc b/winsup/cygwin/exceptions.cc
index badb11da7..21af26ac3 100644
--- a/winsup/cygwin/exceptions.cc
+++ b/winsup/cygwin/exceptions.cc
@@ -618,10 +618,14 @@ EXCEPTION_DISPOSITION
exception::myfault (EXCEPTION_RECORD *e, exception_list *frame, CONTEXT *in,
PDISPATCHER_CONTEXT dispatch)
{
+ if (IS_UNWINDING(e->ExceptionFlags))
+ return ExceptionContinueSearch;
+
PSCOPE_TABLE table = (PSCOPE_TABLE) dispatch->HandlerData;
- RtlUnwindEx (frame,
- (char *) dispatch->ImageBase + table->ScopeRecord[0].JumpTarget,
- e, 0, in, dispatch->HistoryTable);
+ void *jump_target = ((char *) dispatch->ImageBase) + table->ScopeRecord[0].JumpTarget;
+
+ CONTEXT c;
+ RtlUnwindEx (frame, jump_target, e, 0, &c, dispatch->HistoryTable);
/* NOTREACHED, make gcc happy. */
return ExceptionContinueSearch;
}
diff --git a/winsup/cygwin/local_includes/cygtls.h b/winsup/cygwin/local_includes/cygtls.h
index 289f395e4..0b5255495 100644
--- a/winsup/cygwin/local_includes/cygtls.h
+++ b/winsup/cygwin/local_includes/cygtls.h
@@ -344,21 +344,26 @@ public:
void leave () __attribute__ ((returns_twice));
};
-#if defined (__aarch64__)
+#if defined(__aarch64__)
#define EXCEPTION_MYFAULT_REF "_ZN9exception7myfaultEP17_EXCEPTION_RECORDPvP8_CONTEXTP25_DISPATCHER_CONTEXT_ARM64"
-#define TRY_HANDLER_DATA (void) &&__l_try;
-#else
+/* An SEH directive that switches back to the code section. */
+#define SEH_CODE ".text"
+#elif defined(__x86_64__)
#define EXCEPTION_MYFAULT_REF "_ZN9exception7myfaultEP17_EXCEPTION_RECORDPvP8_CONTEXTP19_DISPATCHER_CONTEXT"
-#define TRY_HANDLER_DATA \
- __asm__ goto ("\n" \
- " .seh_handler " EXCEPTION_MYFAULT_REF ", @except \n" \
- " .seh_handlerdata \n" \
- " .long 1 \n" \
- " .rva %l[__l_try],%l[__l_endtry],%l[__l_except],%l[__l_except] \n" \
- " .seh_code \n" \
- : : : : __l_try, __l_endtry, __l_except)
+#define SEH_CODE ".seh_code"
#endif
+#define TRY_HANDLER_DATA \
+ __asm__ goto ("\n\
+ .seh_handler " \
+ EXCEPTION_MYFAULT_REF ", \
+ @except \n\
+ .seh_handlerdata \n\
+ .long 1 \n\
+ .rva %l[__l_try],%l[__l_endtry],%l[__l_except],%l[__l_except] \n"\
+ SEH_CODE " \n"\
+ : : : : __l_try, __l_endtry, __l_except)
+
/* Exception handling macros. This is a handmade SEH try/except. */
#define __mem_barrier __asm__ __volatile__ ("" ::: "memory")
#define __try \
--
2.43.0
More information about the Cygwin-patches
mailing list