aboutsummaryrefslogtreecommitdiff
path: root/nptl
diff options
context:
space:
mode:
authorAlan Modra <amodra@gmail.com>2010-05-11 23:43:15 -0500
committerRyan Arnold <ryanarn@etna.rchland.ibm.com>2010-05-11 23:43:41 -0500
commitdd1f42ad8afb25e6930b0e7251520925208f5bc8 (patch)
tree9aa1304d21116a3b513652513c3d8e0d505708e0 /nptl
parent3ad0390e7f8f8401f714a9bd989f4f32df105a97 (diff)
downloadglibc-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/ChangeLog10
-rw-r--r--nptl/sysdeps/unix/sysv/linux/powerpc/powerpc64/sysdep-cancel.h69
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