1
0
Fork 0
mirror of https://github.com/tobast/libunwind-eh_elf.git synced 2024-06-28 12:11:45 +02:00

Fix for failing test-setjmp

On Mon, Nov 14, 2011 at 5:02 PM, Paul Pluzhnikov <ppluzhnikov@google.com> wrote:

> P.S. test-setjmp is failing for me (before or after the patch).
> When I enable assertions (to confirm my new assertions are correct), I see:
>
>  lt-test-setjmp: ../../src/dwarf/Gparser.c:754: apply_reg_state: \
>    Assertion `rs->reg[17].where == DWARF_WHERE_EXPR' failed.
>
> which likely explains that failure.

The problem is actually two-fold:

First, the loops in {sig,}longjmp.c are "do { ... } while (unw_step() >= 0);"

But unw_step() returns 0 on reaching the end of the chain (_start),
and the loop should stop there.

The second problem is that with this commit:
  c67da0b50e
glibc obfuscates value of SP in jmp_buf, so we might as well just give up.

Patch attached.

Thanks,
--
Paul Pluzhnikov
This commit is contained in:
Paul Pluzhnikov 2011-11-14 23:45:09 -08:00 committed by Arun Sharma
parent d84e5d5d24
commit 297d9cd07d
2 changed files with 34 additions and 2 deletions

View file

@ -35,6 +35,20 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
#include "jmpbuf.h"
#include "setjmp_i.h"
#if defined(__GLIBC__) && __GLIBC_PREREQ(2, 4)
/* Starting with glibc-2.4, {sig,}setjmp in GLIBC obfuscates the
register values in jmp_buf by XORing them with a "random"
canary value.
This makes it impossible to implement longjmp, as we
can never match wp[JB_SP], unless we decode the canary first.
Doing so is possible, but doesn't appear to be worth the trouble,
so we simply defer to glibc longjmp here. */
#else
void
_longjmp (jmp_buf env, int val)
{
@ -75,7 +89,7 @@ _longjmp (jmp_buf env, int val)
abort ();
}
while (unw_step (&c) >= 0);
while (unw_step (&c) > 0);
abort ();
}
@ -90,4 +104,6 @@ longjmp (jmp_buf env, int val)
_longjmp (env, val);
}
#endif /* __GLIBC__ */
#endif

View file

@ -35,6 +35,20 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
# define _NSIG (_SIG_MAXSIG - 1)
#endif
#if defined(__GLIBC__) && __GLIBC_PREREQ(2, 4)
/* Starting with glibc-2.4, {sig,}setjmp in GLIBC obfuscates the
register values in jmp_buf by XORing them with a "random"
canary value.
This makes it impossible to implement longjmp, as we
can never match wp[JB_SP], unless we decode the canary first.
Doing so is possible, but doesn't appear to be worth the trouble,
so we simply defer to glibc siglongjmp here. */
#else
void
siglongjmp (sigjmp_buf env, int val)
{
@ -96,7 +110,9 @@ siglongjmp (sigjmp_buf env, int val)
abort ();
}
while (unw_step (&c) >= 0);
while (unw_step (&c) > 0);
abort ();
}
#endif /* __GLIBC__ */