Skip to content

Instantly share code, notes, and snippets.

@fairlight1337
Last active January 22, 2024 17:29
Show Gist options
  • Star 13 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save fairlight1337/55978671ace2c75020eddbfbdd670221 to your computer and use it in GitHub Desktop.
Save fairlight1337/55978671ace2c75020eddbfbdd670221 to your computer and use it in GitHub Desktop.
Catching SIGSEGV (Segmentation Faults) in C
// This code installs a custom signal handler for the SIGSEGV signal
// (segmentation fault) and then purposefully creates a segmentation
// fault. The custom handler `handler` is then entered, which now
// increases the instruction pointer by 1, skipping the current byte
// of the faulty instruction. This is done for as long as the faulty
// instruction is still active; in the below case, that's 2 bytes.
// Note: This is for 64 bit systems. If you prefer 32 bit, change
// `REG_RIP` to `REG_EIP`. I didn't bother putting an appropriate
// `#ifdef` here.
#include <iostream>
#include <string.h>
#include <signal.h>
void handler(int nSignum, siginfo_t* si, void* vcontext) {
std::cout << "Segmentation fault" << std::endl;
ucontext_t* context = (ucontext_t*)vcontext;
context->uc_mcontext.gregs[REG_RIP]++;
}
int main() {
std::cout << "Start" << std::endl;
struct sigaction action;
memset(&action, 0, sizeof(struct sigaction));
action.sa_flags = SA_SIGINFO;
action.sa_sigaction = handler;
sigaction(SIGSEGV, &action, NULL);
int* x = 0;
int y = *x;
std::cout << "End" << std::endl;
return 0;
}
@fairlight1337
Copy link
Author

fairlight1337 commented Apr 23, 2016

I did this as a cpp file (and use the std::cout machinery) because I like it that way. The relevant SIGSEGV catching code is pure C, though.

string.h is only in there for memset.

The segfault happens when entering line 37,

int y = *x;

because then the value referenced by int* x (which is 0) is dereferenced.

@varun1729
Copy link

Do not use cout as it is not signal or thread safe use POSIX compliant write(2), which is unbuffered unlike cout.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment