Greetings, We have a multi-threaded application that runs on an embedded Linux platform. In the past, the application was built with a 3.3.2 GNU gcc compiler and ran on a PXA-based system running Linux 2.4.27. We built a SEGV signal handler that we armed in each thread's main() function. This signal handler simply called the libc backtrace() function. This scenario worked very well for our device beta test by non-technical users. Whenever the system crashed via segv we squirreled away the information on the device and retrieved it at convenient times, namely when the device was connected to our server over a wireless network. Now, we're moving to a new platform, although it's still ARM-based, running Linux 2.6.21. Our application has been ported to GNU GCC 4.1.1. What we have discovered is that backtrace() doesn't work under 4.1.1, so we can't do the same thing we did under 3.3.2. We found two patches to 4.1.1: http://gcc.gnu.org/ml/gcc-patches/2006-06/msg00357.html and http://www.ecos.sourceware.org/ml/libc-ports/2006-06/msg00045.html When we applied these patches to gcc 4.1.1, backtrace() tended to work a little better, but what we've noticed is that the backtrace is still inconsistent at unwinding the frame pointer, and the registers and program context tended to be those from the signal handler, which was NOT the case under 3.3.2. We need a way to fix this problem, if a solution exists. One solution we tried was to build our own backtrace() function showed inconsistent results, and it would be much better if we leveraged the libc backtrace function. Another solution was to fork gdb in batch mode in the signal handler, instead of calling backtrace(). This solution was also sub-optimal, producing inconsistent backtraces and, in addition, this requires gdb on the embedded device, which is space inefficient. I've included a test program (not muti-threaded) that we have used to test various solutions. If you have a solution to this problem, please let us know. If you need any more information, please let us know. Thanks in advance for any assistance you can provide. -blair #include <stdio.h> #include <execinfo.h> #include <stdlib.h> #include <time.h> #include <pthread.h> #include <execinfo.h> #include <signal.h> #include <sigcontextinfo.h> /* added this to account for the changes to the EABI frame format in gcc 4.1.1 */ struct layout { struct layout *__unbounded next; void *__unbounded sp; void *__unbounded return_address; }; int __arm_backtrace(int **arr, int maxsiz) { int cnt = 0; void *fp = __builtin_frame_address (0); struct layout *lp = (struct layout *)(fp - 12); while (cnt < maxsiz) { printf("lp[%d]: %p ra: %p next: %p\n", cnt, (void *)lp, (void *)lp->return_address, (void *)lp->next); arr[cnt++] = (void *)lp->return_address; if (!lp->next) { break; } lp = lp->next - 1; } return cnt; } static void catch_segfault (int signal, SIGCONTEXT ctx) { int *arr[32]; int size, i; struct sigaction sa; char **strings; printf("in %s\n", __FUNCTION__); #ifdef USE_LIBC_BACKTRACE size = backtrace((void **)arr, 32); #else size = __arm_backtrace(arr, 32); #endif strings = backtrace_symbols ((void **)arr, size); printf ("Obtained %zd stack frames.\n", size); for (i = 0; i < size; i++) printf ("%s\n", strings[i]); free (strings); /* Pass on the signal (so that a core file is produced). */ sa.sa_handler = SIG_DFL; sigemptyset (&sa.sa_mask); sa.sa_flags = 0; sigaction (signal, &sa, NULL); raise (signal); } #define INSTALL_FOR_SIG(sig) \ sigaction(sig, &sa, NULL) void install_fh(void) { struct sigaction sa; char *path = NULL; char *where; sa.sa_handler = (void *) catch_segfault; sigemptyset (&sa.sa_mask); sa.sa_flags = SA_RESTART; INSTALL_FOR_SIG (SIGSEGV); } int routine4(volatile int arg) { printf("in %s at %.8p\n", __FUNCTION__, routine4); *(int *)0 = 0xdeadbeef; return 1; } int routine3(volatile int arg) { printf("in %s at %.8p\n", __FUNCTION__, routine3); return routine4(0xdead4444); } int routine2(volatile int arg) { printf("in %s at %.8p\n", __FUNCTION__, routine2); return routine3(0xdead3333); } int routine1(volatile int arg) { printf("in %s at %.8p\n", __FUNCTION__, routine1)