Consider this program under GNU/Linux (x86_64):
------------- np.c -------------------
#include <cstdio>
#include <csignal>
#include <cstring>
#include <cstdlib>
static void handler(int sig)
{
printf("got signal %d\n", sig);
throw 1;
}
int (*my_vector)(int);
int *bar;
int main(int argc, char *argv[])
{
struct sigaction sa;
memset(&sa, 0, sizeof(sa));
sa.sa_handler = handler;
sa.sa_flags = SA_RESTART;
sigemptyset(&sa.sa_mask);
int rv = sigaction(SIGSEGV, &sa, NULL);
if (rv) {
perror("sigaction failed");
exit(1);
}
try {
//*bar = 6;
rv = my_vector(0);
} catch (int c) {
printf("I cought %d\n", c);
exit(0);
}
printf("No exception\n");
return 0;
}
------------------8<---------------------
$ g++ -fnon-call-exceptions -o np np.cc
$ ./np
got signal 11
terminate called after throwing an instance of 'int'
Aborted (core dumped)
However if we uncomment the '//*bar = 6;' line we get:
$ ./np
got signal 11
I cought 1
This happens because the libgcc unwinder cannot find unwinding
information for the PC at the point of the SIGSEGV.
However, we know that usually when we end up with a PC of zero, it is
because we called through a NULL function pointer. In this case, we
could use the return address (perhaps with a slight adjustment to
compensate for the call instruction) to do the unwinding.
Would it make any sense to build something like this into libgcc?
Or if we want to do this do we need to patch up the register state
before executing the throw?
David Daney