[llvm-commits] [compiler-rt] r157388 - in /compiler-rt/trunk/lib: asan/asan_interceptors.cc asan/output_tests/heap-overflow.cc asan/output_tests/interception_failure_test-linux.cc asan/output_tests/interception_malloc_test-linux.cc asan/output_tests/interception_test-linux.cc asan/output_tests/strncpy-overflow.cc asan/output_tests/test_output.sh asan/output_tests/use-after-free.cc interception/interception.h interception/interception_linux.cc interception/interception_linux.h tsan/rtl/tsan_rtl_report.cc

Dmitry Vyukov dvyukov at google.com
Thu May 24 06:54:32 PDT 2012


Author: dvyukov
Date: Thu May 24 08:54:31 2012
New Revision: 157388

URL: http://llvm.org/viewvc/llvm-project?rev=157388&view=rev
Log:
asan/tsan: weak interceptors
The idea isthat asan/tsan can survive if user intercepts the same functions. At the same time user has an ability to call back into asan/tsan runtime. See the following tests for examples:
asan/output_tests/interception_failure_test-linux.cc
asan/output_tests/interception_test-linux.cc
asan/output_tests/interception_malloc_test-linux.cc


Added:
    compiler-rt/trunk/lib/asan/output_tests/interception_failure_test-linux.cc   (with props)
    compiler-rt/trunk/lib/asan/output_tests/interception_malloc_test-linux.cc   (with props)
    compiler-rt/trunk/lib/asan/output_tests/interception_test-linux.cc   (with props)
Modified:
    compiler-rt/trunk/lib/asan/asan_interceptors.cc
    compiler-rt/trunk/lib/asan/output_tests/heap-overflow.cc
    compiler-rt/trunk/lib/asan/output_tests/strncpy-overflow.cc
    compiler-rt/trunk/lib/asan/output_tests/test_output.sh
    compiler-rt/trunk/lib/asan/output_tests/use-after-free.cc
    compiler-rt/trunk/lib/interception/interception.h
    compiler-rt/trunk/lib/interception/interception_linux.cc
    compiler-rt/trunk/lib/interception/interception_linux.h
    compiler-rt/trunk/lib/tsan/rtl/tsan_rtl_report.cc

Modified: compiler-rt/trunk/lib/asan/asan_interceptors.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/asan/asan_interceptors.cc?rev=157388&r1=157387&r2=157388&view=diff
==============================================================================
--- compiler-rt/trunk/lib/asan/asan_interceptors.cc (original)
+++ compiler-rt/trunk/lib/asan/asan_interceptors.cc Thu May 24 08:54:31 2012
@@ -743,6 +743,11 @@
 }
 #endif  // ASAN_INTERCEPT_ATOLL_AND_STRTOLL
 
