]> Cypherpunks repositories - gostls13.git/commitdiff
runtime: use libc for signal functions on iOS
authorElias Naur <elias.naur@gmail.com>
Thu, 7 Jun 2018 10:19:42 +0000 (12:19 +0200)
committerKeith Randall <khr@golang.org>
Tue, 12 Jun 2018 17:05:46 +0000 (17:05 +0000)
Also:
 - Add extra SystemStack space for darwin/arm64 just
like for darwin/arm.
 - Removed redundant stack alignment; the arm64 hardware enforces
 the 16 byte alignment.
 - Save and restore the g registers at library initialization.
 - Zero g registers since libpreinit can call libc functions
 that in turn use asmcgocall. asmcgocall requires an initialized g.
 - Change asmcgocall to work even if no g is set. The change mimics
 amd64.

Change-Id: I1b8c63b07cfec23b909c0d215b50dc229f8adbc8
Reviewed-on: https://go-review.googlesource.com/117176
Run-TryBot: Keith Randall <khr@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Keith Randall <khr@golang.org>
src/cmd/vet/all/whitelist/darwin_arm.txt
src/cmd/vet/all/whitelist/darwin_arm64.txt
src/runtime/asm_arm.s
src/runtime/asm_arm64.s
src/runtime/rt0_darwin_arm64.s
src/runtime/stack.go
src/runtime/sys_darwin_arm.s
src/runtime/sys_darwin_arm64.s

index 8e935b6ff2dc2240a83adc862bdf3a24dfdc8155..1c25c6a9397655b7629cf408737d82543b307b69 100644 (file)
@@ -1,11 +1,5 @@
 // darwin/arm-specific vet whitelist. See readme.txt for details.
 
-// False positives due to comments in assembly.
-// To be removed. See CL 27154.
-
-runtime/sys_darwin_arm.s: [arm] sigfwd: use of unnamed argument 0(FP); offset 0 is fn+0(FP)
-
-
 // Ok.
 
 runtime/asm_arm.s: [arm] sigreturn: function sigreturn missing Go declaration
index 8cab997961a37df999e7a2844a72a06b2b40eb54..a1edb7138328217ad4e04c33fc50dc826b537239 100644 (file)
@@ -1,5 +1,3 @@
 // darwin/arm64-specific vet whitelist. See readme.txt for details.
 
-runtime/sys_darwin_arm64.s: [arm64] sigtramp: 24(RSP) should be infostyle+8(FP)
-runtime/sys_darwin_arm64.s: [arm64] sigtramp: 24(RSP) should be infostyle+8(FP)
 runtime/asm_arm64.s: [arm64] sigreturn: function sigreturn missing Go declaration
index 545e58e9b04217fe40c898f4b03dbe7bf1666f27..6722ba760fb540de2e77929d366c962f6c3cc5b7 100644 (file)
@@ -36,25 +36,28 @@ TEXT _rt0_arm_lib(SB),NOSPLIT,$104
        MOVW    R6, 20(R13)
        MOVW    R7, 24(R13)
        MOVW    R8, 28(R13)
-       MOVW    R11, 32(R13)
+       MOVW    g, 32(R13)
+       MOVW    R11, 36(R13)
 
        // Skip floating point registers on GOARM < 6.
        MOVB    runtime·goarm(SB), R11
        CMP     $6, R11
        BLT     skipfpsave
-       MOVD    F8, (32+8*1)(R13)
-       MOVD    F9, (32+8*2)(R13)
-       MOVD    F10, (32+8*3)(R13)
-       MOVD    F11, (32+8*4)(R13)
-       MOVD    F12, (32+8*5)(R13)
-       MOVD    F13, (32+8*6)(R13)
-       MOVD    F14, (32+8*7)(R13)
-       MOVD    F15, (32+8*8)(R13)
+       MOVD    F8, (40+8*0)(R13)
+       MOVD    F9, (40+8*1)(R13)
+       MOVD    F10, (40+8*2)(R13)
+       MOVD    F11, (40+8*3)(R13)
+       MOVD    F12, (40+8*4)(R13)
+       MOVD    F13, (40+8*5)(R13)
+       MOVD    F14, (40+8*6)(R13)
+       MOVD    F15, (40+8*7)(R13)
 skipfpsave:
        // Save argc/argv.
        MOVW    R0, _rt0_arm_lib_argc<>(SB)
        MOVW    R1, _rt0_arm_lib_argv<>(SB)
 
