Here is an example of using sigaction on linux in x86 assembler code as abstracted from: NasmX86
my $end = Label;
Jmp $end; # Jump over subroutine definition
my $start = SetLabel;
Enter 0, 0; # Inline code of signal handler
Mov r15, rbp; # Preserve the new stack frame
Mov rbp, "[rbp]"; # Restore our last stack frame
PrintOutTraceBack; # Print our trace back
Mov rbp, r15; # Restore supplied stack frame
Exit(0); # Exit so we do not trampoline. Exit with code zero to show that the program is functioning correctly, else L<Assemble> will report an error.
Leave;
Ret;
SetLabel $end;
Mov r15, 0; # Push sufficient zeros onto the stack to make a struct sigaction as described in: https://www.man7.org/linux/man-pages/man2/sigaction.2.html
Push r15 for 1..16;
Mov r15, $start; # Actual signal handler
Mov "[rsp]", r15; # Show as signal handler
Mov "[rsp+0x10]", r15; # Add as trampoline as well - which is fine because we exit in the handler so this will never be called
Mov r15, 0x4000000; # Mask to show we have a trampoline which is, apparently, required on x86
Mov "[rsp+0x8]", r15; # Confirm we have a trampoline
Mov rax, 13; # Sigaction from "kill -l"
Mov rdi, 11; # Confirmed SIGSEGV = 11 from kill -l and tracing with sde64
Mov rsi, rsp; # Sigaction structure on stack
Mov rdx, 0; # Confirmed by trace
Mov r10, 8; # Found by tracing "signal.c" with sde64 it is the width of the signal set and mask. "signal.c" is reproduced below.
Syscall;
Add rsp, 128;
my $s = Subroutine # Subrotuine that will cause an error to occur to force a trace back to be printed
{Mov r15, 0;
Mov r15, "[r15]"; # Try to read an unmapped memory location
} [qw(in)], name => 'sub that causes a segv'; # The name that will appear in the trace back
$s->call(K(in, 42));
ok Assemble(debug => 0, keep2 => 'signal', emulator=>0, eq => <<END); # Cannot use the emulator because it does not understand signals
Subroutine trace back, depth: 0000 0000 0000 0001
0000 0000 0000 002A sub that causes a segv
END
# /var/isde/sde64 -mix -ptr-check -debugtrace -- ./signal
##include <stdlib.h>
##include <stdio.h>
##include <signal.h>
##include <string.h>
##include <unistd.h>
#
#void handle_sigint(int sig)
# {exit(sig);
# }
#
#int main(void)
# {struct sigaction s;
# memset(&s, 0, sizeof(s));
# s.sa_sigaction = (void *)handle_sigint;
#
# long a = 0xabcdef;
# sigaction(SIGSEGV, &s, 0);
# long *c = 0; *c = a;
# }
#
# gcc -finput-charset=UTF-8 -fmax-errors=7 -rdynamic -Wall -Wextra -Wno-unused-function -o signal signal.c && /var/isde/sde64 -mix -ptr-check -debugtrace -- ./signal; echo $?;