+#define ASAN_INTERCEPT_FUNC(name) do { \
+      if (!INTERCEPT_FUNCTION(name) && FLAG_v > 0) \
+        Report("AddressSanitizer: failed to intercept '" #name "'\n"); \
+    } while (0)
+
 #if defined(_WIN32)
 INTERCEPTOR_WINAPI(DWORD, CreateThread,
                    void* security, size_t stack_size,
@@ -758,7 +763,7 @@
 
 namespace __asan {
 void InitializeWindowsInterceptors() {
-  CHECK(INTERCEPT_FUNCTION(CreateThread));
+  ASAN_INTERCEPT_FUNC(CreateThread);
 }
 
 }  // namespace __asan
@@ -771,65 +776,65 @@
   CHECK(was_called_once == false);
   was_called_once = true;
   // Intercept mem* functions.
-  CHECK(INTERCEPT_FUNCTION(memcmp));
-  CHECK(INTERCEPT_FUNCTION(memmove));
-  CHECK(INTERCEPT_FUNCTION(memset));
+  ASAN_INTERCEPT_FUNC(memcmp);
+  ASAN_INTERCEPT_FUNC(memmove);
+  ASAN_INTERCEPT_FUNC(memset);
   if (PLATFORM_HAS_DIFFERENT_MEMCPY_AND_MEMMOVE) {
-    CHECK(INTERCEPT_FUNCTION(memcpy));
+    ASAN_INTERCEPT_FUNC(memcpy);
   } else {
     REAL(memcpy) = REAL(memmove);
   }
 
   // Intercept str* functions.
-  CHECK(INTERCEPT_FUNCTION(strcat));  // NOLINT
-  CHECK(INTERCEPT_FUNCTION(strchr));
-  CHECK(INTERCEPT_FUNCTION(strcmp));
-  CHECK(INTERCEPT_FUNCTION(strcpy));  // NOLINT
-  CHECK(INTERCEPT_FUNCTION(strlen));
-  CHECK(INTERCEPT_FUNCTION(strncmp));
-  CHECK(INTERCEPT_FUNCTION(strncpy));
+  ASAN_INTERCEPT_FUNC(strcat);  // NOLINT
+  ASAN_INTERCEPT_FUNC(strchr);
+  ASAN_INTERCEPT_FUNC(strcmp);
+  ASAN_INTERCEPT_FUNC(strcpy);  // NOLINT
+  ASAN_INTERCEPT_FUNC(strlen);
+  ASAN_INTERCEPT_FUNC(strncmp);
+  ASAN_INTERCEPT_FUNC(strncpy);
 #if !defined(_WIN32)
-  CHECK(INTERCEPT_FUNCTION(strcasecmp));
-  CHECK(INTERCEPT_FUNCTION(strdup));
-  CHECK(INTERCEPT_FUNCTION(strncasecmp));
+  ASAN_INTERCEPT_FUNC(strcasecmp);
+  ASAN_INTERCEPT_FUNC(strdup);
+  ASAN_INTERCEPT_FUNC(strncasecmp);
 # ifndef __APPLE__
-  CHECK(INTERCEPT_FUNCTION(index));
+  ASAN_INTERCEPT_FUNC(index);
 # else
-  CHECK(OVERRIDE_FUNCTION(index, WRAP(strchr)));
+  CHECK(OVERRIDE_FUNCTION(index, WRAP(strchr));
 # endif
 #endif
 #if ASAN_INTERCEPT_STRNLEN
-  CHECK(INTERCEPT_FUNCTION(strnlen));
+  ASAN_INTERCEPT_FUNC(strnlen);
 #endif
 
-  CHECK(INTERCEPT_FUNCTION(atoi));
-  CHECK(INTERCEPT_FUNCTION(atol));
-  CHECK(INTERCEPT_FUNCTION(strtol));
+  ASAN_INTERCEPT_FUNC(atoi);
+  ASAN_INTERCEPT_FUNC(atol);
+  ASAN_INTERCEPT_FUNC(strtol);
 #if ASAN_INTERCEPT_ATOLL_AND_STRTOLL
-  CHECK(INTERCEPT_FUNCTION(atoll));
-  CHECK(INTERCEPT_FUNCTION(strtoll));
+  ASAN_INTERCEPT_FUNC(atoll);
+  ASAN_INTERCEPT_FUNC(strtoll);
 #endif
 
   // Intecept signal- and jump-related functions.
-  CHECK(INTERCEPT_FUNCTION(longjmp));
+  ASAN_INTERCEPT_FUNC(longjmp);
 #if ASAN_INTERCEPT_SIGNAL_AND_SIGACTION
-  CHECK(INTERCEPT_FUNCTION(sigaction));
-  CHECK(INTERCEPT_FUNCTION(signal));
+  ASAN_INTERCEPT_FUNC(sigaction);
+  ASAN_INTERCEPT_FUNC(signal);
 #endif
 
 #if !defined(_WIN32)
-  CHECK(INTERCEPT_FUNCTION(_longjmp));
+  ASAN_INTERCEPT_FUNC(_longjmp);
   INTERCEPT_FUNCTION(__cxa_throw);
 # if !defined(__APPLE__)
   // On Darwin siglongjmp tailcalls longjmp, so we don't want to intercept it
   // there.
-  CHECK(INTERCEPT_FUNCTION(siglongjmp));
+  ASAN_INTERCEPT_FUNC(siglongjmp);
 # endif
 #endif
 
   // Intercept threading-related functions
 #if !defined(_WIN32)
-  CHECK(INTERCEPT_FUNCTION(pthread_create));
+  ASAN_INTERCEPT_FUNC(pthread_create);
 #endif
 
   // Some Windows-specific interceptors.

Modified: compiler-rt/trunk/lib/asan/output_tests/heap-overflow.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/asan/output_tests/heap-overflow.cc?rev=157388&r1=157387&r2=157388&view=diff
==============================================================================
--- compiler-rt/trunk/lib/asan/output_tests/heap-overflow.cc (original)
+++ compiler-rt/trunk/lib/asan/output_tests/heap-overflow.cc Thu May 24 08:54:31 2012
@@ -13,7 +13,7 @@
 // Check-Common: {{0x.* is located 0 bytes to the right of 10-byte region}}
 // Check-Common: {{allocated by thread T0 here:}}
 
-// Check-Linux: {{    #0 0x.* in malloc}}
+// Check-Linux: {{    #0 0x.* in __xsan_malloc}}
 // Check-Linux: {{    #1 0x.* in main .*heap-overflow.cc:[45]}}
 
 // Check-Darwin: {{    #0 0x.* in .*mz_malloc.*}}

Added: compiler-rt/trunk/lib/asan/output_tests/interception_failure_test-linux.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/asan/output_tests/interception_failure_test-linux.cc?rev=157388&view=auto
==============================================================================
--- compiler-rt/trunk/lib/asan/output_tests/interception_failure_test-linux.cc (added)
+++ compiler-rt/trunk/lib/asan/output_tests/interception_failure_test-linux.cc Thu May 24 08:54:31 2012
@@ -0,0 +1,17 @@
+#include <stdlib.h>
+#include <stdio.h>
+
+extern "C" long strtol(const char *nptr, char **endptr, int base) {
+  fprintf(stderr, "my_strtol_interceptor\n");
+  return 0;
+}
+
+int main() {
+  char *x = (char*)malloc(10 * sizeof(char));
+  free(x);
+  return (int)strtol(x, 0, 10);
+}
+
+// Check-Common: my_strtol_interceptor
+// CHECK-NOT: heap-use-after-free
+

Propchange: compiler-rt/trunk/lib/asan/output_tests/interception_failure_test-linux.cc
------------------------------------------------------------------------------
    svn:eol-style = LF

Added: compiler-rt/trunk/lib/asan/output_tests/interception_malloc_test-linux.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/asan/output_tests/interception_malloc_test-linux.cc?rev=157388&view=auto
==============================================================================
--- compiler-rt/trunk/lib/asan/output_tests/interception_malloc_test-linux.cc (added)
+++ compiler-rt/trunk/lib/asan/output_tests/interception_malloc_test-linux.cc Thu May 24 08:54:31 2012
@@ -0,0 +1,19 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+
+extern "C" void *__xsan_malloc(size_t size);
+extern "C" void *malloc(size_t size) {
+  write(2, "malloc call\n", sizeof("malloc call\n") - 1);
+  return __xsan_malloc(size);
+}
+
+int main() {
+  char *x = (char*)malloc(10 * sizeof(char));
+  free(x);
+  return (int)strtol(x, 0, 10);
+}
+
+// Check-Common: malloc call
+// Check-Common: heap-use-after-free
+

Propchange: compiler-rt/trunk/lib/asan/output_tests/interception_malloc_test-linux.cc
------------------------------------------------------------------------------
    svn:eol-style = LF

Added: compiler-rt/trunk/lib/asan/output_tests/interception_test-linux.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/asan/output_tests/interception_test-linux.cc?rev=157388&view=auto
==============================================================================
--- compiler-rt/trunk/lib/asan/output_tests/interception_test-linux.cc (added)
+++ compiler-rt/trunk/lib/asan/output_tests/interception_test-linux.cc Thu May 24 08:54:31 2012
@@ -0,0 +1,18 @@
+#include <stdlib.h>
+#include <stdio.h>
+
+extern "C" long __xsan_strtol(const char *nptr, char **endptr, int base);
+extern "C" long strtol(const char *nptr, char **endptr, int base) {
+  fprintf(stderr, "my_strtol_interceptor\n");
+  return __xsan_strtol(nptr, endptr, base);
+}
+
+int main() {
+  char *x = (char*)malloc(10 * sizeof(char));
+  free(x);
+  return (int)strtol(x, 0, 10);
+}
+
+// Check-Common: my_strtol_interceptor
+// Check-Common: heap-use-after-free
+

Propchange: compiler-rt/trunk/lib/asan/output_tests/interception_test-linux.cc
------------------------------------------------------------------------------
    svn:eol-style = LF

Modified: compiler-rt/trunk/lib/asan/output_tests/strncpy-overflow.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/asan/output_tests/strncpy-overflow.cc?rev=157388&r1=157387&r2=157388&view=diff
==============================================================================
--- compiler-rt/trunk/lib/asan/output_tests/strncpy-overflow.cc (original)
+++ compiler-rt/trunk/lib/asan/output_tests/strncpy-overflow.cc Thu May 24 08:54:31 2012
@@ -9,13 +9,13 @@
 }
 
 // Check-Common: {{WRITE of size 1 at 0x.* thread T0}}
-// Check-Linux: {{    #0 0x.* in strncpy}}
+// Check-Linux: {{    #0 0x.* in __xsan_strncpy}}
 // Check-Darwin: {{    #0 0x.* in wrap_strncpy}}
 // Check-Common: {{    #1 0x.* in main .*strncpy-overflow.cc:[78]}}
 // Check-Common: {{0x.* is located 0 bytes to the right of 9-byte region}}
 // Check-Common: {{allocated by thread T0 here:}}
 
-// Check-Linux: {{    #0 0x.* in malloc}}
+// Check-Linux: {{    #0 0x.* in __xsan_malloc}}
 // Check-Linux: {{    #1 0x.* in main .*strncpy-overflow.cc:6}}
 
 // Check-Darwin: {{    #0 0x.* in .*mz_malloc.*}}

Modified: compiler-rt/trunk/lib/asan/output_tests/test_output.sh
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/asan/output_tests/test_output.sh?rev=157388&r1=157387&r2=157388&view=diff
==============================================================================
--- compiler-rt/trunk/lib/asan/output_tests/test_output.sh (original)
+++ compiler-rt/trunk/lib/asan/output_tests/test_output.sh Thu May 24 08:54:31 2012
@@ -14,7 +14,7 @@
   ./$1 2>&1 | $SYMBOLIZER 2> /dev/null | c++filt > $TMP_ASAN_REPORT
 }
 
