diff options
author | Alan Modra <amodra@gmail.com> | 2010-05-11 23:43:15 -0500 |
---|---|---|
committer | Ryan Arnold <ryanarn@etna.rchland.ibm.com> | 2010-05-11 23:43:41 -0500 |
commit | dd1f42ad8afb25e6930b0e7251520925208f5bc8 (patch) | |
tree | 9aa1304d21116a3b513652513c3d8e0d505708e0 /nptl | |
parent | 3ad0390e7f8f8401f714a9bd989f4f32df105a97 (diff) | |
download | glibc-dd1f42ad8afb25e6930b0e7251520925208f5bc8.zip glibc-dd1f42ad8afb25e6930b0e7251520925208f5bc8.tar.gz glibc-dd1f42ad8afb25e6930b0e7251520925208f5bc8.tar.bz2 |
Fix PowerPC64 glibc assembly to properly work with the linker automatic
multiple toc support, which may be needed when a static libc is linked into a
large app. The requirements are: a) No tail calls are allowed to functions in
a different object file, ie. a plain branch is not allowed. b) All calls to
functions in a different object file must be followed by a nop.
On PowerPC64, the parameter save area and the cr save location for the current
function are in the previous frame, just like the lr save location. The
parameter save area, cr save location and lr save location in the current
frame are for use by *called* functions. In a number of places, glibc
assembly used the wrong area, leaving those functions at the mercy of any
called functions. We just happen to be lucky so far, but that may change with
future versions of gcc.
Diffstat (limited to 'nptl')
-rw-r--r-- | nptl/ChangeLog | 10 | ||||
-rw-r--r-- | nptl/sysdeps/unix/sysv/linux/powerpc/powerpc64/sysdep-cancel.h | 69 |
2 files changed, 54 insertions, 25 deletions
diff --git a/nptl/ChangeLog b/nptl/ChangeLog index dde74f4..d9f9ef6 100644 --- a/nptl/ChangeLog +++ b/nptl/ChangeLog @@ -1,3 +1,13 @@ +2010-05-01 Alan Modra <amodra@gmail.com> + * sysdeps/unix/sysv/linux/powerpc/powerpc64/sysdep-cancel.h + (PSEUDO): Use correct cr save. Don't use wrong parm save area + to save temps. Correct cfi for possible later frame manipulation. + (DOCARGS_1, UNDOCARGS_1): Use the correct parm save area. + (DOCARGS_2, UNDOCARGS_2, DOCARGS_3, UNDOCARGS_3): Likewise. + (DOCARGS_4, UNDOCARGS_4, DOCARGS_5, UNDOCARGS_5): Likewise. + (DOCARGS_6, UNDOCARGS_6): Likewise. + (CENABLE, CDISABLE): Add nops for non-shared calls. + 2010-03-23 Luis Machado <luisgpm@br.ibm.com> * pthread_cond_timedwait.c: Add check for diff --git a/nptl/sysdeps/unix/sysv/linux/powerpc/powerpc64/sysdep-cancel.h b/nptl/sysdeps/unix/sysv/linux/powerpc/powerpc64/sysdep-cancel.h index 707765a..597630c 100644 --- a/nptl/sysdeps/unix/sysv/linux/powerpc/powerpc64/sysdep-cancel.h +++ b/nptl/sysdeps/unix/sysv/linux/powerpc/powerpc64/sysdep-cancel.h @@ -52,51 +52,70 @@ cfi_offset (lr, 16); \ DOCARGS_##args; /* save syscall args around CENABLE. */ \ CENABLE; \ - std 3,72(1); /* store CENABLE return value (MASK). */ \ + std 3,112(1); /* store CENABLE return value (MASK). */ \ UNDOCARGS_##args; /* restore syscall args. */ \ DO_CALL (SYS_ify (syscall_name)); \ mfcr 0; /* save CR/R3 around CDISABLE. */ \ - std 3,64(1); \ - std 0,8(1); \ - ld 3,72(1); /* pass MASK to CDISABLE. */ \ + std 3,120(1); \ + std 0,128+8(1); \ + cfi_offset (cr, 8); \ + ld 3,112(1); /* pass MASK to CDISABLE. */ \ CDISABLE; \ ld 9,128+16(1); \ - ld 0,8(1); /* restore CR/R3. */ \ - ld 3,64(1); \ + ld 0,128+8(1); /* restore CR/R3. */ \ + ld 3,120(1); \ mtlr 9; \ mtcr 0; \ - addi 1,1,128; + addi 1,1,128; \ + cfi_adjust_cfa_offset (-128); \ + cfi_restore (lr); \ + cfi_restore (cr) # define DOCARGS_0 # define UNDOCARGS_0 -# define DOCARGS_1 std 3,80(1); DOCARGS_0 -# define UNDOCARGS_1 ld 3,80(1); UNDOCARGS_0 +# define DOCARGS_1 std 3,128+48(1); DOCARGS_0 +# define UNDOCARGS_1 ld 3,128+48(1); UNDOCARGS_0 -# define DOCARGS_2 std 4,88(1); DOCARGS_1 -# define UNDOCARGS_2 ld 4,88(1); UNDOCARGS_1 +# define DOCARGS_2 std 4,128+56(1); DOCARGS_1 +# define UNDOCARGS_2 ld 4,128+56(1); UNDOCARGS_1 -# define DOCARGS_3 std 5,96(1); DOCARGS_2 -# define UNDOCARGS_3 ld 5,96(1); UNDOCARGS_2 +# define DOCARGS_3 std 5,128+64(1); DOCARGS_2 +# define UNDOCARGS_3 ld 5,128+64(1); UNDOCARGS_2 -# define DOCARGS_4 std 6,104(1); DOCARGS_3 -# define UNDOCARGS_4 ld 6,104(1); UNDOCARGS_3 +# define DOCARGS_4 std 6,128+72(1); DOCARGS_3 +# define UNDOCARGS_4 ld 6,128+72(1); UNDOCARGS_3 -# define DOCARGS_5 std 7,112(1); DOCARGS_4 -# define UNDOCARGS_5 ld 7,112(1); UNDOCARGS_4 +# define DOCARGS_5 std 7,128+80(1); DOCARGS_4 +# define UNDOCARGS_5 ld 7,128+80(1); UNDOCARGS_4 -# define DOCARGS_6 std 8,120(1); DOCARGS_5 -# define UNDOCARGS_6 ld 8,120(1); UNDOCARGS_5 +# define DOCARGS_6 std 8,128+88(1); DOCARGS_5 +# define UNDOCARGS_6 ld 8,128+88(1); UNDOCARGS_5 # ifdef IS_IN_libpthread -# define CENABLE bl JUMPTARGET(__pthread_enable_asynccancel) -# define CDISABLE bl JUMPTARGET(__pthread_disable_asynccancel) +# ifdef SHARED +# define CENABLE bl JUMPTARGET(__pthread_enable_asynccancel) +# define CDISABLE bl JUMPTARGET(__pthread_disable_asynccancel) +# else +# define CENABLE bl JUMPTARGET(__pthread_enable_asynccancel); nop +# define CDISABLE bl JUMPTARGET(__pthread_disable_asynccancel); nop +# endif # elif !defined NOT_IN_libc -# define CENABLE bl JUMPTARGET(__libc_enable_asynccancel) -# define CDISABLE bl JUMPTARGET(__libc_disable_asynccancel) +# ifdef SHARED +# define CENABLE bl JUMPTARGET(__libc_enable_asynccancel) +# define CDISABLE bl JUMPTARGET(__libc_disable_asynccancel) +# else +# define CENABLE bl JUMPTARGET(__libc_enable_asynccancel); nop +# define CDISABLE bl JUMPTARGET(__libc_disable_asynccancel); nop +# endif # elif defined IS_IN_librt -# define CENABLE bl JUMPTARGET(__librt_enable_asynccancel) -# define CDISABLE bl JUMPTARGET(__librt_disable_asynccancel) +# ifdef SHARED +# define CENABLE bl JUMPTARGET(__librt_enable_asynccancel) +# define CDISABLE bl JUMPTARGET(__librt_disable_asynccancel) +# else +# define CENABLE bl JUMPTARGET(__librt_enable_asynccancel); nop +# define CDISABLE bl JUMPTARGET(__librt_disable_asynccancel); nop +# endif # else # error Unsupported library # endif |