assemblyhandlersigfpe

How do I return to mainline code from a signal handler in assembler?


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.)


Solution

  • 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.