diff --git a/compiler-rt/lib/asan/Makefile.old b/compiler-rt/lib/asan/Makefile.old index 4ab80e20bcb1..a6f496d1b7d3 100644 --- a/compiler-rt/lib/asan/Makefile.old +++ b/compiler-rt/lib/asan/Makefile.old @@ -60,6 +60,7 @@ endif CLANG_FLAGS= CLANG_VERSION=3.2 CLANG_BUILD=$(ROOT)/../../../../build/Release+Asserts +CLANG_BUILD=/Users/glider/src/asan/llvm/llvm_cmake_build CLANG_CC=$(CLANG_BUILD)/bin/clang $(CLANG_FLAGS) CLANG_CXX=$(CLANG_BUILD)/bin/clang++ $(CLANG_FLAGS) FILE_CHECK=$(CLANG_BUILD)/bin/FileCheck @@ -146,7 +147,9 @@ CLANG_ASAN_CXX=$(CLANG_CXX) \ -mllvm -asan-use-after-return=$(ASAN_UAR) \ $(COMMON_ASAN_DEFINES) -CLANG_ASAN_LD=$(CLANG_CXX) -faddress-sanitizer +#CLANG_ASAN_LD=$(CLANG_CXX) -faddress-sanitizer +#CLANG_ASAN_LD=$(CLANG_CXX) -L/Users/glider/src/asan/llvm/llvm_cmake_build/projects/compiler-rt/lib/asan/lib -lclang_rt.asan_osx_dynamic #-faddress-sanitizer +CLANG_ASAN_LD=$(CLANG_CXX) -faddress-sanitizer -faddress-sanitizer-dynamic-runtime GCC_ASAN_PATH=SET_FROM_COMMAND_LINE GCC_ASAN_CXX=$(GCC_ASAN_PATH)/g++ \ diff --git a/compiler-rt/lib/asan/asan_flags.h b/compiler-rt/lib/asan/asan_flags.h index d58a833a8bd3..8b5c11ca1a77 100644 --- a/compiler-rt/lib/asan/asan_flags.h +++ b/compiler-rt/lib/asan/asan_flags.h @@ -84,6 +84,9 @@ struct Flags { // By default, disable core dumper on 64-bit - it makes little sense // to dump 16T+ core. bool disable_core; + // Allow the tool to re-exec the program. This may interfere badly with the + // debugger. + bool allow_reexec; // Strips this prefix from file paths in error reports. const char *strip_path_prefix; }; diff --git a/compiler-rt/lib/asan/asan_interceptors.h b/compiler-rt/lib/asan/asan_interceptors.h index 32816920f7a3..3b3e90ef93ff 100644 --- a/compiler-rt/lib/asan/asan_interceptors.h +++ b/compiler-rt/lib/asan/asan_interceptors.h @@ -24,6 +24,7 @@ DECLARE_REAL(char*, strchr, const char *str, int c) DECLARE_REAL(uptr, strlen, const char *s) DECLARE_REAL(char*, strncpy, char *to, const char *from, uptr size) DECLARE_REAL(uptr, strnlen, const char *s, uptr maxlen) +DECLARE_REAL(char*, strstr, const char *s1, const char *s2) struct sigaction; DECLARE_REAL(int, sigaction, int signum, const struct sigaction *act, struct sigaction *oldact) diff --git a/compiler-rt/lib/asan/asan_internal.h b/compiler-rt/lib/asan/asan_internal.h index 4ed138c87e60..d72a5569549b 100644 --- a/compiler-rt/lib/asan/asan_internal.h +++ b/compiler-rt/lib/asan/asan_internal.h @@ -100,6 +100,7 @@ void *AsanDoesNotSupportStaticLinkage(); void GetPcSpBp(void *context, uptr *pc, uptr *sp, uptr *bp); +void MaybeReexec(); bool AsanInterceptsSignal(int signum); void SetAlternateSignalStack(); void UnsetAlternateSignalStack(); diff --git a/compiler-rt/lib/asan/asan_linux.cc b/compiler-rt/lib/asan/asan_linux.cc index 9a3d6bdb15a6..ddaefb29f45d 100644 --- a/compiler-rt/lib/asan/asan_linux.cc +++ b/compiler-rt/lib/asan/asan_linux.cc @@ -40,6 +40,10 @@ extern "C" void* _DYNAMIC; namespace __asan { +void MaybeReexec() { + // No need to re-exec on Linux. +} + void *AsanDoesNotSupportStaticLinkage() { // This will fail to link with -static. return &_DYNAMIC; // defined in link.h diff --git a/compiler-rt/lib/asan/asan_mac.cc b/compiler-rt/lib/asan/asan_mac.cc index 8e8b6649fc1c..4a5b6ecf88fd 100644 --- a/compiler-rt/lib/asan/asan_mac.cc +++ b/compiler-rt/lib/asan/asan_mac.cc @@ -23,7 +23,8 @@ #include "asan_thread_registry.h" #include "sanitizer_common/sanitizer_libc.h" -#include // for _NSGetEnviron +#include // for _NSGetArgv +#include // for dladdr() #include #include #include @@ -83,6 +84,42 @@ bool PlatformHasDifferentMemcpyAndMemmove() { return GetMacosVersion() == MACOS_VERSION_SNOW_LEOPARD; } +extern "C" +void __asan_init(); + +static const char kDyldInsertLibraries[] = "DYLD_INSERT_LIBRARIES"; + +void MaybeReexec() { + if (!flags()->allow_reexec) return; +#if MAC_INTERPOSE_FUNCTIONS + // If the program is linked with the dynamic ASan runtime library, make sure + // the library is preloaded so that the wrappers work. If it is not, set + // DYLD_INSERT_LIBRARIES and re-exec ourselves. + Dl_info info; + int result = dladdr((void*)__asan_init, &info); + const char *dyld_insert_libraries = GetEnv(kDyldInsertLibraries); + if (!dyld_insert_libraries || + !REAL(strstr)(dyld_insert_libraries, info.dli_fname)) { + // DYLD_INSERT_LIBRARIES is not set or does not contain the runtime + // library. + char program_name[1024]; + uint32_t buf_size = sizeof(program_name); + _NSGetExecutablePath(program_name, &buf_size); + // Ok to use setenv() since the wrappers don't depend on the value of + // asan_inited. + setenv(kDyldInsertLibraries, info.dli_fname, /*overwrite*/0); + if (flags()->verbosity >= 1) { + Report("exec()-ing the program with\n"); + Report("%s=%s\n", kDyldInsertLibraries, info.dli_fname); + Report("to enable ASan wrappers.\n"); + Report("Set ASAN_OPTIONS=allow_reexec=0 to disable this.\n"); + } + execv(program_name, *_NSGetArgv()); + } +#endif // MAC_INTERPOSE_FUNCTIONS + // If we're not using the dynamic runtime, do nothing. +} + // No-op. Mac does not support static linkage anyway. void *AsanDoesNotSupportStaticLinkage() { return 0; diff --git a/compiler-rt/lib/asan/asan_rtl.cc b/compiler-rt/lib/asan/asan_rtl.cc index 661a078e22bf..70b180143b0e 100644 --- a/compiler-rt/lib/asan/asan_rtl.cc +++ b/compiler-rt/lib/asan/asan_rtl.cc @@ -101,6 +101,7 @@ static void ParseFlagsFromString(Flags *f, const char *str) { ParseFlag(str, &f->atexit, "atexit"); ParseFlag(str, &f->disable_core, "disable_core"); ParseFlag(str, &f->strip_path_prefix, "strip_path_prefix"); + ParseFlag(str, &f->allow_reexec, "allow_reexec"); } extern "C" { @@ -137,6 +138,7 @@ void InitializeFlags(Flags *f, const char *env) { f->atexit = false; f->disable_core = (__WORDSIZE == 64); f->strip_path_prefix = ""; + f->allow_reexec = true; // Override from user-specified string. ParseFlagsFromString(f, __asan_default_options()); @@ -293,7 +295,8 @@ void __asan_init() { // Make sure we are not statically linked. AsanDoesNotSupportStaticLinkage(); - // Initialize flags. + // Initialize flags. This must be done early, because most of the + // initialization steps look at flags(). const char *options = GetEnv("ASAN_OPTIONS"); InitializeFlags(flags(), options); @@ -301,6 +304,10 @@ void __asan_init() { Report("Parsed ASAN_OPTIONS: %s\n", options); } + // Re-exec ourselves if we need to set additional env or command line args. + MaybeReexec(); + + if (flags()->atexit) { Atexit(asan_atexit); } diff --git a/compiler-rt/lib/asan/asan_win.cc b/compiler-rt/lib/asan/asan_win.cc index d50ee143c7f9..5d416440b1c1 100644 --- a/compiler-rt/lib/asan/asan_win.cc +++ b/compiler-rt/lib/asan/asan_win.cc @@ -153,6 +153,10 @@ void AsanTSDSet(void *tsd) { } // ---------------------- Various stuff ---------------- {{{1 +void MaybeReexec() { + // No need to re-exec on Windows. +} + void *AsanDoesNotSupportStaticLinkage() { #if defined(_DEBUG) #error Please build the runtime with a non-debug CRT: /MD or /MT