On 10/20/2016 10:28 AM, Florian Weimer 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.
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
begin
Asm ("# BEFORE", Volatile => True);
declare
B : Unbounded_String;
begin
Asm ("# WITHIN", Volatile => True);
end;
Asm ("# AFTER", Volatile => True);
end Proc;
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
instruction.
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
unwind tables.
So the issue is the PC is expected to be pointing to the start of the
next instruction after whatever threw the exception.
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.
Jeff