This is the mail archive of the gcc@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: LSDA unwind information is off by one (in __gcc_personality_v0)


On 10/20/2016 07:17 PM, Andreas Schwab wrote:
On Okt 20 2016, Florian Weimer <fweimer@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


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]