+       MOVW    $0, g // Initialize g.
+
        // Synchronous initialization.
        CALL    runtime·libpreinit(SB)
 
@@ -77,21 +80,22 @@ rr:
        MOVB    runtime·goarm(SB), R11
        CMP     $6, R11
        BLT     skipfprest
-       MOVD    (32+8*1)(R13), F8
-       MOVD    (32+8*2)(R13), F9
-       MOVD    (32+8*3)(R13), F10
-       MOVD    (32+8*4)(R13), F11
-       MOVD    (32+8*5)(R13), F12
-       MOVD    (32+8*6)(R13), F13
-       MOVD    (32+8*7)(R13), F14
-       MOVD    (32+8*8)(R13), F15
+       MOVD    (40+8*0)(R13), F8
+       MOVD    (40+8*1)(R13), F9
+       MOVD    (40+8*2)(R13), F10
+       MOVD    (40+8*3)(R13), F11
+       MOVD    (40+8*4)(R13), F12
+       MOVD    (40+8*5)(R13), F13
+       MOVD    (40+8*6)(R13), F14
+       MOVD    (40+8*7)(R13), F15
 skipfprest:
        MOVW    12(R13), R4
        MOVW    16(R13), R5
        MOVW    20(R13), R6
        MOVW    24(R13), R7
        MOVW    28(R13), R8
-       MOVW    32(R13), R11
+       MOVW    32(R13), g
+       MOVW    36(R13), R11
        RET
 
 // _rt0_arm_lib_go initializes the Go runtime.
@@ -582,6 +586,8 @@ TEXT ·asmcgocall(SB),NOSPLIT,$0-12
        MOVW    arg+4(FP), R0
 
        MOVW    R13, R2
+       CMP     $0, g
+       BEQ nosave
        MOVW    g, R4
 
        // Figure out if we need to switch to m->g0 stack.
@@ -590,10 +596,10 @@ TEXT ·asmcgocall(SB),NOSPLIT,$0-12
        MOVW    g_m(g), R8
        MOVW    m_gsignal(R8), R3
        CMP     R3, g
-       BEQ     noswitch
+       BEQ     nosave
        MOVW    m_g0(R8), R3
        CMP     R3, g
-       BEQ     noswitch
+       BEQ     nosave
        BL      gosave<>(SB)
        MOVW    R0, R5
        MOVW    R3, R0
@@ -602,7 +608,6 @@ TEXT ·asmcgocall(SB),NOSPLIT,$0-12
        MOVW    (g_sched+gobuf_sp)(g), R13
 
        // Now on a scheduling stack (a pthread-created stack).
-noswitch:
        SUB     $24, R13
        BIC     $0x7, R13       // alignment for gcc ABI
        MOVW    R4, 20(R13) // save old g
@@ -624,6 +629,30 @@ noswitch:
        MOVW    R0, ret+8(FP)
        RET
 
+nosave:
+       // Running on a system stack, perhaps even without a g.
+       // Having no g can happen during thread creation or thread teardown
+       // (see needm/dropm on Solaris, for example).
+       // This code is like the above sequence but without saving/restoring g
+       // and without worrying about the stack moving out from under us
+       // (because we're on a system stack, not a goroutine stack).
+       // The above code could be used directly if already on a system stack,
+       // but then the only path through this code would be a rare case on Solaris.
+       // Using this code for all "already on system stack" calls exercises it more,
+       // which should help keep it correct.
+       SUB     $24, R13
+       BIC     $0x7, R13       // alignment for gcc ABI
+       // save null g in case someone looks during debugging.
+       MOVW    $0, R4
+       MOVW    R4, 20(R13)
+       MOVW    R2, 16(R13)     // Save old stack pointer.
+       BL      (R1)
+       // Restore stack pointer.
+       MOVW    16(R13), R2
+       MOVW    R2, R13
+       MOVW    R0, ret+8(FP)
+       RET
+
 // cgocallback(void (*fn)(void*), void *frame, uintptr framesize, uintptr ctxt)
 // Turn the fn into a Go func (by taking its address) and call
 // cgocallback_gofunc.
