From 1509524bcc7b21e0686565054e0b61be58a2ad9d Mon Sep 17 00:00:00 2001
From: Jakub Jelinek <jakub@redhat.com>
Date: Sat, 11 Feb 2017 00:34:49 +0100
Subject: [PATCH] re PR sanitizer/79341 (Many Asan tests fail on s390)

	PR sanitizer/79341
	* configure.tgt (s390*-*-linux*): Don't disable libsanitizer on
	s390-linux 31-bit.
	* sanitizer_common/sanitizer_internal_defs.h: Cherry-pick upstream
	r294793.
	* sanitizer_common/sanitizer_common_interceptors.inc: Cherry-pick
	upstream r294790.
	* sanitizer_common/sanitizer_linux_s390.cc: Cherry-pick upstream
	r294799.

From-SVN: r245350
---
 libsanitizer/ChangeLog                        | 12 ++++++
 libsanitizer/configure.tgt                    |  3 --
 .../sanitizer_common_interceptors.inc         | 37 +++++++++++++------
 .../sanitizer_internal_defs.h                 |  7 +++-
 .../sanitizer_common/sanitizer_linux_s390.cc  | 24 ++++++++++++
 5 files changed, 68 insertions(+), 15 deletions(-)

diff --git a/libsanitizer/ChangeLog b/libsanitizer/ChangeLog
index c0e5563ac6fb..e60f31bbc466 100644
--- a/libsanitizer/ChangeLog
+++ b/libsanitizer/ChangeLog
@@ -1,3 +1,15 @@
+2017-02-11  Jakub Jelinek  <jakub@redhat.com>
+
+	PR sanitizer/79341
+	* configure.tgt (s390*-*-linux*): Don't disable libsanitizer on
+	s390-linux 31-bit.
+	* sanitizer_common/sanitizer_internal_defs.h: Cherry-pick upstream
+	r294793.
+	* sanitizer_common/sanitizer_common_interceptors.inc: Cherry-pick
+	upstream r294790.
+	* sanitizer_common/sanitizer_linux_s390.cc: Cherry-pick upstream
+	r294799.
+
 2017-02-03  Maxim Ostapenko  <m.ostapenko@samsung.com>
 
 	PR sanitizer/78663
diff --git a/libsanitizer/configure.tgt b/libsanitizer/configure.tgt
index e648051aab82..82e8a5513c59 100644
--- a/libsanitizer/configure.tgt
+++ b/libsanitizer/configure.tgt
@@ -40,9 +40,6 @@ case "${target}" in
   sparc*-*-linux*)
 	;;
   s390*-*-linux*)
-	if test x$ac_cv_sizeof_void_p = x4; then
-		UNSUPPORTED=1
-	fi
 	;;
   arm*-*-linux*)
 	;;
diff --git a/libsanitizer/sanitizer_common/sanitizer_common_interceptors.inc b/libsanitizer/sanitizer_common/sanitizer_common_interceptors.inc
index 38390ed96215..0970eda5ee64 100644
--- a/libsanitizer/sanitizer_common/sanitizer_common_interceptors.inc
+++ b/libsanitizer/sanitizer_common/sanitizer_common_interceptors.inc
@@ -4550,11 +4550,15 @@ void *__tls_get_addr_opt(void *arg);
 //   descriptor offset as an argument instead of a pointer.  GOT address
 //   is passed in r12, so it's necessary to write it in assembly.  This is
 //   the function used by the compiler.
-#define INIT_TLS_GET_ADDR COMMON_INTERCEPT_FUNCTION(__tls_get_addr_internal)
+extern "C" uptr __tls_get_offset_wrapper(void *arg, uptr (*fn)(void *arg));
+#define INIT_TLS_GET_ADDR COMMON_INTERCEPT_FUNCTION(__tls_get_offset)
+DEFINE_REAL(uptr, __tls_get_offset, void *arg)
+extern "C" uptr __tls_get_offset(void *arg);
+extern "C" uptr __interceptor___tls_get_offset(void *arg);
 INTERCEPTOR(uptr, __tls_get_addr_internal, void *arg) {
   void *ctx;
   COMMON_INTERCEPTOR_ENTER(ctx, __tls_get_addr_internal, arg);
-  uptr res = REAL(__tls_get_addr_internal)(arg);
+  uptr res = __tls_get_offset_wrapper(arg, REAL(__tls_get_offset));
   uptr tp = reinterpret_cast<uptr>(__builtin_thread_pointer());
   void *ptr = reinterpret_cast<void *>(res + tp);
   uptr tls_begin, tls_end;
@@ -4566,32 +4570,43 @@ INTERCEPTOR(uptr, __tls_get_addr_internal, void *arg) {
   }
   return res;
 }
-// We need a protected symbol aliasing the above, so that we can jump
+// We need a hidden symbol aliasing the above, so that we can jump
 // directly to it from the assembly below.
 extern "C" __attribute__((alias("__interceptor___tls_get_addr_internal"),
-                          visibility("protected")))
-uptr __interceptor___tls_get_addr_internal_protected(void *arg);
+                          visibility("hidden")))
+uptr __tls_get_addr_hidden(void *arg);
 // Now carefully intercept __tls_get_offset.
 asm(
   ".text\n"
-  ".global __tls_get_offset\n"
-  "__tls_get_offset:\n"
 // The __intercept_ version has to exist, so that gen_dynamic_list.py
 // exports our symbol.
+  ".weak __tls_get_offset\n"
+  ".type __tls_get_offset, @function\n"
+  "__tls_get_offset:\n"
   ".global __interceptor___tls_get_offset\n"
+  ".type __interceptor___tls_get_offset, @function\n"
   "__interceptor___tls_get_offset:\n"
 #ifdef __s390x__
   "la %r2, 0(%r2,%r12)\n"
-  "jg __interceptor___tls_get_addr_internal_protected\n"
+  "jg __tls_get_addr_hidden\n"
 #else
   "basr %r3,0\n"
   "0: la %r2,0(%r2,%r12)\n"
   "l %r4,1f-0b(%r3)\n"
   "b 0(%r4,%r3)\n"
-  "1: .long __interceptor___tls_get_addr_internal_protected - 0b\n"
+  "1: .long __tls_get_addr_hidden - 0b\n"
 #endif
-  ".type __tls_get_offset, @function\n"
-  ".size __tls_get_offset, .-__tls_get_offset\n"
+  ".size __interceptor___tls_get_offset, .-__interceptor___tls_get_offset\n"
+// Assembly wrapper to call REAL(__tls_get_offset)(arg)
+  ".type __tls_get_offset_wrapper, @function\n"
+  "__tls_get_offset_wrapper:\n"
+#ifdef __s390x__
+  "sgr %r2,%r12\n"
+#else
+  "sr %r2,%r12\n"
+#endif
+  "br %r3\n"
+  ".size __tls_get_offset_wrapper, .-__tls_get_offset_wrapper\n"
 );
 #endif // SANITIZER_S390
 #else
diff --git a/libsanitizer/sanitizer_common/sanitizer_internal_defs.h b/libsanitizer/sanitizer_common/sanitizer_internal_defs.h
index b9c906669dee..676ade143d88 100644
--- a/libsanitizer/sanitizer_common/sanitizer_internal_defs.h
+++ b/libsanitizer/sanitizer_common/sanitizer_internal_defs.h
@@ -287,7 +287,12 @@ void NORETURN CheckFailed(const char *file, int line, const char *cond,
 enum LinkerInitialized { LINKER_INITIALIZED = 0 };
 
 #if !defined(_MSC_VER) || defined(__clang__)
-# define GET_CALLER_PC() (uptr)__builtin_return_address(0)
+# if SANITIZER_S390_31
+#  define GET_CALLER_PC() \
+  (uptr)__builtin_extract_return_addr(__builtin_return_address(0))
+# else
+#  define GET_CALLER_PC() (uptr)__builtin_return_address(0)
+# endif
 # define GET_CURRENT_FRAME() (uptr)__builtin_frame_address(0)
 inline void Trap() {
   __builtin_trap();
diff --git a/libsanitizer/sanitizer_common/sanitizer_linux_s390.cc b/libsanitizer/sanitizer_common/sanitizer_linux_s390.cc
index c7d647528aba..3faaa1c26ac3 100644
--- a/libsanitizer/sanitizer_common/sanitizer_linux_s390.cc
+++ b/libsanitizer/sanitizer_common/sanitizer_linux_s390.cc
@@ -134,6 +134,18 @@ static bool FixedCVE_2016_2143() {
   if (ptr[0] == '.')
     patch = internal_simple_strtoll(ptr+1, &ptr, 10);
   if (major < 3) {
+    if (major == 2 && minor == 6 && patch == 32 && ptr[0] == '-' &&
+        internal_strstr(ptr, ".el6")) {
+      // Check RHEL6
+      int r1 = internal_simple_strtoll(ptr+1, &ptr, 10);
+      if (r1 >= 657) // 2.6.32-657.el6 or later
+        return true;
+      if (r1 == 642 && ptr[0] == '.') {
+        int r2 = internal_simple_strtoll(ptr+1, &ptr, 10);
+        if (r2 >= 9) // 2.6.32-642.9.1.el6 or later
+          return true;
+      }
+    }
     // <3.0 is bad.
     return false;
   } else if (major == 3) {
@@ -143,6 +155,18 @@ static bool FixedCVE_2016_2143() {
     // 3.12.58+ is OK.
     if (minor == 12 && patch >= 58)
       return true;
+    if (minor == 10 && patch == 0 && ptr[0] == '-' &&
+        internal_strstr(ptr, ".el7")) {
+      // Check RHEL7
+      int r1 = internal_simple_strtoll(ptr+1, &ptr, 10);
+      if (r1 >= 426) // 3.10.0-426.el7 or later
+        return true;
+      if (r1 == 327 && ptr[0] == '.') {
+        int r2 = internal_simple_strtoll(ptr+1, &ptr, 10);
+        if (r2 >= 27) // 3.10.0-327.27.1.el7 or later
+          return true;
+      }
+    }
     // Otherwise, bad.
     return false;
   } else if (major == 4) {
-- 
GitLab