You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
78 lines
4.1 KiB
78 lines
4.1 KiB
# |
|
# commit 76a9b9986141b1a7d9fd290c349d27fcee780c7a |
|
# Author: Adhemerval Zanella <azanella@linux.vnet.ibm.com> |
|
# Date: Thu Nov 7 05:34:22 2013 -0600 |
|
# |
|
# PowerPC: Fix vDSO missing ODP entries |
|
# |
|
# This patch fixes the vDSO symbol used directed in IFUNC resolver where |
|
# they do not have an associated ODP entry leading to undefined behavior |
|
# in some cases. It adds an artificial OPD static entry to such cases |
|
# and set its TOC to non 0 to avoid triggering lazy resolutions. |
|
# |
|
diff -urN glibc-2.17-c758a686/sysdeps/unix/sysv/linux/powerpc/bits/libc-vdso.h glibc-2.17-c758a686/sysdeps/unix/sysv/linux/powerpc/bits/libc-vdso.h |
|
--- glibc-2.17-c758a686/sysdeps/unix/sysv/linux/powerpc/bits/libc-vdso.h 2015-01-15 16:05:08.853681325 -0500 |
|
+++ glibc-2.17-c758a686/sysdeps/unix/sysv/linux/powerpc/bits/libc-vdso.h 2015-01-15 16:06:11.451747716 -0500 |
|
@@ -34,12 +34,32 @@ |
|
|
|
extern void *__vdso_time; |
|
|
|
-/* This macro is needed for PPC64 to return a skeleton OPD entry of a vDSO |
|
- symbol. This works because _dl_vdso_vsym always return the function |
|
- address, and no vDSO symbols use the TOC or chain pointers from the OPD |
|
- so we can allow them to be garbage. */ |
|
-#if defined(__PPC64__) || defined(__powerpc64__) |
|
-#define VDSO_IFUNC_RET(value) ((void *) &(value)) |
|
+/* The correct solution is for _dl_vdso_vsym to return the address of the OPD |
|
+ for the kernel VDSO function. That address would then be stored in the |
|
+ __vdso_* variables and returned as the result of the IFUNC resolver function. |
|
+ Yet, the kernel does not contain any OPD entries for the VDSO functions |
|
+ (incomplete implementation). However, PLT relocations for IFUNCs still expect |
|
+ the address of an OPD to be returned from the IFUNC resolver function (since |
|
+ PLT entries on PPC64 are just copies of OPDs). The solution for now is to |
|
+ create an artificial static OPD for each VDSO function returned by a resolver |
|
+ function. The TOC value is set to a non-zero value to avoid triggering lazy |
|
+ symbol resolution via .glink0/.plt0 for a zero TOC (requires thread-safe PLT |
|
+ sequences) when the dynamic linker isn't prepared for it e.g. RTLD_NOW. None |
|
+ of the kernel VDSO routines use the TOC or AUX values so any non-zero value |
|
+ will work. Note that function pointer comparisons will not use this artificial |
|
+ static OPD since those are resolved via ADDR64 relocations and will point at |
|
+ the non-IFUNC default OPD for the symbol. Lastly, because the IFUNC relocations |
|
+ are processed immediately at startup the resolver functions and this code need |
|
+ not be thread-safe, but if the caller writes to a PLT slot it must do so in a |
|
+ thread-safe manner with all the required barriers. */ |
|
+#if (defined(__PPC64__) || defined(__powerpc64__)) && _CALL_ELF != 2 |
|
+#define VDSO_IFUNC_RET(value) \ |
|
+ ({ \ |
|
+ static Elf64_FuncDesc vdso_opd = { .fd_toc = ~0x0 }; \ |
|
+ vdso_opd.fd_func = (Elf64_Addr)value; \ |
|
+ &vdso_opd; \ |
|
+ }) |
|
+ |
|
#else |
|
#define VDSO_IFUNC_RET(value) ((void *) (value)) |
|
#endif |
|
diff -urN glibc-2.17-c758a686/sysdeps/unix/sysv/linux/powerpc/gettimeofday.c glibc-2.17-c758a686/sysdeps/unix/sysv/linux/powerpc/gettimeofday.c |
|
--- glibc-2.17-c758a686/sysdeps/unix/sysv/linux/powerpc/gettimeofday.c 2015-01-15 16:05:08.912679502 -0500 |
|
+++ glibc-2.17-c758a686/sysdeps/unix/sysv/linux/powerpc/gettimeofday.c 2015-01-15 16:06:11.451747716 -0500 |
|
@@ -21,6 +21,7 @@ |
|
|
|
# include <dl-vdso.h> |
|
# include <bits/libc-vdso.h> |
|
+# include <dl-machine.h> |
|
|
|
void *gettimeofday_ifunc (void) __asm__ ("__gettimeofday"); |
|
|
|
diff -urN glibc-2.17-c758a686/sysdeps/unix/sysv/linux/powerpc/time.c glibc-2.17-c758a686/sysdeps/unix/sysv/linux/powerpc/time.c |
|
--- glibc-2.17-c758a686/sysdeps/unix/sysv/linux/powerpc/time.c 2015-01-15 16:05:08.912679502 -0500 |
|
+++ glibc-2.17-c758a686/sysdeps/unix/sysv/linux/powerpc/time.c 2015-01-15 16:06:11.451747716 -0500 |
|
@@ -20,7 +20,9 @@ |
|
|
|
# include <time.h> |
|
# include <sysdep.h> |
|
+# include <dl-vdso.h> |
|
# include <bits/libc-vdso.h> |
|
+# include <dl-machine.h> |
|
|
|
void *time_ifunc (void) asm ("time"); |
|
|
|
|