On 10/20/2016 07:17 PM, Andreas Schwab wrote:
On Okt 20 2016, Florian Weimer <fwei...@redhat.com> wrote:
We have a fun little glibc bug which causes pthread_cond_wait to write out
of bounds on i386:
https://sourceware.org/bugzilla/show_bug.cgi?id=20719
Root cause is this in libgcc/unwind-c.c:
130 int ip_before_insn = 0;
…
158 /* Parse the LSDA header. */
159 p = parse_lsda_header (context, language_specific_data, &info);
160 #ifdef HAVE_GETIPINFO
161 ip = _Unwind_GetIPInfo (context, &ip_before_insn);
162 #else
163 ip = _Unwind_GetIP (context);
164 #endif
165 if (! ip_before_insn)
166 --ip;
167 landing_pad = 0;
The PC decrement cannot be possibly meaningful on CISC architectures with
variable instruction lengths. I suspect it's an unintentional leftover
from the ia64 port.
It is valid for all architectures, because the return IP usually points
_after_ the call instruction, which may already be inside the next
unwind region.
I think it's less a property of the PC location, and more a property of
how the call instruction is unwound, i.e. if you get this address by
direct stack unwinding, you want to be the callee nested in the caller's
exception handling region. Subtracting 1 is an extremely hackish way to
achieve that and likely is not portable at all.
The situation is different for signal frame.
Indeed. But there, you get the PC of the instruction to execute next
(maybe with the exception of some faulting instructions). Except that
you need different semantics because the signal handler is not supposed
to be nested in the exception handler region.
See libgcc/unwind-dw2.c:_Unwind_GetIPInfo for the correct way to handle it.
We don't call _Unwind_GetIPInfo from __gcc_personality_v0 because
HAVE_GETIPINFO is not defined. This happens only when using the system
unwinder on ia64, if I'm not mistaken.
Disassembly shows that the code is not compiled in and not part of
libgcc_s.so.1, although _Unwind_GetIPInfo itself has been defined.
Thanks,
Florian