forked from OSchip/llvm-project
ASan: change the strategy we use for installing malloc/free/symbolization hooks on Linux: don't provide a default no-op implementations for hooks in runtime, and optionally call hooks if they are provided by the user. Don't force weak interface functions into runtime.
llvm-svn: 169641
This commit is contained in:
parent
9cadaa7ef8
commit
a0e4706fe6
|
@ -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"
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue