Mark, one of my colleagues, fixed syntax error in your code. That makes the code works on IA-32.
================== t2.cpp for IA32 ================
#define _POSIX_SOURCE 199309
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <execinfo.h>
#include <setjmp.h>
#include <unistd.h>
#define __USE_GNU 1
#include <sys/ucontext.h>
void MyStackWalker (siginfo_t *info, void *my_eip)
{
void *trace[10];
int i;
int trace_size = 0;
char **messages = (char**)NULL;
trace_size = backtrace(trace, 10);
messages = backtrace_symbols(trace, trace_size);
ucontext_t *uc = (ucontext_t *)my_eip;
trace[1] = (void*)uc->uc_mcontext.gregs[REG_RIP];
for (i=0; i<trace_size; i++)
{
printf("\n[bt] %s", messages[i]);
}
free (messages);
}
void MySignalHandler (int signo, siginfo_t *info, void *my_eip)
{
if (signo == SIGFPE)
{
printf("\n A floating point exception has been detected.");
MyStackWalker(info, my_eip);
}
else if (signo == SIGSEGV)
{
printf("\n A segmentation violation has been detected.");
MyStackWalker(info, my_eip);
}
else if (signo == SIGILL)
{
printf("\n An illegal operation has been detected.");
MyStackWalker(info, my_eip);
}
else if (signo == SIGTRAP)
{
printf("\n A out of bounds array has been detected.");
MyStackWalker(info, my_eip);
}
else
{
printf("\n An unknown exception has been detected.");
MyStackWalker(info, my_eip);
}
}
int main()
{
struct sigaction newAct;
newAct.sa_sigaction= &MySignalHandler;
sigemptyset (&newAct.sa_mask);
newAct.sa_flags = SA_RESTART | SA_SIGINFO;
sigaction(SIGFPE, &newAct, NULL);
sigaction(SIGILL, &newAct, NULL);
sigaction(SIGSEGV, &newAct, NULL);
sigaction(SIGTRAP, &newAct, NULL);
}
============================================
$ icc -V
Intel(R) C Compiler Professional for applications running on IA-32, Version 11.0 Build 20090609 Package ID: l_cproc_p_11.0.084
Copyright (C) 1985-2009 Intel Corporation. All rights reserved.
$ icpc t2.cpp
$ g++ t2.cpp
$
However, above code doesn't compile on Intel 64. Then I did some further investigation.It looks that REG_EIP only works on IA-32. In /usr/include/sys/ucontext.h, you may see something like this
#if __WORDSIZE == 64
...
enum
{
REG_R8 = 0,
# define REG_R8 REG_R8
REG_R9,
# define REG_R9 REG_R9
REG_R10,
# define REG_R10 REG_R10
REG_R11,
...
REG_RIP,
# define REG_RIP REG_RIP
...
};
#else /* __WORDSIZE == 32 */
enum
{
...
REG_EIP,
# define REG_EIP REG_EIP
REG_CS,
# define REG_CS REG_CS
REG_EFL,
# define REG_EFL REG_EFL
REG_UESP,
# define REG_UESP REG_UESP
REG_SS
# define REG_SS REG_SS
};
#endif
So, on IA-32, REG_EIP is an enum value. But on Intel 64, REG_EIP is not defined. It seems that you should use REG_RIP instead on Intel 64. With this modification, t2.cpp compiles. See below.
=========== t2.cpp for Intel 64 ================
#define _POSIX_SOURCE 199309
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <execinfo.h>
#include <setjmp.h>
#include <unistd.h>
#define __USE_GNU 1
#include <sys/ucontext.h>
void MyStackWalker (siginfo_t *info, void *my_eip)
{
void *trace[10];
int i;
int trace_size = 0;
char **messages = (char**)NULL;
trace_size = backtrace(trace, 10);
messages = backtrace_symbols(trace, trace_size);
ucontext_t *uc = (ucontext_t *)my_eip;
trace[1] = (void*)uc->uc_mcontext.gregs[REG_RIP];
for (i=0; i<trace_size; i++)
{
printf("\n[bt] %s", messages[i]);
}
free (messages);
}
void MySignalHandler (int signo, siginfo_t *info, void *my_eip)
{
if (signo == SIGFPE)
{
printf("\n A floating point exception has been detected.");
MyStackWalker(info, my_eip);
}
else if (signo == SIGSEGV)
{
printf("\n A segmentation violation has been detected.");
MyStackWalker(info, my_eip);
}
else if (signo == SIGILL)
{
printf("\n An illegal operation has been detected.");
MyStackWalker(info, my_eip);
}
else if (signo == SIGTRAP)
{
printf("\n A out of bounds array has been detected.");
MyStackWalker(info, my_eip);
}
else
{
printf("\n An unknown exception has been detected.");
MyStackWalker(info, my_eip);
}
}
int main()
{
struct sigaction newAct;
newAct.sa_sigaction= &MySignalHandler;
sigemptyset (&newAct.sa_mask);
newAct.sa_flags = SA_RESTART | SA_SIGINFO;
sigaction(SIGFPE, &newAct, NULL);
sigaction(SIGILL, &newAct, NULL);
sigaction(SIGSEGV, &newAct, NULL);
sigaction(SIGTRAP, &newAct, NULL);
}
=======================================
$ icc -V
Intel(R) C Intel(R) 64 Compiler Professional for applications running on Intel(R) 64, Version 11.0 Build 20090609 Package ID: l_cproc_p_11.0.084
Copyright (C) 1985-2009 Intel Corporation. All rights reserved.
$ icpc t2.cpp
$ g++ t2.cpp
$