forked from OSchip/llvm-project
[asan] Add OS X 10.11's new dyld interposition support
On OS X 10.11 (which is currently a public beta), the dynamic linker has been improved so that it doesn't require the use of DYLD_INSERT_LIBRARIES in order for interposition/wrappers to work. This patch adds support of this behavior into ASan – we no longer need to re-exec in case the env. variable is not set. Reviewed at http://reviews.llvm.org/D10924 llvm-svn: 241487
This commit is contained in:
parent
bfa848cfa1
commit
76cc55a94d
|
@ -99,6 +99,23 @@ void DisableReexec() {
|
||||||
reexec_disabled = true;
|
reexec_disabled = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool DyldNeedsEnvVariable() {
|
||||||
|
// If running on OS X 10.11+ or iOS 9.0+, dyld will interpose even if
|
||||||
|
// DYLD_INSERT_LIBRARIES is not set.
|
||||||
|
|
||||||
|
#if SANITIZER_IOSSIM
|
||||||
|
// GetMacosVersion will not work for the simulator, whose kernel version
|
||||||
|
// is tied to the host. Use a weak linking hack for the simulator.
|
||||||
|
// This API was introduced in the same version of the OS as the dyld
|
||||||
|
// optimization.
|
||||||
|
|
||||||
|
// Check for presence of a symbol that is available on OS X 10.11+, iOS 9.0+.
|
||||||
|
return (dlsym(RTLD_NEXT, "mach_memory_info") == nullptr);
|
||||||
|
#else
|
||||||
|
return (GetMacosVersion() <= MACOS_VERSION_YOSEMITE);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
void MaybeReexec() {
|
void MaybeReexec() {
|
||||||
if (reexec_disabled) return;
|
if (reexec_disabled) return;
|
||||||
|
|
||||||
|
@ -114,8 +131,10 @@ void MaybeReexec() {
|
||||||
uptr fname_len = internal_strlen(info.dli_fname);
|
uptr fname_len = internal_strlen(info.dli_fname);
|
||||||
const char *dylib_name = StripModuleName(info.dli_fname);
|
const char *dylib_name = StripModuleName(info.dli_fname);
|
||||||
uptr dylib_name_len = internal_strlen(dylib_name);
|
uptr dylib_name_len = internal_strlen(dylib_name);
|
||||||
if (!dyld_insert_libraries ||
|
|
||||||
!REAL(strstr)(dyld_insert_libraries, dylib_name)) {
|
bool lib_is_in_env =
|
||||||
|
dyld_insert_libraries && REAL(strstr)(dyld_insert_libraries, dylib_name);
|
||||||
|
if (DyldNeedsEnvVariable() && !lib_is_in_env) {
|
||||||
// DYLD_INSERT_LIBRARIES is not set or does not contain the runtime
|
// DYLD_INSERT_LIBRARIES is not set or does not contain the runtime
|
||||||
// library.
|
// library.
|
||||||
char program_name[1024];
|
char program_name[1024];
|
||||||
|
@ -152,6 +171,9 @@ void MaybeReexec() {
|
||||||
CHECK("execv failed" && 0);
|
CHECK("execv failed" && 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!lib_is_in_env)
|
||||||
|
return;
|
||||||
|
|
||||||
// DYLD_INSERT_LIBRARIES is set and contains the runtime library. Let's remove
|
// DYLD_INSERT_LIBRARIES is set and contains the runtime library. Let's remove
|
||||||
// the dylib from the environment variable, because interceptors are installed
|
// the dylib from the environment variable, because interceptors are installed
|
||||||
// and we don't want our children to inherit the variable.
|
// and we don't want our children to inherit the variable.
|
||||||
|
|
|
@ -7,11 +7,25 @@
|
||||||
// RUN: | sed -e 's/.*"\(.*libclang_rt.asan_osx_dynamic.dylib\)".*/\1/'` \
|
// RUN: | sed -e 's/.*"\(.*libclang_rt.asan_osx_dynamic.dylib\)".*/\1/'` \
|
||||||
// RUN: %T/dyld_insert_libraries_reexec/libclang_rt.asan_osx_dynamic.dylib
|
// RUN: %T/dyld_insert_libraries_reexec/libclang_rt.asan_osx_dynamic.dylib
|
||||||
// RUN: %clangxx_asan %s -o %T/dyld_insert_libraries_reexec/a.out
|
// RUN: %clangxx_asan %s -o %T/dyld_insert_libraries_reexec/a.out
|
||||||
|
|
||||||
// RUN: env DYLD_INSERT_LIBRARIES=@executable_path/libclang_rt.asan_osx_dynamic.dylib \
|
// RUN: env DYLD_INSERT_LIBRARIES=@executable_path/libclang_rt.asan_osx_dynamic.dylib \
|
||||||
// RUN: ASAN_OPTIONS=$ASAN_OPTIONS:verbosity=1 %run %T/dyld_insert_libraries_reexec/a.out 2>&1 \
|
// RUN: ASAN_OPTIONS=$ASAN_OPTIONS:verbosity=1 %run %T/dyld_insert_libraries_reexec/a.out 2>&1 \
|
||||||
// RUN: | FileCheck %s
|
// RUN: | FileCheck %s
|
||||||
// RUN: env ASAN_OPTIONS=$ASAN_OPTIONS:verbosity=1 %run %T/dyld_insert_libraries_reexec/a.out 2>&1 \
|
|
||||||
// RUN: | FileCheck --check-prefix=CHECK-NOINSERT %s
|
// RUN: IS_OSX_10_11_OR_HIGHER=$([ `sw_vers -productVersion | cut -d'.' -f2` -lt 11 ]; echo $?)
|
||||||
|
|
||||||
|
// On OS X 10.10 and lower, if the dylib is not DYLD-inserted, ASan will re-exec.
|
||||||
|
// RUN: if [ $IS_OSX_10_11_OR_HIGHER == 0 ]; then \
|
||||||
|
// RUN: env ASAN_OPTIONS=$ASAN_OPTIONS:verbosity=1 %run %T/dyld_insert_libraries_reexec/a.out 2>&1 \
|
||||||
|
// RUN: | FileCheck --check-prefix=CHECK-NOINSERT %s; \
|
||||||
|
// RUN: fi
|
||||||
|
|
||||||
|
// On OS X 10.11 and higher, we don't need to DYLD-insert anymore, and the interceptors
|
||||||
|
// still installed correctly. Let's just check that things work and we don't try to re-exec.
|
||||||
|
// RUN: if [ $IS_OSX_10_11_OR_HIGHER == 1 ]; then \
|
||||||
|
// RUN: env ASAN_OPTIONS=$ASAN_OPTIONS:verbosity=1 %run %T/dyld_insert_libraries_reexec/a.out 2>&1 \
|
||||||
|
// RUN: | FileCheck %s; \
|
||||||
|
// RUN: fi
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue