We now appreciate sa_mask and SA_NODEFER and change the signal mask for the duration of signal handler. This is done by making a sigprocmask syscall at the end of the signal handler. Back-to-back signals will still grow stack as original registers are popped AFTER the block mask is updated. I guess this is why linux has sigreturn(?).
82 lines
1.3 KiB
ArmAsm
82 lines
1.3 KiB
ArmAsm
.section .userspace, "ax"
|
|
|
|
// stack contains
|
|
// (4 bytes) return address
|
|
// (4 bytes) return stack
|
|
// (4 bytes) return rflags
|
|
// (8 bytes) restore sigmask
|
|
// (36 bytes) siginfo_t
|
|
// (4 bytes) signal number
|
|
// (4 bytes) signal handler
|
|
|
|
.global signal_trampoline
|
|
signal_trampoline:
|
|
pushl %esi // gregs
|
|
pushl %edi
|
|
pushl %edx
|
|
pushl %ecx
|
|
pushl %ebx
|
|
pushl %eax
|
|
pushl %ebp
|
|
|
|
// FIXME: populate these
|
|
xorl %eax, %eax
|
|
pushl %eax // stack
|
|
pushl %eax
|
|
pushl %eax
|
|
pushl %eax // sigset
|
|
pushl %eax
|
|
pushl %eax // link
|
|
|
|
movl %esp, %edx // ucontext
|
|
leal 60(%esp), %esi // siginfo
|
|
movl 56(%esp), %edi // signal number
|
|
movl 52(%esp), %eax // handlers
|
|
|
|
// align stack to 16 bytes
|
|
movl %esp, %ebp
|
|
andl $-16, %esp
|
|
|
|
subl $512, %esp
|
|
fxsave (%esp)
|
|
|
|
subl $4, %esp
|
|
pushl %edx
|
|
pushl %esi
|
|
pushl %edi
|
|
call *%eax
|
|
addl $16, %esp
|
|
|
|
fxrstor (%esp)
|
|
addl $512, %esp
|
|
|
|
// restore stack
|
|
movl %ebp, %esp
|
|
addl $24, %esp
|
|
|
|
// restore sigmask
|
|
movl $83, %eax // SYS_SIGPROCMASK
|
|
movl $3, %ebx // SIG_SETMASK
|
|
leal 72(%esp), %ecx // set
|
|
xorl %edx, %edx // oset
|
|
int $0xF0
|
|
|
|
// restore registers
|
|
popl %ebp
|
|
popl %eax
|
|
popl %ebx
|
|
popl %ecx
|
|
popl %edx
|
|
popl %edi
|
|
popl %esi
|
|
|
|
// skip handler, number, siginfo_t, sigmask
|
|
addl $52, %esp
|
|
|
|
// restore flags
|
|
popf
|
|
|
|
movl (%esp), %esp
|
|
|
|
ret
|