index d1b90b056c9070b0d52aa2a3c75c15cd688f3c9a..af389be9fee336fce1b5badc00edaaa571e0c5cf 100644 (file)
@@ -863,6 +863,8 @@ TEXT ·asmcgocall(SB),NOSPLIT,$0-20
        MOVD    arg+8(FP), R0
 
        MOVD    RSP, R2         // save original stack pointer
+       CMP     $0, g
+       BEQ     nosave
        MOVD    g, R4
 
        // Figure out if we need to switch to m->g0 stack.
@@ -871,10 +873,12 @@ TEXT ·asmcgocall(SB),NOSPLIT,$0-20
        MOVD    g_m(g), R8
        MOVD    m_gsignal(R8), R3
        CMP     R3, g
-       BEQ     noswitch
+       BEQ     nosave
        MOVD    m_g0(R8), R3
        CMP     R3, g
-       BEQ     noswitch
+       BEQ     nosave
+
+       // Switch to system stack.
        MOVD    R0, R9  // gosave<> and save_g might clobber R0
        BL      gosave<>(SB)
        MOVD    R3, g
@@ -884,12 +888,10 @@ TEXT ·asmcgocall(SB),NOSPLIT,$0-20
        MOVD    R9, R0
 
        // Now on a scheduling stack (a pthread-created stack).
-noswitch:
        // Save room for two of our pointers /*, plus 32 bytes of callee
        // save area that lives on the caller stack. */
        MOVD    RSP, R13
        SUB     $16, R13
-       BIC     $0xf, R13       // alignment for gcc ABI
        MOVD    R13, RSP
        MOVD    R4, 0(RSP)      // save old g on stack
        MOVD    (g_stack+stack_hi)(R4), R4
@@ -910,6 +912,30 @@ noswitch:
        MOVW    R0, ret+16(FP)
        RET
 
+nosave:
+       // Running on a system stack, perhaps even without a g.
+       // Having no g can happen during thread creation or thread teardown
+       // (see needm/dropm on Solaris, for example).
+       // This code is like the above sequence but without saving/restoring g
+       // and without worrying about the stack moving out from under us
+       // (because we're on a system stack, not a goroutine stack).
+       // The above code could be used directly if already on a system stack,
+       // but then the only path through this code would be a rare case on Solaris.
+       // Using this code for all "already on system stack" calls exercises it more,
+       // which should help keep it correct.
+       MOVD    RSP, R13
+       SUB     $16, R13
+       MOVD    R13, RSP
+       MOVD    $0, R4
+       MOVD    R4, 0(RSP)      // Where above code stores g, in case someone looks during debugging.
+       MOVD    R2, 8(RSP)      // Save original stack pointer.
+       BL      (R1)
+       // Restore stack pointer.
+       MOVD    8(RSP), R2
+       MOVD    R2, RSP 
+       MOVD    R0, ret+16(FP)
+       RET
+
 // cgocallback(void (*fn)(void*), void *frame, uintptr framesize, uintptr ctxt)
 // Turn the fn into a Go func (by taking its address) and call
 // cgocallback_gofunc.
index 719944e626511f160d7328d679a1e591d7c6ce36..d039a8e0abab274413b1fe521b08f6d33f287cfc 100644 (file)
@@ -26,18 +26,21 @@ TEXT _rt0_arm64_darwin_lib(SB),NOSPLIT,$168
        MOVD R25, 72(RSP)
        MOVD R26, 80(RSP)
        MOVD R27, 88(RSP)
