diff --git a/compiler-rt/include/sanitizer/asan_interface.h b/compiler-rt/include/sanitizer/asan_interface.h index a09c6b2af784..5b6a9097fd24 100644 --- a/compiler-rt/include/sanitizer/asan_interface.h +++ b/compiler-rt/include/sanitizer/asan_interface.h @@ -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" diff --git a/compiler-rt/include/sanitizer/common_interface_defs.h b/compiler-rt/include/sanitizer/common_interface_defs.h index e4ba2cb326d2..1eb182095ec9 100644 --- a/compiler-rt/include/sanitizer/common_interface_defs.h +++ b/compiler-rt/include/sanitizer/common_interface_defs.h @@ -30,6 +30,12 @@ # 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 diff --git a/compiler-rt/lib/asan/asan_allocator.cc b/compiler-rt/lib/asan/asan_allocator.cc index 9719aac321d5..6e9f26d46ceb 100644 --- a/compiler-rt/lib/asan/asan_allocator.cc +++ b/compiler-rt/lib/asan/asan_allocator.cc @@ -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; } diff --git a/compiler-rt/lib/asan/asan_internal.h b/compiler-rt/lib/asan/asan_internal.h index 1a50e6033db8..468d997cf262 100644 --- a/compiler-rt/lib/asan/asan_internal.h +++ b/compiler-rt/lib/asan/asan_internal.h @@ -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; diff --git a/compiler-rt/lib/asan/asan_report.cc b/compiler-rt/lib/asan/asan_report.cc index 266ca034fa1f..558e4f202b4a 100644 --- a/compiler-rt/lib/asan/asan_report.cc +++ b/compiler-rt/lib/asan/asan_report.cc @@ -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 diff --git a/compiler-rt/lib/asan/asan_rtl.cc b/compiler-rt/lib/asan/asan_rtl.cc index d205f26d6097..37c9583a7c3f 100644 --- a/compiler-rt/lib/asan/asan_rtl.cc +++ b/compiler-rt/lib/asan/asan_rtl.cc @@ -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; diff --git a/compiler-rt/lib/asan/asan_stack.cc b/compiler-rt/lib/asan/asan_stack.cc index 53a46470a613..ebf22fd34ca1 100644 --- a/compiler-rt/lib/asan/asan_stack.cc +++ b/compiler-rt/lib/asan/asan_stack.cc @@ -17,9 +17,15 @@ 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; diff --git a/compiler-rt/lib/asan/lit_tests/interface_symbols.c b/compiler-rt/lib/asan/lit_tests/interface_symbols.c index 5cbceebd4307..605360601f4b 100644 --- a/compiler-rt/lib/asan/lit_tests/interface_symbols.c +++ b/compiler-rt/lib/asan/lit_tests/interface_symbols.c @@ -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