LinuxQuestions.org
Download your favorite Linux distribution at LQ ISO.
Go Back   LinuxQuestions.org > Blogs > rainbowsally
User Name
Password

Notices

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)

[CHANGELOG:
May 6, 2012 (second edit)
Latest:
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.

Features:
  • 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
Code:
// 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()
{
  asm(
      "mov %ebp, %esp;\n"
      "popl %ebp;\n"
      "mov %ebp, %eax;\n"
      "ret;\n"
     );
  return 0; // not used
}
#else 
#if BITS == 64
void** get_edx()
{
  asm(
      "mov %rbp, %rsp;\n"
      "popl %rbp;\n"
      "mov %rdx, %rax;\n"
      "ret;\n"
     );
  return 0; // not used
}
#else
#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()
{
  test_flag++;
  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

#else
#if BITS == 64
#define CTX_RIP 16

    void**p;
    
    p = (void**)get_rdx();
    p+=5;
    psig_context = p;
    void***context = (void***)psig_context;
    context[CTX_RIP] = (void**)&throw_test;
    
#else
#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)
{
  dbg();  
  init_sighandler(exception_mediator);
  printf("Press ENTER 4 times to test and exit normally\n");  
  for(int i = 0; i < 4; i++)
  {
    getchar();
    try
    {
      char* s = 0;
      printf("%s\n", s);
    }
    catch(const char* s)
    {
      if(test_flag)
        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 1347 Comments 0
« Prev     Main     Next »
Total Comments 0

Comments

 

  



All times are GMT -5. The time now is 07:45 AM.

Main Menu
Advertisement

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