-       FMOVD F8, 96(RSP)
-       FMOVD F9, 104(RSP)
-       FMOVD F10, 112(RSP)
-       FMOVD F11, 120(RSP)
-       FMOVD F12, 128(RSP)
-       FMOVD F13, 136(RSP)
-       FMOVD F14, 144(RSP)
-       FMOVD F15, 152(RSP)
+       MOVD g, 96(RSP)
+       FMOVD F8, 104(RSP)
+       FMOVD F9, 112(RSP)
+       FMOVD F10, 120(RSP)
+       FMOVD F11, 128(RSP)
+       FMOVD F12, 136(RSP)
+       FMOVD F13, 144(RSP)
+       FMOVD F14, 152(RSP)
+       FMOVD F15, 160(RSP)
 
        MOVD  R0, _rt0_arm64_darwin_lib_argc<>(SB)
        MOVD  R1, _rt0_arm64_darwin_lib_argv<>(SB)
 
+       MOVD    $0, g // initialize g to nil
+
        // Synchronous initialization.
        MOVD    $runtime·libpreinit(SB), R4
        BL      (R4)
@@ -58,14 +61,16 @@ TEXT _rt0_arm64_darwin_lib(SB),NOSPLIT,$168
        MOVD 72(RSP), R25
        MOVD 80(RSP), R26
        MOVD 88(RSP), R27
-       FMOVD 96(RSP), F8
-       FMOVD 104(RSP), F9
-       FMOVD 112(RSP), F10
-       FMOVD 120(RSP), F11
-       FMOVD 128(RSP), F12
-       FMOVD 136(RSP), F13
-       FMOVD 144(RSP), F14
-       FMOVD 152(RSP), F15
+       MOVD 96(RSP), g
+       FMOVD 104(RSP), F8
+       FMOVD 112(RSP), F9
+       FMOVD 120(RSP), F10
+       FMOVD 128(RSP), F11
+       FMOVD 136(RSP), F12
+       FMOVD 144(RSP), F13
+       FMOVD 152(RSP), F14
+       FMOVD 160(RSP), F15
+
        RET
 
 TEXT _rt0_arm64_darwin_lib_go(SB),NOSPLIT,$0