-# check_program exe_file source_file check_prefix
+# check_program exe_file source_file check_prefixf
 check_program() {
   run_program $1
   $FILE_CHECK $2 --check-prefix=$3 < $TMP_ASAN_REPORT
@@ -43,10 +43,14 @@
   for b in 32 64; do
     for O in 0 1 2 3; do
       c=`basename $t .cc`
-      if [[ "$c" == *"-so" ]]
-      then
+      if [[ "$c" == *"-so" ]]; then
         continue
       fi
+      if [[ "$c" == *"-linux" ]]; then
+        if [[ "$OS" != "Linux" ]]; then
+          continue
+        fi
+      fi
       c_so=$c-so
       exe=$c.$b.O$O
       so=$c.$b.O$O-so.so

Modified: compiler-rt/trunk/lib/asan/output_tests/use-after-free.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/asan/output_tests/use-after-free.cc?rev=157388&r1=157387&r2=157388&view=diff
==============================================================================
--- compiler-rt/trunk/lib/asan/output_tests/use-after-free.cc (original)
+++ compiler-rt/trunk/lib/asan/output_tests/use-after-free.cc Thu May 24 08:54:31 2012
@@ -12,7 +12,7 @@
 // Check-Common: {{0x.* is located 5 bytes inside of 10-byte region .0x.*,0x.*}}
 // Check-Common: {{freed by thread T0 here:}}
 
-// Check-Linux: {{    #0 0x.* in free}}
+// Check-Linux: {{    #0 0x.* in __xsan_free}}
 // Check-Linux: {{    #1 0x.* in main .*use-after-free.cc:[45]}}
 
 // Check-Darwin: {{    #0 0x.* in .*mz_free.*}}
@@ -22,7 +22,7 @@
 
 // Check-Common: {{previously allocated by thread T0 here:}}
 
-// Check-Linux: {{    #0 0x.* in malloc}}
+// Check-Linux: {{    #0 0x.* in __xsan_malloc}}
 // Check-Linux: {{    #1 0x.* in main .*use-after-free.cc:3}}
 
 // Check-Darwin: {{    #0 0x.* in .*mz_malloc.*}}

Modified: compiler-rt/trunk/lib/interception/interception.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/interception/interception.h?rev=157388&r1=157387&r2=157388&view=diff
==============================================================================
--- compiler-rt/trunk/lib/interception/interception.h (original)
+++ compiler-rt/trunk/lib/interception/interception.h Thu May 24 08:54:31 2012
@@ -61,20 +61,26 @@
 //           source file (to define a pointer to overriden function).
 
 // How it works:
-// To replace weak system functions on Linux we just need to declare functions
+// To replace system functions on Linux we just need to declare functions
 // with same names in our library and then obtain the real function pointers
-// using dlsym(). This is not so on Mac OS, where the two-level namespace makes
+// using dlsym().
+// There is one complication. A user may also intercept some of the functions
+// we intercept. To resolve this we declare our interceptors with __xsan_
+// prefix, and then make actual interceptors weak aliases to __xsan_
+// functions.
+// This is not so on Mac OS, where the two-level namespace makes
 // our replacement functions invisible to other libraries. This may be overcomed
 // using the DYLD_FORCE_FLAT_NAMESPACE, but some errors loading the shared
-// libraries in Chromium were noticed when doing so.
-// Instead we use mach_override, a handy framework for patching functions at
-// runtime. To avoid possible name clashes, our replacement functions have
+// libraries in Chromium were noticed when doing so. Instead we use
+// mach_override, a handy framework for patching functions at runtime.
+// To avoid possible name clashes, our replacement functions have
 // the "wrap_" prefix on Mac.
 
 #if defined(__APPLE__)
 # define WRAP(x) wrap_##x
 # define WRAPPER_NAME(x) "wrap_"#x
 # define INTERCEPTOR_ATTRIBUTE
+# define DECLARE_WRAPPER(ret_type, convention, func, ...)
 #elif defined(_WIN32)
 # if defined(_DLL)  // DLL CRT
 #  define WRAP(x) x
@@ -85,10 +91,14 @@
 #  define WRAPPER_NAME(x) "wrap_"#x
 #  define INTERCEPTOR_ATTRIBUTE
 # endif
+# define DECLARE_WRAPPER(ret_type, convention, func, ...)
 #else
-# define WRAP(x) x
-# define WRAPPER_NAME(x) #x
+# define WRAP(x) __xsan_ ## x
+# define WRAPPER_NAME(x) "__xsan_" #x
 # define INTERCEPTOR_ATTRIBUTE __attribute__((visibility("default")))
+# define DECLARE_WRAPPER(ret_type, convention, func, ...) \
+    extern "C" ret_type convention func(__VA_ARGS__) \
+    __attribute__((weak, alias("__xsan_" #func), visibility("default")))
 #endif
 
 #define PTR_TO_REAL(x) real_##x
@@ -125,6 +135,7 @@
 
 #define INTERCEPTOR_EX(ret_type, convention, func, ...) \
   DEFINE_REAL_EX(ret_type, convention, func, __VA_ARGS__); \
+  DECLARE_WRAPPER(ret_type, convention, func, __VA_ARGS__); \
   extern "C" \
   INTERCEPTOR_ATTRIBUTE \
   ret_type convention WRAP(func)(__VA_ARGS__)

Modified: compiler-rt/trunk/lib/interception/interception_linux.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/interception/interception_linux.cc?rev=157388&r1=157387&r2=157388&view=diff
==============================================================================
--- compiler-rt/trunk/lib/interception/interception_linux.cc (original)
+++ compiler-rt/trunk/lib/interception/interception_linux.cc Thu May 24 08:54:31 2012
@@ -18,9 +18,10 @@
 #include <dlfcn.h>   // for dlsym
 
 namespace __interception {
-bool GetRealFunctionAddress(const char *func_name, void **func_addr) {
+bool GetRealFunctionAddress(const char *func_name, void **func_addr,
+    void *real, void *wrapper) {
   *func_addr = dlsym(RTLD_NEXT, func_name);
-  return (*func_addr != NULL);
+  return real == wrapper;
 }
 }  // namespace __interception
 

Modified: compiler-rt/trunk/lib/interception/interception_linux.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/interception/interception_linux.h?rev=157388&r1=157387&r2=157388&view=diff
==============================================================================
--- compiler-rt/trunk/lib/interception/interception_linux.h (original)
+++ compiler-rt/trunk/lib/interception/interception_linux.h Thu May 24 08:54:31 2012
@@ -23,11 +23,13 @@
 
 namespace __interception {
 // returns true if a function with the given name was found.
-bool GetRealFunctionAddress(const char *func_name, void **func_addr);
+bool GetRealFunctionAddress(const char *func_name, void **func_addr,
+    void *real, void *wrapper);
 }  // namespace __interception
 
 #define INTERCEPT_FUNCTION_LINUX(func) \
-    ::__interception::GetRealFunctionAddress(#func, (void**)&REAL(func))
+    ::__interception::GetRealFunctionAddress(#func, (void**)&REAL(func), \
+    (void*)&(func), (void*)&WRAP(func))
 
 #endif  // INTERCEPTION_LINUX_H
 #endif  // __linux__

Modified: compiler-rt/trunk/lib/tsan/rtl/tsan_rtl_report.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/rtl/tsan_rtl_report.cc?rev=157388&r1=157387&r2=157388&view=diff
==============================================================================
--- compiler-rt/trunk/lib/tsan/rtl/tsan_rtl_report.cc (original)
+++ compiler-rt/trunk/lib/tsan/rtl/tsan_rtl_report.cc Thu May 24 08:54:31 2012
@@ -32,7 +32,7 @@
 static void StackStripMain(ReportStack *stack) {
   ReportStack *last_frame = 0;
   ReportStack *last_frame2 = 0;
-  const char *prefix = "interception_wrap_";
+  const char *prefix = "__xsan_";
   uptr prefix_len = internal_strlen(prefix);
   const char *path_prefix = flags()->strip_path_prefix;
   uptr path_prefix_len = internal_strlen(path_prefix);





More information about the llvm-commits mailing list