ASan: change the strategy we use for installing malloc/free/symbolization hooks on...
authorAlexey Samsonov <samsonov@google.com>
Fri, 7 Dec 2012 22:01:28 +0000 (22:01 +0000)
committerAlexey Samsonov <samsonov@google.com>
Fri, 7 Dec 2012 22:01:28 +0000 (22:01 +0000)
llvm-svn: 169641

compiler-rt/include/sanitizer/asan_interface.h
compiler-rt/include/sanitizer/common_interface_defs.h
compiler-rt/lib/asan/asan_allocator.cc
compiler-rt/lib/asan/asan_internal.h
compiler-rt/lib/asan/asan_report.cc
compiler-rt/lib/asan/asan_rtl.cc
compiler-rt/lib/asan/asan_stack.cc
compiler-rt/lib/asan/lit_tests/interface_symbols.c

index a09c6b2..5b6a909 100644 (file)
@@ -140,7 +140,7 @@ extern "C" {
   // User may provide function that would be called right when ASan detects
   // an error. This can be used to notice cases when ASan detects an error, but
   // the program crashes before ASan report is printed.
-  void __asan_on_error()
+  /* OPTIONAL */ void __asan_on_error()
       SANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE;
 
   // User may provide its own implementation for symbolization function.
@@ -148,7 +148,8 @@ extern "C" {
   // "out_buffer". Description should be at most "out_size" bytes long.
   // User-specified function should return true if symbolization was
   // successful.
-  bool __asan_symbolize(const void *pc, char *out_buffer, int out_size)
+  /* OPTIONAL */ bool __asan_symbolize(const void *pc, char *out_buffer,
+                                       int out_size)
       SANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE;
 
   // Returns the estimated number of bytes that will be reserved by allocator
@@ -188,20 +189,19 @@ extern "C" {
   void __asan_print_accumulated_stats()
       SANITIZER_INTERFACE_ATTRIBUTE;
 
-  // This function may be overriden by user to provide a string containing
-  // ASan runtime options. See asan_flags.h for details.
-  const char* __asan_default_options()
+  // This function may be optionally provided by user and should return
+  // a string containing ASan runtime options. See asan_flags.h for details.
+  /* OPTIONAL */ const char* __asan_default_options()
       SANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE;
 
-  // Malloc hooks that may be overriden by user.
+  // Malloc hooks that may be optionally provided by user.
   // __asan_malloc_hook(ptr, size) is called immediately after
   //   allocation of "size" bytes, which returned "ptr".
   // __asan_free_hook(ptr) is called immediately before
   //   deallocation of "ptr".
-  // If user doesn't provide implementations of these hooks, they are no-op.
-  void __asan_malloc_hook(void *ptr, uptr size)
+  /* OPTIONAL */ void __asan_malloc_hook(void *ptr, uptr size)
       SANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE;
-  void __asan_free_hook(void *ptr)
+  /* OPTIONAL */ void __asan_free_hook(void *ptr)
       SANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE;
 }  // extern "C"
 
index e4ba2cb..1eb1820 100644 (file)
 # define SANITIZER_WEAK_ATTRIBUTE  __attribute__((weak))
 #endif
 
+#ifdef __linux__
+# define SANITIZER_SUPPORTS_WEAK_HOOKS 1
+#else
+# define SANITIZER_SUPPORTS_WEAK_HOOKS 0
+#endif
+
 // __has_feature
 #if !defined(__has_feature)
 # define __has_feature(x) 0
index 9719aac..6e9f26d 100644 (file)
@@ -757,7 +757,8 @@ static u8 *Reallocate(u8 *old_ptr, uptr new_size,
 
 }  // namespace __asan
 
-// Default (no-op) implementation of malloc hooks.
+#if !SANITIZER_SUPPORTS_WEAK_HOOKS
+// Provide default (no-op) implementation of malloc hooks.
 extern "C" {
 SANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE
 void __asan_malloc_hook(void *ptr, uptr size) {
@@ -769,26 +770,27 @@ void __asan_free_hook(void *ptr) {
   (void)ptr;
 }
 }  // extern "C"
+#endif
 
 namespace __asan {
 
 SANITIZER_INTERFACE_ATTRIBUTE
 void *asan_memalign(uptr alignment, uptr size, StackTrace *stack) {
   void *ptr = (void*)Allocate(alignment, size, stack);
-  __asan_malloc_hook(ptr, size);
+  ASAN_MALLOC_HOOK(ptr, size);
   return ptr;
 }
 
 SANITIZER_INTERFACE_ATTRIBUTE
 void asan_free(void *ptr, StackTrace *stack) {
-  __asan_free_hook(ptr);
+  ASAN_FREE_HOOK(ptr);
   Deallocate((u8*)ptr, stack);
 }
 
 SANITIZER_INTERFACE_ATTRIBUTE
 void *asan_malloc(uptr size, StackTrace *stack) {
   void *ptr = (void*)Allocate(0, size, stack);
-  __asan_malloc_hook(ptr, size);
+  ASAN_MALLOC_HOOK(ptr, size);
   return ptr;
 }
 
@@ -796,17 +798,17 @@ void *asan_calloc(uptr nmemb, uptr size, StackTrace *stack) {
   void *ptr = (void*)Allocate(0, nmemb * size, stack);
   if (ptr)
     REAL(memset)(ptr, 0, nmemb * size);
-  __asan_malloc_hook(ptr, nmemb * size);
+  ASAN_MALLOC_HOOK(ptr, size);
   return ptr;
 }
 
 void *asan_realloc(void *p, uptr size, StackTrace *stack) {
   if (p == 0) {
     void *ptr = (void*)Allocate(0, size, stack);
-    __asan_malloc_hook(ptr, size);
+    ASAN_MALLOC_HOOK(ptr, size);
     return ptr;
   } else if (size == 0) {
-    __asan_free_hook(p);
+    ASAN_FREE_HOOK(p);
     Deallocate((u8*)p, stack);
     return 0;
   }
@@ -815,7 +817,7 @@ void *asan_realloc(void *p, uptr size, StackTrace *stack) {
 
 void *asan_valloc(uptr size, StackTrace *stack) {
   void *ptr = (void*)Allocate(GetPageSizeCached(), size, stack);
-  __asan_malloc_hook(ptr, size);
+  ASAN_MALLOC_HOOK(ptr, size);
   return ptr;
 }
 
@@ -827,7 +829,7 @@ void *asan_pvalloc(uptr size, StackTrace *stack) {
     size = PageSize;
   }
   void *ptr = (void*)Allocate(PageSize, size, stack);
-  __asan_malloc_hook(ptr, size);
+  ASAN_MALLOC_HOOK(ptr, size);
   return ptr;
 }
 
@@ -835,7 +837,7 @@ int asan_posix_memalign(void **memptr, uptr alignment, uptr size,
                           StackTrace *stack) {
   void *ptr = Allocate(alignment, size, stack);
   CHECK(IsAligned((uptr)ptr, alignment));
-  __asan_malloc_hook(ptr, size);
+  ASAN_MALLOC_HOOK(ptr, size);
   *memptr = ptr;
   return 0;
 }
index 1a50e60..468d997 100644 (file)
@@ -145,6 +145,15 @@ bool PlatformHasDifferentMemcpyAndMemmove();
 # define PLATFORM_HAS_DIFFERENT_MEMCPY_AND_MEMMOVE true
 #endif  // __APPLE__
 
+// Add convenient macro for interface functions that may be represented as
+// weak hooks.
+#define ASAN_MALLOC_HOOK(ptr, size) \
+  if (&__asan_malloc_hook) __asan_malloc_hook(ptr, size)
+#define ASAN_FREE_HOOK(ptr) \
+  if (&__asan_free_hook) __asan_free_hook(ptr)
+#define ASAN_ON_ERROR() \
+  if (&__asan_on_error) __asan_on_error()
+
 extern int asan_inited;
 // Used to avoid infinite recursion in __asan_init().
 extern bool asan_init_is_running;
index 266ca03..558e4f2 100644 (file)
@@ -322,7 +322,7 @@ class ScopedInErrorReport {
       // Die() to bypass any additional checks.
       Exit(flags()->exitcode);
     }
-    __asan_on_error();
+    ASAN_ON_ERROR();
     reporting_thread_tid = asanThreadRegistry().GetCurrentTidOrInvalid();
     Printf("===================================================="
            "=============\n");
@@ -524,7 +524,9 @@ void NOINLINE __asan_set_error_report_callback(void (*callback)(const char*)) {
   }
 }
 
+#if !SANITIZER_SUPPORTS_WEAK_HOOKS
 // Provide default implementation of __asan_on_error that does nothing
 // and may be overriden by user.
 SANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE NOINLINE
 void __asan_on_error() {}
+#endif
index d205f26..37c9583 100644 (file)
@@ -66,6 +66,10 @@ Flags *flags() {
   return &asan_flags;
 }
 
+static const char *MaybeCallAsanDefaultOptions() {
+  return (&__asan_default_options) ? __asan_default_options() : "";
+}
+
 static void ParseFlagsFromString(Flags *f, const char *str) {
   ParseFlag(str, &f->quarantine_size, "quarantine_size");
   ParseFlag(str, &f->symbolize, "symbolize");
@@ -102,12 +106,6 @@ static void ParseFlagsFromString(Flags *f, const char *str) {
   ParseFlag(str, &f->log_path, "log_path");
 }
 
-extern "C" {
-SANITIZER_WEAK_ATTRIBUTE
-SANITIZER_INTERFACE_ATTRIBUTE
-const char* __asan_default_options() { return ""; }
-}  // extern "C"
-
 void InitializeFlags(Flags *f, const char *env) {
   internal_memset(f, 0, sizeof(*f));
 
@@ -141,10 +139,10 @@ void InitializeFlags(Flags *f, const char *env) {
   f->log_path = 0;
 
   // Override from user-specified string.
-  ParseFlagsFromString(f, __asan_default_options());
+  ParseFlagsFromString(f, MaybeCallAsanDefaultOptions());
   if (flags()->verbosity) {
     Report("Using the defaults from __asan_default_options: %s\n",
-           __asan_default_options());
+           MaybeCallAsanDefaultOptions());
   }
 
   // Override from command line.
@@ -241,15 +239,10 @@ static NOINLINE void force_interface_symbols() {
     case 27: __asan_set_error_exit_code(0); break;
     case 28: __asan_stack_free(0, 0, 0); break;
     case 29: __asan_stack_malloc(0, 0); break;
-    case 30: __asan_on_error(); break;
-    case 31: __asan_default_options(); break;
-    case 32: __asan_before_dynamic_init(0, 0); break;
-    case 33: __asan_after_dynamic_init(); break;
-    case 34: __asan_malloc_hook(0, 0); break;
-    case 35: __asan_free_hook(0); break;
-    case 36: __asan_symbolize(0, 0, 0); break;
-    case 37: __asan_poison_stack_memory(0, 0); break;
-    case 38: __asan_unpoison_stack_memory(0, 0); break;
+    case 30: __asan_before_dynamic_init(0, 0); break;
+    case 31: __asan_after_dynamic_init(); break;
+    case 32: __asan_poison_stack_memory(0, 0); break;
+    case 33: __asan_unpoison_stack_memory(0, 0); break;
   }
 }
 
@@ -263,6 +256,13 @@ static void asan_atexit() {
 // ---------------------- Interface ---------------- {{{1
 using namespace __asan;  // NOLINT
 
+#if !SANITIZER_SUPPORTS_WEAK_HOOKS
+extern "C" {
+SANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE
+const char* __asan_default_options() { return ""; }
+}  // extern "C"
+#endif
+
 int NOINLINE __asan_set_error_exit_code(int exit_code) {
   int old = flags()->exitcode;
   flags()->exitcode = exit_code;
index 53a4647..ebf22fd 100644 (file)
 
 namespace __asan {
 
+static bool MaybeCallAsanSymbolize(const void *pc, char *out_buffer,
+                                   int out_size) {
+  return (&__asan_symbolize) ? __asan_symbolize(pc, out_buffer, out_size)
+                             : false;
+}
+
 void PrintStack(StackTrace *stack) {
   stack->PrintStack(stack->trace, stack->size, flags()->symbolize,
-                    flags()->strip_path_prefix, __asan_symbolize);
+                    flags()->strip_path_prefix, MaybeCallAsanSymbolize);
 }
 
 }  // namespace __asan
@@ -29,7 +35,7 @@ void PrintStack(StackTrace *stack) {
 // Provide default implementation of __asan_symbolize that does nothing
 // and may be overriden by user if he wants to use his own symbolization.
 // ASan on Windows has its own implementation of this.
-#ifndef _WIN32
+#if !defined(_WIN32) && !SANITIZER_SUPPORTS_WEAK_HOOKS
 SANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE NOINLINE
 bool __asan_symbolize(const void *pc, char *out_buffer, int out_size) {
   return false;
index 5cbceeb..6053606 100644 (file)
@@ -1,10 +1,11 @@
 // Check the presense of interface symbols in compiled file.
 
 // RUN: %clang -fsanitize=address -dead_strip -O2 %s -o %t.exe
-// RUN: nm %t.exe | egrep " [TW] " | sed "s/.* T //" | sed "s/.* W //" \
+// RUN: nm %t.exe | grep " T " | sed "s/.* T //" \
 // RUN:    | grep "__asan_" | sed "s/___asan_/__asan_/" > %t.symbols
 // RUN: cat %p/../../../include/sanitizer/asan_interface.h \
 // RUN:    | sed "s/\/\/.*//" | sed "s/typedef.*//" \
+// RUN:    | grep -v "OPTIONAL" \
 // RUN:    | grep "__asan_.*(" | sed "s/.* __asan_/__asan_/;s/(.*//" \
 // RUN:    > %t.interface
 // RUN: echo __asan_report_load1 >> %t.interface