This is the mail archive of the
libc-alpha@sourceware.org
mailing list for the glibc project.
[RFC] powerpc: restore TOC when static longjmp to shared object
- From: Rogerio Alves <rcardoso at linux dot vnet dot ibm dot com>
- To: libc-alpha at sourceware dot org
- Date: Tue, 15 May 2018 14:29:36 -0300
- Subject: [RFC] powerpc: restore TOC when static longjmp to shared object
Hi, everyone
I was trying to fix a issue related to setjmp/longjmp on powerpc64
"ppc64 setjmp/longjmp not fully interoperable with static dlopen":
https://sourceware.org/bugzilla/show_bug.cgi?id=21895
The code sent by the person who reports this problem on bugzilla #21895
uses a static dlopen to a function declared in a shared lib, this
function foo() calls setjmp and a static function inside a static
compiled file calls the longjmp. So the problem is in that case it's not
restoring the r2 (TOC) to the frame as the code who calls the longjmp is
compiled as static but, as setjmp is called inside a shared object file
it will fails once it tries to retrieve the TOC pointer from the memory:
0x3fffb7fb0954 <foo+96> ld r2,24(r1)
Segmentation fault
The problem is that TOC is not being restored to the frame after the
longjmp. I find out those lines at
sysdeps/powerpc/powerpc64/__longjmp-common.S:
#if defined SHARED && !IS_IN (rtld)
std r2,FRAME_TOC_SAVE(r1) /* Restore the callers TOC save
area. */
#endif
/* std r2,FRAME_TOC_SAVE(r1) Restore the TOC save area. */
As described on bugzilla #269:
"In this (simple) case the appl calls [bsd]_setjmp() which transfers to
__setjmp. Both are in libc.so. So by the time __setjmp() gets control
libc.so's TOC is already loaded. In this case we need to reach back
into the callers frame and retrieve the callers TOC from the TOC save
area. But in the static case the TOC is not saved and has not changed.
In GLIBC sysdeps/powerpc/powerpc64/setjmp.S is built 4 times (static,
shared, profiled, and a special version (rtld-setjmp) for the dynamic
linker. In the SHARED case (libc.so), external calls to setjmp will
save the TOC on the stack, but internal libc calls will not. So the
trick is to do the correct thing for each case."
Since the function who calls the longjmp is a static function in a
static compiled file it will not restore the TOC. But, the function that
setjmp is a function inside a share object called via dlopen.
One simple solution would be always restore the TOC pointer by uncomment
the line bellow:
/* std r2,FRAME_TOC_SAVE(r1) Restore the TOC save area. */
Or maybe we can check if we have a valid TOC pointer before restore it,
instead #if defined SHARED.
However, I am not sure if this is something that we should work on.
First of all, as far I known, glibc is deprecating the static dlopen.
Also, on the code attached on bug #21895, after call setjmp function the
code calls a alloca and a memset function and those function are
destroying the caller stack somehow. Then when longjmp executes it gets
a segmentation fault since alloca/memset destroyed the caller stack.
I would like to request for comments on this matter: Should we fix/work
this? Is feasible to change longjmp to always restore TOC pointer? Any
suggestions?
Regards
--
Rogerio Alves
Software Engineer - IBM