I've been writing a program in NASM for Linux. I'd like to be able to return to the normal code path out of a signal handler that I've established for SIGFPE. Stripped-down sample code is:
section .text
global _start
_start: ; --- Enter the program ---
mov ebx,8 ; Load the signal to handle (SIGFPE)
mov ecx,.handle ; Load the handler address
mov eax,48 ; Load the syscall number for signal
int 0x80 ; Establish the handler
mov ebx,0 ; Prepare a divisor for SIGFPE
idiv ebx ; Divide edx:eax by 0
mov ebx,0 ; Set exit status 0 (shouldn't get here)
jmp .exit ; Exit the program
.handle: ; --- Handle a divide exception ---
mov ebx,31 ; Set exit status 31 (instead of real handling)
.exit: ; --- Exit the program ---
mov eax,1 ; Load the syscall number for exit
int 0x80 ; Exit back to the system
Magic numbers are for compactness of code here.
Before the idiv instruction, esp is 0xffffcc00
. At entry to the signal handler, esp is 0xffffc52c
. Quite a bit of stuff has been put on the stack! There's a welter of information out there about __NR_sigreturn. I've had no luck trying to use it. A ret
instruction in the handler just puts me back at the idiv instruction, this time with no handler.
Any ideas about what I can do at the .handle
label to get back safely into the mainline?
(I know that sigaction is available, but I'd like to understand what's going on in this situation.)
A simple ret
will return so as to reattempt the faulting instruction. When using sigaction
to register the signal handler with the flag SA_SIGINFO
, the third argument is a pointer to a ucontext_t
that contains the saved state, which may be altered.