This is the mail archive of the
mailing list for the GCC project.
Re: LSDA unwind information is off by one (in __gcc_personality_v0)
- From: Jeff Law <law at redhat dot com>
- To: Florian Weimer <fweimer at redhat dot com>, "gcc at gnu dot org" <gcc at gnu dot org>
- Date: Thu, 20 Oct 2016 12:37:14 -0600
- Subject: Re: LSDA unwind information is off by one (in __gcc_personality_v0)
- Authentication-results: sourceware.org; auth=none
- References: <firstname.lastname@example.org>
On 10/20/2016 10:28 AM, Florian Weimer wrote:
So the issue is the PC is expected to be pointing to the start of the
next instruction after whatever threw the exception.
We have a fun little glibc bug which causes pthread_cond_wait to write
out of bounds on i386:
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);
163 ip = _Unwind_GetIP (context);
165 if (! ip_before_insn)
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.
I wonder how GCC itself copes with the decrement in
__gcc_personality_v0. This probably matters to Ada the most because it
supports asynchronous exceptions by default.
with Ada.Strings.Unbounded; use Ada.Strings.Unbounded;
with System.Machine_Code; use System.Machine_Code;
procedure Proc is
Asm ("# BEFORE", Volatile => True);
B : Unbounded_String;
Asm ("# WITHIN", Volatile => True);
Asm ("# AFTER", Volatile => True);
Looking at the assembly, there does not seem to be any adjustment for
the off-by-one, but the asynchronous exception handler can be safely
executed multiple times (it has an internal guard flag), so maybe this
never matters. This off-by-one only matters for the exit from exception
handling regions because at the entry, we always get a PC value which is
at least one greater than the initial label because on i386 and x86_64,
the PC coming in from the kernel points after the last executed
I guess my question is if this is all working as designed.
If the decrement is ever removed from the libgcc unwinder, we should add
a compensating NOP in the glibc code. Otherwise, we can just adjust the
Thus the -1 to get back into the right region.
We've had to do similar hackery in gdb, memstomp and probably elsewhere
to deal with this slightly undesirable situation.
Obviously if the PC value is actually pointing at the proper
instruction, then the decrement is highly undesirable as it could put
the adjusted PC into a different exception region.