https://gcc.gnu.org/bugzilla/show_bug.cgi?id=42159
Niklas Hauser <niklas.hauser at arm dot com> changed: What |Removed |Added ---------------------------------------------------------------------------- CC| |niklas.hauser at arm dot com --- Comment #35 from Niklas Hauser <niklas.hauser at arm dot com> --- We can reproduce this issue on OS X 10.12, please see below for a detailed analysis of the underlying problem. This issue is fixed by the patch proposed by Pierre Ossman. Did this patch (or maybe a similar solution) make it upstream already? Summary of cause: The libgcc unwinder implementation is broken for all 64-bit builds of OS X (since 10.6) due to a non-backwards compatible change in the _keymgr API, which does not provide a process-wide image list anymore. Details of cause: This is the minimal example to reproduce the issue on OS X (>10.6): #include <iostream> int main() { try { throw 20; } catch (int e) { std::cout << "Exception No. " << e << "\n"; } return 0; } Running this application will cause a SIGABRT: g++ -static-libgcc -o failboat main.cpp && ./failboat [1] 4047 abort ./failboat Stack trace of this failure is: ... #12 0x00007fff5fbff370 in ?? () #13 0x00000001000987c1 in uw_init_context_1 () #14 0x0000000100098e1e in _Unwind_RaiseException () #15 0x000000010000d81b in __cxa_throw () #16 0x0000000100000b30 in main () at main.cpp:4 We're failing an assert in uw_init_context_1 (gcc/libgcc/unwind-dw2.c:1578): code = uw_frame_state_for (context, &fs); gcc_assert (code == _URC_NO_REASON); Specifically uw_frame_state_for returns code _URC_END_OF_STACK and this then fails the gcc_assert, which then unwraps in a SIGABRT. uw_frame_state_for() calls _Unwind_Find_FDE() in gcc/libgcc/unwind-dw2.c:1249, which returns NULL however and the entire function therefore returns _URC_END_OF_STACK: fde = _Unwind_Find_FDE (context->ra + _Unwind_IsSignalFrame (context) - 1, &context->bases); if (fde == NULL) { return _URC_END_OF_STACK; } _Unwind_Find_FDE() is defined in gcc/libgcc/unwind-dw2-fde.c:1027, EXCEPT on OS X (aka. Darwin), where it is reimplemented in gcc/libgcc/config/unwind-dw2-fde-darwin.c:244! This implementation uses the _keymgr API to access Dwarf2 object lists and ELF images (with the KEYMGR_GCC3_DW2_OBJ_LIST and KEYMGR_GCC3_LIVE_IMAGE_LIST keys, respectively). The function first checks the Dwarf2 object lists, then falls back to using the original implementation (which has been renamed to _Unwind_Find_registered_FDE()) before searching the ELF images in examine_objects: the_obj_info = _keymgr_get_and_lock_processwide_ptr (KEYMGR_GCC3_DW2_OBJ_LIST); if (! the_obj_info) the_obj_info = calloc (1, sizeof (*the_obj_info)); if (the_obj_info != NULL) { /* code removed for brevity */ ret = _Unwind_Find_registered_FDE (pc, bases); } /* OK, didn't find it in the list of FDEs we've seen before, so go through and look at the new ones. */ if (ret == NULL) ret = examine_objects (pc, bases, the_obj_info == NULL); Here the first call to KEYMGR_GCC3_DW2_OBJ_LIST returns NULL, thus an empty object list is allocated. _Unwind_Find_registered_FDE() returns NULL too, since it operates only on previously seen objects, of which there are none yet. Finally, examine_objects is finally called, which contains: image = _keymgr_get_and_lock_processwide_ptr (KEYMGR_GCC3_LIVE_IMAGE_LIST); Note how the KEYMGR_GCC3_DW2_OBJ_LIST list is used as a "cache" of previously seen Dwarf2 objects and is first populated by examine_objects() using the KEYMGR_GCC3_LIVE_IMAGE_LIST. However, on 64-bit builds of OS X, KEYMGR_GCC3_LIVE_IMAGE_LIST always returns NULL and so the image information can never be retrieved. The reason for this is found in the implementation of keymgr.c, which is published here: https://opensource.apple.com/source/keymgr/keymgr-28/keymgr.c.auto.html. At the very bottom, in __keymgr_initializer() it says: #if __x86_64__ /* On Mac OS X 10.6, libunwind in libSystem.dylib implements all unwinding functionality. */ /* libunwind does not use keymgr, so there is no need to maintain KEYMGR_GCC3_LIVE_IMAGE_LIST */ /* in sync with dyld's list of images. But there might be some i386 or ppc applications that */ /* carry around there own copy of the unwinder (from libgcc.a) and need KEYMGR_GCC3_LIVE_IMAGE_LIST. */ #else /* register with dyld so that we are notified about all loaded mach-o images */ _dyld_register_func_for_add_image (dwarf2_unwind_dyld_add_image_hook); _dyld_register_func_for_remove_image (dwarf2_unwind_dyld_remove_image_hook); #endif /* __x86_64__ */ On 64-bit builds of OS X these images are simply never added. The libgcc unwinder code can therefore never work, since it relies on this information.