https://gcc.gnu.org/bugzilla/show_bug.cgi?id=71951
Wilco <wilco at gcc dot gnu.org> changed: What |Removed |Added ---------------------------------------------------------------------------- Status|RESOLVED |REOPENED Last reconfirmed| |2017-07-28 CC| |wilco at gcc dot gnu.org Resolution|DUPLICATE |--- Ever confirmed|0 |1 --- Comment #13 from Wilco <wilco at gcc dot gnu.org> --- (In reply to Icenowy Zheng from comment #12) > (In reply to Wilco from comment #11) > > (In reply to Icenowy Zheng from comment #10) > > > In my environment (glibc 2.25, and both the building scripts of glibc and > > > gcc have -fomit-frame-pointer automatically enabled), this bug is not > > > fully > > > resolved yet. > > > > > > With GCC upgraded to 6.4.0, GDB debugger started to work correctly. (With > > > GCC 6.3.0 GDB cannot even work and segfault at unwind code in libgcc). > > > > > > However, if I still build GCC with -fomit-frame-pointer in CFLAGS, the > > > backtrace() function of glibc cannot work, and segfault at line 240 of > > > libgcc/unwind-dw2.c . > > > > > > By reading the source code, I think the unwind code is still trying to get > > > CFA from the register x29, and when debugging I found that the x29 > > > register > > > in the unwind context is 0 (because of -fomit-frame-pointer), so line 240 > > > is > > > dereferencing a NULL pointer, so it segfaulted. > > > > > > Maybe the behavior that accessing x29 register to get CFA is not correct? > > > > Well if everything built with -fomit-frame-pointer then it is definitely > > wrong to read x29. Can you give more info similar to comment #3? > > I didn't remember a lot as this issue is already fixed in our build system > by removing -fomit-frame-pointer. > > But I remember part of the stacktrace: > > _Unwind_GetGR(index=29) at libgcc/unwind-dw2.c:240 <= segfault here > _Unwind_GetPtr(index=29) at libgcc/unwind-dw2.c:251 > uw_update_context_1() at libgcc/unwind-dw2.c:1410 > _Unwind_Backtrace() at libgcc/unwind.inc (line number forgot) > backtrace() in libc.so.6 Right, so it's trivial to reproduce since every call to backtrace will crash immediately if libgcc is built with -fomit-frame-pointer in any GCC version. The issue is due to the weird way the generic unwind code works - there is no code to setup the frame pointer. So in order to unwind any function with a frame pointer, the very first function that is unwound (_Unwind_Backtrace in this case) must use the frame pointer. That way the frame pointer is restored and its value can now be read by _Unwind_GetGR without crashing. A quick workaround is: #define LIBGCC2_UNWIND_ATTRIBUTE __attribute__((optimize ("no-omit-frame-pointer"))) Oddly enough I don't see any other targets do this, so this problem may be widespread... Note this workaround wouldn't work if there could be multiple frame pointers or several registers which may contain a frame pointer.