http://gcc.gnu.org/bugzilla/show_bug.cgi?id=50678
--- Comment #50 from Iain Sandoe <iains at gcc dot gnu.org> 2011-10-18 19:18:38 UTC --- well I've hit a few issues. 1. _Unwind_Find_FDE is not part of the public interface (nor are the types it needs). 2. if the vendor decides to 'fix' libunwind .. we won't detect this ... (although I still think this idea is worth pursuing, on the grounds that 'no fix' or a fix to Libc are more likely). 3. _Unwind_Find_FDE is returning NULL in the following proof-of-concept hack.. .. not having any joy debugging this from the c++ case (maybe have to try a newer debugger).. (have to do some other things for a while - but if you can spot my obvious mistake .. then let me know). #if defined (__x86_64__) /* Work around radar #10302855/pr50678, where the unwinders (libunwind or libgcc_s depending on the system revision) and the DWARF unwind data for the sigtramp have different ideas about register numbering (causing rbx and rdx to be transposed). */ #define DX86FIX_CHECKED 0x01 #define DX86FIX_DOFIXUP 0x02 struct dwarf_eh_bases { void *tbase; void *dbase; void *func; }; typedef int sword __attribute__ ((mode (SI))); typedef unsigned int uword __attribute__ ((mode (SI))); struct dwarf_fde { uword length; sword CIE_delta; unsigned char pc_begin[]; } __attribute__ ((packed, aligned (__alignof__ (void *)))); extern struct dwarf_fde * _Unwind_Find_FDE (void *, struct dwarf_eh_bases *); static void __gnat_darwin_maybe_fixup_unwind_context (ucontext_t *uc, void *ad) { static unsigned need_fixup = 0; /* Look for the FDE for the sig tramp. */ if ((need_fixup & DX86FIX_CHECKED) == 0) { struct dwarf_eh_bases bases; const struct dwarf_fde *myfde = _Unwind_Find_FDE (ad, &bases); if (myfde == NULL) need_fixup |= DX86FIX_DOFIXUP; /* We're likely broken. */ else { unsigned MCONTEXT_SS_RBX, MCONTEXT_SS_RDX, ts; /* These are the offsets for the registers. */ ts = __builtin_offsetof (_STRUCT_MCONTEXT,__ss); MCONTEXT_SS_RBX = __builtin_offsetof (_STRUCT_X86_THREAD_STATE64,__rbx); MCONTEXT_SS_RBX += ts; MCONTEXT_SS_RDX = __builtin_offsetof (_STRUCT_X86_THREAD_STATE64,__rdx); MCONTEXT_SS_RDX += ts; // UNFINISHED } need_fixup |= DX86FIX_CHECKED; } if (need_fixup & DX86FIX_DOFIXUP) { unsigned long t = uc->uc_mcontext->__ss.__rbx; uc->uc_mcontext->__ss.__rbx = uc->uc_mcontext->__ss.__rdx; uc->uc_mcontext->__ss.__rdx = t; } } #endif static void __gnat_error_handler (int sig, siginfo_t *si, void *ucontext) { struct Exception_Data *exception; const char *msg; #if defined (__x86_64__) /* We pass the address from here so that we don't need to worry about inlining. */ __gnat_darwin_maybe_fixup_unwind_context ((ucontext_t *)ucontext, __builtin_return_address (0)); #endif