This is the mail archive of the libc-alpha@sourceware.org mailing list for the glibc 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]

[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


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