7

I am a C dummy and working on a C project which asked me to write a signal handler to catch SIGSEGV signal and perform some operations.

Basically, the main program will try to access a memory chunk that is neither readable or writable. When the main program access this chunk of memory it will raise a SIGSEGV signal, and in my signal handler function I will catch the signal and use mprotect() to convert that memory chunk into readable & writable.

But I don't know is there any way to get the address which caused SIGSEGV when signal is catched by my signal handler. I cannot do anything if I don't have the actual address which caused SIGSEGV. And I am not allowed to grab address from main into my signal handler.

can someone help me? Thanks!

melpomene
  • 84,125
  • 8
  • 85
  • 148
Zirui Bai
  • 93
  • 6

1 Answers1

4

At least on Linux the answer is yes.

You use sigaction to register your signal handler, and you set the SA_SIGINFO flag and set a sa_sigaction handler.

This gives you access to a siginfo_t (second argument to your signal handler), which (among other things) contains a void *si_addr; field that (for SIGSEGV) contains the faulting address.

#define _POSIX_C_SOURCE 199309L
#include <signal.h>

void my_handler(int sig, siginfo_t *info, void *ucontext) {
    ... info->si_addr ...
}

...
struct sigaction act = {0};
act.sa_sigaction = my_handler;
act.sa_flags = SA_SIGINFO;
sigaction(SIGSEGV, &act, NULL);

See man 2 sigaction for details.

melpomene
  • 84,125
  • 8
  • 85
  • 148
  • Hello, I cannot find si_addr in my *info structure, there are only _sifields, si_code, si_errno, and si_signo. – Zirui Bai Nov 28 '18 at 23:23
  • Hello, I found the si_addr under _sifields->_sigfault->si_addr. – Zirui Bai Nov 28 '18 at 23:27
  • Hello, now I am in another trouble: when I try to compile my handler prototype says "unknown type name ‘siginfo_t’". Also, when I try to assign my handler function like this: "act.__sigaction_handler.sa_sigaction = handler_function;" I got the error: "‘union ’ has no member named ‘__sigaction_handler’" Is there anyway to solve this? Thanks! – Zirui Bai Nov 28 '18 at 23:44
  • @ZiruiBai 1) What OS are you on? 2) What happens when you try my code? – melpomene Nov 28 '18 at 23:44
  • 1. ubuntu 16.04. 2. your code won't work on my machine, I have to use act.__sigaction_handler.sa_sigaction to assign handler function and use info->_sifields._sigfault.si_addr to get fault address. – Zirui Bai Nov 28 '18 at 23:47
  • won't compile, showing error "unknown type name ‘siginfo_t’" – Zirui Bai Nov 28 '18 at 23:50
  • I changed my code as the same with yours now, and this is the only error when compile. – Zirui Bai Nov 28 '18 at 23:52
  • @ZiruiBai Can you post your source file and compilation options somewhere? – melpomene Nov 28 '18 at 23:52
  • Hello: I kind of found the reason. when I put prototype within .c file associated with my code it will compile, but when I put this into .h file associated with my code it won't work. – Zirui Bai Nov 28 '18 at 23:56
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/184439/discussion-between-melpomene-and-zirui-bai). – melpomene Nov 28 '18 at 23:57