Red Hat Bugzilla – Bug 481498
Incomplete unwind info despite -fasynchronous-unwind-tables
Last modified: 2009-07-13 05:49:39 EDT
Description of problem:
gcc generates incomplete unwind information despite the use of -fasynchronous-unwind-tables. The result is that thread cancellation fails in glibc.
This shows itself in the compilation of cancellation.c on x86. I do not know whether other archs are affected since the other factors contributing to recognizing the problem are different. Only on x86 do we have a reproducer so far.
The actual problem is a function exit in the middle of the code. The function uses a call frame end %ebp to handle it. The exit uses "leave;ret" to exit the function. But it does not, for the ret instruction, corrects the CFA offset in the .eh_frame section.
Version-Release number of selected component (if applicable):
Steps to Reproduce:
1.compile nptl/cancellation.c from glibc. Just a normal configuration for 686.
The __pthread_enable_asynccancel code contains this in the generated asm code:
.loc 1 31 0
movl %esp, %ebp
This .eh_frame translates to (shown using eu-readelf):
[ 34] FDE length=24 cie=[ 0]
initial_location: 0x40 (offset: 0x173c)
address_range: 0x51 (end offset: 0x178d)
advance_loc 1 to 0x173d
offset r5 (reg5) at cfa-8
advance_loc 2 to 0x173f
def_cfa_register r5 (reg5)
As can be seen, the setup of the stack frame is described, but it is missing that for the duration of the 'ret' instruction only the CFA offset is back to 4.
Unwind info taking 'leave' into account so that unwinding works even when it happens when the 'ret' instruction is currently executed.
I added a reference to the bug which has been filed against glibc because of this gcc problem.
This is a pretty severe problem. It means that, in this specific case, some unwind handlers aren't executed. This includes for x86 the one locking the mutex in can pthread_cond_wait is interrupted. This is pretty severe.
Created attachment 329946 [details]
Reduced test case
This is a reduced test case. Compile it with
gcc -m32 -O2 -march=core2 -fgnu89-inline -g -fPIC -fexceptions -fasynchronous-unwind-tables -c n.i
If you leave out the -march=core2 gcc won't generate the leave instruction but the resulting code (using push/pop) still is wrong. So it is not the pattern for leave alone.
Yes, gcc doesn't generate unwind info for the epilogues. This is a known issue for several years, but it might be quite hard to implement it.
Richard, what is the status of the epilogue unwind info fix?
Fixed in rawhide.