index e40fa9cc1b41e543fce2b23145856c3360242ac6..d83e9d6722f4e61842a1aadd2c3c1c9e9be74fa9 100644 (file)
@@ -64,8 +64,8 @@ const (
        // StackSystem is a number of additional bytes to add
        // to each stack below the usual guard area for OS-specific
        // purposes like signal handling. Used on Windows, Plan 9,
-       // and Darwin/ARM because they do not use a separate stack.
-       _StackSystem = sys.GoosWindows*512*sys.PtrSize + sys.GoosPlan9*512 + sys.GoosDarwin*sys.GoarchArm*1024
+       // and iOS because they do not use a separate stack.
+       _StackSystem = sys.GoosWindows*512*sys.PtrSize + sys.GoosPlan9*512 + sys.GoosDarwin*sys.GoarchArm*1024 + sys.GoosDarwin*sys.GoarchArm64*1024
 
        // The minimum size of stack used by Go code
        _StackMin = 2048
index a940d95732c1ef13b5c4ffb813afb95bc4a48e52..5f6c90343747fa035afb154fae75305a35ab30a8 100644 (file)
@@ -61,14 +61,12 @@ TEXT runtime·exit_trampoline(SB),NOSPLIT|NOFRAME,$0
        MOVW    $1002, R1
        MOVW    R0, (R1)        // fail hard
 
-TEXT runtime·raiseproc(SB),NOSPLIT,$24
-       MOVW    $SYS_getpid, R12
-       SWI     $0x80
+TEXT runtime·raiseproc_trampoline(SB),NOSPLIT,$0
+       MOVW    0(R0), R8       // signal
+       BL      libc_getpid(SB)
        // arg 1 pid already in R0 from getpid
-       MOVW    sig+0(FP), R1   // arg 2 - signal
-       MOVW    $1, R2  // arg 3 - posix
-       MOVW    $SYS_kill, R12
-       SWI $0x80
+       MOVW    R8, R1  // arg 2 signal
+       BL      libc_kill(SB)
        RET
 
 TEXT runtime·mmap_trampoline(SB),NOSPLIT,$0
@@ -174,91 +172,89 @@ TEXT runtime·sigfwd(SB),NOSPLIT,$0-16
        MOVW    R4, R13
        RET
 
-// Sigtramp's job is to call the actual signal handler.
-// It is called with the following arguments on the stack:
-//      LR     "return address" - ignored
-//      R0     actual handler
-//      R1     siginfo style - ignored
-//      R2     signal number
-//      R3     siginfo
-//      -4(FP) context, beware that 0(FP) is the saved LR
 TEXT runtime·sigtramp(SB),NOSPLIT,$0
+       // Reserve space for callee-save registers and arguments.
+       SUB     $36, R13
+
+       MOVW    R4, 12(R13)
+       MOVW    R5, 16(R13)
+       MOVW    R6, 20(R13)
+       MOVW    R7, 24(R13)
+       MOVW    R8, 28(R13)
+       MOVW    R11, 32(R13)
+
+       // Save arguments.
+       MOVW    R0, 4(R13)      // sig
+       MOVW    R1, 8(R13)      // info
+       MOVW    R2, 12(R13)     // ctx
+
        // this might be called in external code context,
        // where g is not set.
-       // first save R0, because runtime·load_g will clobber it
-       MOVM.DB.W [R0], (R13)
        MOVB    runtime·iscgo(SB), R0
        CMP     $0, R0
        BL.NE   runtime·load_g(SB)
 
-       CMP     $0, g
-       BNE     cont
-       // fake function call stack frame for badsignal
-       // we only need to pass R2 (signal number), but
-       // badsignal will expect R2 at 4(R13), so we also
-       // push R1 onto stack. turns out we do need R1
-       // to do sigreturn.
-       MOVM.DB.W [R1,R2], (R13)
-       MOVW    $runtime·badsignal(SB), R11
-       BL      (R11)
-       MOVM.IA.W [R1], (R13) // saved infostype
-       ADD             $(4+4), R13 // +4: also need to remove the pushed R0.
-       MOVW    ucontext-4(FP), R0 // load ucontext
-       B       ret
-
-cont:
-       // Restore R0
-       MOVM.IA.W (R13), [R0]
+       MOVW    R13, R6
+       CMP     $0, g
+       BEQ nog
 
-       // NOTE: some Darwin/ARM kernels always use the main stack to run the
-       // signal handler. We need to switch to gsignal ourselves.
+       // iOS always use the main stack to run the signal handler.
+       // We need to switch to gsignal ourselves.
        MOVW    g_m(g), R11
        MOVW    m_gsignal(R11), R5
        MOVW    (g_stack+stack_hi)(R5), R6
-       SUB             $28, R6
-
-       // copy arguments for call to sighandler
-       MOVW    R2, 4(R6) // signal num
-       MOVW    R3, 8(R6) // signal info
-       MOVW    g, 16(R6) // old_g
-       MOVW    context-4(FP), R4
-       MOVW    R4, 12(R6) // context
-
-       // Backup ucontext and infostyle
-       MOVW    R4, 20(R6)
-       MOVW    R1, 24(R6)
-
-       // switch stack and g
-       MOVW    R6, R13 // sigtramp is not re-entrant, so no need to back up R13.
-       MOVW    R5, g
-
-       BL      (R0)
-
-       // call sigreturn
-       MOVW    20(R13), R0     // saved ucontext
-       MOVW    24(R13), R1     // saved infostyle
-ret:
-       MOVW    $SYS_sigreturn, R12 // sigreturn(ucontext, infostyle)
-       SWI     $0x80
 
-       // if sigreturn fails, we can do nothing but exit
-       B       runtime·exit(SB)
+nog:
+       // Restore arguments.
+       MOVW    4(R13), R0
+       MOVW    8(R13), R1
+       MOVW    12(R13), R2
+
+       // Reserve space for args and the stack pointer on the
+       // gsignal stack.
+       SUB $24, R6
+       // Save stack pointer.
+       MOVW    R13, R4
+       MOVW    R4, 16(R6)
+       // Switch to gsignal stack.
+       MOVW    R6, R13
+
+       // Call sigtrampgo
+       MOVW    R0, 4(R13)
+       MOVW    R1, 8(R13)
+       MOVW    R2, 12(R13)
+       BL      runtime·sigtrampgo(SB)
+
+       // Switch to old stack.
+       MOVW    16(R13), R5
+       MOVW    R5, R13
+
+       // Restore callee-save registers.
+       MOVW    12(R13), R4
+       MOVW    16(R13), R5
+       MOVW    20(R13), R6
+       MOVW    24(R13), R7
+       MOVW    28(R13), R8
+       MOVW    32(R13), R11
+
+       ADD $36, R13
 
-TEXT runtime·sigprocmask(SB),NOSPLIT,$0
-       MOVW    how+0(FP), R0
-       MOVW    new+4(FP), R1
-       MOVW    old+8(FP), R2
-       MOVW    $SYS_pthread_sigmask, R12
-       SWI     $0x80
-       BL.CS   notok<>(SB)
        RET
 
-TEXT runtime·sigaction(SB),NOSPLIT,$0
-       MOVW    mode+0(FP), R0
-       MOVW    new+4(FP), R1
-       MOVW    old+8(FP), R2
-       MOVW    $SYS_sigaction, R12
-       SWI     $0x80
+TEXT runtime·sigprocmask_trampoline(SB),NOSPLIT,$0
+       MOVW    4(R0), R1       // arg 2 new
+       MOVW    8(R0), R2       // arg 3 old
+       MOVW    0(R0), R0       // arg 1 how
+       BL      libc_pthread_sigmask(SB)
+       CMP     $0, R0
+       BL.NE   notok<>(SB)
+       RET
+
+TEXT runtime·sigaction_trampoline(SB),NOSPLIT,$0
+       MOVW    4(R0), R1       // arg 2 new
+       MOVW    8(R0), R2       // arg 3 old
+       MOVW    0(R0), R0       // arg 1 how
+       BL      libc_sigaction(SB)
        RET
 
 TEXT runtime·usleep_trampoline(SB),NOSPLIT,$0
@@ -387,10 +383,11 @@ TEXT runtime·closeonexec(SB),NOSPLIT,$0
        SWI     $0x80
        RET
 
-// sigaltstack on some darwin/arm version is buggy and will always
-// run the signal handler on the main stack, so our sigtramp has
+// sigaltstack is not supported on iOS, so our sigtramp has
 // to do the stack switch ourselves.
-TEXT runtime·sigaltstack(SB),NOSPLIT,$0
+TEXT runtime·sigaltstack_trampoline(SB),NOSPLIT,$0
+       MOVW    $43, R0
+       BL      libc_exit(SB)
        RET
 
 // Thread related functions
index d13e44afcfa2f4c1e1e9254632d2ee8dd3b65869..c21a5566fa0e66fb4ef4c2c265b216f52376b38c 100644 (file)
@@ -61,14 +61,12 @@ TEXT runtime·exit_trampoline(SB),NOSPLIT|NOFRAME,$0
        MOVD    $1002, R1
        MOVD    R0, (R1)        // fail hard
 
-TEXT runtime·raiseproc(SB),NOSPLIT,$0
-       MOVW    $SYS_getpid, R16
-       SVC     $0x80
+TEXT runtime·raiseproc_trampoline(SB),NOSPLIT,$0
+       MOVD    0(R0), R19      // signal
+       BL      libc_getpid(SB)
        // arg 1 pid already in R0 from getpid
-       MOVW    sig+0(FP), R1   // arg 2 - signal
-       MOVW    $1, R2  // arg 3 - posix
-       MOVW    $SYS_kill, R16
-       SVC     $0x80
+       MOVD    R19, R1 // arg 2 signal
+       BL      libc_kill(SB)
        RET
 
 TEXT runtime·mmap_trampoline(SB),NOSPLIT,$0
@@ -158,95 +156,104 @@ TEXT runtime·sigfwd(SB),NOSPLIT,$0-32
        BL      (R11)
        RET
 
-// Sigtramp's job is to call the actual signal handler.
-// It is called with the following arguments on the stack:
-//     LR      "return address" - ignored
-//     R0      actual handler
-//     R1      siginfo style - ignored
-//     R2      signal number
-//     R3      siginfo
-//     R4      context
 TEXT runtime·sigtramp(SB),NOSPLIT,$0
+       // Reserve space for callee-save registers and arguments.
+       SUB     $(8*16), RSP
+
+       // Save callee-save registers.
+       MOVD    R19, (8*4)(RSP)
+       MOVD    R20, (8*5)(RSP)
+       MOVD    R21, (8*6)(RSP)
+       MOVD    R22, (8*7)(RSP)
+       MOVD    R23, (8*8)(RSP)
+       MOVD    R24, (8*9)(RSP)
+       MOVD    R25, (8*10)(RSP)
+       MOVD    R26, (8*11)(RSP)
+       MOVD    R27, (8*12)(RSP)
+       MOVD    g, (8*13)(RSP)
+       MOVD    R29, (8*14)(RSP)
+
+       // Save arguments.
+       MOVW    R0, (8*1)(RSP)  // sig
+       MOVD    R1, (8*2)(RSP)  // info
+       MOVD    R2, (8*3)(RSP)  // ctx
+
        // this might be called in external code context,
        // where g is not set.
-       // first save R0, because runtime·load_g will clobber it
-       MOVD.W  R0, -16(RSP)    // note: stack must be 16-byte aligned
        MOVB    runtime·iscgo(SB), R0
        CMP     $0, R0
        BEQ     2(PC)
        BL      runtime·load_g(SB)
 
-       CMP     $0, g
-       BNE     cont
-       // fake function call stack frame for badsignal
-       // we only need to pass R2 (signal number), but
-       // badsignal will expect R2 at 8(RSP), so we also
-       // push R1 onto stack. turns out we do need R1
-       // to do sigreturn.
-       MOVD.W  R1, -16(RSP)
-       MOVD    R2, 8(RSP)
-       MOVD    R4, 24(RSP)     // save ucontext, badsignal might clobber R4
-       MOVD    $runtime·badsignal(SB), R26
-       BL      (R26)
-       MOVD    0(RSP), R1      // saved infostype
-       MOVD    24(RSP), R0     // the ucontext
-       ADD     $(16+16), RSP
-       B       ret
-
-cont:
-       // Restore R0
-       MOVD.P  16(RSP), R0
-
-       // NOTE: some Darwin/ARM kernels always use the main stack to run the
-       // signal handler. We need to switch to gsignal ourselves.
+       MOVD RSP, R6
+       CMP      $0, g
+       BEQ      nog
+       // iOS always use the main stack to run the signal handler.
+       // We need to switch to gsignal ourselves.
        MOVD    g_m(g), R11
        MOVD    m_gsignal(R11), R5
        MOVD    (g_stack+stack_hi)(R5), R6
-       SUB     $64, R6
 
-       // copy arguments for call to sighandler
-       MOVD    R2, 8(R6)       // signal num
-       MOVD    R3, 16(R6)      // signal info
-       MOVD    R4, 24(R6)      // context
-       MOVD    g, 32(R6)       // old_g
-
-       // Backup ucontext and infostyle
-       MOVD    R4, 40(R6)
-       MOVD    R1, 48(R6)
+nog:
+       // Restore arguments.
+       MOVW    (8*1)(RSP), R0
+       MOVD    (8*2)(RSP), R1
+       MOVD    (8*3)(RSP), R2
+
+       // Reserve space for args and the stack pointer on the
+       // gsignal stack.
+       SUB     $48, R6
+       // Save stack pointer.
+       MOVD    RSP, R4
+       MOVD    R4, (8*4)(R6)
+       // Switch to gsignal stack.
+       MOVD    R6, RSP
+
+       // Call sigtrampgo.
+       MOVW    R0, (8*1)(RSP)
+       MOVD    R1, (8*2)(RSP)
+       MOVD    R2, (8*3)(RSP)
+       MOVD    $runtime·sigtrampgo(SB), R11
+       BL      (R11)
 
-       // switch stack and g
-       MOVD    R6, RSP // sigtramp is not re-entrant, so no need to back up RSP.
-       MOVD    R5, g
+       // Switch to old stack.
+       MOVD    (8*4)(RSP), R5
+       MOVD    R5, RSP
 
-       BL      (R0)
+       // Restore callee-save registers.
+       MOVD    (8*4)(RSP), R19
+       MOVD    (8*5)(RSP), R20
+       MOVD    (8*6)(RSP), R21
+       MOVD    (8*7)(RSP), R22
+       MOVD    (8*8)(RSP), R23
+       MOVD    (8*9)(RSP), R24
+       MOVD    (8*10)(RSP), R25
+       MOVD    (8*11)(RSP), R26
+       MOVD    (8*12)(RSP), R27
+       MOVD    (8*13)(RSP), g
+       MOVD    (8*14)(RSP), R29
 
-       // call sigreturn
-       MOVD    40(RSP), R0     // saved ucontext
-       MOVD    48(RSP), R1     // saved infostyle
-ret:
-       MOVW    $SYS_sigreturn, R16 // sigreturn(ucontext, infostyle)
-       SVC     $0x80
+       ADD $(8*16), RSP
 
-       // if sigreturn fails, we can do nothing but exit
-       B       runtime·exit(SB)
+       RET
 
-TEXT runtime·sigprocmask(SB),NOSPLIT,$0
-       MOVW    how+0(FP), R0
-       MOVD    new+8(FP), R1
-       MOVD    old+16(FP), R2
-       MOVW    $SYS_pthread_sigmask, R16
-       SVC     $0x80
-       BCC     2(PC)
+TEXT runtime·sigprocmask_trampoline(SB),NOSPLIT,$0
+       MOVD    8(R0), R1       // arg 2 new
+       MOVD    16(R0), R2      // arg 3 old
+       MOVW    0(R0), R0       // arg 1 how
+       BL      libc_pthread_sigmask(SB)
+       CMP $0, R0
+       BEQ     2(PC)
        BL      notok<>(SB)
        RET
 
-TEXT runtime·sigaction(SB),NOSPLIT,$0
-       MOVW    mode+0(FP), R0
-       MOVD    new+8(FP), R1
-       MOVD    old+16(FP), R2
-       MOVW    $SYS_sigaction, R16
-       SVC     $0x80
-       BCC     2(PC)
+TEXT runtime·sigaction_trampoline(SB),NOSPLIT,$0
+       MOVD    8(R0), R1       // arg 2 new
+       MOVD    16(R0), R2      // arg 3 old
+       MOVW    0(R0), R0       // arg 1 how
+       BL      libc_sigaction(SB)
+       CMP     $0, R0
+       BEQ     2(PC)
        BL      notok<>(SB)
        RET
 
@@ -375,10 +382,12 @@ TEXT runtime·closeonexec(SB),NOSPLIT,$0
        SVC     $0x80
        RET
 
-// sigaltstack on some darwin/arm version is buggy and will always
+// sigaltstack on iOS is not supported and will always
 // run the signal handler on the main stack, so our sigtramp has
 // to do the stack switch ourselves.
-TEXT runtime·sigaltstack(SB),NOSPLIT,$0
+TEXT runtime·sigaltstack_trampoline(SB),NOSPLIT,$0
+       MOVW    $43, R0
+       BL      libc_exit(SB)
        RET
 
 // Thread related functions