The symptom is that if you segfault and then throw an exception in the segfault handler call-saved fields in the Condition Register are corrupted.
The reason is that the unwinder data for CR in the vDSO is wrong. The line that affects the CR is here in arch/powerpc/kernel/vdso64/sigtramp.S: rsave (70, 38*RSIZE) /* cr */ This restores a 64-bit register from offset 38 in the sigcontext register save area to DWARF Column 70. This much is correct... Unfortunately, gcc saves and restores only the *least significant* 32-bit half of CR on the stack. As this is a big-endian machine, the result is that when unwinding __kernel_sigtramp_rt64 the correctly saved CR is written to the upper half of the word on the stack, not the lower half, and the saved CR is overwritten with zeroes. It is not immediately clear to me how to fix this: I think you would need to find a DWARF expression that copies a halfword value. Test case attached. Tested on Kernel 2.6.18-8.1.10.el5. Andrew. #include <signal.h> #include <cstddef> #include <cstdio> class SegfaultException { }; void catch_segv (int) { throw new SegfaultException; } void segfault (int *p) { fprintf (stderr, "%n", *p); } int main(int argc, char **argv) { unsigned long cr, cr2; __asm__ __volatile__ ("mtcrf 8, %0" : : "r" (0x2000): "cr4"); struct sigaction sa; sa.sa_handler = catch_segv; sigemptyset (&sa.sa_mask); sa.sa_flags = SA_NODEFER; sigaction (SIGSEGV, &sa, NULL); __asm__ __volatile__ ("mfcr %0" : "=r" (cr)); fprintf (stderr, "cr = 0x%x\n", cr & 0xfff000); try { segfault(NULL); } catch (SegfaultException *a) { } __asm__ __volatile__ ("mfcr %0" : "=r" (cr)); fprintf (stderr, "cr = 0x%x\n", cr & 0xfff000); return 0; }