]> git.saurik.com Git - apple/libplatform.git/blobdiff - src/setjmp/generic/sigtramp.c
libplatform-254.40.4.tar.gz
[apple/libplatform.git] / src / setjmp / generic / sigtramp.c
index 32e31db7d800513f964a98113643ef0ae9873f7b..ce9f50531db088b897a9ec843a2c187e9d149496 100644 (file)
@@ -44,9 +44,9 @@ extern int __sigreturn(ucontext_t *, int, uintptr_t);
  * Note that the kernel saves/restores all of our register state.
  */
 
-/* On i386, i386/sys/_sigtramp.s defines this. There is no in_sigtramp on arm */
-#if defined(__DYNAMIC__) && defined(__x86_64__)
-OS_NOEXPORT
+/* On i386, i386/sys/_sigtramp.s defines this. */
+#if defined(__DYNAMIC__) && !defined(__i386__)
+OS_NOEXPORT int __in_sigtramp;
 int __in_sigtramp = 0;
 #endif
 
@@ -72,7 +72,7 @@ _sigunaltstack(int set)
 {
         /* sigreturn(uctx, ctxstyle); */
        /* syscall (SYS_SIGRETURN, uctx, ctxstyle); */
-       __sigreturn (NULL, (set == SS_ONSTACK) ? UC_SET_ALT_STACK : UC_RESET_ALT_STACK, 0);
+       __sigreturn (NULL, (set & SS_ONSTACK) ? UC_SET_ALT_STACK : UC_RESET_ALT_STACK, 0);
 }
 
 /* On these architectures, _sigtramp is implemented in assembly to
@@ -88,21 +88,37 @@ _sigtramp(
        ucontext_t              *uctx,
        uintptr_t               token
 ) {
+       __in_sigtramp = sig;
        int ctxstyle = UC_FLAVOR;
 
-       if (sigstyle == UC_TRAD)
-               sa_handler(sig);
-       else {
+       /* Some variants are not supposed to get the last 2 parameters but it's
+        * easier to pass them along - especially on arm64 whereby the extra fields
+        * are probably in caller save registers anyways, thereby making no
+        * difference to callee if we populate them or not.
+        *
+        *
+        * Moreover, sigaction(2)'s man page implies that the following behavior
+        * should be supported:
+        *
+        *      If the SA_SIGINFO flag is not set, the handler function should match
+        *      either the ANSI C or traditional BSD prototype and be pointed to by
+        *      the sa_handler member of struct sigaction.  In practice, FreeBSD
+        *      always sends the three arguments of the latter and since the ANSI C
+        *      prototype is a subset, both will work.
+        *
+        * See <rdar://problem/51448812> bad siginfo struct sent to SIGCHILD signal
+        * handler in arm64 process
+        */
 #if TARGET_OS_WATCH
-               // <rdar://problem/22016014>
-               sa_sigaction(sig, sinfo, NULL);
+       // <rdar://problem/22016014>
+       sa_sigaction(sig, sinfo, NULL);
 #else
-               sa_sigaction(sig, sinfo, uctx);
+       sa_sigaction(sig, sinfo, uctx);
 #endif
-       }
 
-        /* sigreturn(uctx, ctxstyle); */
+       /* sigreturn(uctx, ctxstyle); */
        /* syscall (SYS_SIGRETURN, uctx, ctxstyle); */
+       __in_sigtramp = 0;
        __sigreturn (uctx, ctxstyle, token);
        __builtin_trap(); /* __sigreturn returning is a fatal error */
 }