forked from OSchip/llvm-project
If the program is linked to a dynamic ASan runtime which is not present in DYLD_INSERT_LIBRARIES
(which, in turn, is required for our interceptors to take effect), re-exec the program with DYLD_INSERT_LIBRARIES set. llvm-svn: 162547
This commit is contained in:
parent
d79d80b4a0
commit
fefc1e989c
|
@ -60,6 +60,7 @@ endif
|
||||||
CLANG_FLAGS=
|
CLANG_FLAGS=
|
||||||
CLANG_VERSION=3.2
|
CLANG_VERSION=3.2
|
||||||
CLANG_BUILD=$(ROOT)/../../../../build/Release+Asserts
|
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_CC=$(CLANG_BUILD)/bin/clang $(CLANG_FLAGS)
|
||||||
CLANG_CXX=$(CLANG_BUILD)/bin/clang++ $(CLANG_FLAGS)
|
CLANG_CXX=$(CLANG_BUILD)/bin/clang++ $(CLANG_FLAGS)
|
||||||
FILE_CHECK=$(CLANG_BUILD)/bin/FileCheck
|
FILE_CHECK=$(CLANG_BUILD)/bin/FileCheck
|
||||||
|
@ -146,7 +147,9 @@ CLANG_ASAN_CXX=$(CLANG_CXX) \
|
||||||
-mllvm -asan-use-after-return=$(ASAN_UAR) \
|
-mllvm -asan-use-after-return=$(ASAN_UAR) \
|
||||||
$(COMMON_ASAN_DEFINES)
|
$(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_PATH=SET_FROM_COMMAND_LINE
|
||||||
GCC_ASAN_CXX=$(GCC_ASAN_PATH)/g++ \
|
GCC_ASAN_CXX=$(GCC_ASAN_PATH)/g++ \
|
||||||
|
|
|
@ -84,6 +84,9 @@ struct Flags {
|
||||||
// By default, disable core dumper on 64-bit - it makes little sense
|
// By default, disable core dumper on 64-bit - it makes little sense
|
||||||
// to dump 16T+ core.
|
// to dump 16T+ core.
|
||||||
bool disable_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.
|
// Strips this prefix from file paths in error reports.
|
||||||
const char *strip_path_prefix;
|
const char *strip_path_prefix;
|
||||||
};
|
};
|
||||||
|
|
|
@ -24,6 +24,7 @@ DECLARE_REAL(char*, strchr, const char *str, int c)
|
||||||
DECLARE_REAL(uptr, strlen, const char *s)
|
DECLARE_REAL(uptr, strlen, const char *s)
|
||||||
DECLARE_REAL(char*, strncpy, char *to, const char *from, uptr size)
|
DECLARE_REAL(char*, strncpy, char *to, const char *from, uptr size)
|
||||||
DECLARE_REAL(uptr, strnlen, const char *s, uptr maxlen)
|
DECLARE_REAL(uptr, strnlen, const char *s, uptr maxlen)
|
||||||
|
DECLARE_REAL(char*, strstr, const char *s1, const char *s2)
|
||||||
struct sigaction;
|
struct sigaction;
|
||||||
DECLARE_REAL(int, sigaction, int signum, const struct sigaction *act,
|
DECLARE_REAL(int, sigaction, int signum, const struct sigaction *act,
|
||||||
struct sigaction *oldact)
|
struct sigaction *oldact)
|
||||||
|
|
|
@ -100,6 +100,7 @@ void *AsanDoesNotSupportStaticLinkage();
|
||||||
|
|
||||||
void GetPcSpBp(void *context, uptr *pc, uptr *sp, uptr *bp);
|
void GetPcSpBp(void *context, uptr *pc, uptr *sp, uptr *bp);
|
||||||
|
|
||||||
|
void MaybeReexec();
|
||||||
bool AsanInterceptsSignal(int signum);
|
bool AsanInterceptsSignal(int signum);
|
||||||
void SetAlternateSignalStack();
|
void SetAlternateSignalStack();
|
||||||
void UnsetAlternateSignalStack();
|
void UnsetAlternateSignalStack();
|
||||||
|
|
|
@ -40,6 +40,10 @@ extern "C" void* _DYNAMIC;
|
||||||
|
|
||||||
namespace __asan {
|
namespace __asan {
|
||||||
|
|
||||||
|
void MaybeReexec() {
|
||||||
|
// No need to re-exec on Linux.
|
||||||
|
}
|
||||||
|
|
||||||
void *AsanDoesNotSupportStaticLinkage() {
|
void *AsanDoesNotSupportStaticLinkage() {
|
||||||
// This will fail to link with -static.
|
// This will fail to link with -static.
|
||||||
return &_DYNAMIC; // defined in link.h
|
return &_DYNAMIC; // defined in link.h
|
||||||
|
|
|
@ -23,7 +23,8 @@
|
||||||
#include "asan_thread_registry.h"
|
#include "asan_thread_registry.h"
|
||||||
#include "sanitizer_common/sanitizer_libc.h"
|
#include "sanitizer_common/sanitizer_libc.h"
|
||||||
|
|
||||||
#include <crt_externs.h> // for _NSGetEnviron
|
#include <crt_externs.h> // for _NSGetArgv
|
||||||
|
#include <dlfcn.h> // for dladdr()
|
||||||
#include <mach-o/dyld.h>
|
#include <mach-o/dyld.h>
|
||||||
#include <mach-o/loader.h>
|
#include <mach-o/loader.h>
|
||||||
#include <sys/mman.h>
|
#include <sys/mman.h>
|
||||||
|
@ -83,6 +84,42 @@ bool PlatformHasDifferentMemcpyAndMemmove() {
|
||||||
return GetMacosVersion() == MACOS_VERSION_SNOW_LEOPARD;
|
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.
|
// No-op. Mac does not support static linkage anyway.
|
||||||
void *AsanDoesNotSupportStaticLinkage() {
|
void *AsanDoesNotSupportStaticLinkage() {
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -101,6 +101,7 @@ static void ParseFlagsFromString(Flags *f, const char *str) {
|
||||||
ParseFlag(str, &f->atexit, "atexit");
|
ParseFlag(str, &f->atexit, "atexit");
|
||||||
ParseFlag(str, &f->disable_core, "disable_core");
|
ParseFlag(str, &f->disable_core, "disable_core");
|
||||||
ParseFlag(str, &f->strip_path_prefix, "strip_path_prefix");
|
ParseFlag(str, &f->strip_path_prefix, "strip_path_prefix");
|
||||||
|
ParseFlag(str, &f->allow_reexec, "allow_reexec");
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
|
@ -137,6 +138,7 @@ void InitializeFlags(Flags *f, const char *env) {
|
||||||
f->atexit = false;
|
f->atexit = false;
|
||||||
f->disable_core = (__WORDSIZE == 64);
|
f->disable_core = (__WORDSIZE == 64);
|
||||||
f->strip_path_prefix = "";
|
f->strip_path_prefix = "";
|
||||||
|
f->allow_reexec = true;
|
||||||
|
|
||||||
// Override from user-specified string.
|
// Override from user-specified string.
|
||||||
ParseFlagsFromString(f, __asan_default_options());
|
ParseFlagsFromString(f, __asan_default_options());
|
||||||
|
@ -293,7 +295,8 @@ void __asan_init() {
|
||||||
// Make sure we are not statically linked.
|
// Make sure we are not statically linked.
|
||||||
AsanDoesNotSupportStaticLinkage();
|
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");
|
const char *options = GetEnv("ASAN_OPTIONS");
|
||||||
InitializeFlags(flags(), options);
|
InitializeFlags(flags(), options);
|
||||||
|
|
||||||
|
@ -301,6 +304,10 @@ void __asan_init() {
|
||||||
Report("Parsed ASAN_OPTIONS: %s\n", options);
|
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) {
|
if (flags()->atexit) {
|
||||||
Atexit(asan_atexit);
|
Atexit(asan_atexit);
|
||||||
}
|
}
|
||||||
|
|
|
@ -153,6 +153,10 @@ void AsanTSDSet(void *tsd) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// ---------------------- Various stuff ---------------- {{{1
|
// ---------------------- Various stuff ---------------- {{{1
|
||||||
|
void MaybeReexec() {
|
||||||
|
// No need to re-exec on Windows.
|
||||||
|
}
|
||||||
|
|
||||||
void *AsanDoesNotSupportStaticLinkage() {
|
void *AsanDoesNotSupportStaticLinkage() {
|
||||||
#if defined(_DEBUG)
|
#if defined(_DEBUG)
|
||||||
#error Please build the runtime with a non-debug CRT: /MD or /MT
|
#error Please build the runtime with a non-debug CRT: /MD or /MT
|
||||||
|
|
Loading…
Reference in New Issue