Did you know LQ has a Linux Hardware Compatibility List?
Go Back > Blogs > rainbowsally
User Name


Rate this Entry

Handle segmentation faults in try-catch block

Posted 05-06-2012 at 12:52 AM by rainbowsally
Updated 05-06-2012 at 05:19 AM by rainbowsally (updated code for 32 and also 64 bit arch)

May 6, 2012 (second edit)
Tested 64 bit code (and also 32), corrected close brace in function that got lost in the #if-#else-#endif mixup (with extern "C" close brace)... nevermind. It works now.

  • catch segmentation faults and continue normally

Don't underestimate this concept. We'll be using it in the GUI-Interactive interpreter.

This is a highly simplified version of the SEH for linux experiment posted earlier on. In that one ALL the registers are available through the sigcontext struct. In this one we only need eip/rip and so we can deal with the struct as an array of pointers (or longs, but pointers are more useful).

It is assumed that the fault is understood and has been fully handled. In this test we are in essence verifying that address 0 is not available for reading. ;-)

[The other experiment told what kind of read/write access caused the fault.]

There is nothing to "fix" in this case except the return address, so here we go.

file: src/main.cpp
// main.cpp for segv catch test

#include <stdio.h>  // printf() 
#include <signal.h> // signal()

#define BITS 32

void dbg(){}

extern "C"

#if BITS == 32
void** get_ebp()
      "mov %ebp, %esp;\n"
      "popl %ebp;\n"
      "mov %ebp, %eax;\n"
  return 0; // not used
#if BITS == 64
void** get_edx()
      "mov %rbp, %rsp;\n"
      "popl %rbp;\n"
      "mov %rdx, %rax;\n"
  return 0; // not used
#warning BITS must be defined (either 32 or 64)
#endif // 64
#endif // 32

static void exception_mediator(int signum);

int mem_test_var;

static struct sigaction new_action;

static void init_sighandler(void (*fn)(int))
  new_action.sa_handler = fn;
  sigemptyset (&new_action.sa_mask);
  new_action.sa_flags = SA_SIGINFO;
  sigaction(11, &new_action, 0); // sigsegv only

void** psig_context; // a pointer we can get at in asm
int test_flag;

void throw_test()
  throw("Segment violation\nContinuing...\n\n");

static void exception_mediator(int signum)
#if BITS == 32
#define CTX_EIP 14
  void** p = get_ebp();
  p += 2; // &signum
  p = (void**)p[2];                     // pointers
  p += 5;                               // psig_context
  psig_context = (void**)p;
  // get context
  void*** context = (void***)psig_context;
  // set new eip as though it were a call
  context[CTX_EIP] = (void**)&throw_test;
// } not close brace here -rs

#if BITS == 64
#define CTX_RIP 16

    p = (void**)get_rdx();
    psig_context = p;
    void***context = (void***)psig_context;
    context[CTX_RIP] = (void**)&throw_test;
#warning BITS must be defined (either 32 or 64)
#endif // 64
#endif // 32
} // add close brace here -rs

} // extern "C"

int main(int argc, char** argv)
  printf("Press ENTER 4 times to test and exit normally\n");  
  for(int i = 0; i < 4; i++)
      char* s = 0;
      printf("%s\n", s);
    catch(const char* s)
        printf("%s", s);
      test_flag = 0;
  printf("\nExiting normally\n");  
  return 0;
This is preset for ix86 architecture. You can also try x86_64 if your machine can handle it. Other architectures haven't been tested but it's very likely that once you find the sigcontext struct, the registers the struct will be identical.

The Computer Mad Science Team

Posted in Uncategorized
Views 1300 Comments 0
« Prev     Main     Next »
Total Comments 0




All times are GMT -5. The time now is 11:34 PM.

Main Menu

Write for LQ is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions @linuxquestions
Facebook: linuxquestions Google+: linuxquestions
Open Source Consulting | Domain Registration