From fb8112c05bb43dda18c3a2743117355d26ba695e Mon Sep 17 00:00:00 2001 From: Hal Finkel Date: Fri, 23 Oct 2015 20:37:51 +0000 Subject: [PATCH 01/68] Fixup test/ubsan/TestCases/Misc/coverage-levels.cc, LLVM is smarter Fixing up this test case because LLVM is smarter now, and can better analyze: if ((argc << shift) == 16) in this test case. git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/trunk@251147 91177308-0d34-0410-b5e6-96231b3b80d8 --- test/ubsan/TestCases/Misc/coverage-levels.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/ubsan/TestCases/Misc/coverage-levels.cc b/test/ubsan/TestCases/Misc/coverage-levels.cc index 9e3a8b31c5..046d8868e4 100644 --- a/test/ubsan/TestCases/Misc/coverage-levels.cc +++ b/test/ubsan/TestCases/Misc/coverage-levels.cc @@ -38,4 +38,4 @@ int main(int argc, char **argv) { // to dump coverage. // CHECK1: 1 PCs written // CHECK2: 3 PCs written -// CHECK3: 4 PCs written +// CHECK3: 3 PCs written From d1165cd1d46bdbab405e82c84248908bf61f0648 Mon Sep 17 00:00:00 2001 From: Adhemerval Zanella Date: Mon, 26 Oct 2015 18:15:14 +0000 Subject: [PATCH 02/68] [compiler-rt] Enable ptrace sanitizer for arm This patch enables the ptrace syscall interceptors for arm and adds support for both PTRACE_GETVFPREGS and PTRACE_SETVFPREGS used to get the VFP register from ARM. The ptrace tests is also updated with arm and PTRACE_GETVFPREGS tests. git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/trunk@251321 91177308-0d34-0410-b5e6-96231b3b80d8 --- .../sanitizer_common_interceptors.inc | 4 +++ .../sanitizer_platform_interceptors.h | 2 +- .../sanitizer_platform_limits_posix.cc | 25 +++++++++++++++---- .../sanitizer_platform_limits_posix.h | 5 +++- .../TestCases/Linux/ptrace.cc | 19 +++++++++++--- 5 files changed, 44 insertions(+), 11 deletions(-) diff --git a/lib/sanitizer_common/sanitizer_common_interceptors.inc b/lib/sanitizer_common/sanitizer_common_interceptors.inc index 26fb916e68..20eb4b56cc 100644 --- a/lib/sanitizer_common/sanitizer_common_interceptors.inc +++ b/lib/sanitizer_common/sanitizer_common_interceptors.inc @@ -2454,6 +2454,8 @@ INTERCEPTOR(uptr, ptrace, int request, int pid, void *addr, void *data) { COMMON_INTERCEPTOR_READ_RANGE(ctx, data, struct_user_fpregs_struct_sz); else if (request == ptrace_setfpxregs) COMMON_INTERCEPTOR_READ_RANGE(ctx, data, struct_user_fpxregs_struct_sz); + else if (request == ptrace_setvfpregs) + COMMON_INTERCEPTOR_READ_RANGE(ctx, data, struct_user_vfpregs_struct_sz); else if (request == ptrace_setsiginfo) COMMON_INTERCEPTOR_READ_RANGE(ctx, data, siginfo_t_sz); else if (request == ptrace_setregset) { @@ -2476,6 +2478,8 @@ INTERCEPTOR(uptr, ptrace, int request, int pid, void *addr, void *data) { COMMON_INTERCEPTOR_WRITE_RANGE(ctx, data, struct_user_fpregs_struct_sz); else if (request == ptrace_getfpxregs) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, data, struct_user_fpxregs_struct_sz); + else if (request == ptrace_getvfpregs) + COMMON_INTERCEPTOR_WRITE_RANGE(ctx, data, struct_user_vfpregs_struct_sz); else if (request == ptrace_getsiginfo) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, data, siginfo_t_sz); else if (request == ptrace_geteventmsg) diff --git a/lib/sanitizer_common/sanitizer_platform_interceptors.h b/lib/sanitizer_common/sanitizer_platform_interceptors.h index 03dba853b1..a96941b578 100644 --- a/lib/sanitizer_common/sanitizer_platform_interceptors.h +++ b/lib/sanitizer_common/sanitizer_platform_interceptors.h @@ -133,7 +133,7 @@ #define SANITIZER_INTERCEPT_READDIR64 SI_LINUX_NOT_ANDROID #define SANITIZER_INTERCEPT_PTRACE SI_LINUX_NOT_ANDROID && \ (defined(__i386) || defined(__x86_64) || defined(__mips64) || \ - defined(__powerpc64__) || defined(__aarch64__)) + defined(__powerpc64__) || defined(__aarch64__) || defined(__arm__)) #define SANITIZER_INTERCEPT_SETLOCALE SI_NOT_WINDOWS #define SANITIZER_INTERCEPT_GETCWD SI_NOT_WINDOWS #define SANITIZER_INTERCEPT_GET_CURRENT_DIR_NAME SI_LINUX_NOT_ANDROID diff --git a/lib/sanitizer_common/sanitizer_platform_limits_posix.cc b/lib/sanitizer_common/sanitizer_platform_limits_posix.cc index 9cfaec5cc8..7aebc9c00b 100644 --- a/lib/sanitizer_common/sanitizer_platform_limits_posix.cc +++ b/lib/sanitizer_common/sanitizer_platform_limits_posix.cc @@ -119,8 +119,11 @@ #if SANITIZER_LINUX || SANITIZER_FREEBSD # include # include -# if defined(__mips64) || defined(__aarch64__) +# if defined(__mips64) || defined(__aarch64__) || defined(__arm__) # include +# ifdef __arm__ +typedef struct user_fpregs elf_fpregset_t; +# endif # endif # include #endif @@ -304,8 +307,8 @@ unsigned struct_ElfW_Phdr_sz = sizeof(Elf_Phdr); #if SANITIZER_LINUX && !SANITIZER_ANDROID && \ (defined(__i386) || defined(__x86_64) || defined(__mips64) || \ - defined(__powerpc64__) || defined(__aarch64__)) -#if defined(__mips64) || defined(__powerpc64__) + defined(__powerpc64__) || defined(__aarch64__) || defined(__arm__)) +#if defined(__mips64) || defined(__powerpc64__) || defined(__arm__) unsigned struct_user_regs_struct_sz = sizeof(struct pt_regs); unsigned struct_user_fpregs_struct_sz = sizeof(elf_fpregset_t); #elif defined(__aarch64__) @@ -316,11 +319,16 @@ unsigned struct_ElfW_Phdr_sz = sizeof(Elf_Phdr); unsigned struct_user_fpregs_struct_sz = sizeof(struct user_fpregs_struct); #endif // __mips64 || __powerpc64__ || __aarch64__ #if defined(__x86_64) || defined(__mips64) || defined(__powerpc64__) || \ - defined(__aarch64__) + defined(__aarch64__) || defined(__arm__) unsigned struct_user_fpxregs_struct_sz = 0; #else unsigned struct_user_fpxregs_struct_sz = sizeof(struct user_fpxregs_struct); -#endif // __x86_64 || __mips64 || __powerpc64__ || __aarch64__ +#endif // __x86_64 || __mips64 || __powerpc64__ || __aarch64__ || __arm__ +#ifdef __arm__ + unsigned struct_user_vfpregs_struct_sz = ARM_VFPREGS_SIZE; +#else + unsigned struct_user_vfpregs_struct_sz = 0; +#endif int ptrace_peektext = PTRACE_PEEKTEXT; int ptrace_peekdata = PTRACE_PEEKDATA; @@ -346,6 +354,13 @@ unsigned struct_ElfW_Phdr_sz = sizeof(Elf_Phdr); int ptrace_getfpxregs = -1; int ptrace_setfpxregs = -1; #endif // PTRACE_GETFPXREGS/PTRACE_SETFPXREGS +#if defined(PTRACE_GETVFPREGS) && defined(PTRACE_SETVFPREGS) + int ptrace_getvfpregs = PTRACE_GETVFPREGS; + int ptrace_setvfpregs = PTRACE_SETVFPREGS; +#else + int ptrace_getvfpregs = -1; + int ptrace_setvfpregs = -1; +#endif int ptrace_geteventmsg = PTRACE_GETEVENTMSG; #if (defined(PTRACE_GETSIGINFO) && defined(PTRACE_SETSIGINFO)) || \ (defined(PT_GETSIGINFO) && defined(PT_SETSIGINFO)) diff --git a/lib/sanitizer_common/sanitizer_platform_limits_posix.h b/lib/sanitizer_common/sanitizer_platform_limits_posix.h index c598fe0d71..2978e7b9ce 100644 --- a/lib/sanitizer_common/sanitizer_platform_limits_posix.h +++ b/lib/sanitizer_common/sanitizer_platform_limits_posix.h @@ -736,10 +736,11 @@ namespace __sanitizer { #if SANITIZER_LINUX && !SANITIZER_ANDROID && \ (defined(__i386) || defined(__x86_64) || defined(__mips64) || \ - defined(__powerpc64__) || defined(__aarch64__)) + defined(__powerpc64__) || defined(__aarch64__) || defined(__arm__)) extern unsigned struct_user_regs_struct_sz; extern unsigned struct_user_fpregs_struct_sz; extern unsigned struct_user_fpxregs_struct_sz; + extern unsigned struct_user_vfpregs_struct_sz; extern int ptrace_peektext; extern int ptrace_peekdata; @@ -750,6 +751,8 @@ namespace __sanitizer { extern int ptrace_setfpregs; extern int ptrace_getfpxregs; extern int ptrace_setfpxregs; + extern int ptrace_getvfpregs; + extern int ptrace_setvfpregs; extern int ptrace_getsiginfo; extern int ptrace_setsiginfo; extern int ptrace_getregset; diff --git a/test/sanitizer_common/TestCases/Linux/ptrace.cc b/test/sanitizer_common/TestCases/Linux/ptrace.cc index 561446620a..67b6474304 100644 --- a/test/sanitizer_common/TestCases/Linux/ptrace.cc +++ b/test/sanitizer_common/TestCases/Linux/ptrace.cc @@ -10,7 +10,7 @@ #include #include #include -#if __mips64 +#if __mips64 || __arm__ #include #include #endif @@ -43,23 +43,34 @@ int main(void) { printf("%x\n", fpregs.mxcsr); #endif // __x86_64__ -#if (__powerpc64__ || __mips64) +#if (__powerpc64__ || __mips64 || __arm__) struct pt_regs regs; res = ptrace((enum __ptrace_request)PTRACE_GETREGS, pid, NULL, ®s); assert(!res); #if (__powerpc64__) if (regs.nip) printf("%lx\n", regs.nip); -#else +#elif (__mips64) if (regs.cp0_epc) printf("%lx\n", regs.cp0_epc); +#elif (__arm__) + if (regs.ARM_pc) + printf("%lx\n", regs.ARM_pc); #endif +#if (__powerpc64 || __mips64) elf_fpregset_t fpregs; res = ptrace((enum __ptrace_request)PTRACE_GETFPREGS, pid, NULL, &fpregs); assert(!res); if ((elf_greg_t)fpregs[32]) // fpscr printf("%lx\n", (elf_greg_t)fpregs[32]); -#endif // (__powerpc64__ || __mips64) +#elif (__arm__) + char regbuf[ARM_VFPREGS_SIZE]; + res = ptrace((enum __ptrace_request)PTRACE_GETVFPREGS, pid, 0, regbuf); + assert(!res); + unsigned fpscr = *(unsigned*)(regbuf + (32 * 8)); + printf ("%x\n", fpscr); +#endif +#endif // (__powerpc64__ || __mips64 || __arm__) #if (__aarch64__) struct iovec regset_io; From 80f1d254b31f2c607e0f02f9d79a6687207b871e Mon Sep 17 00:00:00 2001 From: Adhemerval Zanella Date: Mon, 26 Oct 2015 18:55:04 +0000 Subject: [PATCH 03/68] [compiler-rt] Fix ptrace interceptor for aarch64 This patch fixes the ptrace interceptor for aarch64. The PTRACE_GETREGSET ptrace syscall with with invalid memory might zero the iovec::iov_base field and then masking the subsequent check after the syscall (since it will be 0 and it will not trigger an invalid access). The fix is to copy the value on a local variable and use its value on the checks. The patch also adds more coverage on the Linux/ptrace.cc testcase by addding check for PTRACE_GETREGSET for both general and floating registers (aarch64 definitions added only). git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/trunk@251331 91177308-0d34-0410-b5e6-96231b3b80d8 --- .../sanitizer_common_interceptors.inc | 19 +++- test/asan/TestCases/Linux/ptrace.cc | 92 ++++++++++++++++--- 2 files changed, 94 insertions(+), 17 deletions(-) diff --git a/lib/sanitizer_common/sanitizer_common_interceptors.inc b/lib/sanitizer_common/sanitizer_common_interceptors.inc index 20eb4b56cc..6d99b5100f 100644 --- a/lib/sanitizer_common/sanitizer_common_interceptors.inc +++ b/lib/sanitizer_common/sanitizer_common_interceptors.inc @@ -2446,6 +2446,7 @@ INTERCEPTOR(int, readdir64_r, void *dirp, __sanitizer_dirent64 *entry, INTERCEPTOR(uptr, ptrace, int request, int pid, void *addr, void *data) { void *ctx; COMMON_INTERCEPTOR_ENTER(ctx, ptrace, request, pid, addr, data); + __sanitizer_iovec local_iovec; if (data) { if (request == ptrace_setregs) @@ -2458,9 +2459,15 @@ INTERCEPTOR(uptr, ptrace, int request, int pid, void *addr, void *data) { COMMON_INTERCEPTOR_READ_RANGE(ctx, data, struct_user_vfpregs_struct_sz); else if (request == ptrace_setsiginfo) COMMON_INTERCEPTOR_READ_RANGE(ctx, data, siginfo_t_sz); - else if (request == ptrace_setregset) { - __sanitizer_iovec *iov = (__sanitizer_iovec *)data; - COMMON_INTERCEPTOR_READ_RANGE(ctx, iov->iov_base, iov->iov_len); + // Some kernel might zero the iovec::iov_base in case of invalid + // write access. In this case copy the invalid address for further + // inspection. + else if (request == ptrace_setregset || request == ptrace_getregset) { + __sanitizer_iovec *iovec = (__sanitizer_iovec*)data; + COMMON_INTERCEPTOR_READ_RANGE(ctx, iovec, sizeof(*iovec)); + local_iovec = *iovec; + if (request == ptrace_setregset) + COMMON_INTERCEPTOR_READ_RANGE(ctx, iovec->iov_base, iovec->iov_len); } } @@ -2485,8 +2492,10 @@ INTERCEPTOR(uptr, ptrace, int request, int pid, void *addr, void *data) { else if (request == ptrace_geteventmsg) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, data, sizeof(unsigned long)); else if (request == ptrace_getregset) { - __sanitizer_iovec *iov = (__sanitizer_iovec *)data; - COMMON_INTERCEPTOR_WRITE_RANGE(ctx, iov->iov_base, iov->iov_len); + __sanitizer_iovec *iovec = (__sanitizer_iovec*)data; + COMMON_INTERCEPTOR_WRITE_RANGE(ctx, iovec, sizeof(*iovec)); + COMMON_INTERCEPTOR_WRITE_RANGE(ctx, local_iovec.iov_base, + local_iovec.iov_len); } } return res; diff --git a/test/asan/TestCases/Linux/ptrace.cc b/test/asan/TestCases/Linux/ptrace.cc index 6840ebe28b..99a25d0bfe 100644 --- a/test/asan/TestCases/Linux/ptrace.cc +++ b/test/asan/TestCases/Linux/ptrace.cc @@ -3,7 +3,6 @@ // // RUN: %clangxx_asan -O0 %s -o %t && %run %t // RUN: %clangxx_asan -DPOSITIVE -O0 %s -o %t && not %run %t 2>&1 | FileCheck %s -// REQUIRES: x86_64-supported-target,i386-supported-target #include #include @@ -12,6 +11,55 @@ #include #include #include +#include // for iovec +#include // for NT_PRSTATUS +#ifdef __aarch64__ +# include +#endif + +#if defined(__i386__) || defined(__x86_64__) +typedef user_regs_struct regs_struct; +typedef user_fpregs_struct fpregs_struct; +#if defined(__i386__) +#define REG_IP eip +#else +#define REG_IP rip +#endif +#define PRINT_REG_PC(__regs) printf ("%lx\n", (unsigned long) (__regs.REG_IP)) +#define PRINT_REG_FP(__fpregs) printf ("%lx\n", (unsigned long) (__fpregs.cwd)) +#define __PTRACE_FPREQUEST PTRACE_GETFPREGS + +#elif defined(__aarch64__) +typedef struct user_pt_regs regs_struct; +typedef struct user_fpsimd_state fpregs_struct; +#define PRINT_REG_PC(__regs) printf ("%x\n", (unsigned) (__regs.pc)) +#define PRINT_REG_FP(__fpregs) printf ("%x\n", (unsigned) (__fpregs.fpsr)) +#define ARCH_IOVEC_FOR_GETREGSET + +#elif defined(__powerpc64__) +typedef struct pt_regs regs_struct; +typedef elf_fpregset_t fpregs_struct; +#define PRINT_REG_PC(__regs) printf ("%lx\n", (unsigned long) (__regs.nip)) +#define PRINT_REG_FP(__fpregs) printf ("%lx\n", (elf_greg_t)fpregs[32]) +#define ARCH_IOVEC_FOR_GETREGSET + +#elif defined(__mips64) +typedef struct pt_regs regs_struct; +typedef elf_fpregset_t fpregs_struct; +#define PRINT_REG_PC(__regs) printf ("%lx\n", (unsigned long) (__regs.cp0_epc)) +#define PRINT_REG_FP(__fpregs) printf ("%lx\n", (elf_greg_t) (__fpregs[32])) +#define __PTRACE_FPREQUEST PTRACE_GETFPREGS + +#elif defined(__arm__) +# include +# include +typedef struct pt_regs regs_struct; +typedef char fpregs_struct[ARM_VFPREGS_SIZE]; +#define PRINT_REG_PC(__regs) printf ("%x\n", (unsigned) (__regs.ARM_pc)) +#define PRINT_REG_FP(__fpregs) printf ("%x\n", (unsigned) (__fpregs + 32 * 8)) +#define __PTRACE_FPREQUEST PTRACE_GETVFPREGS +#endif + int main(void) { pid_t pid; @@ -21,28 +69,48 @@ int main(void) { execl("/bin/true", "true", NULL); } else { wait(NULL); - user_regs_struct regs; + regs_struct regs; + regs_struct* volatile pregs = ®s; +#ifdef ARCH_IOVEC_FOR_GETREGSET + struct iovec regset_io; +#endif int res; - user_regs_struct * volatile pregs = ®s; + #ifdef POSITIVE ++pregs; #endif - res = ptrace(PTRACE_GETREGS, pid, NULL, pregs); + +#ifdef ARCH_IOVEC_FOR_GETREGSET +# define __PTRACE_REQUEST PTRACE_GETREGSET +# define __PTRACE_ARGS (void*)NT_PRSTATUS, (void*)®set_io + regset_io.iov_base = pregs; + regset_io.iov_len = sizeof(regs_struct); +#else +# define __PTRACE_REQUEST PTRACE_GETREGS +# define __PTRACE_ARGS NULL, pregs +#endif + res = ptrace((enum __ptrace_request)__PTRACE_REQUEST, pid, __PTRACE_ARGS); // CHECK: AddressSanitizer: stack-buffer-overflow // CHECK: {{.*ptrace.cc:}}[[@LINE-2]] assert(!res); -#ifdef __x86_64__ - printf("%lx\n", (unsigned long)regs.rip); + PRINT_REG_PC(regs); + + fpregs_struct fpregs; +#ifdef ARCH_IOVEC_FOR_GETREGSET +# define __PTRACE_FPREQUEST PTRACE_GETREGSET +# define __PTRACE_FPARGS (void*)NT_PRSTATUS, (void*)®set_io + regset_io.iov_base = &fpregs; + regset_io.iov_len = sizeof(fpregs_struct); + res = ptrace((enum __ptrace_request)PTRACE_GETREGSET, pid, (void*)NT_FPREGSET, + (void*)®set_io); #else - printf("%lx\n", regs.eip); +# define __PTRACE_FPARGS NULL, &fpregs #endif - - user_fpregs_struct fpregs; - res = ptrace(PTRACE_GETFPREGS, pid, NULL, &fpregs); + res = ptrace((enum __ptrace_request)__PTRACE_FPREQUEST, pid, __PTRACE_FPARGS); assert(!res); - printf("%lx\n", (unsigned long)fpregs.cwd); + PRINT_REG_FP(fpregs); -#ifndef __x86_64__ +#ifdef __i386__ user_fpxregs_struct fpxregs; res = ptrace(PTRACE_GETFPXREGS, pid, NULL, &fpxregs); assert(!res); From 303dfb2aa76d4851c72cc30e5997f3c77f3b67c3 Mon Sep 17 00:00:00 2001 From: Evgeniy Stepanov Date: Mon, 26 Oct 2015 20:55:35 +0000 Subject: [PATCH 04/68] [msan] Fix process_vm_readv test. The check for the glibc version was not working as expected (dlsym was finding the interceptor instead of the libc implementation). git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/trunk@251345 91177308-0d34-0410-b5e6-96231b3b80d8 --- test/msan/Linux/process_vm_readv.cc | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/test/msan/Linux/process_vm_readv.cc b/test/msan/Linux/process_vm_readv.cc index c52b5d0eda..29dc95dccc 100644 --- a/test/msan/Linux/process_vm_readv.cc +++ b/test/msan/Linux/process_vm_readv.cc @@ -10,18 +10,15 @@ #include #include -typedef ssize_t (*process_vm_readwritev_fn)(pid_t, const iovec *, unsigned long, +typedef ssize_t (*process_vm_readv_fn)(pid_t, const iovec *, unsigned long, const iovec *, unsigned long, unsigned long); int main(void) { // This requires glibc 2.15. - process_vm_readwritev_fn process_vm_readv = - (process_vm_readwritev_fn)dlsym(RTLD_DEFAULT, "process_vm_readv"); - process_vm_readwritev_fn process_vm_writev = - (process_vm_readwritev_fn)dlsym(RTLD_DEFAULT, "process_vm_writev"); - if (!process_vm_readv) { - assert(!process_vm_writev); + process_vm_readv_fn libc_process_vm_readv = + (process_vm_readv_fn)dlsym(RTLD_NEXT, "process_vm_readv"); + if (!libc_process_vm_readv) { // Exit with success, emulating the expected output. #ifdef POSITIVE printf("process_vm_readv not found!\n"); @@ -32,7 +29,6 @@ int main(void) { return 0; #endif } - assert(process_vm_readv && process_vm_writev); char a[100]; memset(a, 0xab, 100); From be4b740a008d2555891a752256737bfec20b6f57 Mon Sep 17 00:00:00 2001 From: Alexey Samsonov Date: Mon, 26 Oct 2015 21:48:49 +0000 Subject: [PATCH 05/68] asan_symbolize.py: Call llvm-symbolizer with --functions=linkage instead of --functions=short. git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/trunk@251356 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/asan/scripts/asan_symbolize.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/asan/scripts/asan_symbolize.py b/lib/asan/scripts/asan_symbolize.py index 5b519e3acd..e6d43cd3f4 100755 --- a/lib/asan/scripts/asan_symbolize.py +++ b/lib/asan/scripts/asan_symbolize.py @@ -77,7 +77,7 @@ def open_llvm_symbolizer(self): cmd = [self.symbolizer_path, '--use-symbol-table=true', '--demangle=%s' % demangle, - '--functions=short', + '--functions=linkage', '--inlining=true', '--default-arch=%s' % self.default_arch] if self.system == 'Darwin': From 1e49033911cf973be2a1362a8f555b3a77a65410 Mon Sep 17 00:00:00 2001 From: Evgeniy Stepanov Date: Mon, 26 Oct 2015 22:19:44 +0000 Subject: [PATCH 06/68] [asan] Don't use asanwrapper in 64-bit android tests. Asanwrapper is required on older android versions to work around undesired linker behavior. It is not required on L and newer, and does not fully support multiarch devices. git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/trunk@251359 91177308-0d34-0410-b5e6-96231b3b80d8 --- test/asan/android_commands/android_run.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/asan/android_commands/android_run.py b/test/asan/android_commands/android_run.py index 6bda6e96d2..272d2110e5 100755 --- a/test/asan/android_commands/android_run.py +++ b/test/asan/android_commands/android_run.py @@ -19,14 +19,14 @@ def build_env(): return ' '.join(args) is_64bit = (subprocess.check_output(['file', sys.argv[0] + '.real']).find('64-bit') != -1) -asanwrapper = "asanwrapper64" if is_64bit else "asanwrapper" +asanwrapper = "" if is_64bit else "asanwrapper " device_env = build_env() device_args = ' '.join(sys.argv[1:]) # FIXME: escape? device_stdout = device_binary + '.stdout' device_stderr = device_binary + '.stderr' device_exitcode = device_binary + '.exitcode' -ret = adb(['shell', 'cd %s && %s %s %s %s >%s 2>%s ; echo $? >%s' % +ret = adb(['shell', 'cd %s && %s %s%s %s >%s 2>%s ; echo $? >%s' % (ANDROID_TMPDIR, device_env, asanwrapper, device_binary, device_args, device_stdout, device_stderr, device_exitcode)]) if ret != 0: From cfdab24ba88b09efd9cf4f968fdc961e3135a0eb Mon Sep 17 00:00:00 2001 From: Evgeniy Stepanov Date: Mon, 26 Oct 2015 22:19:46 +0000 Subject: [PATCH 07/68] [asan] Switch back to BFD linker in asan/android tests. We've switched to Gold earlier because of a minor misconfiguration of the BFD linker in Android NDK. It turns out, Gold has much bigger problems: https://sourceware.org/bugzilla/show_bug.cgi?id=19163 (a bug is actually in the android runtime loader, but it means that gold does not work with android L and even M). Switching back to BFD and adding a workaround by explicitly linking libm to all tests. git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/trunk@251360 91177308-0d34-0410-b5e6-96231b3b80d8 --- test/asan/lit.cfg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/asan/lit.cfg b/test/asan/lit.cfg index e3e86bddbc..fd99f66996 100644 --- a/test/asan/lit.cfg +++ b/test/asan/lit.cfg @@ -60,7 +60,7 @@ else: # BFD linker in 64-bit android toolchains fails to find libm.so, which is a # transitive shared library dependency (via asan runtime). if config.android: - extra_linkflags += ["-fuse-ld=gold"] + extra_linkflags += ["-lm"] # Setup default compiler flags used with -fsanitize=address option. # FIXME: Review the set of required flags and check if it can be reduced. From 0aea26272a7966a9f4ddf314f7cf1c76e431ee40 Mon Sep 17 00:00:00 2001 From: Evgeniy Stepanov Date: Mon, 26 Oct 2015 22:19:47 +0000 Subject: [PATCH 08/68] [asan] Fix throw-call-test to properly XFAIL on android/aarch64. The test is sensitive to stack layout changes. Tweak it a bit to expose the bug on aarch64 as well as on arm. git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/trunk@251361 91177308-0d34-0410-b5e6-96231b3b80d8 --- test/asan/TestCases/throw_call_test.cc | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/test/asan/TestCases/throw_call_test.cc b/test/asan/TestCases/throw_call_test.cc index 20e9a5ee56..4b3910dce1 100644 --- a/test/asan/TestCases/throw_call_test.cc +++ b/test/asan/TestCases/throw_call_test.cc @@ -23,12 +23,15 @@ void ReallyThrow() { __attribute__((noinline)) void Throw() { - int a, b, c, d, e; + int a, b, c, d, e, f, g, h; pretend_to_do_something(&a); pretend_to_do_something(&b); pretend_to_do_something(&c); pretend_to_do_something(&d); pretend_to_do_something(&e); + pretend_to_do_something(&f); + pretend_to_do_something(&g); + pretend_to_do_something(&h); fprintf(stderr, "Throw stack = %p\n", &a); ReallyThrow(); } @@ -37,9 +40,9 @@ __attribute__((noinline)) void CheckStack() { int ar[100]; pretend_to_do_something(ar); + fprintf(stderr, "CheckStack stack = %p, %p\n", ar, ar + 100); for (int i = 0; i < 100; i++) ar[i] = i; - fprintf(stderr, "CheckStack stack = %p, %p\n", ar, ar + 100); } int main(int argc, char** argv) { From db03c085a1d2ea5b9a5bc84665c95582b324b0ca Mon Sep 17 00:00:00 2001 From: Evgeniy Stepanov Date: Mon, 26 Oct 2015 22:19:50 +0000 Subject: [PATCH 09/68] [asan] Mark 5 tests unsupported on Android. git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/trunk@251362 91177308-0d34-0410-b5e6-96231b3b80d8 --- test/asan/TestCases/Linux/stress_dtls.c | 1 + test/asan/TestCases/Posix/coverage-caller-callee.cc | 1 + test/asan/TestCases/coverage-levels.cc | 2 +- test/asan/TestCases/coverage-order-pcs.cc | 1 + test/asan/TestCases/coverage-tracing.cc | 1 + 5 files changed, 5 insertions(+), 1 deletion(-) diff --git a/test/asan/TestCases/Linux/stress_dtls.c b/test/asan/TestCases/Linux/stress_dtls.c index bbf4b3e0ef..fd1ce0cd47 100644 --- a/test/asan/TestCases/Linux/stress_dtls.c +++ b/test/asan/TestCases/Linux/stress_dtls.c @@ -1,4 +1,5 @@ // REQUIRES: asan-64-bits +// UNSUPPORTED: android // Stress test dynamic TLS + dlopen + threads. // // Note that glibc 2.15 seems utterly broken on this test, diff --git a/test/asan/TestCases/Posix/coverage-caller-callee.cc b/test/asan/TestCases/Posix/coverage-caller-callee.cc index 99cce23c3d..fb8b9bf92a 100644 --- a/test/asan/TestCases/Posix/coverage-caller-callee.cc +++ b/test/asan/TestCases/Posix/coverage-caller-callee.cc @@ -11,6 +11,7 @@ // RUN: rm -f caller-callee*.sancov // // REQUIRES: asan-64-bits +// UNSUPPORTED: android // // CHECK-10-1: CovDump: 10 caller-callee pairs written // CHECK-9-2: CovDump: 18 caller-callee pairs written diff --git a/test/asan/TestCases/coverage-levels.cc b/test/asan/TestCases/coverage-levels.cc index effc9cdbd9..612bbd8377 100644 --- a/test/asan/TestCases/coverage-levels.cc +++ b/test/asan/TestCases/coverage-levels.cc @@ -16,7 +16,7 @@ // RUN: %env_asan_opts=coverage=1:coverage_pcs=0:verbosity=1 %run %t 2>&1 | FileCheck %s --check-prefix=CHECK3_NOPCS // // REQUIRES: asan-64-bits - +// UNSUPPORTED: android volatile int sink; int main(int argc, char **argv) { if (argc == 0) diff --git a/test/asan/TestCases/coverage-order-pcs.cc b/test/asan/TestCases/coverage-order-pcs.cc index 4f148d8547..dcab69474a 100644 --- a/test/asan/TestCases/coverage-order-pcs.cc +++ b/test/asan/TestCases/coverage-order-pcs.cc @@ -20,6 +20,7 @@ // RUN: rm -rf $DIR // Ordering works only in 64-bit mode for now. // REQUIRES: asan-64-bits +// UNSUPPORTED: android #include void foo() { fprintf(stderr, "FOO\n"); } diff --git a/test/asan/TestCases/coverage-tracing.cc b/test/asan/TestCases/coverage-tracing.cc index b4b68a064f..b7755f847d 100644 --- a/test/asan/TestCases/coverage-tracing.cc +++ b/test/asan/TestCases/coverage-tracing.cc @@ -25,6 +25,7 @@ // RUN: rm -rf %T/coverage-tracing // // REQUIRES: asan-64-bits +// UNSUPPORTED: android #include volatile int sink; From 9a9266f68fdc99e8e906b6b0a725a9d726c16fcd Mon Sep 17 00:00:00 2001 From: Evgeniy Stepanov Date: Tue, 27 Oct 2015 00:11:28 +0000 Subject: [PATCH 10/68] [msan] Yet another attempt to fix process_vm_readv test. git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/trunk@251372 91177308-0d34-0410-b5e6-96231b3b80d8 --- test/msan/Linux/process_vm_readv.cc | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/test/msan/Linux/process_vm_readv.cc b/test/msan/Linux/process_vm_readv.cc index 29dc95dccc..601c0d247d 100644 --- a/test/msan/Linux/process_vm_readv.cc +++ b/test/msan/Linux/process_vm_readv.cc @@ -10,14 +10,14 @@ #include #include -typedef ssize_t (*process_vm_readv_fn)(pid_t, const iovec *, unsigned long, +typedef ssize_t (*process_vm_readwritev_fn)(pid_t, const iovec *, unsigned long, const iovec *, unsigned long, unsigned long); int main(void) { // This requires glibc 2.15. - process_vm_readv_fn libc_process_vm_readv = - (process_vm_readv_fn)dlsym(RTLD_NEXT, "process_vm_readv"); + process_vm_readwritev_fn libc_process_vm_readv = + (process_vm_readwritev_fn)dlsym(RTLD_NEXT, "process_vm_readv"); if (!libc_process_vm_readv) { // Exit with success, emulating the expected output. #ifdef POSITIVE @@ -30,6 +30,11 @@ int main(void) { #endif } + process_vm_readwritev_fn process_vm_readv = + (process_vm_readwritev_fn)dlsym(RTLD_DEFAULT, "process_vm_readv"); + process_vm_readwritev_fn process_vm_writev = + (process_vm_readwritev_fn)dlsym(RTLD_DEFAULT, "process_vm_writev"); + char a[100]; memset(a, 0xab, 100); From 3b26b21edb329fc2abdbe6768f2d7c947203362b Mon Sep 17 00:00:00 2001 From: Daniel Sanders Date: Tue, 27 Oct 2015 01:35:57 +0000 Subject: [PATCH 11/68] Attempt to fix asan's ptrace.cc on the clang-cmake-mips builder after r251331. git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/trunk@251379 91177308-0d34-0410-b5e6-96231b3b80d8 --- test/asan/TestCases/Linux/ptrace.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/asan/TestCases/Linux/ptrace.cc b/test/asan/TestCases/Linux/ptrace.cc index 99a25d0bfe..b222849b9a 100644 --- a/test/asan/TestCases/Linux/ptrace.cc +++ b/test/asan/TestCases/Linux/ptrace.cc @@ -43,7 +43,7 @@ typedef elf_fpregset_t fpregs_struct; #define PRINT_REG_FP(__fpregs) printf ("%lx\n", (elf_greg_t)fpregs[32]) #define ARCH_IOVEC_FOR_GETREGSET -#elif defined(__mips64) +#elif defined(__mips__) typedef struct pt_regs regs_struct; typedef elf_fpregset_t fpregs_struct; #define PRINT_REG_PC(__regs) printf ("%lx\n", (unsigned long) (__regs.cp0_epc)) From fcec98e04490399a3f60dbb97a5d7ce902ff89f0 Mon Sep 17 00:00:00 2001 From: Anna Zaks Date: Tue, 27 Oct 2015 20:12:53 +0000 Subject: [PATCH 12/68] [asan] On OS X, tag mapped regions with VM_MEMORY_ANALYSIS_TOOL tag This will tag all mmapped memory sanitizers use with "Performance tool data" when viewed in vmmap. (Even though sanitizers are not performance tools, it's the best available match and better than having the unidentified objects.) http://reviews.llvm.org/D13609 git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/trunk@251445 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/sanitizer_common/sanitizer_mac.cc | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/sanitizer_common/sanitizer_mac.cc b/lib/sanitizer_common/sanitizer_mac.cc index d448ddaba6..3151cf8b91 100644 --- a/lib/sanitizer_common/sanitizer_mac.cc +++ b/lib/sanitizer_common/sanitizer_mac.cc @@ -41,6 +41,7 @@ extern char **environ; #include #include #include +#include #include #include #include @@ -59,6 +60,7 @@ namespace __sanitizer { // ---------------------- sanitizer_libc.h uptr internal_mmap(void *addr, size_t length, int prot, int flags, int fd, u64 offset) { + if (fd == -1) fd = VM_MAKE_TAG(VM_MEMORY_ANALYSIS_TOOL); return (uptr)mmap(addr, length, prot, flags, fd, offset); } From 6f70a3cc0c15a83bc45af7134283ab3687ef52f2 Mon Sep 17 00:00:00 2001 From: Anna Zaks Date: Tue, 27 Oct 2015 20:12:55 +0000 Subject: [PATCH 13/68] [asan] Sort headers. git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/trunk@251446 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/asan/asan_mac.cc | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/asan/asan_mac.cc b/lib/asan/asan_mac.cc index 0f0f9bb087..8e23c71be5 100644 --- a/lib/asan/asan_mac.cc +++ b/lib/asan/asan_mac.cc @@ -33,17 +33,17 @@ extern "C" { #endif #include // for dladdr() +#include +#include #include #include +#include +#include // for free() #include #include #include #include -#include -#include -#include // for free() #include -#include namespace __asan { From 72f38c18d7a51953e3708bcb4d36d519395cfc4b Mon Sep 17 00:00:00 2001 From: Anna Zaks Date: Tue, 27 Oct 2015 20:13:01 +0000 Subject: [PATCH 14/68] [asan] On OS X, log reports to syslog and os_trace When ASan currently detects a bug, by default it will only print out the text of the report to stderr. This patch changes this behavior and writes the full text of the report to syslog before we terminate the process. It also calls os_trace (Activity Tracing available on OS X and iOS) with a message saying that the report is available in syslog. This is useful, because this message will be shown in the crash log. For this to work, the patch makes sure we store the full report into error_message_buffer unconditionally, and it also strips out ANSI escape sequences from the report (they are used when producing colored reports). I've initially tried to log to syslog during printing, which is done on Android right now. The advantage is that if we crash during error reporting or the produced error does not go through ScopedInErrorReport, we would still get a (partial) message in the syslog. However, that solution is very problematic on OS X. One issue is that the logging routine uses GCD, which may spawn a new thread on its behalf. In many cases, the reporting logic locks threadRegistry, which leads to deadlocks. Reviewed at http://reviews.llvm.org/D13452 git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/trunk@251447 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/asan/asan_report.cc | 40 ++++++++++-------- lib/asan/tests/asan_test_main.cc | 3 +- lib/sanitizer_common/sanitizer_common.cc | 34 +++++++++++++++ lib/sanitizer_common/sanitizer_common.h | 19 ++++++++- .../sanitizer_common_libcdep.cc | 22 ++++++++++ lib/sanitizer_common/sanitizer_flags.inc | 2 +- .../sanitizer_linux_libcdep.cc | 24 ++--------- lib/sanitizer_common/sanitizer_mac.cc | 41 +++++++++++++++++++ lib/sanitizer_common/sanitizer_printf.cc | 2 +- .../tests/sanitizer_common_test.cc | 24 +++++++++++ test/asan/lit.cfg | 2 + test/ubsan/lit.common.cfg | 1 + 12 files changed, 171 insertions(+), 43 deletions(-) diff --git a/lib/asan/asan_report.cc b/lib/asan/asan_report.cc index 957ac14eaf..5c266b6532 100644 --- a/lib/asan/asan_report.cc +++ b/lib/asan/asan_report.cc @@ -31,6 +31,7 @@ static void (*error_report_callback)(const char*); static char *error_message_buffer = nullptr; static uptr error_message_buffer_pos = 0; static uptr error_message_buffer_size = 0; +static BlockingMutex error_message_buf_mutex(LINKER_INITIALIZED); struct ReportData { uptr pc; @@ -46,16 +47,21 @@ static bool report_happened = false; static ReportData report_data = {}; void AppendToErrorMessageBuffer(const char *buffer) { - if (error_message_buffer) { - uptr length = internal_strlen(buffer); - CHECK_GE(error_message_buffer_size, error_message_buffer_pos); - uptr remaining = error_message_buffer_size - error_message_buffer_pos; - internal_strncpy(error_message_buffer + error_message_buffer_pos, - buffer, remaining); - error_message_buffer[error_message_buffer_size - 1] = '\0'; - // FIXME: reallocate the buffer instead of truncating the message. - error_message_buffer_pos += Min(remaining, length); + BlockingMutexLock l(&error_message_buf_mutex); + if (!error_message_buffer) { + error_message_buffer_size = 1 << 16; + error_message_buffer = + (char*)MmapOrDie(error_message_buffer_size, __func__); + error_message_buffer_pos = 0; } + uptr length = internal_strlen(buffer); + CHECK_GE(error_message_buffer_size, error_message_buffer_pos); + uptr remaining = error_message_buffer_size - error_message_buffer_pos; + internal_strncpy(error_message_buffer + error_message_buffer_pos, + buffer, remaining); + error_message_buffer[error_message_buffer_size - 1] = '\0'; + // FIXME: reallocate the buffer instead of truncating the message. + error_message_buffer_pos += Min(remaining, length); } // ---------------------- Decorator ------------------------------ {{{1 @@ -664,8 +670,13 @@ class ScopedInErrorReport { // Print memory stats. if (flags()->print_stats) __asan_print_accumulated_stats(); - if (error_report_callback) { - error_report_callback(error_message_buffer); + { + BlockingMutexLock l(&error_message_buf_mutex); + LogFullErrorReport(error_message_buffer); + + if (error_report_callback) { + error_report_callback(error_message_buffer); + } } Report("ABORTING\n"); Die(); @@ -1061,13 +1072,8 @@ void __asan_report_error(uptr pc, uptr bp, uptr sp, uptr addr, int is_write, } void NOINLINE __asan_set_error_report_callback(void (*callback)(const char*)) { + BlockingMutexLock l(&error_message_buf_mutex); error_report_callback = callback; - if (callback) { - error_message_buffer_size = 1 << 16; - error_message_buffer = - (char*)MmapOrDie(error_message_buffer_size, __func__); - error_message_buffer_pos = 0; - } } void __asan_describe_address(uptr addr) { diff --git a/lib/asan/tests/asan_test_main.cc b/lib/asan/tests/asan_test_main.cc index 5958cb8a06..cdaf801d91 100644 --- a/lib/asan/tests/asan_test_main.cc +++ b/lib/asan/tests/asan_test_main.cc @@ -19,7 +19,8 @@ extern "C" const char* __asan_default_options() { #if SANITIZER_MAC // On Darwin, we default to `abort_on_error=1`, which would make tests run // much slower. Let's override this and run lit tests with 'abort_on_error=0'. - return "symbolize=false:abort_on_error=0"; + // Also, make sure we do not overwhelm the syslog while testing. + return "symbolize=false:abort_on_error=0:log_to_syslog=0"; #else return "symbolize=false"; #endif diff --git a/lib/sanitizer_common/sanitizer_common.cc b/lib/sanitizer_common/sanitizer_common.cc index 2fb88688d1..db734d6286 100644 --- a/lib/sanitizer_common/sanitizer_common.cc +++ b/lib/sanitizer_common/sanitizer_common.cc @@ -295,6 +295,40 @@ void ReportErrorSummary(const char *error_type, const AddressInfo &info) { } #endif +// Removes the ANSI escape sequences from the input string (in-place). +void RemoveANSIEscapeSequencesFromString(char *str) { + if (!str) + return; + + // We are going to remove the escape sequences in place. + char *s = str; + char *z = str; + while (*s != '\0') { + CHECK_GE(s, z); + // Skip over ANSI escape sequences with pointer 's'. + if (*s == '\033' && *(s + 1) == '[') { + s = internal_strchrnul(s, 'm'); + if (*s == '\0') { + break; + } + s++; + continue; + } + // 's' now points at a character we want to keep. Copy over the buffer + // content if the escape sequence has been perviously skipped andadvance + // both pointers. + if (s != z) + *z = *s; + + // If we have not seen an escape sequence, just advance both pointers. + z++; + s++; + } + + // Null terminate the string. + *z = '\0'; +} + void LoadedModule::set(const char *module_name, uptr base_address) { clear(); full_name_ = internal_strdup(module_name); diff --git a/lib/sanitizer_common/sanitizer_common.h b/lib/sanitizer_common/sanitizer_common.h index bfd0d6e12a..63c772bc4e 100644 --- a/lib/sanitizer_common/sanitizer_common.h +++ b/lib/sanitizer_common/sanitizer_common.h @@ -162,6 +162,7 @@ void SetLowLevelAllocateCallback(LowLevelAllocateCallback callback); // IO void RawWrite(const char *buffer); bool ColorizeReports(); +void RemoveANSIEscapeSequencesFromString(char *buffer); void Printf(const char *format, ...); void Report(const char *format, ...); void SetPrintfAndReportCallback(void (*callback)(const char *)); @@ -648,13 +649,27 @@ enum AndroidApiLevel { ANDROID_POST_LOLLIPOP = 23 }; +void WriteToSyslog(const char *buffer); + +#if SANITIZER_MAC +void LogFullErrorReport(const char *error_message_buffer); +#else +INLINE void LogFullErrorReport(const char *error_message_buffer) {} +#endif + +#if SANITIZER_LINUX || SANITIZER_MAC +void WriteOneLineToSyslog(const char *s); +#else +INLINE void WriteOneLineToSyslog(const char *s) {} +#endif + #if SANITIZER_LINUX // Initialize Android logging. Any writes before this are silently lost. void AndroidLogInit(); -void WriteToSyslog(const char *buffer); +bool ShouldLogAfterPrintf(); #else INLINE void AndroidLogInit() {} -INLINE void WriteToSyslog(const char *buffer) {} +INLINE bool ShouldLogAfterPrintf() { return false; } #endif #if SANITIZER_ANDROID diff --git a/lib/sanitizer_common/sanitizer_common_libcdep.cc b/lib/sanitizer_common/sanitizer_common_libcdep.cc index 1b65bced75..865f0d5874 100644 --- a/lib/sanitizer_common/sanitizer_common_libcdep.cc +++ b/lib/sanitizer_common/sanitizer_common_libcdep.cc @@ -12,6 +12,7 @@ //===----------------------------------------------------------------------===// #include "sanitizer_common.h" +#include "sanitizer_allocator_internal.h" #include "sanitizer_flags.h" #include "sanitizer_stackdepot.h" #include "sanitizer_stacktrace.h" @@ -116,6 +117,27 @@ void BackgroundThread(void *arg) { } } +void WriteToSyslog(const char *buffer) { + char *copy = internal_strdup(buffer); + char *p = copy; + char *q; + + // Remove color sequences since syslogs cannot print them. + RemoveANSIEscapeSequencesFromString(copy); + + // Print one line at a time. + // syslog, at least on Android, has an implicit message length limit. + do { + q = internal_strchr(p, '\n'); + if (q) + *q = '\0'; + WriteOneLineToSyslog(p); + if (q) + p = q + 1; + } while (q); + InternalFree(copy); +} + void MaybeStartBackgroudThread() { #if SANITIZER_LINUX // Need to implement/test on other platforms. // Start the background thread if one of the rss limits is given. diff --git a/lib/sanitizer_common/sanitizer_flags.inc b/lib/sanitizer_common/sanitizer_flags.inc index e742d85466..3b685db5a5 100644 --- a/lib/sanitizer_common/sanitizer_flags.inc +++ b/lib/sanitizer_common/sanitizer_flags.inc @@ -56,7 +56,7 @@ COMMON_FLAG( "Mention name of executable when reporting error and " "append executable name to logs (as in \"log_path.exe_name.pid\").") COMMON_FLAG( - bool, log_to_syslog, SANITIZER_ANDROID, + bool, log_to_syslog, SANITIZER_ANDROID || SANITIZER_MAC, "Write all sanitizer output to syslog in addition to other means of " "logging.") COMMON_FLAG( diff --git a/lib/sanitizer_common/sanitizer_linux_libcdep.cc b/lib/sanitizer_common/sanitizer_linux_libcdep.cc index 97c65676bf..cf58f04aa4 100644 --- a/lib/sanitizer_common/sanitizer_linux_libcdep.cc +++ b/lib/sanitizer_common/sanitizer_linux_libcdep.cc @@ -548,16 +548,16 @@ void AndroidLogInit() { atomic_store(&android_log_initialized, 1, memory_order_release); } -static bool IsSyslogAvailable() { +bool ShouldLogAfterPrintf() { return atomic_load(&android_log_initialized, memory_order_acquire); } #else void AndroidLogInit() {} -static bool IsSyslogAvailable() { return true; } +bool ShouldLogAfterPrintf() { return true; } #endif // SANITIZER_ANDROID -static void WriteOneLineToSyslog(const char *s) { +void WriteOneLineToSyslog(const char *s) { #if SANITIZER_ANDROID &&__ANDROID_API__ < 21 __android_log_write(ANDROID_LOG_INFO, NULL, s); #else @@ -565,24 +565,6 @@ static void WriteOneLineToSyslog(const char *s) { #endif } -void WriteToSyslog(const char *buffer) { - if (!IsSyslogAvailable()) - return; - char *copy = internal_strdup(buffer); - char *p = copy; - char *q; - // syslog, at least on Android, has an implicit message length limit. - // Print one line at a time. - do { - q = internal_strchr(p, '\n'); - if (q) - *q = '\0'; - WriteOneLineToSyslog(p); - if (q) - p = q + 1; - } while (q); - InternalFree(copy); -} #endif // SANITIZER_LINUX } // namespace __sanitizer diff --git a/lib/sanitizer_common/sanitizer_mac.cc b/lib/sanitizer_common/sanitizer_mac.cc index 3151cf8b91..951a48a713 100644 --- a/lib/sanitizer_common/sanitizer_mac.cc +++ b/lib/sanitizer_common/sanitizer_mac.cc @@ -36,12 +36,14 @@ extern char **environ; #endif +#include #include #include #include #include #include #include +#include #include #include #include @@ -371,6 +373,45 @@ uptr GetRSS() { return info.resident_size; } +static BlockingMutex syslog_lock(LINKER_INITIALIZED); + +void WriteOneLineToSyslog(const char *s) { + syslog_lock.CheckLocked(); + asl_log(nullptr, nullptr, ASL_LEVEL_ERR, "%s", s); +} + +void LogFullErrorReport(const char *buffer) { + // Log with os_trace. This will make it into the crash log. + if (GetMacosVersion() >= MACOS_VERSION_MAVERICKS) { + // os_trace requires the message (format parameter) to be a string literal. + if (internal_strncmp(SanitizerToolName, "AddressSanitizer", + sizeof("AddressSanitizer") - 1) == 0) + os_trace("Address Sanitizer reported a failure."); + else if (internal_strncmp(SanitizerToolName, "UndefinedBehaviorSanitizer", + sizeof("UndefinedBehaviorSanitizer") - 1) == 0) + os_trace("Undefined Behavior Sanitizer reported a failure."); + else if (internal_strncmp(SanitizerToolName, "ThreadSanitizer", + sizeof("ThreadSanitizer") - 1) == 0) + os_trace("Thread Sanitizer reported a failure."); + else + os_trace("Sanitizer tool reported a failure."); + + if (common_flags()->log_to_syslog) + os_trace("Consult syslog for more information."); + } + + // Log to syslog. + // The logging on OS X may call pthread_create so we need the threading + // environment to be fully initialized. Also, this should never be called when + // holding the thread registry lock since that may result in a deadlock. If + // the reporting thread holds the thread registry mutex, and asl_log waits + // for GCD to dispatch a new thread, the process will deadlock, because the + // pthread_create wrapper needs to acquire the lock as well. + BlockingMutexLock l(&syslog_lock); + if (common_flags()->log_to_syslog) + WriteToSyslog(buffer); +} + void *internal_start_thread(void (*func)(void *arg), void *arg) { return 0; } void internal_join_thread(void *th) { } diff --git a/lib/sanitizer_common/sanitizer_printf.cc b/lib/sanitizer_common/sanitizer_printf.cc index 5f4725ec1d..2794e667e6 100644 --- a/lib/sanitizer_common/sanitizer_printf.cc +++ b/lib/sanitizer_common/sanitizer_printf.cc @@ -278,7 +278,7 @@ static void SharedPrintfCode(bool append_pid, const char *format, # undef CHECK_NEEDED_LENGTH } RawWrite(buffer); - if (common_flags()->log_to_syslog) + if (common_flags()->log_to_syslog && ShouldLogAfterPrintf()) WriteToSyslog(buffer); CallPrintfAndReportCallback(buffer); // If we had mapped any memory, clean up. diff --git a/lib/sanitizer_common/tests/sanitizer_common_test.cc b/lib/sanitizer_common/tests/sanitizer_common_test.cc index c1bb797db2..6fc308ad14 100644 --- a/lib/sanitizer_common/tests/sanitizer_common_test.cc +++ b/lib/sanitizer_common/tests/sanitizer_common_test.cc @@ -208,6 +208,30 @@ TEST(SanitizerCommon, StripPathPrefix) { EXPECT_STREQ("file.h", StripPathPrefix("/usr/lib/./file.h", "/usr/lib/")); } +TEST(SanitizerCommon, RemoveANSIEscapeSequencesFromString) { + RemoveANSIEscapeSequencesFromString(nullptr); + const char *buffs[22] = { + "Default", "Default", + "\033[95mLight magenta", "Light magenta", + "\033[30mBlack\033[32mGreen\033[90mGray", "BlackGreenGray", + "\033[106mLight cyan \033[107mWhite ", "Light cyan White ", + "\033[31mHello\033[0m World", "Hello World", + "\033[38;5;82mHello \033[38;5;198mWorld", "Hello World", + "123[653456789012", "123[653456789012", + "Normal \033[5mBlink \033[25mNormal", "Normal Blink Normal", + "\033[106m\033[107m", "", + "", "", + " ", " ", + }; + + for (size_t i = 0; i < ARRAY_SIZE(buffs); i+=2) { + char *buffer_copy = internal_strdup(buffs[i]); + RemoveANSIEscapeSequencesFromString(buffer_copy); + EXPECT_STREQ(buffer_copy, buffs[i+1]); + InternalFree(buffer_copy); + } +} + TEST(SanitizerCommon, InternalScopedString) { InternalScopedString str(10); EXPECT_EQ(0U, str.length()); diff --git a/test/asan/lit.cfg b/test/asan/lit.cfg index fd99f66996..835547090a 100644 --- a/test/asan/lit.cfg +++ b/test/asan/lit.cfg @@ -34,7 +34,9 @@ default_asan_opts = '' if config.host_os == 'Darwin': # On Darwin, we default to `abort_on_error=1`, which would make tests run # much slower. Let's override this and run lit tests with 'abort_on_error=0'. + # Also, make sure we do not overwhelm the syslog while testing. default_asan_opts = 'abort_on_error=0' + default_asan_opts += ':log_to_syslog=0' if default_asan_opts: config.environment['ASAN_OPTIONS'] = default_asan_opts default_asan_opts += ':' diff --git a/test/ubsan/lit.common.cfg b/test/ubsan/lit.common.cfg index 8e84406664..e50862983d 100644 --- a/test/ubsan/lit.common.cfg +++ b/test/ubsan/lit.common.cfg @@ -42,6 +42,7 @@ if config.host_os == 'Darwin': # On Darwin, we default to `abort_on_error=1`, which would make tests run # much slower. Let's override this and run lit tests with 'abort_on_error=0'. default_ubsan_opts += ['abort_on_error=0'] + default_ubsan_opts += ['log_to_syslog=0'] default_ubsan_opts_str = ':'.join(default_ubsan_opts) if default_ubsan_opts_str: config.environment['UBSAN_OPTIONS'] = default_ubsan_opts_str From daaaf7a8ab20deb7ac4d49bb338205e740f940f4 Mon Sep 17 00:00:00 2001 From: Daniel Sanders Date: Tue, 27 Oct 2015 23:13:26 +0000 Subject: [PATCH 15/68] [mips][asan] XFAIL ptrace.cc It was recently enabled for non-x86 targets and doesn't seem to work for MIPS. The reason is currently unclear so XFAILing while I investigate. git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/trunk@251466 91177308-0d34-0410-b5e6-96231b3b80d8 --- test/asan/TestCases/Linux/ptrace.cc | 1 + 1 file changed, 1 insertion(+) diff --git a/test/asan/TestCases/Linux/ptrace.cc b/test/asan/TestCases/Linux/ptrace.cc index b222849b9a..d87d90be47 100644 --- a/test/asan/TestCases/Linux/ptrace.cc +++ b/test/asan/TestCases/Linux/ptrace.cc @@ -1,5 +1,6 @@ // FIXME: https://code.google.com/p/address-sanitizer/issues/detail?id=316 // XFAIL: android +// XFAIL: mips // // RUN: %clangxx_asan -O0 %s -o %t && %run %t // RUN: %clangxx_asan -DPOSITIVE -O0 %s -o %t && not %run %t 2>&1 | FileCheck %s From 29e41712c43ecb82efe2864df2f58817dff99570 Mon Sep 17 00:00:00 2001 From: Anna Zaks Date: Tue, 27 Oct 2015 23:15:05 +0000 Subject: [PATCH 16/68] Revert "[asan] On OS X, log reports to syslog and os_trace" This reverts commit 251447. (Which caused failures on a Linux bot.) git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/trunk@251467 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/asan/asan_report.cc | 40 ++++++++---------- lib/asan/tests/asan_test_main.cc | 3 +- lib/sanitizer_common/sanitizer_common.cc | 34 --------------- lib/sanitizer_common/sanitizer_common.h | 19 +-------- .../sanitizer_common_libcdep.cc | 22 ---------- lib/sanitizer_common/sanitizer_flags.inc | 2 +- .../sanitizer_linux_libcdep.cc | 24 +++++++++-- lib/sanitizer_common/sanitizer_mac.cc | 41 ------------------- lib/sanitizer_common/sanitizer_printf.cc | 2 +- .../tests/sanitizer_common_test.cc | 24 ----------- test/asan/lit.cfg | 2 - test/ubsan/lit.common.cfg | 1 - 12 files changed, 43 insertions(+), 171 deletions(-) diff --git a/lib/asan/asan_report.cc b/lib/asan/asan_report.cc index 5c266b6532..957ac14eaf 100644 --- a/lib/asan/asan_report.cc +++ b/lib/asan/asan_report.cc @@ -31,7 +31,6 @@ static void (*error_report_callback)(const char*); static char *error_message_buffer = nullptr; static uptr error_message_buffer_pos = 0; static uptr error_message_buffer_size = 0; -static BlockingMutex error_message_buf_mutex(LINKER_INITIALIZED); struct ReportData { uptr pc; @@ -47,21 +46,16 @@ static bool report_happened = false; static ReportData report_data = {}; void AppendToErrorMessageBuffer(const char *buffer) { - BlockingMutexLock l(&error_message_buf_mutex); - if (!error_message_buffer) { - error_message_buffer_size = 1 << 16; - error_message_buffer = - (char*)MmapOrDie(error_message_buffer_size, __func__); - error_message_buffer_pos = 0; + if (error_message_buffer) { + uptr length = internal_strlen(buffer); + CHECK_GE(error_message_buffer_size, error_message_buffer_pos); + uptr remaining = error_message_buffer_size - error_message_buffer_pos; + internal_strncpy(error_message_buffer + error_message_buffer_pos, + buffer, remaining); + error_message_buffer[error_message_buffer_size - 1] = '\0'; + // FIXME: reallocate the buffer instead of truncating the message. + error_message_buffer_pos += Min(remaining, length); } - uptr length = internal_strlen(buffer); - CHECK_GE(error_message_buffer_size, error_message_buffer_pos); - uptr remaining = error_message_buffer_size - error_message_buffer_pos; - internal_strncpy(error_message_buffer + error_message_buffer_pos, - buffer, remaining); - error_message_buffer[error_message_buffer_size - 1] = '\0'; - // FIXME: reallocate the buffer instead of truncating the message. - error_message_buffer_pos += Min(remaining, length); } // ---------------------- Decorator ------------------------------ {{{1 @@ -670,13 +664,8 @@ class ScopedInErrorReport { // Print memory stats. if (flags()->print_stats) __asan_print_accumulated_stats(); - { - BlockingMutexLock l(&error_message_buf_mutex); - LogFullErrorReport(error_message_buffer); - - if (error_report_callback) { - error_report_callback(error_message_buffer); - } + if (error_report_callback) { + error_report_callback(error_message_buffer); } Report("ABORTING\n"); Die(); @@ -1072,8 +1061,13 @@ void __asan_report_error(uptr pc, uptr bp, uptr sp, uptr addr, int is_write, } void NOINLINE __asan_set_error_report_callback(void (*callback)(const char*)) { - BlockingMutexLock l(&error_message_buf_mutex); error_report_callback = callback; + if (callback) { + error_message_buffer_size = 1 << 16; + error_message_buffer = + (char*)MmapOrDie(error_message_buffer_size, __func__); + error_message_buffer_pos = 0; + } } void __asan_describe_address(uptr addr) { diff --git a/lib/asan/tests/asan_test_main.cc b/lib/asan/tests/asan_test_main.cc index cdaf801d91..5958cb8a06 100644 --- a/lib/asan/tests/asan_test_main.cc +++ b/lib/asan/tests/asan_test_main.cc @@ -19,8 +19,7 @@ extern "C" const char* __asan_default_options() { #if SANITIZER_MAC // On Darwin, we default to `abort_on_error=1`, which would make tests run // much slower. Let's override this and run lit tests with 'abort_on_error=0'. - // Also, make sure we do not overwhelm the syslog while testing. - return "symbolize=false:abort_on_error=0:log_to_syslog=0"; + return "symbolize=false:abort_on_error=0"; #else return "symbolize=false"; #endif diff --git a/lib/sanitizer_common/sanitizer_common.cc b/lib/sanitizer_common/sanitizer_common.cc index db734d6286..2fb88688d1 100644 --- a/lib/sanitizer_common/sanitizer_common.cc +++ b/lib/sanitizer_common/sanitizer_common.cc @@ -295,40 +295,6 @@ void ReportErrorSummary(const char *error_type, const AddressInfo &info) { } #endif -// Removes the ANSI escape sequences from the input string (in-place). -void RemoveANSIEscapeSequencesFromString(char *str) { - if (!str) - return; - - // We are going to remove the escape sequences in place. - char *s = str; - char *z = str; - while (*s != '\0') { - CHECK_GE(s, z); - // Skip over ANSI escape sequences with pointer 's'. - if (*s == '\033' && *(s + 1) == '[') { - s = internal_strchrnul(s, 'm'); - if (*s == '\0') { - break; - } - s++; - continue; - } - // 's' now points at a character we want to keep. Copy over the buffer - // content if the escape sequence has been perviously skipped andadvance - // both pointers. - if (s != z) - *z = *s; - - // If we have not seen an escape sequence, just advance both pointers. - z++; - s++; - } - - // Null terminate the string. - *z = '\0'; -} - void LoadedModule::set(const char *module_name, uptr base_address) { clear(); full_name_ = internal_strdup(module_name); diff --git a/lib/sanitizer_common/sanitizer_common.h b/lib/sanitizer_common/sanitizer_common.h index 63c772bc4e..bfd0d6e12a 100644 --- a/lib/sanitizer_common/sanitizer_common.h +++ b/lib/sanitizer_common/sanitizer_common.h @@ -162,7 +162,6 @@ void SetLowLevelAllocateCallback(LowLevelAllocateCallback callback); // IO void RawWrite(const char *buffer); bool ColorizeReports(); -void RemoveANSIEscapeSequencesFromString(char *buffer); void Printf(const char *format, ...); void Report(const char *format, ...); void SetPrintfAndReportCallback(void (*callback)(const char *)); @@ -649,27 +648,13 @@ enum AndroidApiLevel { ANDROID_POST_LOLLIPOP = 23 }; -void WriteToSyslog(const char *buffer); - -#if SANITIZER_MAC -void LogFullErrorReport(const char *error_message_buffer); -#else -INLINE void LogFullErrorReport(const char *error_message_buffer) {} -#endif - -#if SANITIZER_LINUX || SANITIZER_MAC -void WriteOneLineToSyslog(const char *s); -#else -INLINE void WriteOneLineToSyslog(const char *s) {} -#endif - #if SANITIZER_LINUX // Initialize Android logging. Any writes before this are silently lost. void AndroidLogInit(); -bool ShouldLogAfterPrintf(); +void WriteToSyslog(const char *buffer); #else INLINE void AndroidLogInit() {} -INLINE bool ShouldLogAfterPrintf() { return false; } +INLINE void WriteToSyslog(const char *buffer) {} #endif #if SANITIZER_ANDROID diff --git a/lib/sanitizer_common/sanitizer_common_libcdep.cc b/lib/sanitizer_common/sanitizer_common_libcdep.cc index 865f0d5874..1b65bced75 100644 --- a/lib/sanitizer_common/sanitizer_common_libcdep.cc +++ b/lib/sanitizer_common/sanitizer_common_libcdep.cc @@ -12,7 +12,6 @@ //===----------------------------------------------------------------------===// #include "sanitizer_common.h" -#include "sanitizer_allocator_internal.h" #include "sanitizer_flags.h" #include "sanitizer_stackdepot.h" #include "sanitizer_stacktrace.h" @@ -117,27 +116,6 @@ void BackgroundThread(void *arg) { } } -void WriteToSyslog(const char *buffer) { - char *copy = internal_strdup(buffer); - char *p = copy; - char *q; - - // Remove color sequences since syslogs cannot print them. - RemoveANSIEscapeSequencesFromString(copy); - - // Print one line at a time. - // syslog, at least on Android, has an implicit message length limit. - do { - q = internal_strchr(p, '\n'); - if (q) - *q = '\0'; - WriteOneLineToSyslog(p); - if (q) - p = q + 1; - } while (q); - InternalFree(copy); -} - void MaybeStartBackgroudThread() { #if SANITIZER_LINUX // Need to implement/test on other platforms. // Start the background thread if one of the rss limits is given. diff --git a/lib/sanitizer_common/sanitizer_flags.inc b/lib/sanitizer_common/sanitizer_flags.inc index 3b685db5a5..e742d85466 100644 --- a/lib/sanitizer_common/sanitizer_flags.inc +++ b/lib/sanitizer_common/sanitizer_flags.inc @@ -56,7 +56,7 @@ COMMON_FLAG( "Mention name of executable when reporting error and " "append executable name to logs (as in \"log_path.exe_name.pid\").") COMMON_FLAG( - bool, log_to_syslog, SANITIZER_ANDROID || SANITIZER_MAC, + bool, log_to_syslog, SANITIZER_ANDROID, "Write all sanitizer output to syslog in addition to other means of " "logging.") COMMON_FLAG( diff --git a/lib/sanitizer_common/sanitizer_linux_libcdep.cc b/lib/sanitizer_common/sanitizer_linux_libcdep.cc index cf58f04aa4..97c65676bf 100644 --- a/lib/sanitizer_common/sanitizer_linux_libcdep.cc +++ b/lib/sanitizer_common/sanitizer_linux_libcdep.cc @@ -548,16 +548,16 @@ void AndroidLogInit() { atomic_store(&android_log_initialized, 1, memory_order_release); } -bool ShouldLogAfterPrintf() { +static bool IsSyslogAvailable() { return atomic_load(&android_log_initialized, memory_order_acquire); } #else void AndroidLogInit() {} -bool ShouldLogAfterPrintf() { return true; } +static bool IsSyslogAvailable() { return true; } #endif // SANITIZER_ANDROID -void WriteOneLineToSyslog(const char *s) { +static void WriteOneLineToSyslog(const char *s) { #if SANITIZER_ANDROID &&__ANDROID_API__ < 21 __android_log_write(ANDROID_LOG_INFO, NULL, s); #else @@ -565,6 +565,24 @@ void WriteOneLineToSyslog(const char *s) { #endif } +void WriteToSyslog(const char *buffer) { + if (!IsSyslogAvailable()) + return; + char *copy = internal_strdup(buffer); + char *p = copy; + char *q; + // syslog, at least on Android, has an implicit message length limit. + // Print one line at a time. + do { + q = internal_strchr(p, '\n'); + if (q) + *q = '\0'; + WriteOneLineToSyslog(p); + if (q) + p = q + 1; + } while (q); + InternalFree(copy); +} #endif // SANITIZER_LINUX } // namespace __sanitizer diff --git a/lib/sanitizer_common/sanitizer_mac.cc b/lib/sanitizer_common/sanitizer_mac.cc index 951a48a713..3151cf8b91 100644 --- a/lib/sanitizer_common/sanitizer_mac.cc +++ b/lib/sanitizer_common/sanitizer_mac.cc @@ -36,14 +36,12 @@ extern char **environ; #endif -#include #include #include #include #include #include #include -#include #include #include #include @@ -373,45 +371,6 @@ uptr GetRSS() { return info.resident_size; } -static BlockingMutex syslog_lock(LINKER_INITIALIZED); - -void WriteOneLineToSyslog(const char *s) { - syslog_lock.CheckLocked(); - asl_log(nullptr, nullptr, ASL_LEVEL_ERR, "%s", s); -} - -void LogFullErrorReport(const char *buffer) { - // Log with os_trace. This will make it into the crash log. - if (GetMacosVersion() >= MACOS_VERSION_MAVERICKS) { - // os_trace requires the message (format parameter) to be a string literal. - if (internal_strncmp(SanitizerToolName, "AddressSanitizer", - sizeof("AddressSanitizer") - 1) == 0) - os_trace("Address Sanitizer reported a failure."); - else if (internal_strncmp(SanitizerToolName, "UndefinedBehaviorSanitizer", - sizeof("UndefinedBehaviorSanitizer") - 1) == 0) - os_trace("Undefined Behavior Sanitizer reported a failure."); - else if (internal_strncmp(SanitizerToolName, "ThreadSanitizer", - sizeof("ThreadSanitizer") - 1) == 0) - os_trace("Thread Sanitizer reported a failure."); - else - os_trace("Sanitizer tool reported a failure."); - - if (common_flags()->log_to_syslog) - os_trace("Consult syslog for more information."); - } - - // Log to syslog. - // The logging on OS X may call pthread_create so we need the threading - // environment to be fully initialized. Also, this should never be called when - // holding the thread registry lock since that may result in a deadlock. If - // the reporting thread holds the thread registry mutex, and asl_log waits - // for GCD to dispatch a new thread, the process will deadlock, because the - // pthread_create wrapper needs to acquire the lock as well. - BlockingMutexLock l(&syslog_lock); - if (common_flags()->log_to_syslog) - WriteToSyslog(buffer); -} - void *internal_start_thread(void (*func)(void *arg), void *arg) { return 0; } void internal_join_thread(void *th) { } diff --git a/lib/sanitizer_common/sanitizer_printf.cc b/lib/sanitizer_common/sanitizer_printf.cc index 2794e667e6..5f4725ec1d 100644 --- a/lib/sanitizer_common/sanitizer_printf.cc +++ b/lib/sanitizer_common/sanitizer_printf.cc @@ -278,7 +278,7 @@ static void SharedPrintfCode(bool append_pid, const char *format, # undef CHECK_NEEDED_LENGTH } RawWrite(buffer); - if (common_flags()->log_to_syslog && ShouldLogAfterPrintf()) + if (common_flags()->log_to_syslog) WriteToSyslog(buffer); CallPrintfAndReportCallback(buffer); // If we had mapped any memory, clean up. diff --git a/lib/sanitizer_common/tests/sanitizer_common_test.cc b/lib/sanitizer_common/tests/sanitizer_common_test.cc index 6fc308ad14..c1bb797db2 100644 --- a/lib/sanitizer_common/tests/sanitizer_common_test.cc +++ b/lib/sanitizer_common/tests/sanitizer_common_test.cc @@ -208,30 +208,6 @@ TEST(SanitizerCommon, StripPathPrefix) { EXPECT_STREQ("file.h", StripPathPrefix("/usr/lib/./file.h", "/usr/lib/")); } -TEST(SanitizerCommon, RemoveANSIEscapeSequencesFromString) { - RemoveANSIEscapeSequencesFromString(nullptr); - const char *buffs[22] = { - "Default", "Default", - "\033[95mLight magenta", "Light magenta", - "\033[30mBlack\033[32mGreen\033[90mGray", "BlackGreenGray", - "\033[106mLight cyan \033[107mWhite ", "Light cyan White ", - "\033[31mHello\033[0m World", "Hello World", - "\033[38;5;82mHello \033[38;5;198mWorld", "Hello World", - "123[653456789012", "123[653456789012", - "Normal \033[5mBlink \033[25mNormal", "Normal Blink Normal", - "\033[106m\033[107m", "", - "", "", - " ", " ", - }; - - for (size_t i = 0; i < ARRAY_SIZE(buffs); i+=2) { - char *buffer_copy = internal_strdup(buffs[i]); - RemoveANSIEscapeSequencesFromString(buffer_copy); - EXPECT_STREQ(buffer_copy, buffs[i+1]); - InternalFree(buffer_copy); - } -} - TEST(SanitizerCommon, InternalScopedString) { InternalScopedString str(10); EXPECT_EQ(0U, str.length()); diff --git a/test/asan/lit.cfg b/test/asan/lit.cfg index 835547090a..fd99f66996 100644 --- a/test/asan/lit.cfg +++ b/test/asan/lit.cfg @@ -34,9 +34,7 @@ default_asan_opts = '' if config.host_os == 'Darwin': # On Darwin, we default to `abort_on_error=1`, which would make tests run # much slower. Let's override this and run lit tests with 'abort_on_error=0'. - # Also, make sure we do not overwhelm the syslog while testing. default_asan_opts = 'abort_on_error=0' - default_asan_opts += ':log_to_syslog=0' if default_asan_opts: config.environment['ASAN_OPTIONS'] = default_asan_opts default_asan_opts += ':' diff --git a/test/ubsan/lit.common.cfg b/test/ubsan/lit.common.cfg index e50862983d..8e84406664 100644 --- a/test/ubsan/lit.common.cfg +++ b/test/ubsan/lit.common.cfg @@ -42,7 +42,6 @@ if config.host_os == 'Darwin': # On Darwin, we default to `abort_on_error=1`, which would make tests run # much slower. Let's override this and run lit tests with 'abort_on_error=0'. default_ubsan_opts += ['abort_on_error=0'] - default_ubsan_opts += ['log_to_syslog=0'] default_ubsan_opts_str = ':'.join(default_ubsan_opts) if default_ubsan_opts_str: config.environment['UBSAN_OPTIONS'] = default_ubsan_opts_str From 1a2a5a81cc5ea70f134028a85ac9f956e10f6941 Mon Sep 17 00:00:00 2001 From: Ivan Krasin Date: Wed, 28 Oct 2015 20:45:34 +0000 Subject: [PATCH 17/68] sanitizer_common: be more verbose, when symbolizer is not found. Summary: I have othen been stuck when I got an ASAN report, but no symbols are resolved. The reasons might be different, and it always requires a bit of detective work to track down. These more verbose error messages will help the users like me. Reviewers: samsonov Subscribers: llvm-commits Differential Revision: http://reviews.llvm.org/D14135 git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/trunk@251553 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/sanitizer_common/sanitizer_symbolizer_posix_libcdep.cc | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/lib/sanitizer_common/sanitizer_symbolizer_posix_libcdep.cc b/lib/sanitizer_common/sanitizer_symbolizer_posix_libcdep.cc index 0ed236a0f3..a19b0a6786 100644 --- a/lib/sanitizer_common/sanitizer_symbolizer_posix_libcdep.cc +++ b/lib/sanitizer_common/sanitizer_symbolizer_posix_libcdep.cc @@ -446,14 +446,16 @@ static void ChooseSymbolizerTools(IntrusiveList *list, if (SymbolizerTool *tool = ChooseExternalSymbolizer(allocator)) { list->push_back(tool); - } else { - VReport(2, "No internal or external symbolizer found.\n"); } #if SANITIZER_MAC VReport(2, "Using dladdr symbolizer.\n"); list->push_back(new(*allocator) DlAddrSymbolizer()); #endif // SANITIZER_MAC + + if (list->size() == 0) { + Report("WARNING: no internal or external symbolizer found.\n"); + } } Symbolizer *Symbolizer::PlatformInit() { From 700dda1402cb6454f4237cf672336bb4407ff5ab Mon Sep 17 00:00:00 2001 From: Evgeniy Stepanov Date: Wed, 28 Oct 2015 20:45:52 +0000 Subject: [PATCH 18/68] [asan] Disable a flaky test on Android. Bug: https://github.com/google/sanitizers/issues/618 git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/trunk@251554 91177308-0d34-0410-b5e6-96231b3b80d8 --- test/asan/TestCases/coverage-reset.cc | 3 +++ 1 file changed, 3 insertions(+) diff --git a/test/asan/TestCases/coverage-reset.cc b/test/asan/TestCases/coverage-reset.cc index 5c648cc95e..1f5eed4c85 100644 --- a/test/asan/TestCases/coverage-reset.cc +++ b/test/asan/TestCases/coverage-reset.cc @@ -3,6 +3,9 @@ // RUN: %clangxx_asan -fsanitize-coverage=func %s -o %t // RUN: %env_asan_opts=coverage=1 %run %t +// https://github.com/google/sanitizers/issues/618 +// UNSUPPORTED: android + #include #include #include From bd58cbc2f3708fdd1de35b2d09b4ec648829a9a5 Mon Sep 17 00:00:00 2001 From: Evgeniy Stepanov Date: Wed, 28 Oct 2015 22:55:12 +0000 Subject: [PATCH 19/68] [asan] Fix asan_device_setup script on KitKat. app_process32, when started via a shell script wrapper, needs a different security context to satisty SELinux. Patch by Abhishek Arya. git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/trunk@251572 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/asan/scripts/asan_device_setup | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/asan/scripts/asan_device_setup b/lib/asan/scripts/asan_device_setup index 626573c586..338b8d501b 100755 --- a/lib/asan/scripts/asan_device_setup +++ b/lib/asan/scripts/asan_device_setup @@ -276,6 +276,7 @@ if [[ -n "$ASAN_RT64" ]]; then adb_pull /system/bin/asanwrapper64 "$TMPDIROLD" || true else adb_pull /system/lib/"$ASAN_RT" "$TMPDIROLD" || true + adb_pull /system/bin/app_process32 "$TMPDIROLD" || true adb_pull /system/bin/app_process.wrap "$TMPDIROLD" || true adb_pull /system/bin/asanwrapper "$TMPDIROLD" || true fi @@ -401,6 +402,7 @@ if ! ( cd "$TMPDIRBASE" && diff -qr old/ new/ ) ; then install "$TMPDIR/asanwrapper64" /system/bin 755 else install "$TMPDIR/$ASAN_RT" /system/lib 644 + install "$TMPDIR/app_process32" /system/bin 755 $CTX install "$TMPDIR/app_process.wrap" /system/bin 755 $CTX install "$TMPDIR/asanwrapper" /system/bin 755 $CTX From a1eec3a36d28210e67e91ac9658a27ac6e0d5a84 Mon Sep 17 00:00:00 2001 From: Anna Zaks Date: Wed, 28 Oct 2015 23:18:44 +0000 Subject: [PATCH 20/68] Reapply: [asan] On OS X, log reports to syslog and os_trace When ASan currently detects a bug, by default it will only print out the text of the report to stderr. This patch changes this behavior and writes the full text of the report to syslog before we terminate the process. It also calls os_trace (Activity Tracing available on OS X and iOS) with a message saying that the report is available in syslog. This is useful, because this message will be shown in the crash log. For this to work, the patch makes sure we store the full report into error_message_buffer unconditionally, and it also strips out ANSI escape sequences from the report (they are used when producing colored reports). I've initially tried to log to syslog during printing, which is done on Android right now. The advantage is that if we crash during error reporting or the produced error does not go through ScopedInErrorReport, we would still get a (partial) message in the syslog. However, that solution is very problematic on OS X. One issue is that the logging routine uses GCD, which may spawn a new thread on its behalf. In many cases, the reporting logic locks threadRegistry, which leads to deadlocks. Reviewed at http://reviews.llvm.org/D13452 (In addition, add sanitizer_common_libcdep.cc to buildgo.sh to avoid build failures on Linux.) git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/trunk@251577 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/asan/asan_report.cc | 40 ++++++++++-------- lib/asan/tests/asan_test_main.cc | 3 +- lib/sanitizer_common/sanitizer_common.cc | 34 +++++++++++++++ lib/sanitizer_common/sanitizer_common.h | 19 ++++++++- .../sanitizer_common_libcdep.cc | 27 +++++++++++- .../sanitizer_common_nolibc.cc | 4 +- lib/sanitizer_common/sanitizer_flags.inc | 2 +- .../sanitizer_linux_libcdep.cc | 24 ++--------- lib/sanitizer_common/sanitizer_mac.cc | 41 +++++++++++++++++++ lib/sanitizer_common/sanitizer_printf.cc | 2 +- .../tests/sanitizer_common_test.cc | 24 +++++++++++ lib/tsan/go/buildgo.sh | 1 + test/asan/lit.cfg | 2 + test/ubsan/lit.common.cfg | 1 + 14 files changed, 178 insertions(+), 46 deletions(-) diff --git a/lib/asan/asan_report.cc b/lib/asan/asan_report.cc index 957ac14eaf..5c266b6532 100644 --- a/lib/asan/asan_report.cc +++ b/lib/asan/asan_report.cc @@ -31,6 +31,7 @@ static void (*error_report_callback)(const char*); static char *error_message_buffer = nullptr; static uptr error_message_buffer_pos = 0; static uptr error_message_buffer_size = 0; +static BlockingMutex error_message_buf_mutex(LINKER_INITIALIZED); struct ReportData { uptr pc; @@ -46,16 +47,21 @@ static bool report_happened = false; static ReportData report_data = {}; void AppendToErrorMessageBuffer(const char *buffer) { - if (error_message_buffer) { - uptr length = internal_strlen(buffer); - CHECK_GE(error_message_buffer_size, error_message_buffer_pos); - uptr remaining = error_message_buffer_size - error_message_buffer_pos; - internal_strncpy(error_message_buffer + error_message_buffer_pos, - buffer, remaining); - error_message_buffer[error_message_buffer_size - 1] = '\0'; - // FIXME: reallocate the buffer instead of truncating the message. - error_message_buffer_pos += Min(remaining, length); + BlockingMutexLock l(&error_message_buf_mutex); + if (!error_message_buffer) { + error_message_buffer_size = 1 << 16; + error_message_buffer = + (char*)MmapOrDie(error_message_buffer_size, __func__); + error_message_buffer_pos = 0; } + uptr length = internal_strlen(buffer); + CHECK_GE(error_message_buffer_size, error_message_buffer_pos); + uptr remaining = error_message_buffer_size - error_message_buffer_pos; + internal_strncpy(error_message_buffer + error_message_buffer_pos, + buffer, remaining); + error_message_buffer[error_message_buffer_size - 1] = '\0'; + // FIXME: reallocate the buffer instead of truncating the message. + error_message_buffer_pos += Min(remaining, length); } // ---------------------- Decorator ------------------------------ {{{1 @@ -664,8 +670,13 @@ class ScopedInErrorReport { // Print memory stats. if (flags()->print_stats) __asan_print_accumulated_stats(); - if (error_report_callback) { - error_report_callback(error_message_buffer); + { + BlockingMutexLock l(&error_message_buf_mutex); + LogFullErrorReport(error_message_buffer); + + if (error_report_callback) { + error_report_callback(error_message_buffer); + } } Report("ABORTING\n"); Die(); @@ -1061,13 +1072,8 @@ void __asan_report_error(uptr pc, uptr bp, uptr sp, uptr addr, int is_write, } void NOINLINE __asan_set_error_report_callback(void (*callback)(const char*)) { + BlockingMutexLock l(&error_message_buf_mutex); error_report_callback = callback; - if (callback) { - error_message_buffer_size = 1 << 16; - error_message_buffer = - (char*)MmapOrDie(error_message_buffer_size, __func__); - error_message_buffer_pos = 0; - } } void __asan_describe_address(uptr addr) { diff --git a/lib/asan/tests/asan_test_main.cc b/lib/asan/tests/asan_test_main.cc index 5958cb8a06..cdaf801d91 100644 --- a/lib/asan/tests/asan_test_main.cc +++ b/lib/asan/tests/asan_test_main.cc @@ -19,7 +19,8 @@ extern "C" const char* __asan_default_options() { #if SANITIZER_MAC // On Darwin, we default to `abort_on_error=1`, which would make tests run // much slower. Let's override this and run lit tests with 'abort_on_error=0'. - return "symbolize=false:abort_on_error=0"; + // Also, make sure we do not overwhelm the syslog while testing. + return "symbolize=false:abort_on_error=0:log_to_syslog=0"; #else return "symbolize=false"; #endif diff --git a/lib/sanitizer_common/sanitizer_common.cc b/lib/sanitizer_common/sanitizer_common.cc index 2fb88688d1..db734d6286 100644 --- a/lib/sanitizer_common/sanitizer_common.cc +++ b/lib/sanitizer_common/sanitizer_common.cc @@ -295,6 +295,40 @@ void ReportErrorSummary(const char *error_type, const AddressInfo &info) { } #endif +// Removes the ANSI escape sequences from the input string (in-place). +void RemoveANSIEscapeSequencesFromString(char *str) { + if (!str) + return; + + // We are going to remove the escape sequences in place. + char *s = str; + char *z = str; + while (*s != '\0') { + CHECK_GE(s, z); + // Skip over ANSI escape sequences with pointer 's'. + if (*s == '\033' && *(s + 1) == '[') { + s = internal_strchrnul(s, 'm'); + if (*s == '\0') { + break; + } + s++; + continue; + } + // 's' now points at a character we want to keep. Copy over the buffer + // content if the escape sequence has been perviously skipped andadvance + // both pointers. + if (s != z) + *z = *s; + + // If we have not seen an escape sequence, just advance both pointers. + z++; + s++; + } + + // Null terminate the string. + *z = '\0'; +} + void LoadedModule::set(const char *module_name, uptr base_address) { clear(); full_name_ = internal_strdup(module_name); diff --git a/lib/sanitizer_common/sanitizer_common.h b/lib/sanitizer_common/sanitizer_common.h index bfd0d6e12a..63c772bc4e 100644 --- a/lib/sanitizer_common/sanitizer_common.h +++ b/lib/sanitizer_common/sanitizer_common.h @@ -162,6 +162,7 @@ void SetLowLevelAllocateCallback(LowLevelAllocateCallback callback); // IO void RawWrite(const char *buffer); bool ColorizeReports(); +void RemoveANSIEscapeSequencesFromString(char *buffer); void Printf(const char *format, ...); void Report(const char *format, ...); void SetPrintfAndReportCallback(void (*callback)(const char *)); @@ -648,13 +649,27 @@ enum AndroidApiLevel { ANDROID_POST_LOLLIPOP = 23 }; +void WriteToSyslog(const char *buffer); + +#if SANITIZER_MAC +void LogFullErrorReport(const char *error_message_buffer); +#else +INLINE void LogFullErrorReport(const char *error_message_buffer) {} +#endif + +#if SANITIZER_LINUX || SANITIZER_MAC +void WriteOneLineToSyslog(const char *s); +#else +INLINE void WriteOneLineToSyslog(const char *s) {} +#endif + #if SANITIZER_LINUX // Initialize Android logging. Any writes before this are silently lost. void AndroidLogInit(); -void WriteToSyslog(const char *buffer); +bool ShouldLogAfterPrintf(); #else INLINE void AndroidLogInit() {} -INLINE void WriteToSyslog(const char *buffer) {} +INLINE bool ShouldLogAfterPrintf() { return false; } #endif #if SANITIZER_ANDROID diff --git a/lib/sanitizer_common/sanitizer_common_libcdep.cc b/lib/sanitizer_common/sanitizer_common_libcdep.cc index 1b65bced75..9095002aa6 100644 --- a/lib/sanitizer_common/sanitizer_common_libcdep.cc +++ b/lib/sanitizer_common/sanitizer_common_libcdep.cc @@ -12,6 +12,7 @@ //===----------------------------------------------------------------------===// #include "sanitizer_common.h" +#include "sanitizer_allocator_internal.h" #include "sanitizer_flags.h" #include "sanitizer_stackdepot.h" #include "sanitizer_stacktrace.h" @@ -46,6 +47,7 @@ void SetSandboxingCallback(void (*f)()) { } void ReportErrorSummary(const char *error_type, StackTrace *stack) { +#if !SANITIZER_GO if (!common_flags()->print_summary) return; if (stack->size == 0) { @@ -58,6 +60,7 @@ void ReportErrorSummary(const char *error_type, StackTrace *stack) { SymbolizedStack *frame = Symbolizer::GetOrInit()->SymbolizePC(pc); ReportErrorSummary(error_type, frame->info); frame->ClearAll(); +#endif } static void (*SoftRssLimitExceededCallback)(bool exceeded); @@ -116,8 +119,30 @@ void BackgroundThread(void *arg) { } } +void WriteToSyslog(const char *buffer) { + char *copy = internal_strdup(buffer); + char *p = copy; + char *q; + + // Remove color sequences since syslogs cannot print them. + RemoveANSIEscapeSequencesFromString(copy); + + // Print one line at a time. + // syslog, at least on Android, has an implicit message length limit. + do { + q = internal_strchr(p, '\n'); + if (q) + *q = '\0'; + WriteOneLineToSyslog(p); + if (q) + p = q + 1; + } while (q); + InternalFree(copy); +} + void MaybeStartBackgroudThread() { -#if SANITIZER_LINUX // Need to implement/test on other platforms. +#if SANITIZER_LINUX && \ + !SANITIZER_GO // Need to implement/test on other platforms. // Start the background thread if one of the rss limits is given. if (!common_flags()->hard_rss_limit_mb && !common_flags()->soft_rss_limit_mb) return; diff --git a/lib/sanitizer_common/sanitizer_common_nolibc.cc b/lib/sanitizer_common/sanitizer_common_nolibc.cc index 65d1e37f62..89c17e0797 100644 --- a/lib/sanitizer_common/sanitizer_common_nolibc.cc +++ b/lib/sanitizer_common/sanitizer_common_nolibc.cc @@ -18,9 +18,9 @@ namespace __sanitizer { #if SANITIZER_LINUX -void WriteToSyslog(const char *buffer) {} +bool ShouldLogAfterPrintf() { return false; } #endif - +void WriteToSyslog(const char *buffer) {} void Abort() { internal__exit(1); } } // namespace __sanitizer diff --git a/lib/sanitizer_common/sanitizer_flags.inc b/lib/sanitizer_common/sanitizer_flags.inc index e742d85466..3b685db5a5 100644 --- a/lib/sanitizer_common/sanitizer_flags.inc +++ b/lib/sanitizer_common/sanitizer_flags.inc @@ -56,7 +56,7 @@ COMMON_FLAG( "Mention name of executable when reporting error and " "append executable name to logs (as in \"log_path.exe_name.pid\").") COMMON_FLAG( - bool, log_to_syslog, SANITIZER_ANDROID, + bool, log_to_syslog, SANITIZER_ANDROID || SANITIZER_MAC, "Write all sanitizer output to syslog in addition to other means of " "logging.") COMMON_FLAG( diff --git a/lib/sanitizer_common/sanitizer_linux_libcdep.cc b/lib/sanitizer_common/sanitizer_linux_libcdep.cc index 97c65676bf..cf58f04aa4 100644 --- a/lib/sanitizer_common/sanitizer_linux_libcdep.cc +++ b/lib/sanitizer_common/sanitizer_linux_libcdep.cc @@ -548,16 +548,16 @@ void AndroidLogInit() { atomic_store(&android_log_initialized, 1, memory_order_release); } -static bool IsSyslogAvailable() { +bool ShouldLogAfterPrintf() { return atomic_load(&android_log_initialized, memory_order_acquire); } #else void AndroidLogInit() {} -static bool IsSyslogAvailable() { return true; } +bool ShouldLogAfterPrintf() { return true; } #endif // SANITIZER_ANDROID -static void WriteOneLineToSyslog(const char *s) { +void WriteOneLineToSyslog(const char *s) { #if SANITIZER_ANDROID &&__ANDROID_API__ < 21 __android_log_write(ANDROID_LOG_INFO, NULL, s); #else @@ -565,24 +565,6 @@ static void WriteOneLineToSyslog(const char *s) { #endif } -void WriteToSyslog(const char *buffer) { - if (!IsSyslogAvailable()) - return; - char *copy = internal_strdup(buffer); - char *p = copy; - char *q; - // syslog, at least on Android, has an implicit message length limit. - // Print one line at a time. - do { - q = internal_strchr(p, '\n'); - if (q) - *q = '\0'; - WriteOneLineToSyslog(p); - if (q) - p = q + 1; - } while (q); - InternalFree(copy); -} #endif // SANITIZER_LINUX } // namespace __sanitizer diff --git a/lib/sanitizer_common/sanitizer_mac.cc b/lib/sanitizer_common/sanitizer_mac.cc index 3151cf8b91..951a48a713 100644 --- a/lib/sanitizer_common/sanitizer_mac.cc +++ b/lib/sanitizer_common/sanitizer_mac.cc @@ -36,12 +36,14 @@ extern char **environ; #endif +#include #include #include #include #include #include #include +#include #include #include #include @@ -371,6 +373,45 @@ uptr GetRSS() { return info.resident_size; } +static BlockingMutex syslog_lock(LINKER_INITIALIZED); + +void WriteOneLineToSyslog(const char *s) { + syslog_lock.CheckLocked(); + asl_log(nullptr, nullptr, ASL_LEVEL_ERR, "%s", s); +} + +void LogFullErrorReport(const char *buffer) { + // Log with os_trace. This will make it into the crash log. + if (GetMacosVersion() >= MACOS_VERSION_MAVERICKS) { + // os_trace requires the message (format parameter) to be a string literal. + if (internal_strncmp(SanitizerToolName, "AddressSanitizer", + sizeof("AddressSanitizer") - 1) == 0) + os_trace("Address Sanitizer reported a failure."); + else if (internal_strncmp(SanitizerToolName, "UndefinedBehaviorSanitizer", + sizeof("UndefinedBehaviorSanitizer") - 1) == 0) + os_trace("Undefined Behavior Sanitizer reported a failure."); + else if (internal_strncmp(SanitizerToolName, "ThreadSanitizer", + sizeof("ThreadSanitizer") - 1) == 0) + os_trace("Thread Sanitizer reported a failure."); + else + os_trace("Sanitizer tool reported a failure."); + + if (common_flags()->log_to_syslog) + os_trace("Consult syslog for more information."); + } + + // Log to syslog. + // The logging on OS X may call pthread_create so we need the threading + // environment to be fully initialized. Also, this should never be called when + // holding the thread registry lock since that may result in a deadlock. If + // the reporting thread holds the thread registry mutex, and asl_log waits + // for GCD to dispatch a new thread, the process will deadlock, because the + // pthread_create wrapper needs to acquire the lock as well. + BlockingMutexLock l(&syslog_lock); + if (common_flags()->log_to_syslog) + WriteToSyslog(buffer); +} + void *internal_start_thread(void (*func)(void *arg), void *arg) { return 0; } void internal_join_thread(void *th) { } diff --git a/lib/sanitizer_common/sanitizer_printf.cc b/lib/sanitizer_common/sanitizer_printf.cc index 5f4725ec1d..2794e667e6 100644 --- a/lib/sanitizer_common/sanitizer_printf.cc +++ b/lib/sanitizer_common/sanitizer_printf.cc @@ -278,7 +278,7 @@ static void SharedPrintfCode(bool append_pid, const char *format, # undef CHECK_NEEDED_LENGTH } RawWrite(buffer); - if (common_flags()->log_to_syslog) + if (common_flags()->log_to_syslog && ShouldLogAfterPrintf()) WriteToSyslog(buffer); CallPrintfAndReportCallback(buffer); // If we had mapped any memory, clean up. diff --git a/lib/sanitizer_common/tests/sanitizer_common_test.cc b/lib/sanitizer_common/tests/sanitizer_common_test.cc index c1bb797db2..6fc308ad14 100644 --- a/lib/sanitizer_common/tests/sanitizer_common_test.cc +++ b/lib/sanitizer_common/tests/sanitizer_common_test.cc @@ -208,6 +208,30 @@ TEST(SanitizerCommon, StripPathPrefix) { EXPECT_STREQ("file.h", StripPathPrefix("/usr/lib/./file.h", "/usr/lib/")); } +TEST(SanitizerCommon, RemoveANSIEscapeSequencesFromString) { + RemoveANSIEscapeSequencesFromString(nullptr); + const char *buffs[22] = { + "Default", "Default", + "\033[95mLight magenta", "Light magenta", + "\033[30mBlack\033[32mGreen\033[90mGray", "BlackGreenGray", + "\033[106mLight cyan \033[107mWhite ", "Light cyan White ", + "\033[31mHello\033[0m World", "Hello World", + "\033[38;5;82mHello \033[38;5;198mWorld", "Hello World", + "123[653456789012", "123[653456789012", + "Normal \033[5mBlink \033[25mNormal", "Normal Blink Normal", + "\033[106m\033[107m", "", + "", "", + " ", " ", + }; + + for (size_t i = 0; i < ARRAY_SIZE(buffs); i+=2) { + char *buffer_copy = internal_strdup(buffs[i]); + RemoveANSIEscapeSequencesFromString(buffer_copy); + EXPECT_STREQ(buffer_copy, buffs[i+1]); + InternalFree(buffer_copy); + } +} + TEST(SanitizerCommon, InternalScopedString) { InternalScopedString str(10); EXPECT_EQ(0U, str.length()); diff --git a/lib/tsan/go/buildgo.sh b/lib/tsan/go/buildgo.sh index a7e12f18c3..8c89d8fe68 100755 --- a/lib/tsan/go/buildgo.sh +++ b/lib/tsan/go/buildgo.sh @@ -20,6 +20,7 @@ SRCS=" ../rtl/tsan_sync.cc ../../sanitizer_common/sanitizer_allocator.cc ../../sanitizer_common/sanitizer_common.cc + ../../sanitizer_common/sanitizer_common_libcdep.cc ../../sanitizer_common/sanitizer_deadlock_detector2.cc ../../sanitizer_common/sanitizer_flag_parser.cc ../../sanitizer_common/sanitizer_flags.cc diff --git a/test/asan/lit.cfg b/test/asan/lit.cfg index fd99f66996..835547090a 100644 --- a/test/asan/lit.cfg +++ b/test/asan/lit.cfg @@ -34,7 +34,9 @@ default_asan_opts = '' if config.host_os == 'Darwin': # On Darwin, we default to `abort_on_error=1`, which would make tests run # much slower. Let's override this and run lit tests with 'abort_on_error=0'. + # Also, make sure we do not overwhelm the syslog while testing. default_asan_opts = 'abort_on_error=0' + default_asan_opts += ':log_to_syslog=0' if default_asan_opts: config.environment['ASAN_OPTIONS'] = default_asan_opts default_asan_opts += ':' diff --git a/test/ubsan/lit.common.cfg b/test/ubsan/lit.common.cfg index 8e84406664..e50862983d 100644 --- a/test/ubsan/lit.common.cfg +++ b/test/ubsan/lit.common.cfg @@ -42,6 +42,7 @@ if config.host_os == 'Darwin': # On Darwin, we default to `abort_on_error=1`, which would make tests run # much slower. Let's override this and run lit tests with 'abort_on_error=0'. default_ubsan_opts += ['abort_on_error=0'] + default_ubsan_opts += ['log_to_syslog=0'] default_ubsan_opts_str = ':'.join(default_ubsan_opts) if default_ubsan_opts_str: config.environment['UBSAN_OPTIONS'] = default_ubsan_opts_str From 5b3b8a081dc6b6c9550a0ea802e02e0b041f51fe Mon Sep 17 00:00:00 2001 From: Adhemerval Zanella Date: Thu, 29 Oct 2015 13:04:19 +0000 Subject: [PATCH 21/68] [compiler-rt] [msan] Unify aarch64 mapping This patch unify the 39-bit and 42-bit mapping for aarch64 to use only one instrumentation algorithm. A runtime check avoid mapping 42-bit only segments for 39-bit kernels. The mapping to use now is for 39 and 42-bits: 0x00000000000ULL-0x01000000000ULL MappingDesc::INVALID 0x01000000000ULL-0x02000000000ULL MappingDesc::SHADOW 0x02000000000ULL-0x03000000000ULL MappingDesc::ORIGIN 0x03000000000ULL-0x04000000000ULL MappingDesc::SHADOW 0x04000000000ULL-0x05000000000ULL MappingDesc::ORIGIN 0x05000000000ULL-0x06000000000ULL MappingDesc::APP 0x06000000000ULL-0x07000000000ULL MappingDesc::INVALID 0x07000000000ULL-0x08000000000ULL MappingDesc::APP And only for 42-bits: 0x08000000000ULL-0x09000000000ULL MappingDesc::INVALID 0x09000000000ULL-0x0A000000000ULL MappingDesc::SHADOW 0x0A000000000ULL-0x0B000000000ULL MappingDesc::ORIGIN 0x0B000000000ULL-0x0F000000000ULL MappingDesc::INVALID 0x0F000000000ULL-0x10000000000ULL MappingDesc::APP 0x10000000000ULL-0x11000000000ULL MappingDesc::INVALID 0x11000000000ULL-0x12000000000ULL MappingDesc::APP 0x12000000000ULL-0x17000000000ULL MappingDesc::INVALID 0x17000000000ULL-0x18000000000ULL MappingDesc::SHADOW 0x18000000000ULL-0x19000000000ULL MappingDesc::ORIGIN 0x19000000000ULL-0x20000000000ULL MappingDesc::INVALID 0x20000000000ULL-0x21000000000ULL MappingDesc::APP 0x21000000000ULL-0x26000000000ULL MappingDesc::INVALID 0x26000000000ULL-0x27000000000ULL MappingDesc::SHADOW 0x27000000000ULL-0x28000000000ULL MappingDesc::ORIGIN 0x28000000000ULL-0x29000000000ULL MappingDesc::SHADOW 0x29000000000ULL-0x2A000000000ULL MappingDesc::ORIGIN 0x2A000000000ULL-0x2B000000000ULL MappingDesc::APP 0x2B000000000ULL-0x2C000000000ULL MappingDesc::INVALID 0x2C000000000ULL-0x2D000000000ULL MappingDesc::SHADOW 0x2D000000000ULL-0x2E000000000ULL MappingDesc::ORIGIN 0x2E000000000ULL-0x2F000000000ULL MappingDesc::APP 0x2F000000000ULL-0x39000000000ULL MappingDesc::INVALID 0x39000000000ULL-0x3A000000000ULL MappingDesc::SHADOW 0x3A000000000ULL-0x3B000000000ULL MappingDesc::ORIGIN 0x3B000000000ULL-0x3C000000000ULL MappingDesc::APP 0x3C000000000ULL-0x3D000000000ULL MappingDesc::INVALID 0x3D000000000ULL-0x3E000000000ULL MappingDesc::SHADOW 0x3E000000000ULL-0x3F000000000ULL MappingDesc::ORIGIN 0x3F000000000ULL-0x40000000000ULL MappingDesc::APP And although complex it provides a better memory utilization that previous one. [1] http://reviews.llvm.org/D13817 git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/trunk@251625 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/msan/msan.cc | 2 - lib/msan/msan.h | 86 +++++++++++++++++------------- lib/msan/msan_linux.cc | 6 +++ test/msan/chained_origin_limits.cc | 4 -- test/msan/mmap.cc | 32 +++++++---- test/msan/strlen_of_shadow.cc | 16 +----- 6 files changed, 78 insertions(+), 68 deletions(-) diff --git a/lib/msan/msan.cc b/lib/msan/msan.cc index 87f2cdf2e9..b64dcb6ffe 100644 --- a/lib/msan/msan.cc +++ b/lib/msan/msan.cc @@ -380,8 +380,6 @@ void __msan_init() { CacheBinaryName(); InitializeFlags(); - CheckVMASize(); - __sanitizer_set_report_path(common_flags()->log_path); InitializeInterceptors(); diff --git a/lib/msan/msan.h b/lib/msan/msan.h index 2d779834a1..2079a592b7 100644 --- a/lib/msan/msan.h +++ b/lib/msan/msan.h @@ -54,44 +54,58 @@ const MappingDesc kMemoryLayout[] = { #elif SANITIZER_LINUX && defined(__aarch64__) -# if SANITIZER_AARCH64_VMA == 39 +// The mapping describes both 39-bits and 42-bits. AArch64 maps: +// - 0x00000000000-0x00010000000: 39/42-bits program own segments +// - 0x05500000000-0x05600000000: 39-bits PIE program segments +// - 0x07f80000000-0x07fffffffff: 39-bits libraries segments +// - 0x2aa00000000-0x2ab00000000: 42-bits PIE program segments +// - 0x3ff00000000-0x3ffffffffff: 42-bits libraries segments +// It is fragmented in multiples segments to increase the memory available +// on 42-bits (12.21% of total VMA available for 42-bits and 13.28 for +// 39 bits). const MappingDesc kMemoryLayout[] = { - {0x0000000000ULL, 0x4000000000ULL, MappingDesc::INVALID, "invalid"}, - {0x4000000000ULL, 0x4300000000ULL, MappingDesc::SHADOW, "shadow"}, - {0x4300000000ULL, 0x4600000000ULL, MappingDesc::ORIGIN, "origin"}, - {0x4600000000ULL, 0x5500000000ULL, MappingDesc::INVALID, "invalid"}, - {0x5500000000ULL, 0x5600000000ULL, MappingDesc::APP, "app"}, - {0x5600000000ULL, 0x7000000000ULL, MappingDesc::INVALID, "invalid"}, - {0x7000000000ULL, 0x8000000000ULL, MappingDesc::APP, "app"} + {0x00000000000ULL, 0x01000000000ULL, MappingDesc::INVALID, "invalid"}, + {0x01000000000ULL, 0x02000000000ULL, MappingDesc::SHADOW, "shadow-2"}, + {0x02000000000ULL, 0x03000000000ULL, MappingDesc::ORIGIN, "origin-2"}, + {0x03000000000ULL, 0x04000000000ULL, MappingDesc::SHADOW, "shadow-1"}, + {0x04000000000ULL, 0x05000000000ULL, MappingDesc::ORIGIN, "origin-1"}, + {0x05000000000ULL, 0x06000000000ULL, MappingDesc::APP, "app-1"}, + {0x06000000000ULL, 0x07000000000ULL, MappingDesc::INVALID, "invalid"}, + {0x07000000000ULL, 0x08000000000ULL, MappingDesc::APP, "app-2"}, + {0x08000000000ULL, 0x09000000000ULL, MappingDesc::INVALID, "invalid"}, + // The mappings below are used only for 42-bits VMA. + {0x09000000000ULL, 0x0A000000000ULL, MappingDesc::SHADOW, "shadow-3"}, + {0x0A000000000ULL, 0x0B000000000ULL, MappingDesc::ORIGIN, "origin-3"}, + {0x0B000000000ULL, 0x0F000000000ULL, MappingDesc::INVALID, "invalid"}, + {0x0F000000000ULL, 0x10000000000ULL, MappingDesc::APP, "app-3"}, + {0x10000000000ULL, 0x11000000000ULL, MappingDesc::INVALID, "invalid"}, + {0x11000000000ULL, 0x12000000000ULL, MappingDesc::APP, "app-4"}, + {0x12000000000ULL, 0x17000000000ULL, MappingDesc::INVALID, "invalid"}, + {0x17000000000ULL, 0x18000000000ULL, MappingDesc::SHADOW, "shadow-4"}, + {0x18000000000ULL, 0x19000000000ULL, MappingDesc::ORIGIN, "origin-4"}, + {0x19000000000ULL, 0x20000000000ULL, MappingDesc::INVALID, "invalid"}, + {0x20000000000ULL, 0x21000000000ULL, MappingDesc::APP, "app-5"}, + {0x21000000000ULL, 0x26000000000ULL, MappingDesc::INVALID, "invalid"}, + {0x26000000000ULL, 0x27000000000ULL, MappingDesc::SHADOW, "shadow-5"}, + {0x27000000000ULL, 0x28000000000ULL, MappingDesc::ORIGIN, "origin-5"}, + {0x28000000000ULL, 0x29000000000ULL, MappingDesc::SHADOW, "shadow-7"}, + {0x29000000000ULL, 0x2A000000000ULL, MappingDesc::ORIGIN, "origin-7"}, + {0x2A000000000ULL, 0x2B000000000ULL, MappingDesc::APP, "app-6"}, + {0x2B000000000ULL, 0x2C000000000ULL, MappingDesc::INVALID, "invalid"}, + {0x2C000000000ULL, 0x2D000000000ULL, MappingDesc::SHADOW, "shadow-6"}, + {0x2D000000000ULL, 0x2E000000000ULL, MappingDesc::ORIGIN, "origin-6"}, + {0x2E000000000ULL, 0x2F000000000ULL, MappingDesc::APP, "app-7"}, + {0x2F000000000ULL, 0x39000000000ULL, MappingDesc::INVALID, "invalid"}, + {0x39000000000ULL, 0x3A000000000ULL, MappingDesc::SHADOW, "shadow-9"}, + {0x3A000000000ULL, 0x3B000000000ULL, MappingDesc::ORIGIN, "origin-9"}, + {0x3B000000000ULL, 0x3C000000000ULL, MappingDesc::APP, "app-8"}, + {0x3C000000000ULL, 0x3D000000000ULL, MappingDesc::INVALID, "invalid"}, + {0x3D000000000ULL, 0x3E000000000ULL, MappingDesc::SHADOW, "shadow-8"}, + {0x3E000000000ULL, 0x3F000000000ULL, MappingDesc::ORIGIN, "origin-8"}, + {0x3F000000000ULL, 0x40000000000ULL, MappingDesc::APP, "app-9"}, }; -// Maps low and high app ranges to contiguous space with zero base: -// Low: 55 0000 0000 - 55 ffff ffff -> 1 0000 0000 - 1 ffff ffff -// High: 70 0000 0000 - 7f ffff ffff -> 0 0000 0000 - f ffff ffff -# define LINEARIZE_MEM(mem) \ - (((uptr)(mem) & ~0x7C00000000ULL) ^ 0x100000000ULL) -# define MEM_TO_SHADOW(mem) (LINEARIZE_MEM((mem)) + 0x4000000000ULL) -# define SHADOW_TO_ORIGIN(shadow) (((uptr)(shadow)) + 0x300000000ULL) - -# elif SANITIZER_AARCH64_VMA == 42 -const MappingDesc kMemoryLayout[] = { - {0x00000000000ULL, 0x10000000000ULL, MappingDesc::INVALID, "invalid"}, - {0x10000000000ULL, 0x11b00000000ULL, MappingDesc::SHADOW, "shadow"}, - {0x11b00000000ULL, 0x12000000000ULL, MappingDesc::INVALID, "invalid"}, - {0x12000000000ULL, 0x13b00000000ULL, MappingDesc::ORIGIN, "origin"}, - {0x13b00000000ULL, 0x2aa00000000ULL, MappingDesc::INVALID, "invalid"}, - {0x2aa00000000ULL, 0x2ab00000000ULL, MappingDesc::APP, "app"}, - {0x2ab00000000ULL, 0x3f000000000ULL, MappingDesc::INVALID, "invalid"}, - {0x3f000000000ULL, 0x40000000000ULL, MappingDesc::APP, "app"}, -}; -// Maps low and high app ranges to contigous space with zero base: -// 2 aa00 0000 00 - 2 ab00 0000 00: -> 1a00 0000 00 - 1aff ffff ff -// 3 f000 0000 00 - 4 0000 0000 00: -> 0000 0000 00 - 0fff ffff ff -# define LINEARIZE_MEM(mem) \ - (((uptr)(mem) & ~0x3E000000000ULL) ^ 0x1000000000ULL) -# define MEM_TO_SHADOW(mem) (LINEARIZE_MEM((mem)) + 0x10000000000ULL) -# define SHADOW_TO_ORIGIN(shadow) (((uptr)(shadow)) + 0x2000000000ULL) - -# endif // SANITIZER_AARCH64_VMA +# define MEM_TO_SHADOW(mem) ((uptr)mem ^ 0x6000000000ULL) +# define SHADOW_TO_ORIGIN(shadow) (((uptr)(shadow)) + 0x1000000000ULL) #elif SANITIZER_LINUX && defined(__powerpc64__) diff --git a/lib/msan/msan_linux.cc b/lib/msan/msan_linux.cc index 2888eb528d..ab3be91fcf 100644 --- a/lib/msan/msan_linux.cc +++ b/lib/msan/msan_linux.cc @@ -119,12 +119,18 @@ bool InitShadow(bool init_origins) { return false; } + const uptr maxVirtualAddress = GetMaxVirtualAddress(); + for (unsigned i = 0; i < kMemoryLayoutSize; ++i) { uptr start = kMemoryLayout[i].start; uptr end = kMemoryLayout[i].end; uptr size= end - start; MappingDesc::Type type = kMemoryLayout[i].type; + // Check if the segment should be mapped based on platform constraints. + if (start >= maxVirtualAddress) + continue; + bool map = type == MappingDesc::SHADOW || (init_origins && type == MappingDesc::ORIGIN); bool protect = type == MappingDesc::INVALID || diff --git a/test/msan/chained_origin_limits.cc b/test/msan/chained_origin_limits.cc index 889d4ea853..90fd09a86b 100644 --- a/test/msan/chained_origin_limits.cc +++ b/test/msan/chained_origin_limits.cc @@ -61,10 +61,6 @@ // RUN: MSAN_OPTIONS=origin_history_size=7,origin_history_per_stack_limit=0 not %run %t >%t.out 2>&1 // RUN: FileCheck %s --check-prefix=CHECK7 < %t.out -// -// AArch64 fails with -fsanitize-memory-track-origins=2 with and invalid access -// on 'return buf[50]'. -// XFAIL: aarch64 #include #include diff --git a/test/msan/mmap.cc b/test/msan/mmap.cc index 962836cd65..27a8bb2d6e 100644 --- a/test/msan/mmap.cc +++ b/test/msan/mmap.cc @@ -23,17 +23,27 @@ bool AddrIsApp(void *p) { #elif defined(__powerpc64__) return addr < 0x000100000000ULL || addr >= 0x300000000000ULL; #elif defined(__aarch64__) - unsigned long vma = SystemVMA(); - if (vma == 39) - return (addr >= 0x5500000000ULL && addr < 0x5600000000ULL) || - (addr > 0x7000000000ULL); - else if (vma == 42) - return (addr >= 0x2aa00000000ULL && addr < 0x2ab00000000ULL) || - (addr > 0x3f000000000ULL); - else { - fprintf(stderr, "unsupported vma: %lu\n", vma); - exit(1); - } + + struct AddrMapping { + uintptr_t start; + uintptr_t end; + } mappings[] = { + {0x05000000000ULL, 0x06000000000ULL}, + {0x07000000000ULL, 0x08000000000ULL}, + {0x0F000000000ULL, 0x10000000000ULL}, + {0x11000000000ULL, 0x12000000000ULL}, + {0x20000000000ULL, 0x21000000000ULL}, + {0x2A000000000ULL, 0x2B000000000ULL}, + {0x2E000000000ULL, 0x2F000000000ULL}, + {0x3B000000000ULL, 0x3C000000000ULL}, + {0x3F000000000ULL, 0x40000000000ULL}, + }; + const size_t mappingsSize = sizeof (mappings) / sizeof (mappings[0]); + + for (int i=0; i= mappings[i].start && addr < mappings[i].end) + return true; + return false; #endif } diff --git a/test/msan/strlen_of_shadow.cc b/test/msan/strlen_of_shadow.cc index 0594f00945..3066dd5b61 100644 --- a/test/msan/strlen_of_shadow.cc +++ b/test/msan/strlen_of_shadow.cc @@ -20,21 +20,7 @@ const char *mem_to_shadow(const char *p) { (((uintptr_t)(mem) & ~0x200000000000ULL) ^ 0x100000000000ULL) return (char *)(LINEARIZE_MEM(p) + 0x080000000000ULL); #elif defined(__aarch64__) - unsigned long vma = SystemVMA(); - -#define LINEARIZE_MEM_39(mem) \ - (((uintptr_t)(mem) & ~0x7C00000000ULL) ^ 0x100000000ULL) -#define LINEARIZE_MEM_42(mem) \ - (((uintptr_t)(mem) & ~0x3E000000000ULL) ^ 0x1000000000ULL) - - if (vma == 39) - return (char *)(LINEARIZE_MEM_39(p) + 0x4000000000ULL); - else if (vma == 42) - return (char *)(LINEARIZE_MEM_42(p) + 0x10000000000ULL); - else { - fprintf(stderr, "unsupported vma: %lu\n", vma); - exit(1); - } + return (char *)((uintptr_t)p ^ 0x6000000000ULL); #endif } From 8f11ffecd852191e2690d132f8475ec6bbc1fdd0 Mon Sep 17 00:00:00 2001 From: Saleem Abdulrasool Date: Thu, 29 Oct 2015 20:36:55 +0000 Subject: [PATCH 22/68] Sanitizer: define WIN32_LEAN_AND_MEAN Define WIN32_LEAN_AND_MEAN before including Windows.h. This is already being done in some places. This does it more broadly. This permits building ASAN on Linux for Winndows, as well as reduces the amount of included declarations. git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/trunk@251649 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/asan/asan_win.cc | 1 + lib/asan/asan_win_dynamic_runtime_thunk.cc | 1 + lib/interception/interception_win.cc | 1 + lib/sanitizer_common/sanitizer_symbolizer_win.cc | 1 + 4 files changed, 4 insertions(+) diff --git a/lib/asan/asan_win.cc b/lib/asan/asan_win.cc index f5a467a29d..28ec076807 100644 --- a/lib/asan/asan_win.cc +++ b/lib/asan/asan_win.cc @@ -14,6 +14,7 @@ #include "sanitizer_common/sanitizer_platform.h" #if SANITIZER_WINDOWS +#define WIN32_LEAN_AND_MEAN #include #include diff --git a/lib/asan/asan_win_dynamic_runtime_thunk.cc b/lib/asan/asan_win_dynamic_runtime_thunk.cc index d59f9f5768..d5a14088da 100644 --- a/lib/asan/asan_win_dynamic_runtime_thunk.cc +++ b/lib/asan/asan_win_dynamic_runtime_thunk.cc @@ -24,6 +24,7 @@ // Using #ifdef rather than relying on Makefiles etc. // simplifies the build procedure. #ifdef ASAN_DYNAMIC_RUNTIME_THUNK +#define WIN32_LEAN_AND_MEAN #include // First, declare CRT sections we'll be using in this file diff --git a/lib/interception/interception_win.cc b/lib/interception/interception_win.cc index e3197ddc1a..4c04c83b98 100644 --- a/lib/interception/interception_win.cc +++ b/lib/interception/interception_win.cc @@ -15,6 +15,7 @@ #ifdef _WIN32 #include "interception.h" +#define WIN32_LEAN_AND_MEAN #include namespace __interception { diff --git a/lib/sanitizer_common/sanitizer_symbolizer_win.cc b/lib/sanitizer_common/sanitizer_symbolizer_win.cc index b6aa6ca374..b1dceebf45 100644 --- a/lib/sanitizer_common/sanitizer_symbolizer_win.cc +++ b/lib/sanitizer_common/sanitizer_symbolizer_win.cc @@ -14,6 +14,7 @@ #include "sanitizer_platform.h" #if SANITIZER_WINDOWS +#define WIN32_LEAN_AND_MEAN #include #include #pragma comment(lib, "dbghelp.lib") From 6f7eaaad0459ef493a1036872d4cc298369262d1 Mon Sep 17 00:00:00 2001 From: Alexey Samsonov Date: Fri, 30 Oct 2015 18:52:31 +0000 Subject: [PATCH 23/68] Revert "Apply modernize-use-default to compiler-rt." This reverts commit r250823. Replacing at least some of empty constructors with "= default" variants is a semantical change which we don't want. E.g. __tsan::ClockBlock contains a union of large arrays, and it's critical for correctness and performance that we don't memset() these arrays in the constructor. git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/trunk@251717 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/asan/asan_fake_stack.h | 2 +- lib/msan/msan_allocator.h | 2 +- lib/sanitizer_common/sanitizer_bitvector.h | 4 ++-- lib/tsan/rtl/tsan_clock.h | 3 ++- lib/tsan/rtl/tsan_mutex.cc | 5 +++-- lib/tsan/rtl/tsan_report.cc | 5 +++-- lib/tsan/rtl/tsan_rtl_thread.cc | 3 ++- lib/ubsan/ubsan_diag.h | 2 +- 8 files changed, 15 insertions(+), 11 deletions(-) diff --git a/lib/asan/asan_fake_stack.h b/lib/asan/asan_fake_stack.h index bf1a66cb11..3b1d9eb3b5 100644 --- a/lib/asan/asan_fake_stack.h +++ b/lib/asan/asan_fake_stack.h @@ -155,7 +155,7 @@ class FakeStack { void ForEachFakeFrame(RangeIteratorCallback callback, void *arg); private: - FakeStack() = default; + FakeStack() { } static const uptr kFlagsOffset = 4096; // This is were the flags begin. // Must match the number of uses of DEFINE_STACK_MALLOC_FREE_WITH_CLASS_ID COMPILER_CHECK(kNumberOfSizeClasses == 11); diff --git a/lib/msan/msan_allocator.h b/lib/msan/msan_allocator.h index a9a27e1057..407942e54c 100644 --- a/lib/msan/msan_allocator.h +++ b/lib/msan/msan_allocator.h @@ -26,7 +26,7 @@ struct MsanThreadLocalMallocStorage { private: // These objects are allocated via mmap() and are zero-initialized. - MsanThreadLocalMallocStorage() = default; + MsanThreadLocalMallocStorage() {} }; } // namespace __msan diff --git a/lib/sanitizer_common/sanitizer_bitvector.h b/lib/sanitizer_common/sanitizer_bitvector.h index ef61486bff..d8472732ff 100644 --- a/lib/sanitizer_common/sanitizer_bitvector.h +++ b/lib/sanitizer_common/sanitizer_bitvector.h @@ -87,7 +87,7 @@ class BasicBitVector { // } class Iterator { public: - Iterator() = default; + Iterator() { } explicit Iterator(const BasicBitVector &bv) : bv_(bv) {} bool hasNext() const { return !bv_.empty(); } uptr next() { return bv_.getAndClearFirstOne(); } @@ -273,7 +273,7 @@ class TwoLevelBitVector { // } class Iterator { public: - Iterator() = default; + Iterator() { } explicit Iterator(const TwoLevelBitVector &bv) : bv_(bv), i0_(0), i1_(0) { it1_.clear(); it2_.clear(); diff --git a/lib/tsan/rtl/tsan_clock.h b/lib/tsan/rtl/tsan_clock.h index fd6509335f..4e352cb81d 100644 --- a/lib/tsan/rtl/tsan_clock.h +++ b/lib/tsan/rtl/tsan_clock.h @@ -33,7 +33,8 @@ struct ClockBlock { ClockElem clock[kClockCount]; }; - ClockBlock() = default; + ClockBlock() { + } }; typedef DenseSlabAlloc ClockAlloc; diff --git a/lib/tsan/rtl/tsan_mutex.cc b/lib/tsan/rtl/tsan_mutex.cc index e18f6fa70c..9dd24803b1 100644 --- a/lib/tsan/rtl/tsan_mutex.cc +++ b/lib/tsan/rtl/tsan_mutex.cc @@ -126,8 +126,9 @@ void InitializeMutex() { #endif } -// Rely on zero initialization because some mutexes can be locked before ctor. -InternalDeadlockDetector::InternalDeadlockDetector() = default; +InternalDeadlockDetector::InternalDeadlockDetector() { + // Rely on zero initialization because some mutexes can be locked before ctor. +} #if SANITIZER_DEBUG && !SANITIZER_GO void InternalDeadlockDetector::Lock(MutexType t) { diff --git a/lib/tsan/rtl/tsan_report.cc b/lib/tsan/rtl/tsan_report.cc index 9445c409dd..f4b06878a5 100644 --- a/lib/tsan/rtl/tsan_report.cc +++ b/lib/tsan/rtl/tsan_report.cc @@ -67,8 +67,9 @@ ReportMop::ReportMop() : mset(MBlockReportMutex) { } -// FIXME(dvyukov): it must be leaking a lot of memory. -ReportDesc::~ReportDesc() = default; +ReportDesc::~ReportDesc() { + // FIXME(dvyukov): it must be leaking a lot of memory. +} #ifndef SANITIZER_GO diff --git a/lib/tsan/rtl/tsan_rtl_thread.cc b/lib/tsan/rtl/tsan_rtl_thread.cc index a167ce1986..66c78cfdd7 100644 --- a/lib/tsan/rtl/tsan_rtl_thread.cc +++ b/lib/tsan/rtl/tsan_rtl_thread.cc @@ -31,7 +31,8 @@ ThreadContext::ThreadContext(int tid) } #ifndef SANITIZER_GO -ThreadContext::~ThreadContext() = default; +ThreadContext::~ThreadContext() { +} #endif void ThreadContext::OnDead() { diff --git a/lib/ubsan/ubsan_diag.h b/lib/ubsan/ubsan_diag.h index daa5ab2b82..2aa62eb743 100644 --- a/lib/ubsan/ubsan_diag.h +++ b/lib/ubsan/ubsan_diag.h @@ -150,7 +150,7 @@ class Diag { /// An individual diagnostic message argument. struct Arg { - Arg() = default; + Arg() {} Arg(const char *String) : Kind(AK_String), String(String) {} Arg(TypeName TN) : Kind(AK_TypeName), String(TN.getName()) {} Arg(UIntMax UInt) : Kind(AK_UInt), UInt(UInt) {} From fe1142ec1069bb92bdc43e4f9ab16a0de374c6ff Mon Sep 17 00:00:00 2001 From: Kuba Brecka Date: Tue, 3 Nov 2015 14:13:59 +0000 Subject: [PATCH 24/68] [tsan] CMake support for TSan on OS X Hi, this patch adds a CMake flag called `COMPILER_RT_ENABLE_TSAN_OSX`, which is off by default. If enabled, the build system will be building the OS X version of the TSan runtime library (called `libclang_rt.tsan_osx_dynamic.dylib`). I'll submit patches that fix OS X build errors shortly. This is part of an effort to port TSan to OS X, and it's one the very first steps. Don't expect TSan on OS X to actually work or pass tests at this point. git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/trunk@251915 91177308-0d34-0410-b5e6-96231b3b80d8 --- cmake/config-ix.cmake | 8 +++ lib/tsan/CMakeLists.txt | 104 ++++++++++++++++++++++----------------- test/tsan/CMakeLists.txt | 2 +- 3 files changed, 68 insertions(+), 46 deletions(-) diff --git a/cmake/config-ix.cmake b/cmake/config-ix.cmake index cd57ac558c..f137d51c7f 100644 --- a/cmake/config-ix.cmake +++ b/cmake/config-ix.cmake @@ -290,6 +290,7 @@ if(APPLE) set(SANITIZER_COMMON_SUPPORTED_OS osx) set(BUILTIN_SUPPORTED_OS osx) set(PROFILE_SUPPORTED_OS osx) + set(TSAN_SUPPORTED_OS osx) if(NOT SANITIZER_MIN_OSX_VERSION) string(REGEX MATCH "-mmacosx-version-min=([.0-9]+)" MACOSX_VERSION_MIN_FLAG "${CMAKE_CXX_FLAGS}") @@ -547,6 +548,13 @@ else() set(COMPILER_RT_HAS_TSAN FALSE) endif() +if(APPLE) + option(COMPILER_RT_ENABLE_TSAN_OSX "Enable building TSan for OS X - Experimental" Off) + if(COMPILER_RT_ENABLE_TSAN_OSX) + set(COMPILER_RT_HAS_TSAN TRUE) + endif() +endif() + if (COMPILER_RT_HAS_SANITIZER_COMMON AND UBSAN_SUPPORTED_ARCH AND OS_NAME MATCHES "Darwin|Linux|FreeBSD|Windows") set(COMPILER_RT_HAS_UBSAN TRUE) diff --git a/lib/tsan/CMakeLists.txt b/lib/tsan/CMakeLists.txt index 2f246d42b4..fb382d7ee1 100644 --- a/lib/tsan/CMakeLists.txt +++ b/lib/tsan/CMakeLists.txt @@ -83,52 +83,66 @@ set(TSAN_HEADERS set(TSAN_RUNTIME_LIBRARIES) add_custom_target(tsan) -foreach(arch ${TSAN_SUPPORTED_ARCH}) - if(arch STREQUAL "x86_64") - set(TSAN_ASM_SOURCES rtl/tsan_rtl_amd64.S) - # Pass ASM file directly to the C++ compiler. - set_source_files_properties(${TSAN_ASM_SOURCES} PROPERTIES - LANGUAGE C) - # Sanity check for Go runtime. - set(BUILDGO_SCRIPT ${CMAKE_CURRENT_SOURCE_DIR}/go/buildgo.sh) - add_custom_target(GotsanRuntimeCheck - COMMAND env "CC=${CMAKE_C_COMPILER} ${CMAKE_C_COMPILER_ARG1}" - IN_TMPDIR=1 SILENT=1 ${BUILDGO_SCRIPT} - DEPENDS clang_rt.tsan-${arch} ${BUILDGO_SCRIPT} - WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/go - COMMENT "Checking TSan Go runtime..." - VERBATIM) - else() - set(TSAN_ASM_SOURCES) - endif() +if(APPLE) add_compiler_rt_runtime(clang_rt.tsan - STATIC - ARCHS ${arch} - SOURCES ${TSAN_SOURCES} ${TSAN_ASM_SOURCES} - $ - $ - $ - $ - CFLAGS ${TSAN_RTL_CFLAGS}) - add_compiler_rt_runtime(clang_rt.tsan_cxx - STATIC - ARCHS ${arch} - SOURCES ${TSAN_CXX_SOURCES} - $ - CFLAGS ${TSAN_RTL_CFLAGS}) - list(APPEND TSAN_RUNTIME_LIBRARIES clang_rt.tsan-${arch} - clang_rt.tsan_cxx-${arch}) - add_sanitizer_rt_symbols(clang_rt.tsan - ARCHS ${arch} - EXTRA rtl/tsan.syms.extra) - add_sanitizer_rt_symbols(clang_rt.tsan_cxx - ARCHS ${arch} - EXTRA rtl/tsan.syms.extra) - add_dependencies(tsan clang_rt.tsan-${arch} - clang_rt.tsan_cxx-${arch} - clang_rt.tsan-${arch}-symbols - clang_rt.tsan_cxx-${arch}-symbols) -endforeach() + SHARED + OS ${TSAN_SUPPORTED_OS} + ARCHS ${TSAN_SUPPORTED_ARCH} + SOURCES ${TSAN_SOURCES} + OBJECT_LIBS RTInterception + RTSanitizerCommon + RTSanitizerCommonLibc + RTUbsan + CFLAGS ${TSAN_RTL_CFLAGS} + PARENT_TARGET tsan) +else() + foreach(arch ${TSAN_SUPPORTED_ARCH}) + if(arch STREQUAL "x86_64") + set(TSAN_ASM_SOURCES rtl/tsan_rtl_amd64.S) + # Pass ASM file directly to the C++ compiler. + set_source_files_properties(${TSAN_ASM_SOURCES} PROPERTIES + LANGUAGE C) + # Sanity check for Go runtime. + set(BUILDGO_SCRIPT ${CMAKE_CURRENT_SOURCE_DIR}/go/buildgo.sh) + add_custom_target(GotsanRuntimeCheck + COMMAND env "CC=${CMAKE_C_COMPILER} ${CMAKE_C_COMPILER_ARG1}" + IN_TMPDIR=1 SILENT=1 ${BUILDGO_SCRIPT} + DEPENDS clang_rt.tsan-${arch} ${BUILDGO_SCRIPT} + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/go + COMMENT "Checking TSan Go runtime..." + VERBATIM) + else() + set(TSAN_ASM_SOURCES) + endif() + add_compiler_rt_runtime(clang_rt.tsan + STATIC + ARCHS ${arch} + SOURCES ${TSAN_SOURCES} ${TSAN_ASM_SOURCES} + $ + $ + $ + $ + CFLAGS ${TSAN_RTL_CFLAGS}) + add_compiler_rt_runtime(clang_rt.tsan_cxx + STATIC + ARCHS ${arch} + SOURCES ${TSAN_CXX_SOURCES} + $ + CFLAGS ${TSAN_RTL_CFLAGS}) + list(APPEND TSAN_RUNTIME_LIBRARIES clang_rt.tsan-${arch} + clang_rt.tsan_cxx-${arch}) + add_sanitizer_rt_symbols(clang_rt.tsan + ARCHS ${arch} + EXTRA rtl/tsan.syms.extra) + add_sanitizer_rt_symbols(clang_rt.tsan_cxx + ARCHS ${arch} + EXTRA rtl/tsan.syms.extra) + add_dependencies(tsan clang_rt.tsan-${arch} + clang_rt.tsan_cxx-${arch} + clang_rt.tsan-${arch}-symbols + clang_rt.tsan_cxx-${arch}-symbols) + endforeach() +endif() add_dependencies(compiler-rt tsan) diff --git a/test/tsan/CMakeLists.txt b/test/tsan/CMakeLists.txt index 6068556706..1492ddb64f 100644 --- a/test/tsan/CMakeLists.txt +++ b/test/tsan/CMakeLists.txt @@ -1,5 +1,5 @@ set(TSAN_TEST_DEPS ${SANITIZER_COMMON_LIT_TEST_DEPS}) -if(NOT ${COMPILER_RT_DEFAULT_TARGET_ARCH} MATCHES "mips") +if(NOT ${COMPILER_RT_DEFAULT_TARGET_ARCH} MATCHES "mips" AND NOT APPLE) list(APPEND TSAN_TEST_DEPS GotsanRuntimeCheck) endif() if(NOT COMPILER_RT_STANDALONE_BUILD) From 28992d9bb6467a122d1597ebc8e86f5018aa7ce7 Mon Sep 17 00:00:00 2001 From: Kuba Brecka Date: Tue, 3 Nov 2015 14:22:51 +0000 Subject: [PATCH 25/68] [tsan] Port TSan interceptors on OS X This patch modifies `tsan_interceptors.cc` to be buildable on OS X. Several of the intercepted methods are not available on OS X, so we need to `#if !SANITIZER_MAC` them. Plus a few other fixes, e.g. `pthread_yield` doesn't exist, let's use `internal_sched_yield` instead. This is part of an effort to port TSan to OS X, and it's one the very first steps. Don't expect TSan on OS X to actually work or pass tests at this point. Differential Revision: http://reviews.llvm.org/D14237 git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/trunk@251916 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/tsan/rtl/tsan_interceptors.cc | 254 ++++++++++++++++++------------ 1 file changed, 151 insertions(+), 103 deletions(-) diff --git a/lib/tsan/rtl/tsan_interceptors.cc b/lib/tsan/rtl/tsan_interceptors.cc index c0864218e0..c911965b40 100644 --- a/lib/tsan/rtl/tsan_interceptors.cc +++ b/lib/tsan/rtl/tsan_interceptors.cc @@ -28,16 +28,28 @@ #include "tsan_mman.h" #include "tsan_fd.h" +#if SANITIZER_POSIX +#include "sanitizer_common/sanitizer_posix.h" +#endif + using namespace __tsan; // NOLINT -#if SANITIZER_FREEBSD +#if SANITIZER_FREEBSD || SANITIZER_MAC #define __errno_location __error -#define __libc_realloc __realloc -#define __libc_calloc __calloc #define stdout __stdoutp #define stderr __stderrp #endif +#if SANITIZER_FREEBSD +#define __libc_realloc __realloc +#define __libc_calloc __calloc +#elif SANITIZER_MAC +#define __libc_malloc REAL(malloc) +#define __libc_realloc REAL(realloc) +#define __libc_calloc REAL(calloc) +#define __libc_free REAL(free) +#endif + #if SANITIZER_LINUX || SANITIZER_FREEBSD #define PTHREAD_CREATE_DETACHED 1 #elif SANITIZER_MAC @@ -80,7 +92,6 @@ extern "C" int pthread_attr_setstacksize(void *attr, uptr stacksize); extern "C" int pthread_key_create(unsigned *key, void (*destructor)(void* v)); extern "C" int pthread_setspecific(unsigned key, const void *v); DECLARE_REAL(int, pthread_mutexattr_gettype, void *, void *) -extern "C" int pthread_yield(); extern "C" int pthread_sigmask(int how, const __sanitizer_sigset_t *set, __sanitizer_sigset_t *oldset); // REAL(sigfillset) defined in common interceptors. @@ -323,6 +334,79 @@ TSAN_INTERCEPTOR(int, nanosleep, void *req, void *rem) { return res; } +TSAN_INTERCEPTOR(void*, malloc, uptr size) { + if (cur_thread()->in_symbolizer) + return __libc_malloc(size); + void *p = 0; + { + SCOPED_INTERCEPTOR_RAW(malloc, size); + p = user_alloc(thr, pc, size); + } + invoke_malloc_hook(p, size); + return p; +} + +#if !SANITIZER_MAC +TSAN_INTERCEPTOR(void*, __libc_memalign, uptr align, uptr sz) { + SCOPED_TSAN_INTERCEPTOR(__libc_memalign, align, sz); + return user_alloc(thr, pc, sz, align); +} +#endif + +TSAN_INTERCEPTOR(void*, calloc, uptr size, uptr n) { + if (cur_thread()->in_symbolizer) + return __libc_calloc(size, n); + void *p = 0; + { + SCOPED_INTERCEPTOR_RAW(calloc, size, n); + p = user_calloc(thr, pc, size, n); + } + invoke_malloc_hook(p, n * size); + return p; +} + +TSAN_INTERCEPTOR(void*, realloc, void *p, uptr size) { + if (cur_thread()->in_symbolizer) + return __libc_realloc(p, size); + if (p) + invoke_free_hook(p); + { + SCOPED_INTERCEPTOR_RAW(realloc, p, size); + p = user_realloc(thr, pc, p, size); + } + invoke_malloc_hook(p, size); + return p; +} + +TSAN_INTERCEPTOR(void, free, void *p) { + if (p == 0) + return; + if (cur_thread()->in_symbolizer) + return __libc_free(p); + invoke_free_hook(p); + SCOPED_INTERCEPTOR_RAW(free, p); + user_free(thr, pc, p); +} + +#if !SANITIZER_MAC +TSAN_INTERCEPTOR(void, cfree, void *p) { + if (p == 0) + return; + if (cur_thread()->in_symbolizer) + return __libc_free(p); + invoke_free_hook(p); + SCOPED_INTERCEPTOR_RAW(cfree, p); + user_free(thr, pc, p); +} +#endif + +#if !SANITIZER_MAC +TSAN_INTERCEPTOR(uptr, malloc_usable_size, void *p) { + SCOPED_INTERCEPTOR_RAW(malloc_usable_size, p); + return user_alloc_usable_size(p); +} +#endif + // The sole reason tsan wraps atexit callbacks is to establish synchronization // between callback setup and callback execution. struct AtExitCtx { @@ -381,6 +465,7 @@ static void on_exit_wrapper(int status, void *arg) { __libc_free(ctx); } +#if !SANITIZER_MAC TSAN_INTERCEPTOR(int, on_exit, void(*f)(int, void*), void *arg) { if (cur_thread()->in_symbolizer) return 0; @@ -396,6 +481,7 @@ TSAN_INTERCEPTOR(int, on_exit, void(*f)(int, void*), void *arg) { ThreadIgnoreEnd(thr, pc); return res; } +#endif // Cleanup old bufs. static void JmpBufGarbageCollect(ThreadState *thr, uptr sp) { @@ -519,73 +605,6 @@ TSAN_INTERCEPTOR(void, siglongjmp, uptr *env, int val) { REAL(siglongjmp)(env, val); } -TSAN_INTERCEPTOR(void*, malloc, uptr size) { - if (cur_thread()->in_symbolizer) - return __libc_malloc(size); - void *p = 0; - { - SCOPED_INTERCEPTOR_RAW(malloc, size); - p = user_alloc(thr, pc, size); - } - invoke_malloc_hook(p, size); - return p; -} - -TSAN_INTERCEPTOR(void*, __libc_memalign, uptr align, uptr sz) { - SCOPED_TSAN_INTERCEPTOR(__libc_memalign, align, sz); - return user_alloc(thr, pc, sz, align); -} - -TSAN_INTERCEPTOR(void*, calloc, uptr size, uptr n) { - if (cur_thread()->in_symbolizer) - return __libc_calloc(size, n); - void *p = 0; - { - SCOPED_INTERCEPTOR_RAW(calloc, size, n); - p = user_calloc(thr, pc, size, n); - } - invoke_malloc_hook(p, n * size); - return p; -} - -TSAN_INTERCEPTOR(void*, realloc, void *p, uptr size) { - if (cur_thread()->in_symbolizer) - return __libc_realloc(p, size); - if (p) - invoke_free_hook(p); - { - SCOPED_INTERCEPTOR_RAW(realloc, p, size); - p = user_realloc(thr, pc, p, size); - } - invoke_malloc_hook(p, size); - return p; -} - -TSAN_INTERCEPTOR(void, free, void *p) { - if (p == 0) - return; - if (cur_thread()->in_symbolizer) - return __libc_free(p); - invoke_free_hook(p); - SCOPED_INTERCEPTOR_RAW(free, p); - user_free(thr, pc, p); -} - -TSAN_INTERCEPTOR(void, cfree, void *p) { - if (p == 0) - return; - if (cur_thread()->in_symbolizer) - return __libc_free(p); - invoke_free_hook(p); - SCOPED_INTERCEPTOR_RAW(cfree, p); - user_free(thr, pc, p); -} - -TSAN_INTERCEPTOR(uptr, malloc_usable_size, void *p) { - SCOPED_INTERCEPTOR_RAW(malloc_usable_size, p); - return user_alloc_usable_size(p); -} - TSAN_INTERCEPTOR(uptr, strlen, const char *s) { SCOPED_TSAN_INTERCEPTOR(strlen, s); uptr len = internal_strlen(s); @@ -628,6 +647,7 @@ TSAN_INTERCEPTOR(char*, strchr, char *s, int c) { return res; } +#if !SANITIZER_MAC TSAN_INTERCEPTOR(char*, strchrnul, char *s, int c) { SCOPED_TSAN_INTERCEPTOR(strchrnul, s, c); char *res = REAL(strchrnul)(s, c); @@ -635,6 +655,7 @@ TSAN_INTERCEPTOR(char*, strchrnul, char *s, int c) { READ_STRING(thr, pc, s, len); return res; } +#endif TSAN_INTERCEPTOR(char*, strrchr, char *s, int c) { SCOPED_TSAN_INTERCEPTOR(strrchr, s, c); @@ -692,7 +713,7 @@ TSAN_INTERCEPTOR(void*, mmap, void *addr, long_t sz, int prot, return res; } -#if !SANITIZER_FREEBSD +#if !SANITIZER_FREEBSD && !SANITIZER_MAC TSAN_INTERCEPTOR(void*, mmap64, void *addr, long_t sz, int prot, int flags, int fd, u64 off) { SCOPED_TSAN_INTERCEPTOR(mmap64, addr, sz, prot, flags, fd, off); @@ -722,7 +743,7 @@ TSAN_INTERCEPTOR(int, munmap, void *addr, long_t sz) { return res; } -#if !SANITIZER_FREEBSD +#if !SANITIZER_FREEBSD && !SANITIZER_MAC TSAN_INTERCEPTOR(void*, memalign, uptr align, uptr sz) { SCOPED_INTERCEPTOR_RAW(memalign, align, sz); return user_alloc(thr, pc, sz, align); @@ -732,17 +753,19 @@ TSAN_INTERCEPTOR(void*, memalign, uptr align, uptr sz) { #define TSAN_MAYBE_INTERCEPT_MEMALIGN #endif +#if !SANITIZER_MAC TSAN_INTERCEPTOR(void*, aligned_alloc, uptr align, uptr sz) { SCOPED_INTERCEPTOR_RAW(memalign, align, sz); return user_alloc(thr, pc, sz, align); } +#endif TSAN_INTERCEPTOR(void*, valloc, uptr sz) { SCOPED_INTERCEPTOR_RAW(valloc, sz); return user_alloc(thr, pc, sz, GetPageSizeCached()); } -#if !SANITIZER_FREEBSD +#if !SANITIZER_FREEBSD && !SANITIZER_MAC TSAN_INTERCEPTOR(void*, pvalloc, uptr sz) { SCOPED_INTERCEPTOR_RAW(pvalloc, sz); sz = RoundUp(sz, GetPageSizeCached()); @@ -831,7 +854,7 @@ extern "C" void *__tsan_thread_start_func(void *arg) { } ThreadIgnoreEnd(thr, 0); while ((tid = atomic_load(&p->tid, memory_order_acquire)) == 0) - pthread_yield(); + internal_sched_yield(); ThreadStart(thr, tid, GetTid()); atomic_store(&p->tid, 0, memory_order_release); } @@ -891,7 +914,7 @@ TSAN_INTERCEPTOR(int, pthread_create, // before the new thread got a chance to acquire from it in ThreadStart. atomic_store(&p.tid, tid, memory_order_release); while (atomic_load(&p.tid, memory_order_acquire) != 0) - pthread_yield(); + internal_sched_yield(); } if (attr == &myattr) pthread_attr_destroy(&myattr); @@ -1094,6 +1117,7 @@ TSAN_INTERCEPTOR(int, pthread_mutex_trylock, void *m) { return res; } +#if !SANITIZER_MAC TSAN_INTERCEPTOR(int, pthread_mutex_timedlock, void *m, void *abstime) { SCOPED_TSAN_INTERCEPTOR(pthread_mutex_timedlock, m, abstime); int res = REAL(pthread_mutex_timedlock)(m, abstime); @@ -1102,7 +1126,9 @@ TSAN_INTERCEPTOR(int, pthread_mutex_timedlock, void *m, void *abstime) { } return res; } +#endif +#if !SANITIZER_MAC TSAN_INTERCEPTOR(int, pthread_spin_init, void *m, int pshared) { SCOPED_TSAN_INTERCEPTOR(pthread_spin_init, m, pshared); int res = REAL(pthread_spin_init)(m, pshared); @@ -1145,6 +1171,7 @@ TSAN_INTERCEPTOR(int, pthread_spin_unlock, void *m) { int res = REAL(pthread_spin_unlock)(m); return res; } +#endif TSAN_INTERCEPTOR(int, pthread_rwlock_init, void *m, void *a) { SCOPED_TSAN_INTERCEPTOR(pthread_rwlock_init, m, a); @@ -1182,6 +1209,7 @@ TSAN_INTERCEPTOR(int, pthread_rwlock_tryrdlock, void *m) { return res; } +#if !SANITIZER_MAC TSAN_INTERCEPTOR(int, pthread_rwlock_timedrdlock, void *m, void *abstime) { SCOPED_TSAN_INTERCEPTOR(pthread_rwlock_timedrdlock, m, abstime); int res = REAL(pthread_rwlock_timedrdlock)(m, abstime); @@ -1190,6 +1218,7 @@ TSAN_INTERCEPTOR(int, pthread_rwlock_timedrdlock, void *m, void *abstime) { } return res; } +#endif TSAN_INTERCEPTOR(int, pthread_rwlock_wrlock, void *m) { SCOPED_TSAN_INTERCEPTOR(pthread_rwlock_wrlock, m); @@ -1209,6 +1238,7 @@ TSAN_INTERCEPTOR(int, pthread_rwlock_trywrlock, void *m) { return res; } +#if !SANITIZER_MAC TSAN_INTERCEPTOR(int, pthread_rwlock_timedwrlock, void *m, void *abstime) { SCOPED_TSAN_INTERCEPTOR(pthread_rwlock_timedwrlock, m, abstime); int res = REAL(pthread_rwlock_timedwrlock)(m, abstime); @@ -1217,6 +1247,7 @@ TSAN_INTERCEPTOR(int, pthread_rwlock_timedwrlock, void *m, void *abstime) { } return res; } +#endif TSAN_INTERCEPTOR(int, pthread_rwlock_unlock, void *m) { SCOPED_TSAN_INTERCEPTOR(pthread_rwlock_unlock, m); @@ -1225,6 +1256,7 @@ TSAN_INTERCEPTOR(int, pthread_rwlock_unlock, void *m) { return res; } +#if !SANITIZER_MAC TSAN_INTERCEPTOR(int, pthread_barrier_init, void *b, void *a, unsigned count) { SCOPED_TSAN_INTERCEPTOR(pthread_barrier_init, b, a, count); MemoryWrite(thr, pc, (uptr)b, kSizeLog1); @@ -1250,6 +1282,7 @@ TSAN_INTERCEPTOR(int, pthread_barrier_wait, void *b) { } return res; } +#endif TSAN_INTERCEPTOR(int, pthread_once, void *o, void (*f)()) { SCOPED_INTERCEPTOR_RAW(pthread_once, o, f); @@ -1265,7 +1298,7 @@ TSAN_INTERCEPTOR(int, pthread_once, void *o, void (*f)()) { atomic_store(a, 2, memory_order_release); } else { while (v != 2) { - pthread_yield(); + internal_sched_yield(); v = atomic_load(a, memory_order_acquire); } if (!thr->in_ignored_lib) @@ -1274,7 +1307,7 @@ TSAN_INTERCEPTOR(int, pthread_once, void *o, void (*f)()) { return 0; } -#if !SANITIZER_FREEBSD +#if !SANITIZER_FREEBSD && !SANITIZER_MAC TSAN_INTERCEPTOR(int, __xstat, int version, const char *path, void *buf) { SCOPED_TSAN_INTERCEPTOR(__xstat, version, path, buf); READ_STRING(thr, pc, path, 0); @@ -1286,7 +1319,7 @@ TSAN_INTERCEPTOR(int, __xstat, int version, const char *path, void *buf) { #endif TSAN_INTERCEPTOR(int, stat, const char *path, void *buf) { -#if SANITIZER_FREEBSD +#if SANITIZER_FREEBSD || SANITIZER_MAC SCOPED_TSAN_INTERCEPTOR(stat, path, buf); READ_STRING(thr, pc, path, 0); return REAL(stat)(path, buf); @@ -1297,7 +1330,7 @@ TSAN_INTERCEPTOR(int, stat, const char *path, void *buf) { #endif } -#if !SANITIZER_FREEBSD +#if !SANITIZER_FREEBSD && !SANITIZER_MAC TSAN_INTERCEPTOR(int, __xstat64, int version, const char *path, void *buf) { SCOPED_TSAN_INTERCEPTOR(__xstat64, version, path, buf); READ_STRING(thr, pc, path, 0); @@ -1308,7 +1341,7 @@ TSAN_INTERCEPTOR(int, __xstat64, int version, const char *path, void *buf) { #define TSAN_MAYBE_INTERCEPT___XSTAT64 #endif -#if !SANITIZER_FREEBSD +#if !SANITIZER_FREEBSD && !SANITIZER_MAC TSAN_INTERCEPTOR(int, stat64, const char *path, void *buf) { SCOPED_TSAN_INTERCEPTOR(__xstat64, 0, path, buf); READ_STRING(thr, pc, path, 0); @@ -1319,7 +1352,7 @@ TSAN_INTERCEPTOR(int, stat64, const char *path, void *buf) { #define TSAN_MAYBE_INTERCEPT_STAT64 #endif -#if !SANITIZER_FREEBSD +#if !SANITIZER_FREEBSD && !SANITIZER_MAC TSAN_INTERCEPTOR(int, __lxstat, int version, const char *path, void *buf) { SCOPED_TSAN_INTERCEPTOR(__lxstat, version, path, buf); READ_STRING(thr, pc, path, 0); @@ -1331,7 +1364,7 @@ TSAN_INTERCEPTOR(int, __lxstat, int version, const char *path, void *buf) { #endif TSAN_INTERCEPTOR(int, lstat, const char *path, void *buf) { -#if SANITIZER_FREEBSD +#if SANITIZER_FREEBSD || SANITIZER_MAC SCOPED_TSAN_INTERCEPTOR(lstat, path, buf); READ_STRING(thr, pc, path, 0); return REAL(lstat)(path, buf); @@ -1342,7 +1375,7 @@ TSAN_INTERCEPTOR(int, lstat, const char *path, void *buf) { #endif } -#if !SANITIZER_FREEBSD +#if !SANITIZER_FREEBSD && !SANITIZER_MAC TSAN_INTERCEPTOR(int, __lxstat64, int version, const char *path, void *buf) { SCOPED_TSAN_INTERCEPTOR(__lxstat64, version, path, buf); READ_STRING(thr, pc, path, 0); @@ -1353,7 +1386,7 @@ TSAN_INTERCEPTOR(int, __lxstat64, int version, const char *path, void *buf) { #define TSAN_MAYBE_INTERCEPT___LXSTAT64 #endif -#if !SANITIZER_FREEBSD +#if !SANITIZER_FREEBSD && !SANITIZER_MAC TSAN_INTERCEPTOR(int, lstat64, const char *path, void *buf) { SCOPED_TSAN_INTERCEPTOR(__lxstat64, 0, path, buf); READ_STRING(thr, pc, path, 0); @@ -1364,7 +1397,7 @@ TSAN_INTERCEPTOR(int, lstat64, const char *path, void *buf) { #define TSAN_MAYBE_INTERCEPT_LSTAT64 #endif -#if !SANITIZER_FREEBSD +#if !SANITIZER_FREEBSD && !SANITIZER_MAC TSAN_INTERCEPTOR(int, __fxstat, int version, int fd, void *buf) { SCOPED_TSAN_INTERCEPTOR(__fxstat, version, fd, buf); if (fd > 0) @@ -1377,7 +1410,7 @@ TSAN_INTERCEPTOR(int, __fxstat, int version, int fd, void *buf) { #endif TSAN_INTERCEPTOR(int, fstat, int fd, void *buf) { -#if SANITIZER_FREEBSD +#if SANITIZER_FREEBSD || SANITIZER_MAC SCOPED_TSAN_INTERCEPTOR(fstat, fd, buf); if (fd > 0) FdAccess(thr, pc, fd); @@ -1390,7 +1423,7 @@ TSAN_INTERCEPTOR(int, fstat, int fd, void *buf) { #endif } -#if !SANITIZER_FREEBSD +#if !SANITIZER_FREEBSD && !SANITIZER_MAC TSAN_INTERCEPTOR(int, __fxstat64, int version, int fd, void *buf) { SCOPED_TSAN_INTERCEPTOR(__fxstat64, version, fd, buf); if (fd > 0) @@ -1402,7 +1435,7 @@ TSAN_INTERCEPTOR(int, __fxstat64, int version, int fd, void *buf) { #define TSAN_MAYBE_INTERCEPT___FXSTAT64 #endif -#if !SANITIZER_FREEBSD +#if !SANITIZER_FREEBSD && !SANITIZER_MAC TSAN_INTERCEPTOR(int, fstat64, int fd, void *buf) { SCOPED_TSAN_INTERCEPTOR(__fxstat64, 0, fd, buf); if (fd > 0) @@ -1423,7 +1456,7 @@ TSAN_INTERCEPTOR(int, open, const char *name, int flags, int mode) { return fd; } -#if !SANITIZER_FREEBSD +#if !SANITIZER_FREEBSD && !SANITIZER_MAC TSAN_INTERCEPTOR(int, open64, const char *name, int flags, int mode) { SCOPED_TSAN_INTERCEPTOR(open64, name, flags, mode); READ_STRING(thr, pc, name, 0); @@ -1446,7 +1479,7 @@ TSAN_INTERCEPTOR(int, creat, const char *name, int mode) { return fd; } -#if !SANITIZER_FREEBSD +#if !SANITIZER_FREEBSD && !SANITIZER_MAC TSAN_INTERCEPTOR(int, creat64, const char *name, int mode) { SCOPED_TSAN_INTERCEPTOR(creat64, name, mode); READ_STRING(thr, pc, name, 0); @@ -1476,6 +1509,7 @@ TSAN_INTERCEPTOR(int, dup2, int oldfd, int newfd) { return newfd2; } +#if !SANITIZER_MAC TSAN_INTERCEPTOR(int, dup3, int oldfd, int newfd, int flags) { SCOPED_TSAN_INTERCEPTOR(dup3, oldfd, newfd, flags); int newfd2 = REAL(dup3)(oldfd, newfd, flags); @@ -1483,8 +1517,9 @@ TSAN_INTERCEPTOR(int, dup3, int oldfd, int newfd, int flags) { FdDup(thr, pc, oldfd, newfd2, false); return newfd2; } +#endif -#if !SANITIZER_FREEBSD +#if !SANITIZER_FREEBSD && !SANITIZER_MAC TSAN_INTERCEPTOR(int, eventfd, unsigned initval, int flags) { SCOPED_TSAN_INTERCEPTOR(eventfd, initval, flags); int fd = REAL(eventfd)(initval, flags); @@ -1497,7 +1532,7 @@ TSAN_INTERCEPTOR(int, eventfd, unsigned initval, int flags) { #define TSAN_MAYBE_INTERCEPT_EVENTFD #endif -#if !SANITIZER_FREEBSD +#if !SANITIZER_FREEBSD && !SANITIZER_MAC TSAN_INTERCEPTOR(int, signalfd, int fd, void *mask, int flags) { SCOPED_TSAN_INTERCEPTOR(signalfd, fd, mask, flags); if (fd >= 0) @@ -1512,7 +1547,7 @@ TSAN_INTERCEPTOR(int, signalfd, int fd, void *mask, int flags) { #define TSAN_MAYBE_INTERCEPT_SIGNALFD #endif -#if !SANITIZER_FREEBSD +#if !SANITIZER_FREEBSD && !SANITIZER_MAC TSAN_INTERCEPTOR(int, inotify_init, int fake) { SCOPED_TSAN_INTERCEPTOR(inotify_init, fake); int fd = REAL(inotify_init)(fake); @@ -1525,7 +1560,7 @@ TSAN_INTERCEPTOR(int, inotify_init, int fake) { #define TSAN_MAYBE_INTERCEPT_INOTIFY_INIT #endif -#if !SANITIZER_FREEBSD +#if !SANITIZER_FREEBSD && !SANITIZER_MAC TSAN_INTERCEPTOR(int, inotify_init1, int flags) { SCOPED_TSAN_INTERCEPTOR(inotify_init1, flags); int fd = REAL(inotify_init1)(flags); @@ -1579,7 +1614,7 @@ TSAN_INTERCEPTOR(int, listen, int fd, int backlog) { return res; } -#if !SANITIZER_FREEBSD +#if !SANITIZER_FREEBSD && !SANITIZER_MAC TSAN_INTERCEPTOR(int, epoll_create, int size) { SCOPED_TSAN_INTERCEPTOR(epoll_create, size); int fd = REAL(epoll_create)(size); @@ -1592,7 +1627,7 @@ TSAN_INTERCEPTOR(int, epoll_create, int size) { #define TSAN_MAYBE_INTERCEPT_EPOLL_CREATE #endif -#if !SANITIZER_FREEBSD +#if !SANITIZER_FREEBSD && !SANITIZER_MAC TSAN_INTERCEPTOR(int, epoll_create1, int flags) { SCOPED_TSAN_INTERCEPTOR(epoll_create1, flags); int fd = REAL(epoll_create1)(flags); @@ -1612,7 +1647,7 @@ TSAN_INTERCEPTOR(int, close, int fd) { return REAL(close)(fd); } -#if !SANITIZER_FREEBSD +#if !SANITIZER_FREEBSD && !SANITIZER_MAC TSAN_INTERCEPTOR(int, __close, int fd) { SCOPED_TSAN_INTERCEPTOR(__close, fd); if (fd >= 0) @@ -1625,7 +1660,7 @@ TSAN_INTERCEPTOR(int, __close, int fd) { #endif // glibc guts -#if !SANITIZER_FREEBSD +#if !SANITIZER_FREEBSD && !SANITIZER_MAC TSAN_INTERCEPTOR(void, __res_iclose, void *state, bool free_addr) { SCOPED_TSAN_INTERCEPTOR(__res_iclose, state, free_addr); int fds[64]; @@ -1649,6 +1684,7 @@ TSAN_INTERCEPTOR(int, pipe, int *pipefd) { return res; } +#if !SANITIZER_MAC TSAN_INTERCEPTOR(int, pipe2, int *pipefd, int flags) { SCOPED_TSAN_INTERCEPTOR(pipe2, pipefd, flags); int res = REAL(pipe2)(pipefd, flags); @@ -1656,6 +1692,7 @@ TSAN_INTERCEPTOR(int, pipe2, int *pipefd, int flags) { FdPipeCreate(thr, pc, pipefd[0], pipefd[1]); return res; } +#endif TSAN_INTERCEPTOR(long_t, send, int fd, void *buf, long_t len, int flags) { SCOPED_TSAN_INTERCEPTOR(send, fd, buf, len, flags); @@ -1706,7 +1743,7 @@ TSAN_INTERCEPTOR(void*, tmpfile, int fake) { return res; } -#if !SANITIZER_FREEBSD +#if !SANITIZER_FREEBSD && !SANITIZER_MAC TSAN_INTERCEPTOR(void*, tmpfile64, int fake) { SCOPED_TSAN_INTERCEPTOR(tmpfile64, fake); void *res = REAL(tmpfile64)(fake); @@ -1773,7 +1810,7 @@ TSAN_INTERCEPTOR(int, closedir, void *dirp) { return REAL(closedir)(dirp); } -#if !SANITIZER_FREEBSD +#if !SANITIZER_FREEBSD && !SANITIZER_MAC TSAN_INTERCEPTOR(int, epoll_ctl, int epfd, int op, int fd, void *ev) { SCOPED_TSAN_INTERCEPTOR(epoll_ctl, epfd, op, fd, ev); if (epfd >= 0) @@ -1790,7 +1827,7 @@ TSAN_INTERCEPTOR(int, epoll_ctl, int epfd, int op, int fd, void *ev) { #define TSAN_MAYBE_INTERCEPT_EPOLL_CTL #endif -#if !SANITIZER_FREEBSD +#if !SANITIZER_FREEBSD && !SANITIZER_MAC TSAN_INTERCEPTOR(int, epoll_wait, int epfd, void *ev, int cnt, int timeout) { SCOPED_TSAN_INTERCEPTOR(epoll_wait, epfd, ev, cnt, timeout); if (epfd >= 0) @@ -2089,6 +2126,7 @@ TSAN_INTERCEPTOR(int, vfork, int fake) { return WRAP(fork)(fake); } +#if SANITIZER_LINUX typedef int (*dl_iterate_phdr_cb_t)(__sanitizer_dl_phdr_info *info, SIZE_T size, void *data); struct dl_iterate_phdr_data { @@ -2132,6 +2170,7 @@ TSAN_INTERCEPTOR(int, dl_iterate_phdr, dl_iterate_phdr_cb_t cb, void *data) { int res = REAL(dl_iterate_phdr)(dl_iterate_phdr_cb, &cbdata); return res; } +#endif static int OnExit(ThreadState *thr) { int status = Finalize(thr); @@ -2266,9 +2305,11 @@ static void HandleRecvmsg(ThreadState *thr, uptr pc, MutexRepair(((TsanInterceptorContext *)ctx)->thr, \ ((TsanInterceptorContext *)ctx)->pc, (uptr)m) +#if !SANITIZER_MAC #define COMMON_INTERCEPTOR_HANDLE_RECVMSG(ctx, msg) \ HandleRecvmsg(((TsanInterceptorContext *)ctx)->thr, \ ((TsanInterceptorContext *)ctx)->pc, msg) +#endif #define COMMON_INTERCEPTOR_GET_TLS_RANGE(begin, end) \ if (TsanThread *t = GetCurrentThread()) { \ @@ -2409,18 +2450,21 @@ static void unreachable() { } void InitializeInterceptors() { +#if !SANITIZER_MAC // We need to setup it early, because functions like dlsym() can call it. REAL(memset) = internal_memset; REAL(memcpy) = internal_memcpy; +#endif // Instruct libc malloc to consume less memory. -#if !SANITIZER_FREEBSD +#if !SANITIZER_FREEBSD && !SANITIZER_MAC mallopt(1, 0); // M_MXFAST mallopt(-3, 32*1024); // M_MMAP_THRESHOLD #endif InitializeCommonInterceptors(); +#if !SANITIZER_MAC // We can not use TSAN_INTERCEPT to get setjmp addr, // because it does &setjmp and setjmp is not present in some versions of libc. using __interception::GetRealFunctionAddress; @@ -2428,6 +2472,7 @@ void InitializeInterceptors() { GetRealFunctionAddress("_setjmp", (uptr*)&REAL(_setjmp), 0, 0); GetRealFunctionAddress("sigsetjmp", (uptr*)&REAL(sigsetjmp), 0, 0); GetRealFunctionAddress("__sigsetjmp", (uptr*)&REAL(__sigsetjmp), 0, 0); +#endif TSAN_INTERCEPT(longjmp); TSAN_INTERCEPT(siglongjmp); @@ -2567,9 +2612,12 @@ void InitializeInterceptors() { TSAN_INTERCEPT(__cxa_atexit); TSAN_INTERCEPT(_exit); +#if !SANITIZER_MAC // Need to setup it, because interceptors check that the function is resolved. // But atexit is emitted directly into the module, so can't be resolved. REAL(atexit) = (int(*)(void(*)()))unreachable; +#endif + if (REAL(__cxa_atexit)(&finalize, 0, 0)) { Printf("ThreadSanitizer: failed to setup atexit callback\n"); Die(); From 1d675fa9223743ddb4a5655fdcdb3262825f9578 Mon Sep 17 00:00:00 2001 From: Kuba Brecka Date: Tue, 3 Nov 2015 14:26:00 +0000 Subject: [PATCH 26/68] [tsan] Fix build errors for TSan on OS X This patch moves a few functions from `sanitizer_linux_libcdep.cc` to `sanitizer_posix_libcdep.cc` in order to use them on OS X as well. Plus a few more small build fixes. This is part of an effort to port TSan to OS X, and it's one the very first steps. Don't expect TSan on OS X to actually work or pass tests at this point. Differential Revision: http://reviews.llvm.org/D14235 git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/trunk@251918 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/sanitizer_common/sanitizer_libignore.cc | 2 +- .../sanitizer_linux_libcdep.cc | 41 ------------------ .../sanitizer_posix_libcdep.cc | 42 +++++++++++++++++++ lib/tsan/rtl/tsan_platform_mac.cc | 4 ++ lib/tsan/rtl/tsan_rtl.h | 2 +- 5 files changed, 48 insertions(+), 43 deletions(-) diff --git a/lib/sanitizer_common/sanitizer_libignore.cc b/lib/sanitizer_common/sanitizer_libignore.cc index fabd335856..545393966b 100644 --- a/lib/sanitizer_common/sanitizer_libignore.cc +++ b/lib/sanitizer_common/sanitizer_libignore.cc @@ -9,7 +9,7 @@ #include "sanitizer_platform.h" -#if SANITIZER_FREEBSD || SANITIZER_LINUX +#if SANITIZER_FREEBSD || SANITIZER_LINUX || SANITIZER_MAC #include "sanitizer_libignore.h" #include "sanitizer_flags.h" diff --git a/lib/sanitizer_common/sanitizer_linux_libcdep.cc b/lib/sanitizer_common/sanitizer_linux_libcdep.cc index cf58f04aa4..c5f979bcac 100644 --- a/lib/sanitizer_common/sanitizer_linux_libcdep.cc +++ b/lib/sanitizer_common/sanitizer_linux_libcdep.cc @@ -62,20 +62,6 @@ namespace __sanitizer { -// This function is defined elsewhere if we intercepted pthread_attr_getstack. -extern "C" { -SANITIZER_WEAK_ATTRIBUTE int -real_pthread_attr_getstack(void *attr, void **addr, size_t *size); -} // extern "C" - -static int my_pthread_attr_getstack(void *attr, void **addr, size_t *size) { -#if !SANITIZER_GO - if (&real_pthread_attr_getstack) - return real_pthread_attr_getstack((pthread_attr_t *)attr, addr, size); -#endif - return pthread_attr_getstack((pthread_attr_t *)attr, addr, size); -} - SANITIZER_WEAK_ATTRIBUTE int real_sigaction(int signum, const void *act, void *oldact); @@ -400,33 +386,6 @@ void GetThreadStackAndTls(bool main, uptr *stk_addr, uptr *stk_size, #endif } -#if !SANITIZER_GO -void AdjustStackSize(void *attr_) { - pthread_attr_t *attr = (pthread_attr_t *)attr_; - uptr stackaddr = 0; - size_t stacksize = 0; - my_pthread_attr_getstack(attr, (void**)&stackaddr, &stacksize); - // GLibC will return (0 - stacksize) as the stack address in the case when - // stacksize is set, but stackaddr is not. - bool stack_set = (stackaddr != 0) && (stackaddr + stacksize != 0); - // We place a lot of tool data into TLS, account for that. - const uptr minstacksize = GetTlsSize() + 128*1024; - if (stacksize < minstacksize) { - if (!stack_set) { - if (stacksize != 0) { - VPrintf(1, "Sanitizer: increasing stacksize %zu->%zu\n", stacksize, - minstacksize); - pthread_attr_setstacksize(attr, minstacksize); - } - } else { - Printf("Sanitizer: pre-allocated stack size is insufficient: " - "%zu < %zu\n", stacksize, minstacksize); - Printf("Sanitizer: pthread_create is likely to fail.\n"); - } - } -} -#endif // !SANITIZER_GO - # if !SANITIZER_FREEBSD typedef ElfW(Phdr) Elf_Phdr; # elif SANITIZER_WORDSIZE == 32 && __FreeBSD_version <= 902001 // v9.2 diff --git a/lib/sanitizer_common/sanitizer_posix_libcdep.cc b/lib/sanitizer_common/sanitizer_posix_libcdep.cc index b67a779b90..9ff5328ff6 100644 --- a/lib/sanitizer_common/sanitizer_posix_libcdep.cc +++ b/lib/sanitizer_common/sanitizer_posix_libcdep.cc @@ -276,6 +276,48 @@ void *MmapNoAccess(uptr fixed_addr, uptr size, const char *name) { return (void *)internal_mmap((void *)fixed_addr, size, PROT_NONE, flags, fd, 0); } + +// This function is defined elsewhere if we intercepted pthread_attr_getstack. +extern "C" { +SANITIZER_WEAK_ATTRIBUTE int +real_pthread_attr_getstack(void *attr, void **addr, size_t *size); +} // extern "C" + +static int my_pthread_attr_getstack(void *attr, void **addr, size_t *size) { +#if !SANITIZER_GO && !SANITIZER_MAC + if (&real_pthread_attr_getstack) + return real_pthread_attr_getstack((pthread_attr_t *)attr, addr, size); +#endif + return pthread_attr_getstack((pthread_attr_t *)attr, addr, size); +} + +#if !SANITIZER_GO +void AdjustStackSize(void *attr_) { + pthread_attr_t *attr = (pthread_attr_t *)attr_; + uptr stackaddr = 0; + size_t stacksize = 0; + my_pthread_attr_getstack(attr, (void**)&stackaddr, &stacksize); + // GLibC will return (0 - stacksize) as the stack address in the case when + // stacksize is set, but stackaddr is not. + bool stack_set = (stackaddr != 0) && (stackaddr + stacksize != 0); + // We place a lot of tool data into TLS, account for that. + const uptr minstacksize = GetTlsSize() + 128*1024; + if (stacksize < minstacksize) { + if (!stack_set) { + if (stacksize != 0) { + VPrintf(1, "Sanitizer: increasing stacksize %zu->%zu\n", stacksize, + minstacksize); + pthread_attr_setstacksize(attr, minstacksize); + } + } else { + Printf("Sanitizer: pre-allocated stack size is insufficient: " + "%zu < %zu\n", stacksize, minstacksize); + Printf("Sanitizer: pthread_create is likely to fail.\n"); + } + } +} +#endif // !SANITIZER_GO + } // namespace __sanitizer #endif // SANITIZER_POSIX diff --git a/lib/tsan/rtl/tsan_platform_mac.cc b/lib/tsan/rtl/tsan_platform_mac.cc index b72d9b07ef..32d340268f 100644 --- a/lib/tsan/rtl/tsan_platform_mac.cc +++ b/lib/tsan/rtl/tsan_platform_mac.cc @@ -91,6 +91,10 @@ int call_pthread_cancel_with_cleanup(int(*fn)(void *c, void *m, } #endif +bool IsGlobalVar(uptr addr) { + return false; +} + } // namespace __tsan #endif // SANITIZER_MAC diff --git a/lib/tsan/rtl/tsan_rtl.h b/lib/tsan/rtl/tsan_rtl.h index ae44bc9b3b..2618405757 100644 --- a/lib/tsan/rtl/tsan_rtl.h +++ b/lib/tsan/rtl/tsan_rtl.h @@ -709,7 +709,7 @@ void AcquireReleaseImpl(ThreadState *thr, uptr pc, SyncClock *c); // The trick is that the call preserves all registers and the compiler // does not treat it as a call. // If it does not work for you, use normal call. -#if !SANITIZER_DEBUG && defined(__x86_64__) +#if !SANITIZER_DEBUG && defined(__x86_64__) && !SANITIZER_MAC // The caller may not create the stack frame for itself at all, // so we create a reserve stack frame for it (1024b must be enough). #define HACKY_CALL(f) \ From 4d918b66b18e1b366fd6b8c21ee400f8f7362258 Mon Sep 17 00:00:00 2001 From: Kuba Brecka Date: Tue, 3 Nov 2015 14:30:31 +0000 Subject: [PATCH 27/68] Revert r251918 ("[tsan] Fix build errors for TSan on OS X"). git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/trunk@251919 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/sanitizer_common/sanitizer_libignore.cc | 2 +- .../sanitizer_linux_libcdep.cc | 41 ++++++++++++++++++ .../sanitizer_posix_libcdep.cc | 42 ------------------- lib/tsan/rtl/tsan_platform_mac.cc | 4 -- lib/tsan/rtl/tsan_rtl.h | 2 +- 5 files changed, 43 insertions(+), 48 deletions(-) diff --git a/lib/sanitizer_common/sanitizer_libignore.cc b/lib/sanitizer_common/sanitizer_libignore.cc index 545393966b..fabd335856 100644 --- a/lib/sanitizer_common/sanitizer_libignore.cc +++ b/lib/sanitizer_common/sanitizer_libignore.cc @@ -9,7 +9,7 @@ #include "sanitizer_platform.h" -#if SANITIZER_FREEBSD || SANITIZER_LINUX || SANITIZER_MAC +#if SANITIZER_FREEBSD || SANITIZER_LINUX #include "sanitizer_libignore.h" #include "sanitizer_flags.h" diff --git a/lib/sanitizer_common/sanitizer_linux_libcdep.cc b/lib/sanitizer_common/sanitizer_linux_libcdep.cc index c5f979bcac..cf58f04aa4 100644 --- a/lib/sanitizer_common/sanitizer_linux_libcdep.cc +++ b/lib/sanitizer_common/sanitizer_linux_libcdep.cc @@ -62,6 +62,20 @@ namespace __sanitizer { +// This function is defined elsewhere if we intercepted pthread_attr_getstack. +extern "C" { +SANITIZER_WEAK_ATTRIBUTE int +real_pthread_attr_getstack(void *attr, void **addr, size_t *size); +} // extern "C" + +static int my_pthread_attr_getstack(void *attr, void **addr, size_t *size) { +#if !SANITIZER_GO + if (&real_pthread_attr_getstack) + return real_pthread_attr_getstack((pthread_attr_t *)attr, addr, size); +#endif + return pthread_attr_getstack((pthread_attr_t *)attr, addr, size); +} + SANITIZER_WEAK_ATTRIBUTE int real_sigaction(int signum, const void *act, void *oldact); @@ -386,6 +400,33 @@ void GetThreadStackAndTls(bool main, uptr *stk_addr, uptr *stk_size, #endif } +#if !SANITIZER_GO +void AdjustStackSize(void *attr_) { + pthread_attr_t *attr = (pthread_attr_t *)attr_; + uptr stackaddr = 0; + size_t stacksize = 0; + my_pthread_attr_getstack(attr, (void**)&stackaddr, &stacksize); + // GLibC will return (0 - stacksize) as the stack address in the case when + // stacksize is set, but stackaddr is not. + bool stack_set = (stackaddr != 0) && (stackaddr + stacksize != 0); + // We place a lot of tool data into TLS, account for that. + const uptr minstacksize = GetTlsSize() + 128*1024; + if (stacksize < minstacksize) { + if (!stack_set) { + if (stacksize != 0) { + VPrintf(1, "Sanitizer: increasing stacksize %zu->%zu\n", stacksize, + minstacksize); + pthread_attr_setstacksize(attr, minstacksize); + } + } else { + Printf("Sanitizer: pre-allocated stack size is insufficient: " + "%zu < %zu\n", stacksize, minstacksize); + Printf("Sanitizer: pthread_create is likely to fail.\n"); + } + } +} +#endif // !SANITIZER_GO + # if !SANITIZER_FREEBSD typedef ElfW(Phdr) Elf_Phdr; # elif SANITIZER_WORDSIZE == 32 && __FreeBSD_version <= 902001 // v9.2 diff --git a/lib/sanitizer_common/sanitizer_posix_libcdep.cc b/lib/sanitizer_common/sanitizer_posix_libcdep.cc index 9ff5328ff6..b67a779b90 100644 --- a/lib/sanitizer_common/sanitizer_posix_libcdep.cc +++ b/lib/sanitizer_common/sanitizer_posix_libcdep.cc @@ -276,48 +276,6 @@ void *MmapNoAccess(uptr fixed_addr, uptr size, const char *name) { return (void *)internal_mmap((void *)fixed_addr, size, PROT_NONE, flags, fd, 0); } - -// This function is defined elsewhere if we intercepted pthread_attr_getstack. -extern "C" { -SANITIZER_WEAK_ATTRIBUTE int -real_pthread_attr_getstack(void *attr, void **addr, size_t *size); -} // extern "C" - -static int my_pthread_attr_getstack(void *attr, void **addr, size_t *size) { -#if !SANITIZER_GO && !SANITIZER_MAC - if (&real_pthread_attr_getstack) - return real_pthread_attr_getstack((pthread_attr_t *)attr, addr, size); -#endif - return pthread_attr_getstack((pthread_attr_t *)attr, addr, size); -} - -#if !SANITIZER_GO -void AdjustStackSize(void *attr_) { - pthread_attr_t *attr = (pthread_attr_t *)attr_; - uptr stackaddr = 0; - size_t stacksize = 0; - my_pthread_attr_getstack(attr, (void**)&stackaddr, &stacksize); - // GLibC will return (0 - stacksize) as the stack address in the case when - // stacksize is set, but stackaddr is not. - bool stack_set = (stackaddr != 0) && (stackaddr + stacksize != 0); - // We place a lot of tool data into TLS, account for that. - const uptr minstacksize = GetTlsSize() + 128*1024; - if (stacksize < minstacksize) { - if (!stack_set) { - if (stacksize != 0) { - VPrintf(1, "Sanitizer: increasing stacksize %zu->%zu\n", stacksize, - minstacksize); - pthread_attr_setstacksize(attr, minstacksize); - } - } else { - Printf("Sanitizer: pre-allocated stack size is insufficient: " - "%zu < %zu\n", stacksize, minstacksize); - Printf("Sanitizer: pthread_create is likely to fail.\n"); - } - } -} -#endif // !SANITIZER_GO - } // namespace __sanitizer #endif // SANITIZER_POSIX diff --git a/lib/tsan/rtl/tsan_platform_mac.cc b/lib/tsan/rtl/tsan_platform_mac.cc index 32d340268f..b72d9b07ef 100644 --- a/lib/tsan/rtl/tsan_platform_mac.cc +++ b/lib/tsan/rtl/tsan_platform_mac.cc @@ -91,10 +91,6 @@ int call_pthread_cancel_with_cleanup(int(*fn)(void *c, void *m, } #endif -bool IsGlobalVar(uptr addr) { - return false; -} - } // namespace __tsan #endif // SANITIZER_MAC diff --git a/lib/tsan/rtl/tsan_rtl.h b/lib/tsan/rtl/tsan_rtl.h index 2618405757..ae44bc9b3b 100644 --- a/lib/tsan/rtl/tsan_rtl.h +++ b/lib/tsan/rtl/tsan_rtl.h @@ -709,7 +709,7 @@ void AcquireReleaseImpl(ThreadState *thr, uptr pc, SyncClock *c); // The trick is that the call preserves all registers and the compiler // does not treat it as a call. // If it does not work for you, use normal call. -#if !SANITIZER_DEBUG && defined(__x86_64__) && !SANITIZER_MAC +#if !SANITIZER_DEBUG && defined(__x86_64__) // The caller may not create the stack frame for itself at all, // so we create a reserve stack frame for it (1024b must be enough). #define HACKY_CALL(f) \ From befa80c402fb212eaf3403096c7ff27103b2ce0b Mon Sep 17 00:00:00 2001 From: Kuba Brecka Date: Tue, 3 Nov 2015 14:33:39 +0000 Subject: [PATCH 28/68] Reapply r251918 ("[tsan] Fix build errors for TSan on OS X"). git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/trunk@251920 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/sanitizer_common/sanitizer_libignore.cc | 2 +- .../sanitizer_linux_libcdep.cc | 43 +------------------ lib/sanitizer_common/sanitizer_posix.h | 2 + .../sanitizer_posix_libcdep.cc | 43 +++++++++++++++++++ lib/tsan/rtl/tsan_platform_mac.cc | 4 ++ lib/tsan/rtl/tsan_rtl.h | 2 +- 6 files changed, 52 insertions(+), 44 deletions(-) diff --git a/lib/sanitizer_common/sanitizer_libignore.cc b/lib/sanitizer_common/sanitizer_libignore.cc index fabd335856..545393966b 100644 --- a/lib/sanitizer_common/sanitizer_libignore.cc +++ b/lib/sanitizer_common/sanitizer_libignore.cc @@ -9,7 +9,7 @@ #include "sanitizer_platform.h" -#if SANITIZER_FREEBSD || SANITIZER_LINUX +#if SANITIZER_FREEBSD || SANITIZER_LINUX || SANITIZER_MAC #include "sanitizer_libignore.h" #include "sanitizer_flags.h" diff --git a/lib/sanitizer_common/sanitizer_linux_libcdep.cc b/lib/sanitizer_common/sanitizer_linux_libcdep.cc index cf58f04aa4..0e2a334209 100644 --- a/lib/sanitizer_common/sanitizer_linux_libcdep.cc +++ b/lib/sanitizer_common/sanitizer_linux_libcdep.cc @@ -62,20 +62,6 @@ namespace __sanitizer { -// This function is defined elsewhere if we intercepted pthread_attr_getstack. -extern "C" { -SANITIZER_WEAK_ATTRIBUTE int -real_pthread_attr_getstack(void *attr, void **addr, size_t *size); -} // extern "C" - -static int my_pthread_attr_getstack(void *attr, void **addr, size_t *size) { -#if !SANITIZER_GO - if (&real_pthread_attr_getstack) - return real_pthread_attr_getstack((pthread_attr_t *)attr, addr, size); -#endif - return pthread_attr_getstack((pthread_attr_t *)attr, addr, size); -} - SANITIZER_WEAK_ATTRIBUTE int real_sigaction(int signum, const void *act, void *oldact); @@ -128,7 +114,7 @@ void GetThreadStackTopAndBottom(bool at_initialization, uptr *stack_top, CHECK_EQ(pthread_getattr_np(pthread_self(), &attr), 0); uptr stacksize = 0; void *stackaddr = nullptr; - my_pthread_attr_getstack(&attr, &stackaddr, (size_t*)&stacksize); + my_pthread_attr_getstack(&attr, &stackaddr, &stacksize); pthread_attr_destroy(&attr); CHECK_LE(stacksize, kMaxThreadStackSize); // Sanity check. @@ -400,33 +386,6 @@ void GetThreadStackAndTls(bool main, uptr *stk_addr, uptr *stk_size, #endif } -#if !SANITIZER_GO -void AdjustStackSize(void *attr_) { - pthread_attr_t *attr = (pthread_attr_t *)attr_; - uptr stackaddr = 0; - size_t stacksize = 0; - my_pthread_attr_getstack(attr, (void**)&stackaddr, &stacksize); - // GLibC will return (0 - stacksize) as the stack address in the case when - // stacksize is set, but stackaddr is not. - bool stack_set = (stackaddr != 0) && (stackaddr + stacksize != 0); - // We place a lot of tool data into TLS, account for that. - const uptr minstacksize = GetTlsSize() + 128*1024; - if (stacksize < minstacksize) { - if (!stack_set) { - if (stacksize != 0) { - VPrintf(1, "Sanitizer: increasing stacksize %zu->%zu\n", stacksize, - minstacksize); - pthread_attr_setstacksize(attr, minstacksize); - } - } else { - Printf("Sanitizer: pre-allocated stack size is insufficient: " - "%zu < %zu\n", stacksize, minstacksize); - Printf("Sanitizer: pthread_create is likely to fail.\n"); - } - } -} -#endif // !SANITIZER_GO - # if !SANITIZER_FREEBSD typedef ElfW(Phdr) Elf_Phdr; # elif SANITIZER_WORDSIZE == 32 && __FreeBSD_version <= 902001 // v9.2 diff --git a/lib/sanitizer_common/sanitizer_posix.h b/lib/sanitizer_common/sanitizer_posix.h index 5a9e97d5b5..19fa505c52 100644 --- a/lib/sanitizer_common/sanitizer_posix.h +++ b/lib/sanitizer_common/sanitizer_posix.h @@ -74,6 +74,8 @@ int real_pthread_join(void *th, void **ret); } \ } // namespace __sanitizer +int my_pthread_attr_getstack(void *attr, void **addr, uptr *size); + int internal_sigaction(int signum, const void *act, void *oldact); } // namespace __sanitizer diff --git a/lib/sanitizer_common/sanitizer_posix_libcdep.cc b/lib/sanitizer_common/sanitizer_posix_libcdep.cc index b67a779b90..d7b9f20414 100644 --- a/lib/sanitizer_common/sanitizer_posix_libcdep.cc +++ b/lib/sanitizer_common/sanitizer_posix_libcdep.cc @@ -276,6 +276,49 @@ void *MmapNoAccess(uptr fixed_addr, uptr size, const char *name) { return (void *)internal_mmap((void *)fixed_addr, size, PROT_NONE, flags, fd, 0); } + +// This function is defined elsewhere if we intercepted pthread_attr_getstack. +extern "C" { +SANITIZER_WEAK_ATTRIBUTE int +real_pthread_attr_getstack(void *attr, void **addr, size_t *size); +} // extern "C" + +int my_pthread_attr_getstack(void *attr, void **addr, uptr *size) { +#if !SANITIZER_GO && !SANITIZER_MAC + if (&real_pthread_attr_getstack) + return real_pthread_attr_getstack((pthread_attr_t *)attr, addr, + (size_t *)size); +#endif + return pthread_attr_getstack((pthread_attr_t *)attr, addr, (size_t *)size); +} + +#if !SANITIZER_GO +void AdjustStackSize(void *attr_) { + pthread_attr_t *attr = (pthread_attr_t *)attr_; + uptr stackaddr = 0; + uptr stacksize = 0; + my_pthread_attr_getstack(attr, (void**)&stackaddr, &stacksize); + // GLibC will return (0 - stacksize) as the stack address in the case when + // stacksize is set, but stackaddr is not. + bool stack_set = (stackaddr != 0) && (stackaddr + stacksize != 0); + // We place a lot of tool data into TLS, account for that. + const uptr minstacksize = GetTlsSize() + 128*1024; + if (stacksize < minstacksize) { + if (!stack_set) { + if (stacksize != 0) { + VPrintf(1, "Sanitizer: increasing stacksize %zu->%zu\n", stacksize, + minstacksize); + pthread_attr_setstacksize(attr, minstacksize); + } + } else { + Printf("Sanitizer: pre-allocated stack size is insufficient: " + "%zu < %zu\n", stacksize, minstacksize); + Printf("Sanitizer: pthread_create is likely to fail.\n"); + } + } +} +#endif // !SANITIZER_GO + } // namespace __sanitizer #endif // SANITIZER_POSIX diff --git a/lib/tsan/rtl/tsan_platform_mac.cc b/lib/tsan/rtl/tsan_platform_mac.cc index b72d9b07ef..32d340268f 100644 --- a/lib/tsan/rtl/tsan_platform_mac.cc +++ b/lib/tsan/rtl/tsan_platform_mac.cc @@ -91,6 +91,10 @@ int call_pthread_cancel_with_cleanup(int(*fn)(void *c, void *m, } #endif +bool IsGlobalVar(uptr addr) { + return false; +} + } // namespace __tsan #endif // SANITIZER_MAC diff --git a/lib/tsan/rtl/tsan_rtl.h b/lib/tsan/rtl/tsan_rtl.h index ae44bc9b3b..2618405757 100644 --- a/lib/tsan/rtl/tsan_rtl.h +++ b/lib/tsan/rtl/tsan_rtl.h @@ -709,7 +709,7 @@ void AcquireReleaseImpl(ThreadState *thr, uptr pc, SyncClock *c); // The trick is that the call preserves all registers and the compiler // does not treat it as a call. // If it does not work for you, use normal call. -#if !SANITIZER_DEBUG && defined(__x86_64__) +#if !SANITIZER_DEBUG && defined(__x86_64__) && !SANITIZER_MAC // The caller may not create the stack frame for itself at all, // so we create a reserve stack frame for it (1024b must be enough). #define HACKY_CALL(f) \ From e2b976ac48a231489cc6f84bbdcda7855bd6a4ab Mon Sep 17 00:00:00 2001 From: Kuba Brecka Date: Tue, 3 Nov 2015 14:42:03 +0000 Subject: [PATCH 29/68] Revert r251916 ("[tsan] Port TSan interceptors on OS X"). git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/trunk@251922 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/tsan/rtl/tsan_interceptors.cc | 254 ++++++++++++------------------ 1 file changed, 103 insertions(+), 151 deletions(-) diff --git a/lib/tsan/rtl/tsan_interceptors.cc b/lib/tsan/rtl/tsan_interceptors.cc index c911965b40..c0864218e0 100644 --- a/lib/tsan/rtl/tsan_interceptors.cc +++ b/lib/tsan/rtl/tsan_interceptors.cc @@ -28,26 +28,14 @@ #include "tsan_mman.h" #include "tsan_fd.h" -#if SANITIZER_POSIX -#include "sanitizer_common/sanitizer_posix.h" -#endif - using namespace __tsan; // NOLINT -#if SANITIZER_FREEBSD || SANITIZER_MAC -#define __errno_location __error -#define stdout __stdoutp -#define stderr __stderrp -#endif - #if SANITIZER_FREEBSD +#define __errno_location __error #define __libc_realloc __realloc #define __libc_calloc __calloc -#elif SANITIZER_MAC -#define __libc_malloc REAL(malloc) -#define __libc_realloc REAL(realloc) -#define __libc_calloc REAL(calloc) -#define __libc_free REAL(free) +#define stdout __stdoutp +#define stderr __stderrp #endif #if SANITIZER_LINUX || SANITIZER_FREEBSD @@ -92,6 +80,7 @@ extern "C" int pthread_attr_setstacksize(void *attr, uptr stacksize); extern "C" int pthread_key_create(unsigned *key, void (*destructor)(void* v)); extern "C" int pthread_setspecific(unsigned key, const void *v); DECLARE_REAL(int, pthread_mutexattr_gettype, void *, void *) +extern "C" int pthread_yield(); extern "C" int pthread_sigmask(int how, const __sanitizer_sigset_t *set, __sanitizer_sigset_t *oldset); // REAL(sigfillset) defined in common interceptors. @@ -334,79 +323,6 @@ TSAN_INTERCEPTOR(int, nanosleep, void *req, void *rem) { return res; } -TSAN_INTERCEPTOR(void*, malloc, uptr size) { - if (cur_thread()->in_symbolizer) - return __libc_malloc(size); - void *p = 0; - { - SCOPED_INTERCEPTOR_RAW(malloc, size); - p = user_alloc(thr, pc, size); - } - invoke_malloc_hook(p, size); - return p; -} - -#if !SANITIZER_MAC -TSAN_INTERCEPTOR(void*, __libc_memalign, uptr align, uptr sz) { - SCOPED_TSAN_INTERCEPTOR(__libc_memalign, align, sz); - return user_alloc(thr, pc, sz, align); -} -#endif - -TSAN_INTERCEPTOR(void*, calloc, uptr size, uptr n) { - if (cur_thread()->in_symbolizer) - return __libc_calloc(size, n); - void *p = 0; - { - SCOPED_INTERCEPTOR_RAW(calloc, size, n); - p = user_calloc(thr, pc, size, n); - } - invoke_malloc_hook(p, n * size); - return p; -} - -TSAN_INTERCEPTOR(void*, realloc, void *p, uptr size) { - if (cur_thread()->in_symbolizer) - return __libc_realloc(p, size); - if (p) - invoke_free_hook(p); - { - SCOPED_INTERCEPTOR_RAW(realloc, p, size); - p = user_realloc(thr, pc, p, size); - } - invoke_malloc_hook(p, size); - return p; -} - -TSAN_INTERCEPTOR(void, free, void *p) { - if (p == 0) - return; - if (cur_thread()->in_symbolizer) - return __libc_free(p); - invoke_free_hook(p); - SCOPED_INTERCEPTOR_RAW(free, p); - user_free(thr, pc, p); -} - -#if !SANITIZER_MAC -TSAN_INTERCEPTOR(void, cfree, void *p) { - if (p == 0) - return; - if (cur_thread()->in_symbolizer) - return __libc_free(p); - invoke_free_hook(p); - SCOPED_INTERCEPTOR_RAW(cfree, p); - user_free(thr, pc, p); -} -#endif - -#if !SANITIZER_MAC -TSAN_INTERCEPTOR(uptr, malloc_usable_size, void *p) { - SCOPED_INTERCEPTOR_RAW(malloc_usable_size, p); - return user_alloc_usable_size(p); -} -#endif - // The sole reason tsan wraps atexit callbacks is to establish synchronization // between callback setup and callback execution. struct AtExitCtx { @@ -465,7 +381,6 @@ static void on_exit_wrapper(int status, void *arg) { __libc_free(ctx); } -#if !SANITIZER_MAC TSAN_INTERCEPTOR(int, on_exit, void(*f)(int, void*), void *arg) { if (cur_thread()->in_symbolizer) return 0; @@ -481,7 +396,6 @@ TSAN_INTERCEPTOR(int, on_exit, void(*f)(int, void*), void *arg) { ThreadIgnoreEnd(thr, pc); return res; } -#endif // Cleanup old bufs. static void JmpBufGarbageCollect(ThreadState *thr, uptr sp) { @@ -605,6 +519,73 @@ TSAN_INTERCEPTOR(void, siglongjmp, uptr *env, int val) { REAL(siglongjmp)(env, val); } +TSAN_INTERCEPTOR(void*, malloc, uptr size) { + if (cur_thread()->in_symbolizer) + return __libc_malloc(size); + void *p = 0; + { + SCOPED_INTERCEPTOR_RAW(malloc, size); + p = user_alloc(thr, pc, size); + } + invoke_malloc_hook(p, size); + return p; +} + +TSAN_INTERCEPTOR(void*, __libc_memalign, uptr align, uptr sz) { + SCOPED_TSAN_INTERCEPTOR(__libc_memalign, align, sz); + return user_alloc(thr, pc, sz, align); +} + +TSAN_INTERCEPTOR(void*, calloc, uptr size, uptr n) { + if (cur_thread()->in_symbolizer) + return __libc_calloc(size, n); + void *p = 0; + { + SCOPED_INTERCEPTOR_RAW(calloc, size, n); + p = user_calloc(thr, pc, size, n); + } + invoke_malloc_hook(p, n * size); + return p; +} + +TSAN_INTERCEPTOR(void*, realloc, void *p, uptr size) { + if (cur_thread()->in_symbolizer) + return __libc_realloc(p, size); + if (p) + invoke_free_hook(p); + { + SCOPED_INTERCEPTOR_RAW(realloc, p, size); + p = user_realloc(thr, pc, p, size); + } + invoke_malloc_hook(p, size); + return p; +} + +TSAN_INTERCEPTOR(void, free, void *p) { + if (p == 0) + return; + if (cur_thread()->in_symbolizer) + return __libc_free(p); + invoke_free_hook(p); + SCOPED_INTERCEPTOR_RAW(free, p); + user_free(thr, pc, p); +} + +TSAN_INTERCEPTOR(void, cfree, void *p) { + if (p == 0) + return; + if (cur_thread()->in_symbolizer) + return __libc_free(p); + invoke_free_hook(p); + SCOPED_INTERCEPTOR_RAW(cfree, p); + user_free(thr, pc, p); +} + +TSAN_INTERCEPTOR(uptr, malloc_usable_size, void *p) { + SCOPED_INTERCEPTOR_RAW(malloc_usable_size, p); + return user_alloc_usable_size(p); +} + TSAN_INTERCEPTOR(uptr, strlen, const char *s) { SCOPED_TSAN_INTERCEPTOR(strlen, s); uptr len = internal_strlen(s); @@ -647,7 +628,6 @@ TSAN_INTERCEPTOR(char*, strchr, char *s, int c) { return res; } -#if !SANITIZER_MAC TSAN_INTERCEPTOR(char*, strchrnul, char *s, int c) { SCOPED_TSAN_INTERCEPTOR(strchrnul, s, c); char *res = REAL(strchrnul)(s, c); @@ -655,7 +635,6 @@ TSAN_INTERCEPTOR(char*, strchrnul, char *s, int c) { READ_STRING(thr, pc, s, len); return res; } -#endif TSAN_INTERCEPTOR(char*, strrchr, char *s, int c) { SCOPED_TSAN_INTERCEPTOR(strrchr, s, c); @@ -713,7 +692,7 @@ TSAN_INTERCEPTOR(void*, mmap, void *addr, long_t sz, int prot, return res; } -#if !SANITIZER_FREEBSD && !SANITIZER_MAC +#if !SANITIZER_FREEBSD TSAN_INTERCEPTOR(void*, mmap64, void *addr, long_t sz, int prot, int flags, int fd, u64 off) { SCOPED_TSAN_INTERCEPTOR(mmap64, addr, sz, prot, flags, fd, off); @@ -743,7 +722,7 @@ TSAN_INTERCEPTOR(int, munmap, void *addr, long_t sz) { return res; } -#if !SANITIZER_FREEBSD && !SANITIZER_MAC +#if !SANITIZER_FREEBSD TSAN_INTERCEPTOR(void*, memalign, uptr align, uptr sz) { SCOPED_INTERCEPTOR_RAW(memalign, align, sz); return user_alloc(thr, pc, sz, align); @@ -753,19 +732,17 @@ TSAN_INTERCEPTOR(void*, memalign, uptr align, uptr sz) { #define TSAN_MAYBE_INTERCEPT_MEMALIGN #endif -#if !SANITIZER_MAC TSAN_INTERCEPTOR(void*, aligned_alloc, uptr align, uptr sz) { SCOPED_INTERCEPTOR_RAW(memalign, align, sz); return user_alloc(thr, pc, sz, align); } -#endif TSAN_INTERCEPTOR(void*, valloc, uptr sz) { SCOPED_INTERCEPTOR_RAW(valloc, sz); return user_alloc(thr, pc, sz, GetPageSizeCached()); } -#if !SANITIZER_FREEBSD && !SANITIZER_MAC +#if !SANITIZER_FREEBSD TSAN_INTERCEPTOR(void*, pvalloc, uptr sz) { SCOPED_INTERCEPTOR_RAW(pvalloc, sz); sz = RoundUp(sz, GetPageSizeCached()); @@ -854,7 +831,7 @@ extern "C" void *__tsan_thread_start_func(void *arg) { } ThreadIgnoreEnd(thr, 0); while ((tid = atomic_load(&p->tid, memory_order_acquire)) == 0) - internal_sched_yield(); + pthread_yield(); ThreadStart(thr, tid, GetTid()); atomic_store(&p->tid, 0, memory_order_release); } @@ -914,7 +891,7 @@ TSAN_INTERCEPTOR(int, pthread_create, // before the new thread got a chance to acquire from it in ThreadStart. atomic_store(&p.tid, tid, memory_order_release); while (atomic_load(&p.tid, memory_order_acquire) != 0) - internal_sched_yield(); + pthread_yield(); } if (attr == &myattr) pthread_attr_destroy(&myattr); @@ -1117,7 +1094,6 @@ TSAN_INTERCEPTOR(int, pthread_mutex_trylock, void *m) { return res; } -#if !SANITIZER_MAC TSAN_INTERCEPTOR(int, pthread_mutex_timedlock, void *m, void *abstime) { SCOPED_TSAN_INTERCEPTOR(pthread_mutex_timedlock, m, abstime); int res = REAL(pthread_mutex_timedlock)(m, abstime); @@ -1126,9 +1102,7 @@ TSAN_INTERCEPTOR(int, pthread_mutex_timedlock, void *m, void *abstime) { } return res; } -#endif -#if !SANITIZER_MAC TSAN_INTERCEPTOR(int, pthread_spin_init, void *m, int pshared) { SCOPED_TSAN_INTERCEPTOR(pthread_spin_init, m, pshared); int res = REAL(pthread_spin_init)(m, pshared); @@ -1171,7 +1145,6 @@ TSAN_INTERCEPTOR(int, pthread_spin_unlock, void *m) { int res = REAL(pthread_spin_unlock)(m); return res; } -#endif TSAN_INTERCEPTOR(int, pthread_rwlock_init, void *m, void *a) { SCOPED_TSAN_INTERCEPTOR(pthread_rwlock_init, m, a); @@ -1209,7 +1182,6 @@ TSAN_INTERCEPTOR(int, pthread_rwlock_tryrdlock, void *m) { return res; } -#if !SANITIZER_MAC TSAN_INTERCEPTOR(int, pthread_rwlock_timedrdlock, void *m, void *abstime) { SCOPED_TSAN_INTERCEPTOR(pthread_rwlock_timedrdlock, m, abstime); int res = REAL(pthread_rwlock_timedrdlock)(m, abstime); @@ -1218,7 +1190,6 @@ TSAN_INTERCEPTOR(int, pthread_rwlock_timedrdlock, void *m, void *abstime) { } return res; } -#endif TSAN_INTERCEPTOR(int, pthread_rwlock_wrlock, void *m) { SCOPED_TSAN_INTERCEPTOR(pthread_rwlock_wrlock, m); @@ -1238,7 +1209,6 @@ TSAN_INTERCEPTOR(int, pthread_rwlock_trywrlock, void *m) { return res; } -#if !SANITIZER_MAC TSAN_INTERCEPTOR(int, pthread_rwlock_timedwrlock, void *m, void *abstime) { SCOPED_TSAN_INTERCEPTOR(pthread_rwlock_timedwrlock, m, abstime); int res = REAL(pthread_rwlock_timedwrlock)(m, abstime); @@ -1247,7 +1217,6 @@ TSAN_INTERCEPTOR(int, pthread_rwlock_timedwrlock, void *m, void *abstime) { } return res; } -#endif TSAN_INTERCEPTOR(int, pthread_rwlock_unlock, void *m) { SCOPED_TSAN_INTERCEPTOR(pthread_rwlock_unlock, m); @@ -1256,7 +1225,6 @@ TSAN_INTERCEPTOR(int, pthread_rwlock_unlock, void *m) { return res; } -#if !SANITIZER_MAC TSAN_INTERCEPTOR(int, pthread_barrier_init, void *b, void *a, unsigned count) { SCOPED_TSAN_INTERCEPTOR(pthread_barrier_init, b, a, count); MemoryWrite(thr, pc, (uptr)b, kSizeLog1); @@ -1282,7 +1250,6 @@ TSAN_INTERCEPTOR(int, pthread_barrier_wait, void *b) { } return res; } -#endif TSAN_INTERCEPTOR(int, pthread_once, void *o, void (*f)()) { SCOPED_INTERCEPTOR_RAW(pthread_once, o, f); @@ -1298,7 +1265,7 @@ TSAN_INTERCEPTOR(int, pthread_once, void *o, void (*f)()) { atomic_store(a, 2, memory_order_release); } else { while (v != 2) { - internal_sched_yield(); + pthread_yield(); v = atomic_load(a, memory_order_acquire); } if (!thr->in_ignored_lib) @@ -1307,7 +1274,7 @@ TSAN_INTERCEPTOR(int, pthread_once, void *o, void (*f)()) { return 0; } -#if !SANITIZER_FREEBSD && !SANITIZER_MAC +#if !SANITIZER_FREEBSD TSAN_INTERCEPTOR(int, __xstat, int version, const char *path, void *buf) { SCOPED_TSAN_INTERCEPTOR(__xstat, version, path, buf); READ_STRING(thr, pc, path, 0); @@ -1319,7 +1286,7 @@ TSAN_INTERCEPTOR(int, __xstat, int version, const char *path, void *buf) { #endif TSAN_INTERCEPTOR(int, stat, const char *path, void *buf) { -#if SANITIZER_FREEBSD || SANITIZER_MAC +#if SANITIZER_FREEBSD SCOPED_TSAN_INTERCEPTOR(stat, path, buf); READ_STRING(thr, pc, path, 0); return REAL(stat)(path, buf); @@ -1330,7 +1297,7 @@ TSAN_INTERCEPTOR(int, stat, const char *path, void *buf) { #endif } -#if !SANITIZER_FREEBSD && !SANITIZER_MAC +#if !SANITIZER_FREEBSD TSAN_INTERCEPTOR(int, __xstat64, int version, const char *path, void *buf) { SCOPED_TSAN_INTERCEPTOR(__xstat64, version, path, buf); READ_STRING(thr, pc, path, 0); @@ -1341,7 +1308,7 @@ TSAN_INTERCEPTOR(int, __xstat64, int version, const char *path, void *buf) { #define TSAN_MAYBE_INTERCEPT___XSTAT64 #endif -#if !SANITIZER_FREEBSD && !SANITIZER_MAC +#if !SANITIZER_FREEBSD TSAN_INTERCEPTOR(int, stat64, const char *path, void *buf) { SCOPED_TSAN_INTERCEPTOR(__xstat64, 0, path, buf); READ_STRING(thr, pc, path, 0); @@ -1352,7 +1319,7 @@ TSAN_INTERCEPTOR(int, stat64, const char *path, void *buf) { #define TSAN_MAYBE_INTERCEPT_STAT64 #endif -#if !SANITIZER_FREEBSD && !SANITIZER_MAC +#if !SANITIZER_FREEBSD TSAN_INTERCEPTOR(int, __lxstat, int version, const char *path, void *buf) { SCOPED_TSAN_INTERCEPTOR(__lxstat, version, path, buf); READ_STRING(thr, pc, path, 0); @@ -1364,7 +1331,7 @@ TSAN_INTERCEPTOR(int, __lxstat, int version, const char *path, void *buf) { #endif TSAN_INTERCEPTOR(int, lstat, const char *path, void *buf) { -#if SANITIZER_FREEBSD || SANITIZER_MAC +#if SANITIZER_FREEBSD SCOPED_TSAN_INTERCEPTOR(lstat, path, buf); READ_STRING(thr, pc, path, 0); return REAL(lstat)(path, buf); @@ -1375,7 +1342,7 @@ TSAN_INTERCEPTOR(int, lstat, const char *path, void *buf) { #endif } -#if !SANITIZER_FREEBSD && !SANITIZER_MAC +#if !SANITIZER_FREEBSD TSAN_INTERCEPTOR(int, __lxstat64, int version, const char *path, void *buf) { SCOPED_TSAN_INTERCEPTOR(__lxstat64, version, path, buf); READ_STRING(thr, pc, path, 0); @@ -1386,7 +1353,7 @@ TSAN_INTERCEPTOR(int, __lxstat64, int version, const char *path, void *buf) { #define TSAN_MAYBE_INTERCEPT___LXSTAT64 #endif -#if !SANITIZER_FREEBSD && !SANITIZER_MAC +#if !SANITIZER_FREEBSD TSAN_INTERCEPTOR(int, lstat64, const char *path, void *buf) { SCOPED_TSAN_INTERCEPTOR(__lxstat64, 0, path, buf); READ_STRING(thr, pc, path, 0); @@ -1397,7 +1364,7 @@ TSAN_INTERCEPTOR(int, lstat64, const char *path, void *buf) { #define TSAN_MAYBE_INTERCEPT_LSTAT64 #endif -#if !SANITIZER_FREEBSD && !SANITIZER_MAC +#if !SANITIZER_FREEBSD TSAN_INTERCEPTOR(int, __fxstat, int version, int fd, void *buf) { SCOPED_TSAN_INTERCEPTOR(__fxstat, version, fd, buf); if (fd > 0) @@ -1410,7 +1377,7 @@ TSAN_INTERCEPTOR(int, __fxstat, int version, int fd, void *buf) { #endif TSAN_INTERCEPTOR(int, fstat, int fd, void *buf) { -#if SANITIZER_FREEBSD || SANITIZER_MAC +#if SANITIZER_FREEBSD SCOPED_TSAN_INTERCEPTOR(fstat, fd, buf); if (fd > 0) FdAccess(thr, pc, fd); @@ -1423,7 +1390,7 @@ TSAN_INTERCEPTOR(int, fstat, int fd, void *buf) { #endif } -#if !SANITIZER_FREEBSD && !SANITIZER_MAC +#if !SANITIZER_FREEBSD TSAN_INTERCEPTOR(int, __fxstat64, int version, int fd, void *buf) { SCOPED_TSAN_INTERCEPTOR(__fxstat64, version, fd, buf); if (fd > 0) @@ -1435,7 +1402,7 @@ TSAN_INTERCEPTOR(int, __fxstat64, int version, int fd, void *buf) { #define TSAN_MAYBE_INTERCEPT___FXSTAT64 #endif -#if !SANITIZER_FREEBSD && !SANITIZER_MAC +#if !SANITIZER_FREEBSD TSAN_INTERCEPTOR(int, fstat64, int fd, void *buf) { SCOPED_TSAN_INTERCEPTOR(__fxstat64, 0, fd, buf); if (fd > 0) @@ -1456,7 +1423,7 @@ TSAN_INTERCEPTOR(int, open, const char *name, int flags, int mode) { return fd; } -#if !SANITIZER_FREEBSD && !SANITIZER_MAC +#if !SANITIZER_FREEBSD TSAN_INTERCEPTOR(int, open64, const char *name, int flags, int mode) { SCOPED_TSAN_INTERCEPTOR(open64, name, flags, mode); READ_STRING(thr, pc, name, 0); @@ -1479,7 +1446,7 @@ TSAN_INTERCEPTOR(int, creat, const char *name, int mode) { return fd; } -#if !SANITIZER_FREEBSD && !SANITIZER_MAC +#if !SANITIZER_FREEBSD TSAN_INTERCEPTOR(int, creat64, const char *name, int mode) { SCOPED_TSAN_INTERCEPTOR(creat64, name, mode); READ_STRING(thr, pc, name, 0); @@ -1509,7 +1476,6 @@ TSAN_INTERCEPTOR(int, dup2, int oldfd, int newfd) { return newfd2; } -#if !SANITIZER_MAC TSAN_INTERCEPTOR(int, dup3, int oldfd, int newfd, int flags) { SCOPED_TSAN_INTERCEPTOR(dup3, oldfd, newfd, flags); int newfd2 = REAL(dup3)(oldfd, newfd, flags); @@ -1517,9 +1483,8 @@ TSAN_INTERCEPTOR(int, dup3, int oldfd, int newfd, int flags) { FdDup(thr, pc, oldfd, newfd2, false); return newfd2; } -#endif -#if !SANITIZER_FREEBSD && !SANITIZER_MAC +#if !SANITIZER_FREEBSD TSAN_INTERCEPTOR(int, eventfd, unsigned initval, int flags) { SCOPED_TSAN_INTERCEPTOR(eventfd, initval, flags); int fd = REAL(eventfd)(initval, flags); @@ -1532,7 +1497,7 @@ TSAN_INTERCEPTOR(int, eventfd, unsigned initval, int flags) { #define TSAN_MAYBE_INTERCEPT_EVENTFD #endif -#if !SANITIZER_FREEBSD && !SANITIZER_MAC +#if !SANITIZER_FREEBSD TSAN_INTERCEPTOR(int, signalfd, int fd, void *mask, int flags) { SCOPED_TSAN_INTERCEPTOR(signalfd, fd, mask, flags); if (fd >= 0) @@ -1547,7 +1512,7 @@ TSAN_INTERCEPTOR(int, signalfd, int fd, void *mask, int flags) { #define TSAN_MAYBE_INTERCEPT_SIGNALFD #endif -#if !SANITIZER_FREEBSD && !SANITIZER_MAC +#if !SANITIZER_FREEBSD TSAN_INTERCEPTOR(int, inotify_init, int fake) { SCOPED_TSAN_INTERCEPTOR(inotify_init, fake); int fd = REAL(inotify_init)(fake); @@ -1560,7 +1525,7 @@ TSAN_INTERCEPTOR(int, inotify_init, int fake) { #define TSAN_MAYBE_INTERCEPT_INOTIFY_INIT #endif -#if !SANITIZER_FREEBSD && !SANITIZER_MAC +#if !SANITIZER_FREEBSD TSAN_INTERCEPTOR(int, inotify_init1, int flags) { SCOPED_TSAN_INTERCEPTOR(inotify_init1, flags); int fd = REAL(inotify_init1)(flags); @@ -1614,7 +1579,7 @@ TSAN_INTERCEPTOR(int, listen, int fd, int backlog) { return res; } -#if !SANITIZER_FREEBSD && !SANITIZER_MAC +#if !SANITIZER_FREEBSD TSAN_INTERCEPTOR(int, epoll_create, int size) { SCOPED_TSAN_INTERCEPTOR(epoll_create, size); int fd = REAL(epoll_create)(size); @@ -1627,7 +1592,7 @@ TSAN_INTERCEPTOR(int, epoll_create, int size) { #define TSAN_MAYBE_INTERCEPT_EPOLL_CREATE #endif -#if !SANITIZER_FREEBSD && !SANITIZER_MAC +#if !SANITIZER_FREEBSD TSAN_INTERCEPTOR(int, epoll_create1, int flags) { SCOPED_TSAN_INTERCEPTOR(epoll_create1, flags); int fd = REAL(epoll_create1)(flags); @@ -1647,7 +1612,7 @@ TSAN_INTERCEPTOR(int, close, int fd) { return REAL(close)(fd); } -#if !SANITIZER_FREEBSD && !SANITIZER_MAC +#if !SANITIZER_FREEBSD TSAN_INTERCEPTOR(int, __close, int fd) { SCOPED_TSAN_INTERCEPTOR(__close, fd); if (fd >= 0) @@ -1660,7 +1625,7 @@ TSAN_INTERCEPTOR(int, __close, int fd) { #endif // glibc guts -#if !SANITIZER_FREEBSD && !SANITIZER_MAC +#if !SANITIZER_FREEBSD TSAN_INTERCEPTOR(void, __res_iclose, void *state, bool free_addr) { SCOPED_TSAN_INTERCEPTOR(__res_iclose, state, free_addr); int fds[64]; @@ -1684,7 +1649,6 @@ TSAN_INTERCEPTOR(int, pipe, int *pipefd) { return res; } -#if !SANITIZER_MAC TSAN_INTERCEPTOR(int, pipe2, int *pipefd, int flags) { SCOPED_TSAN_INTERCEPTOR(pipe2, pipefd, flags); int res = REAL(pipe2)(pipefd, flags); @@ -1692,7 +1656,6 @@ TSAN_INTERCEPTOR(int, pipe2, int *pipefd, int flags) { FdPipeCreate(thr, pc, pipefd[0], pipefd[1]); return res; } -#endif TSAN_INTERCEPTOR(long_t, send, int fd, void *buf, long_t len, int flags) { SCOPED_TSAN_INTERCEPTOR(send, fd, buf, len, flags); @@ -1743,7 +1706,7 @@ TSAN_INTERCEPTOR(void*, tmpfile, int fake) { return res; } -#if !SANITIZER_FREEBSD && !SANITIZER_MAC +#if !SANITIZER_FREEBSD TSAN_INTERCEPTOR(void*, tmpfile64, int fake) { SCOPED_TSAN_INTERCEPTOR(tmpfile64, fake); void *res = REAL(tmpfile64)(fake); @@ -1810,7 +1773,7 @@ TSAN_INTERCEPTOR(int, closedir, void *dirp) { return REAL(closedir)(dirp); } -#if !SANITIZER_FREEBSD && !SANITIZER_MAC +#if !SANITIZER_FREEBSD TSAN_INTERCEPTOR(int, epoll_ctl, int epfd, int op, int fd, void *ev) { SCOPED_TSAN_INTERCEPTOR(epoll_ctl, epfd, op, fd, ev); if (epfd >= 0) @@ -1827,7 +1790,7 @@ TSAN_INTERCEPTOR(int, epoll_ctl, int epfd, int op, int fd, void *ev) { #define TSAN_MAYBE_INTERCEPT_EPOLL_CTL #endif -#if !SANITIZER_FREEBSD && !SANITIZER_MAC +#if !SANITIZER_FREEBSD TSAN_INTERCEPTOR(int, epoll_wait, int epfd, void *ev, int cnt, int timeout) { SCOPED_TSAN_INTERCEPTOR(epoll_wait, epfd, ev, cnt, timeout); if (epfd >= 0) @@ -2126,7 +2089,6 @@ TSAN_INTERCEPTOR(int, vfork, int fake) { return WRAP(fork)(fake); } -#if SANITIZER_LINUX typedef int (*dl_iterate_phdr_cb_t)(__sanitizer_dl_phdr_info *info, SIZE_T size, void *data); struct dl_iterate_phdr_data { @@ -2170,7 +2132,6 @@ TSAN_INTERCEPTOR(int, dl_iterate_phdr, dl_iterate_phdr_cb_t cb, void *data) { int res = REAL(dl_iterate_phdr)(dl_iterate_phdr_cb, &cbdata); return res; } -#endif static int OnExit(ThreadState *thr) { int status = Finalize(thr); @@ -2305,11 +2266,9 @@ static void HandleRecvmsg(ThreadState *thr, uptr pc, MutexRepair(((TsanInterceptorContext *)ctx)->thr, \ ((TsanInterceptorContext *)ctx)->pc, (uptr)m) -#if !SANITIZER_MAC #define COMMON_INTERCEPTOR_HANDLE_RECVMSG(ctx, msg) \ HandleRecvmsg(((TsanInterceptorContext *)ctx)->thr, \ ((TsanInterceptorContext *)ctx)->pc, msg) -#endif #define COMMON_INTERCEPTOR_GET_TLS_RANGE(begin, end) \ if (TsanThread *t = GetCurrentThread()) { \ @@ -2450,21 +2409,18 @@ static void unreachable() { } void InitializeInterceptors() { -#if !SANITIZER_MAC // We need to setup it early, because functions like dlsym() can call it. REAL(memset) = internal_memset; REAL(memcpy) = internal_memcpy; -#endif // Instruct libc malloc to consume less memory. -#if !SANITIZER_FREEBSD && !SANITIZER_MAC +#if !SANITIZER_FREEBSD mallopt(1, 0); // M_MXFAST mallopt(-3, 32*1024); // M_MMAP_THRESHOLD #endif InitializeCommonInterceptors(); -#if !SANITIZER_MAC // We can not use TSAN_INTERCEPT to get setjmp addr, // because it does &setjmp and setjmp is not present in some versions of libc. using __interception::GetRealFunctionAddress; @@ -2472,7 +2428,6 @@ void InitializeInterceptors() { GetRealFunctionAddress("_setjmp", (uptr*)&REAL(_setjmp), 0, 0); GetRealFunctionAddress("sigsetjmp", (uptr*)&REAL(sigsetjmp), 0, 0); GetRealFunctionAddress("__sigsetjmp", (uptr*)&REAL(__sigsetjmp), 0, 0); -#endif TSAN_INTERCEPT(longjmp); TSAN_INTERCEPT(siglongjmp); @@ -2612,12 +2567,9 @@ void InitializeInterceptors() { TSAN_INTERCEPT(__cxa_atexit); TSAN_INTERCEPT(_exit); -#if !SANITIZER_MAC // Need to setup it, because interceptors check that the function is resolved. // But atexit is emitted directly into the module, so can't be resolved. REAL(atexit) = (int(*)(void(*)()))unreachable; -#endif - if (REAL(__cxa_atexit)(&finalize, 0, 0)) { Printf("ThreadSanitizer: failed to setup atexit callback\n"); Die(); From 657bd0eb3d9cffc820a1be6e9f4b9e1afdfb296d Mon Sep 17 00:00:00 2001 From: Kuba Brecka Date: Tue, 3 Nov 2015 14:43:39 +0000 Subject: [PATCH 30/68] Reapply r251916 ("[tsan] Port TSan interceptors on OS X"). git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/trunk@251923 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/tsan/rtl/tsan_interceptors.cc | 122 +++++++++++++++++++++--------- 1 file changed, 86 insertions(+), 36 deletions(-) diff --git a/lib/tsan/rtl/tsan_interceptors.cc b/lib/tsan/rtl/tsan_interceptors.cc index c0864218e0..fb6fd750ac 100644 --- a/lib/tsan/rtl/tsan_interceptors.cc +++ b/lib/tsan/rtl/tsan_interceptors.cc @@ -28,16 +28,28 @@ #include "tsan_mman.h" #include "tsan_fd.h" +#if SANITIZER_POSIX +#include "sanitizer_common/sanitizer_posix.h" +#endif + using namespace __tsan; // NOLINT -#if SANITIZER_FREEBSD +#if SANITIZER_FREEBSD || SANITIZER_MAC #define __errno_location __error -#define __libc_realloc __realloc -#define __libc_calloc __calloc #define stdout __stdoutp #define stderr __stderrp #endif +#if SANITIZER_FREEBSD +#define __libc_realloc __realloc +#define __libc_calloc __calloc +#elif SANITIZER_MAC +#define __libc_malloc REAL(malloc) +#define __libc_realloc REAL(realloc) +#define __libc_calloc REAL(calloc) +#define __libc_free REAL(free) +#endif + #if SANITIZER_LINUX || SANITIZER_FREEBSD #define PTHREAD_CREATE_DETACHED 1 #elif SANITIZER_MAC @@ -80,12 +92,13 @@ extern "C" int pthread_attr_setstacksize(void *attr, uptr stacksize); extern "C" int pthread_key_create(unsigned *key, void (*destructor)(void* v)); extern "C" int pthread_setspecific(unsigned key, const void *v); DECLARE_REAL(int, pthread_mutexattr_gettype, void *, void *) -extern "C" int pthread_yield(); extern "C" int pthread_sigmask(int how, const __sanitizer_sigset_t *set, __sanitizer_sigset_t *oldset); // REAL(sigfillset) defined in common interceptors. DECLARE_REAL(int, sigfillset, __sanitizer_sigset_t *set) DECLARE_REAL(int, fflush, __sanitizer_FILE *fp) +DECLARE_REAL(void *, malloc, uptr size); +DECLARE_REAL(void, free, void *ptr); extern "C" void *pthread_self(); extern "C" void _exit(int status); extern "C" int *__errno_location(); @@ -381,6 +394,7 @@ static void on_exit_wrapper(int status, void *arg) { __libc_free(ctx); } +#if !SANITIZER_MAC TSAN_INTERCEPTOR(int, on_exit, void(*f)(int, void*), void *arg) { if (cur_thread()->in_symbolizer) return 0; @@ -396,6 +410,7 @@ TSAN_INTERCEPTOR(int, on_exit, void(*f)(int, void*), void *arg) { ThreadIgnoreEnd(thr, pc); return res; } +#endif // Cleanup old bufs. static void JmpBufGarbageCollect(ThreadState *thr, uptr sp) { @@ -531,10 +546,12 @@ TSAN_INTERCEPTOR(void*, malloc, uptr size) { return p; } +#if !SANITIZER_MAC TSAN_INTERCEPTOR(void*, __libc_memalign, uptr align, uptr sz) { SCOPED_TSAN_INTERCEPTOR(__libc_memalign, align, sz); return user_alloc(thr, pc, sz, align); } +#endif TSAN_INTERCEPTOR(void*, calloc, uptr size, uptr n) { if (cur_thread()->in_symbolizer) @@ -571,6 +588,7 @@ TSAN_INTERCEPTOR(void, free, void *p) { user_free(thr, pc, p); } +#if !SANITIZER_MAC TSAN_INTERCEPTOR(void, cfree, void *p) { if (p == 0) return; @@ -580,11 +598,14 @@ TSAN_INTERCEPTOR(void, cfree, void *p) { SCOPED_INTERCEPTOR_RAW(cfree, p); user_free(thr, pc, p); } +#endif +#if !SANITIZER_MAC TSAN_INTERCEPTOR(uptr, malloc_usable_size, void *p) { SCOPED_INTERCEPTOR_RAW(malloc_usable_size, p); return user_alloc_usable_size(p); } +#endif TSAN_INTERCEPTOR(uptr, strlen, const char *s) { SCOPED_TSAN_INTERCEPTOR(strlen, s); @@ -628,6 +649,7 @@ TSAN_INTERCEPTOR(char*, strchr, char *s, int c) { return res; } +#if !SANITIZER_MAC TSAN_INTERCEPTOR(char*, strchrnul, char *s, int c) { SCOPED_TSAN_INTERCEPTOR(strchrnul, s, c); char *res = REAL(strchrnul)(s, c); @@ -635,6 +657,7 @@ TSAN_INTERCEPTOR(char*, strchrnul, char *s, int c) { READ_STRING(thr, pc, s, len); return res; } +#endif TSAN_INTERCEPTOR(char*, strrchr, char *s, int c) { SCOPED_TSAN_INTERCEPTOR(strrchr, s, c); @@ -692,7 +715,7 @@ TSAN_INTERCEPTOR(void*, mmap, void *addr, long_t sz, int prot, return res; } -#if !SANITIZER_FREEBSD +#if SANITIZER_LINUX TSAN_INTERCEPTOR(void*, mmap64, void *addr, long_t sz, int prot, int flags, int fd, u64 off) { SCOPED_TSAN_INTERCEPTOR(mmap64, addr, sz, prot, flags, fd, off); @@ -722,7 +745,7 @@ TSAN_INTERCEPTOR(int, munmap, void *addr, long_t sz) { return res; } -#if !SANITIZER_FREEBSD +#if SANITIZER_LINUX TSAN_INTERCEPTOR(void*, memalign, uptr align, uptr sz) { SCOPED_INTERCEPTOR_RAW(memalign, align, sz); return user_alloc(thr, pc, sz, align); @@ -732,17 +755,19 @@ TSAN_INTERCEPTOR(void*, memalign, uptr align, uptr sz) { #define TSAN_MAYBE_INTERCEPT_MEMALIGN #endif +#if !SANITIZER_MAC TSAN_INTERCEPTOR(void*, aligned_alloc, uptr align, uptr sz) { SCOPED_INTERCEPTOR_RAW(memalign, align, sz); return user_alloc(thr, pc, sz, align); } +#endif TSAN_INTERCEPTOR(void*, valloc, uptr sz) { SCOPED_INTERCEPTOR_RAW(valloc, sz); return user_alloc(thr, pc, sz, GetPageSizeCached()); } -#if !SANITIZER_FREEBSD +#if SANITIZER_LINUX TSAN_INTERCEPTOR(void*, pvalloc, uptr sz) { SCOPED_INTERCEPTOR_RAW(pvalloc, sz); sz = RoundUp(sz, GetPageSizeCached()); @@ -831,7 +856,7 @@ extern "C" void *__tsan_thread_start_func(void *arg) { } ThreadIgnoreEnd(thr, 0); while ((tid = atomic_load(&p->tid, memory_order_acquire)) == 0) - pthread_yield(); + internal_sched_yield(); ThreadStart(thr, tid, GetTid()); atomic_store(&p->tid, 0, memory_order_release); } @@ -891,7 +916,7 @@ TSAN_INTERCEPTOR(int, pthread_create, // before the new thread got a chance to acquire from it in ThreadStart. atomic_store(&p.tid, tid, memory_order_release); while (atomic_load(&p.tid, memory_order_acquire) != 0) - pthread_yield(); + internal_sched_yield(); } if (attr == &myattr) pthread_attr_destroy(&myattr); @@ -1094,6 +1119,7 @@ TSAN_INTERCEPTOR(int, pthread_mutex_trylock, void *m) { return res; } +#if !SANITIZER_MAC TSAN_INTERCEPTOR(int, pthread_mutex_timedlock, void *m, void *abstime) { SCOPED_TSAN_INTERCEPTOR(pthread_mutex_timedlock, m, abstime); int res = REAL(pthread_mutex_timedlock)(m, abstime); @@ -1102,7 +1128,9 @@ TSAN_INTERCEPTOR(int, pthread_mutex_timedlock, void *m, void *abstime) { } return res; } +#endif +#if !SANITIZER_MAC TSAN_INTERCEPTOR(int, pthread_spin_init, void *m, int pshared) { SCOPED_TSAN_INTERCEPTOR(pthread_spin_init, m, pshared); int res = REAL(pthread_spin_init)(m, pshared); @@ -1145,6 +1173,7 @@ TSAN_INTERCEPTOR(int, pthread_spin_unlock, void *m) { int res = REAL(pthread_spin_unlock)(m); return res; } +#endif TSAN_INTERCEPTOR(int, pthread_rwlock_init, void *m, void *a) { SCOPED_TSAN_INTERCEPTOR(pthread_rwlock_init, m, a); @@ -1182,6 +1211,7 @@ TSAN_INTERCEPTOR(int, pthread_rwlock_tryrdlock, void *m) { return res; } +#if !SANITIZER_MAC TSAN_INTERCEPTOR(int, pthread_rwlock_timedrdlock, void *m, void *abstime) { SCOPED_TSAN_INTERCEPTOR(pthread_rwlock_timedrdlock, m, abstime); int res = REAL(pthread_rwlock_timedrdlock)(m, abstime); @@ -1190,6 +1220,7 @@ TSAN_INTERCEPTOR(int, pthread_rwlock_timedrdlock, void *m, void *abstime) { } return res; } +#endif TSAN_INTERCEPTOR(int, pthread_rwlock_wrlock, void *m) { SCOPED_TSAN_INTERCEPTOR(pthread_rwlock_wrlock, m); @@ -1209,6 +1240,7 @@ TSAN_INTERCEPTOR(int, pthread_rwlock_trywrlock, void *m) { return res; } +#if !SANITIZER_MAC TSAN_INTERCEPTOR(int, pthread_rwlock_timedwrlock, void *m, void *abstime) { SCOPED_TSAN_INTERCEPTOR(pthread_rwlock_timedwrlock, m, abstime); int res = REAL(pthread_rwlock_timedwrlock)(m, abstime); @@ -1217,6 +1249,7 @@ TSAN_INTERCEPTOR(int, pthread_rwlock_timedwrlock, void *m, void *abstime) { } return res; } +#endif TSAN_INTERCEPTOR(int, pthread_rwlock_unlock, void *m) { SCOPED_TSAN_INTERCEPTOR(pthread_rwlock_unlock, m); @@ -1225,6 +1258,7 @@ TSAN_INTERCEPTOR(int, pthread_rwlock_unlock, void *m) { return res; } +#if !SANITIZER_MAC TSAN_INTERCEPTOR(int, pthread_barrier_init, void *b, void *a, unsigned count) { SCOPED_TSAN_INTERCEPTOR(pthread_barrier_init, b, a, count); MemoryWrite(thr, pc, (uptr)b, kSizeLog1); @@ -1250,6 +1284,7 @@ TSAN_INTERCEPTOR(int, pthread_barrier_wait, void *b) { } return res; } +#endif TSAN_INTERCEPTOR(int, pthread_once, void *o, void (*f)()) { SCOPED_INTERCEPTOR_RAW(pthread_once, o, f); @@ -1265,7 +1300,7 @@ TSAN_INTERCEPTOR(int, pthread_once, void *o, void (*f)()) { atomic_store(a, 2, memory_order_release); } else { while (v != 2) { - pthread_yield(); + internal_sched_yield(); v = atomic_load(a, memory_order_acquire); } if (!thr->in_ignored_lib) @@ -1274,7 +1309,7 @@ TSAN_INTERCEPTOR(int, pthread_once, void *o, void (*f)()) { return 0; } -#if !SANITIZER_FREEBSD +#if SANITIZER_LINUX TSAN_INTERCEPTOR(int, __xstat, int version, const char *path, void *buf) { SCOPED_TSAN_INTERCEPTOR(__xstat, version, path, buf); READ_STRING(thr, pc, path, 0); @@ -1286,7 +1321,7 @@ TSAN_INTERCEPTOR(int, __xstat, int version, const char *path, void *buf) { #endif TSAN_INTERCEPTOR(int, stat, const char *path, void *buf) { -#if SANITIZER_FREEBSD +#if SANITIZER_FREEBSD || SANITIZER_MAC SCOPED_TSAN_INTERCEPTOR(stat, path, buf); READ_STRING(thr, pc, path, 0); return REAL(stat)(path, buf); @@ -1297,7 +1332,7 @@ TSAN_INTERCEPTOR(int, stat, const char *path, void *buf) { #endif } -#if !SANITIZER_FREEBSD +#if SANITIZER_LINUX TSAN_INTERCEPTOR(int, __xstat64, int version, const char *path, void *buf) { SCOPED_TSAN_INTERCEPTOR(__xstat64, version, path, buf); READ_STRING(thr, pc, path, 0); @@ -1308,7 +1343,7 @@ TSAN_INTERCEPTOR(int, __xstat64, int version, const char *path, void *buf) { #define TSAN_MAYBE_INTERCEPT___XSTAT64 #endif -#if !SANITIZER_FREEBSD +#if SANITIZER_LINUX TSAN_INTERCEPTOR(int, stat64, const char *path, void *buf) { SCOPED_TSAN_INTERCEPTOR(__xstat64, 0, path, buf); READ_STRING(thr, pc, path, 0); @@ -1319,7 +1354,7 @@ TSAN_INTERCEPTOR(int, stat64, const char *path, void *buf) { #define TSAN_MAYBE_INTERCEPT_STAT64 #endif -#if !SANITIZER_FREEBSD +#if SANITIZER_LINUX TSAN_INTERCEPTOR(int, __lxstat, int version, const char *path, void *buf) { SCOPED_TSAN_INTERCEPTOR(__lxstat, version, path, buf); READ_STRING(thr, pc, path, 0); @@ -1331,7 +1366,7 @@ TSAN_INTERCEPTOR(int, __lxstat, int version, const char *path, void *buf) { #endif TSAN_INTERCEPTOR(int, lstat, const char *path, void *buf) { -#if SANITIZER_FREEBSD +#if SANITIZER_FREEBSD || SANITIZER_MAC SCOPED_TSAN_INTERCEPTOR(lstat, path, buf); READ_STRING(thr, pc, path, 0); return REAL(lstat)(path, buf); @@ -1342,7 +1377,7 @@ TSAN_INTERCEPTOR(int, lstat, const char *path, void *buf) { #endif } -#if !SANITIZER_FREEBSD +#if SANITIZER_LINUX TSAN_INTERCEPTOR(int, __lxstat64, int version, const char *path, void *buf) { SCOPED_TSAN_INTERCEPTOR(__lxstat64, version, path, buf); READ_STRING(thr, pc, path, 0); @@ -1353,7 +1388,7 @@ TSAN_INTERCEPTOR(int, __lxstat64, int version, const char *path, void *buf) { #define TSAN_MAYBE_INTERCEPT___LXSTAT64 #endif -#if !SANITIZER_FREEBSD +#if SANITIZER_LINUX TSAN_INTERCEPTOR(int, lstat64, const char *path, void *buf) { SCOPED_TSAN_INTERCEPTOR(__lxstat64, 0, path, buf); READ_STRING(thr, pc, path, 0); @@ -1364,7 +1399,7 @@ TSAN_INTERCEPTOR(int, lstat64, const char *path, void *buf) { #define TSAN_MAYBE_INTERCEPT_LSTAT64 #endif -#if !SANITIZER_FREEBSD +#if SANITIZER_LINUX TSAN_INTERCEPTOR(int, __fxstat, int version, int fd, void *buf) { SCOPED_TSAN_INTERCEPTOR(__fxstat, version, fd, buf); if (fd > 0) @@ -1377,7 +1412,7 @@ TSAN_INTERCEPTOR(int, __fxstat, int version, int fd, void *buf) { #endif TSAN_INTERCEPTOR(int, fstat, int fd, void *buf) { -#if SANITIZER_FREEBSD +#if SANITIZER_FREEBSD || SANITIZER_MAC SCOPED_TSAN_INTERCEPTOR(fstat, fd, buf); if (fd > 0) FdAccess(thr, pc, fd); @@ -1390,7 +1425,7 @@ TSAN_INTERCEPTOR(int, fstat, int fd, void *buf) { #endif } -#if !SANITIZER_FREEBSD +#if SANITIZER_LINUX TSAN_INTERCEPTOR(int, __fxstat64, int version, int fd, void *buf) { SCOPED_TSAN_INTERCEPTOR(__fxstat64, version, fd, buf); if (fd > 0) @@ -1402,7 +1437,7 @@ TSAN_INTERCEPTOR(int, __fxstat64, int version, int fd, void *buf) { #define TSAN_MAYBE_INTERCEPT___FXSTAT64 #endif -#if !SANITIZER_FREEBSD +#if SANITIZER_LINUX TSAN_INTERCEPTOR(int, fstat64, int fd, void *buf) { SCOPED_TSAN_INTERCEPTOR(__fxstat64, 0, fd, buf); if (fd > 0) @@ -1423,7 +1458,7 @@ TSAN_INTERCEPTOR(int, open, const char *name, int flags, int mode) { return fd; } -#if !SANITIZER_FREEBSD +#if SANITIZER_LINUX TSAN_INTERCEPTOR(int, open64, const char *name, int flags, int mode) { SCOPED_TSAN_INTERCEPTOR(open64, name, flags, mode); READ_STRING(thr, pc, name, 0); @@ -1446,7 +1481,7 @@ TSAN_INTERCEPTOR(int, creat, const char *name, int mode) { return fd; } -#if !SANITIZER_FREEBSD +#if SANITIZER_LINUX TSAN_INTERCEPTOR(int, creat64, const char *name, int mode) { SCOPED_TSAN_INTERCEPTOR(creat64, name, mode); READ_STRING(thr, pc, name, 0); @@ -1476,6 +1511,7 @@ TSAN_INTERCEPTOR(int, dup2, int oldfd, int newfd) { return newfd2; } +#if !SANITIZER_MAC TSAN_INTERCEPTOR(int, dup3, int oldfd, int newfd, int flags) { SCOPED_TSAN_INTERCEPTOR(dup3, oldfd, newfd, flags); int newfd2 = REAL(dup3)(oldfd, newfd, flags); @@ -1483,8 +1519,9 @@ TSAN_INTERCEPTOR(int, dup3, int oldfd, int newfd, int flags) { FdDup(thr, pc, oldfd, newfd2, false); return newfd2; } +#endif -#if !SANITIZER_FREEBSD +#if SANITIZER_LINUX TSAN_INTERCEPTOR(int, eventfd, unsigned initval, int flags) { SCOPED_TSAN_INTERCEPTOR(eventfd, initval, flags); int fd = REAL(eventfd)(initval, flags); @@ -1497,7 +1534,7 @@ TSAN_INTERCEPTOR(int, eventfd, unsigned initval, int flags) { #define TSAN_MAYBE_INTERCEPT_EVENTFD #endif -#if !SANITIZER_FREEBSD +#if SANITIZER_LINUX TSAN_INTERCEPTOR(int, signalfd, int fd, void *mask, int flags) { SCOPED_TSAN_INTERCEPTOR(signalfd, fd, mask, flags); if (fd >= 0) @@ -1512,7 +1549,7 @@ TSAN_INTERCEPTOR(int, signalfd, int fd, void *mask, int flags) { #define TSAN_MAYBE_INTERCEPT_SIGNALFD #endif -#if !SANITIZER_FREEBSD +#if SANITIZER_LINUX TSAN_INTERCEPTOR(int, inotify_init, int fake) { SCOPED_TSAN_INTERCEPTOR(inotify_init, fake); int fd = REAL(inotify_init)(fake); @@ -1525,7 +1562,7 @@ TSAN_INTERCEPTOR(int, inotify_init, int fake) { #define TSAN_MAYBE_INTERCEPT_INOTIFY_INIT #endif -#if !SANITIZER_FREEBSD +#if SANITIZER_LINUX TSAN_INTERCEPTOR(int, inotify_init1, int flags) { SCOPED_TSAN_INTERCEPTOR(inotify_init1, flags); int fd = REAL(inotify_init1)(flags); @@ -1579,7 +1616,7 @@ TSAN_INTERCEPTOR(int, listen, int fd, int backlog) { return res; } -#if !SANITIZER_FREEBSD +#if SANITIZER_LINUX TSAN_INTERCEPTOR(int, epoll_create, int size) { SCOPED_TSAN_INTERCEPTOR(epoll_create, size); int fd = REAL(epoll_create)(size); @@ -1592,7 +1629,7 @@ TSAN_INTERCEPTOR(int, epoll_create, int size) { #define TSAN_MAYBE_INTERCEPT_EPOLL_CREATE #endif -#if !SANITIZER_FREEBSD +#if SANITIZER_LINUX TSAN_INTERCEPTOR(int, epoll_create1, int flags) { SCOPED_TSAN_INTERCEPTOR(epoll_create1, flags); int fd = REAL(epoll_create1)(flags); @@ -1612,7 +1649,7 @@ TSAN_INTERCEPTOR(int, close, int fd) { return REAL(close)(fd); } -#if !SANITIZER_FREEBSD +#if SANITIZER_LINUX TSAN_INTERCEPTOR(int, __close, int fd) { SCOPED_TSAN_INTERCEPTOR(__close, fd); if (fd >= 0) @@ -1625,7 +1662,7 @@ TSAN_INTERCEPTOR(int, __close, int fd) { #endif // glibc guts -#if !SANITIZER_FREEBSD +#if SANITIZER_LINUX TSAN_INTERCEPTOR(void, __res_iclose, void *state, bool free_addr) { SCOPED_TSAN_INTERCEPTOR(__res_iclose, state, free_addr); int fds[64]; @@ -1649,6 +1686,7 @@ TSAN_INTERCEPTOR(int, pipe, int *pipefd) { return res; } +#if !SANITIZER_MAC TSAN_INTERCEPTOR(int, pipe2, int *pipefd, int flags) { SCOPED_TSAN_INTERCEPTOR(pipe2, pipefd, flags); int res = REAL(pipe2)(pipefd, flags); @@ -1656,6 +1694,7 @@ TSAN_INTERCEPTOR(int, pipe2, int *pipefd, int flags) { FdPipeCreate(thr, pc, pipefd[0], pipefd[1]); return res; } +#endif TSAN_INTERCEPTOR(long_t, send, int fd, void *buf, long_t len, int flags) { SCOPED_TSAN_INTERCEPTOR(send, fd, buf, len, flags); @@ -1706,7 +1745,7 @@ TSAN_INTERCEPTOR(void*, tmpfile, int fake) { return res; } -#if !SANITIZER_FREEBSD +#if SANITIZER_LINUX TSAN_INTERCEPTOR(void*, tmpfile64, int fake) { SCOPED_TSAN_INTERCEPTOR(tmpfile64, fake); void *res = REAL(tmpfile64)(fake); @@ -1773,7 +1812,7 @@ TSAN_INTERCEPTOR(int, closedir, void *dirp) { return REAL(closedir)(dirp); } -#if !SANITIZER_FREEBSD +#if SANITIZER_LINUX TSAN_INTERCEPTOR(int, epoll_ctl, int epfd, int op, int fd, void *ev) { SCOPED_TSAN_INTERCEPTOR(epoll_ctl, epfd, op, fd, ev); if (epfd >= 0) @@ -1790,7 +1829,7 @@ TSAN_INTERCEPTOR(int, epoll_ctl, int epfd, int op, int fd, void *ev) { #define TSAN_MAYBE_INTERCEPT_EPOLL_CTL #endif -#if !SANITIZER_FREEBSD +#if SANITIZER_LINUX TSAN_INTERCEPTOR(int, epoll_wait, int epfd, void *ev, int cnt, int timeout) { SCOPED_TSAN_INTERCEPTOR(epoll_wait, epfd, ev, cnt, timeout); if (epfd >= 0) @@ -2089,6 +2128,7 @@ TSAN_INTERCEPTOR(int, vfork, int fake) { return WRAP(fork)(fake); } +#if SANITIZER_LINUX typedef int (*dl_iterate_phdr_cb_t)(__sanitizer_dl_phdr_info *info, SIZE_T size, void *data); struct dl_iterate_phdr_data { @@ -2132,6 +2172,7 @@ TSAN_INTERCEPTOR(int, dl_iterate_phdr, dl_iterate_phdr_cb_t cb, void *data) { int res = REAL(dl_iterate_phdr)(dl_iterate_phdr_cb, &cbdata); return res; } +#endif static int OnExit(ThreadState *thr) { int status = Finalize(thr); @@ -2266,9 +2307,11 @@ static void HandleRecvmsg(ThreadState *thr, uptr pc, MutexRepair(((TsanInterceptorContext *)ctx)->thr, \ ((TsanInterceptorContext *)ctx)->pc, (uptr)m) +#if !SANITIZER_MAC #define COMMON_INTERCEPTOR_HANDLE_RECVMSG(ctx, msg) \ HandleRecvmsg(((TsanInterceptorContext *)ctx)->thr, \ ((TsanInterceptorContext *)ctx)->pc, msg) +#endif #define COMMON_INTERCEPTOR_GET_TLS_RANGE(begin, end) \ if (TsanThread *t = GetCurrentThread()) { \ @@ -2409,18 +2452,21 @@ static void unreachable() { } void InitializeInterceptors() { +#if !SANITIZER_MAC // We need to setup it early, because functions like dlsym() can call it. REAL(memset) = internal_memset; REAL(memcpy) = internal_memcpy; +#endif // Instruct libc malloc to consume less memory. -#if !SANITIZER_FREEBSD +#if SANITIZER_LINUX mallopt(1, 0); // M_MXFAST mallopt(-3, 32*1024); // M_MMAP_THRESHOLD #endif InitializeCommonInterceptors(); +#if !SANITIZER_MAC // We can not use TSAN_INTERCEPT to get setjmp addr, // because it does &setjmp and setjmp is not present in some versions of libc. using __interception::GetRealFunctionAddress; @@ -2428,6 +2474,7 @@ void InitializeInterceptors() { GetRealFunctionAddress("_setjmp", (uptr*)&REAL(_setjmp), 0, 0); GetRealFunctionAddress("sigsetjmp", (uptr*)&REAL(sigsetjmp), 0, 0); GetRealFunctionAddress("__sigsetjmp", (uptr*)&REAL(__sigsetjmp), 0, 0); +#endif TSAN_INTERCEPT(longjmp); TSAN_INTERCEPT(siglongjmp); @@ -2567,9 +2614,12 @@ void InitializeInterceptors() { TSAN_INTERCEPT(__cxa_atexit); TSAN_INTERCEPT(_exit); +#if !SANITIZER_MAC // Need to setup it, because interceptors check that the function is resolved. // But atexit is emitted directly into the module, so can't be resolved. REAL(atexit) = (int(*)(void(*)()))unreachable; +#endif + if (REAL(__cxa_atexit)(&finalize, 0, 0)) { Printf("ThreadSanitizer: failed to setup atexit callback\n"); Die(); From 1d301e42d6dc140d86a861685b37b85d6494ece7 Mon Sep 17 00:00:00 2001 From: Kuba Brecka Date: Tue, 3 Nov 2015 14:45:32 +0000 Subject: [PATCH 31/68] Fixup for r251923 to fix a warning about an extra semicolon. git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/trunk@251924 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/tsan/rtl/tsan_interceptors.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/tsan/rtl/tsan_interceptors.cc b/lib/tsan/rtl/tsan_interceptors.cc index fb6fd750ac..c9dc34934f 100644 --- a/lib/tsan/rtl/tsan_interceptors.cc +++ b/lib/tsan/rtl/tsan_interceptors.cc @@ -97,8 +97,8 @@ extern "C" int pthread_sigmask(int how, const __sanitizer_sigset_t *set, // REAL(sigfillset) defined in common interceptors. DECLARE_REAL(int, sigfillset, __sanitizer_sigset_t *set) DECLARE_REAL(int, fflush, __sanitizer_FILE *fp) -DECLARE_REAL(void *, malloc, uptr size); -DECLARE_REAL(void, free, void *ptr); +DECLARE_REAL(void *, malloc, uptr size) +DECLARE_REAL(void, free, void *ptr) extern "C" void *pthread_self(); extern "C" void _exit(int status); extern "C" int *__errno_location(); From 4356fa3ec6d35e2d2029e42071392e4596b14a23 Mon Sep 17 00:00:00 2001 From: Martell Malone Date: Tue, 3 Nov 2015 15:46:23 +0000 Subject: [PATCH 32/68] Support for 32-bit mingw-w64 in compiler-rt. Add chkstk/alloca for gcc objects. Replace or instructions with test, the latter should be marginally more efficent, as it does not write to memory. Differential Revision: http://reviews.llvm.org/D14044 Patch by vadimcn git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/trunk@251928 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/builtins/CMakeLists.txt | 2 ++ lib/builtins/i386/chkstk.S | 4 ++-- lib/builtins/i386/chkstk2.S | 40 +++++++++++++++++++++++++++++++++ lib/builtins/x86_64/chkstk.S | 4 ++-- lib/builtins/x86_64/chkstk2.S | 42 +++++++++++++++++++++++++++++++++++ 5 files changed, 88 insertions(+), 4 deletions(-) create mode 100644 lib/builtins/i386/chkstk2.S create mode 100644 lib/builtins/x86_64/chkstk2.S diff --git a/lib/builtins/CMakeLists.txt b/lib/builtins/CMakeLists.txt index d6a972e5a5..a2bacf719e 100644 --- a/lib/builtins/CMakeLists.txt +++ b/lib/builtins/CMakeLists.txt @@ -177,6 +177,7 @@ if (NOT MSVC) set(x86_64_SOURCES ${x86_64_SOURCES} x86_64/chkstk.S) + x86_64/chkstk2.S) endif() set(i386_SOURCES @@ -200,6 +201,7 @@ if (NOT MSVC) set(i386_SOURCES ${i386_SOURCES} i386/chkstk.S) + i386/chkstk2.S) endif() set(i686_SOURCES diff --git a/lib/builtins/i386/chkstk.S b/lib/builtins/i386/chkstk.S index 3733d722ef..b59974868f 100644 --- a/lib/builtins/i386/chkstk.S +++ b/lib/builtins/i386/chkstk.S @@ -19,13 +19,13 @@ DEFINE_COMPILERRT_FUNCTION(__chkstk_ms) jb 1f 2: sub $0x1000,%ecx - orl $0,(%ecx) + test %ecx,(%ecx) sub $0x1000,%eax cmp $0x1000,%eax ja 2b 1: sub %eax,%ecx - orl $0,(%ecx) + test %ecx,(%ecx) pop %eax pop %ecx ret diff --git a/lib/builtins/i386/chkstk2.S b/lib/builtins/i386/chkstk2.S new file mode 100644 index 0000000000..7d65bb0889 --- /dev/null +++ b/lib/builtins/i386/chkstk2.S @@ -0,0 +1,40 @@ +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. + +#include "../assembly.h" + +#ifdef __i386__ + +// _chkstk (_alloca) routine - probe stack between %esp and (%esp-%eax) in 4k increments, +// then decrement %esp by %eax. Preserves all registers except %esp and flags. +// This routine is windows specific +// http://msdn.microsoft.com/en-us/library/ms648426.aspx + +.text +.balign 4 +DEFINE_COMPILERRT_FUNCTION(_alloca) // _chkstk and _alloca are the same function +DEFINE_COMPILERRT_FUNCTION(__chkstk) + push %ecx + cmp $0x1000,%eax + lea 8(%esp),%ecx // esp before calling this routine -> ecx + jb 1f +2: + sub $0x1000,%ecx + test %ecx,(%ecx) + sub $0x1000,%eax + cmp $0x1000,%eax + ja 2b +1: + sub %eax,%ecx + test %ecx,(%ecx) + + lea 4(%esp),%eax // load pointer to the return address into eax + mov %ecx,%esp // install the new top of stack pointer into esp + mov -4(%eax),%ecx // restore ecx + push (%eax) // push return address onto the stack + sub %esp,%eax // restore the original value in eax + ret +END_COMPILERRT_FUNCTION(__chkstk) +END_COMPILERRT_FUNCTION(_alloca) + +#endif // __i386__ diff --git a/lib/builtins/x86_64/chkstk.S b/lib/builtins/x86_64/chkstk.S index 5759e84498..4149ac63d9 100644 --- a/lib/builtins/x86_64/chkstk.S +++ b/lib/builtins/x86_64/chkstk.S @@ -24,13 +24,13 @@ DEFINE_COMPILERRT_FUNCTION(___chkstk_ms) jb 1f 2: sub $0x1000,%rcx - orl $0,(%rcx) + test %rcx,(%rcx) sub $0x1000,%rax cmp $0x1000,%rax ja 2b 1: sub %rax,%rcx - orl $0,(%rcx) + test %rcx,(%rcx) pop %rax pop %rcx ret diff --git a/lib/builtins/x86_64/chkstk2.S b/lib/builtins/x86_64/chkstk2.S new file mode 100644 index 0000000000..ac1eb920e0 --- /dev/null +++ b/lib/builtins/x86_64/chkstk2.S @@ -0,0 +1,42 @@ +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. + +#include "../assembly.h" + +#ifdef __x86_64__ + +// _chkstk (_alloca) routine - probe stack between %rsp and (%rsp-%rax) in 4k increments, +// then decrement %rsp by %rax. Preserves all registers except %rsp and flags. +// This routine is windows specific +// http://msdn.microsoft.com/en-us/library/ms648426.aspx + +.text +.balign 4 +DEFINE_COMPILERRT_FUNCTION(__alloca) + mov %rcx,%rax // x64 _alloca is a normal function with parameter in rcx + // fallthrough +DEFINE_COMPILERRT_FUNCTION(___chkstk) + push %rcx + cmp $0x1000,%rax + lea 16(%rsp),%rcx // rsp before calling this routine -> rcx + jb 1f +2: + sub $0x1000,%rcx + test %rcx,(%rcx) + sub $0x1000,%rax + cmp $0x1000,%rax + ja 2b +1: + sub %rax,%rcx + test %rcx,(%rcx) + + lea 8(%rsp),%rax // load pointer to the return address into rax + mov %rcx,%rsp // install the new top of stack pointer into rsp + mov -8(%rax),%rcx // restore rcx + push (%rax) // push return address onto the stack + sub %rsp,%rax // restore the original value in rax + ret +END_COMPILERRT_FUNCTION(___chkstk) +END_COMPILERRT_FUNCTION(__alloca) + +#endif // __x86_64__ From 6754ab20d5e3fc129fcba08c5f5a21b1d0a3326e Mon Sep 17 00:00:00 2001 From: Martell Malone Date: Tue, 3 Nov 2015 16:04:28 +0000 Subject: [PATCH 33/68] Fix r251928 build error git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/trunk@251931 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/builtins/CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/builtins/CMakeLists.txt b/lib/builtins/CMakeLists.txt index a2bacf719e..08929048ed 100644 --- a/lib/builtins/CMakeLists.txt +++ b/lib/builtins/CMakeLists.txt @@ -176,7 +176,7 @@ if (NOT MSVC) if (WIN32) set(x86_64_SOURCES ${x86_64_SOURCES} - x86_64/chkstk.S) + x86_64/chkstk.S x86_64/chkstk2.S) endif() @@ -200,7 +200,7 @@ if (NOT MSVC) if (WIN32) set(i386_SOURCES ${i386_SOURCES} - i386/chkstk.S) + i386/chkstk.S i386/chkstk2.S) endif() From 7f1c97c76620a6ee795792e6120d98a7edf81e65 Mon Sep 17 00:00:00 2001 From: Kuba Brecka Date: Tue, 3 Nov 2015 16:19:37 +0000 Subject: [PATCH 34/68] [tsan] Allow memchr interceptor to be used before initialization on OS X On OS X, `memchr` is called on a newly created thread even before `__tsan_thread_start_func` is invoked, which means that the ThreadState object for that thread will not yet be initialized. Let's add `COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED` into the interceptor to simply call `internal_memchr` in these cases. Differential Revision: http://reviews.llvm.org/D14283 git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/trunk@251935 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/sanitizer_common/sanitizer_common_interceptors.inc | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/sanitizer_common/sanitizer_common_interceptors.inc b/lib/sanitizer_common/sanitizer_common_interceptors.inc index 6d99b5100f..62902a306c 100644 --- a/lib/sanitizer_common/sanitizer_common_interceptors.inc +++ b/lib/sanitizer_common/sanitizer_common_interceptors.inc @@ -441,6 +441,8 @@ INTERCEPTOR(int, memcmp, const void *a1, const void *a2, uptr size) { #if SANITIZER_INTERCEPT_MEMCHR INTERCEPTOR(void*, memchr, const void *s, int c, SIZE_T n) { + if (COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED) + return internal_memchr(s, c, n); void *ctx; COMMON_INTERCEPTOR_ENTER(ctx, memchr, s, c, n); void *res = REAL(memchr)(s, c, n); From d486db8e9130049bd6717c1c5761e25c83c39840 Mon Sep 17 00:00:00 2001 From: Kuba Brecka Date: Wed, 4 Nov 2015 11:39:40 +0000 Subject: [PATCH 35/68] [tsan] Shadow memory setup for OS X Updating the shadow memory initialization in `tsan_platform_mac.cc` to also initialize the meta shadow and to mprotect the memory ranges that need to be avoided. Differential Revision: http://reviews.llvm.org/D14324 git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/trunk@252044 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/tsan/CMakeLists.txt | 7 +- lib/tsan/rtl/tsan_platform.h | 2 + lib/tsan/rtl/tsan_platform_linux.cc | 89 +------------------- lib/tsan/rtl/tsan_platform_mac.cc | 22 +---- lib/tsan/rtl/tsan_platform_posix.cc | 124 ++++++++++++++++++++++++++++ 5 files changed, 136 insertions(+), 108 deletions(-) create mode 100644 lib/tsan/rtl/tsan_platform_posix.cc diff --git a/lib/tsan/CMakeLists.txt b/lib/tsan/CMakeLists.txt index fb382d7ee1..a9cfa14e67 100644 --- a/lib/tsan/CMakeLists.txt +++ b/lib/tsan/CMakeLists.txt @@ -45,11 +45,14 @@ set(TSAN_CXX_SOURCES rtl/tsan_new_delete.cc) if(APPLE) - list(APPEND TSAN_SOURCES rtl/tsan_platform_mac.cc) + list(APPEND TSAN_SOURCES + rtl/tsan_platform_mac.cc + rtl/tsan_platform_posix.cc) elseif(UNIX) # Assume Linux list(APPEND TSAN_SOURCES - rtl/tsan_platform_linux.cc) + rtl/tsan_platform_linux.cc + rtl/tsan_platform_posix.cc) endif() set(TSAN_HEADERS diff --git a/lib/tsan/rtl/tsan_platform.h b/lib/tsan/rtl/tsan_platform.h index dcf9d64c32..87169fc089 100644 --- a/lib/tsan/rtl/tsan_platform.h +++ b/lib/tsan/rtl/tsan_platform.h @@ -340,6 +340,8 @@ uptr ALWAYS_INLINE GetThreadTraceHeader(int tid) { } void InitializePlatform(); +void CheckAndProtect(); +void InitializeShadowMemoryPlatform(); void FlushShadowMemory(); void WriteMemoryProfile(char *buf, uptr buf_size, uptr nthread, uptr nlive); diff --git a/lib/tsan/rtl/tsan_platform_linux.cc b/lib/tsan/rtl/tsan_platform_linux.cc index 51637ad808..65c7b8bcc5 100644 --- a/lib/tsan/rtl/tsan_platform_linux.cc +++ b/lib/tsan/rtl/tsan_platform_linux.cc @@ -132,17 +132,6 @@ void FlushShadowMemory() { } #ifndef SANITIZER_GO -static void ProtectRange(uptr beg, uptr end) { - CHECK_LE(beg, end); - if (beg == end) - return; - if (beg != (uptr)MmapNoAccess(beg, end - beg)) { - Printf("FATAL: ThreadSanitizer can not protect [%zx,%zx]\n", beg, end); - Printf("FATAL: Make sure you are not using unlimited stack\n"); - Die(); - } -} - // Mark shadow for .rodata sections with the special kShadowRodata marker. // Accesses to .rodata can't race, so this saves time, memory and trace space. static void MapRodata() { @@ -200,58 +189,7 @@ static void MapRodata() { internal_close(fd); } -void InitializeShadowMemory() { - // Map memory shadow. - uptr shadow = - (uptr)MmapFixedNoReserve(kShadowBeg, kShadowEnd - kShadowBeg, "shadow"); - if (shadow != kShadowBeg) { - Printf("FATAL: ThreadSanitizer can not mmap the shadow memory\n"); - Printf("FATAL: Make sure to compile with -fPIE and " - "to link with -pie (%p, %p).\n", shadow, kShadowBeg); - Die(); - } - // This memory range is used for thread stacks and large user mmaps. - // Frequently a thread uses only a small part of stack and similarly - // a program uses a small part of large mmap. On some programs - // we see 20% memory usage reduction without huge pages for this range. - // FIXME: don't use constants here. -#if defined(__x86_64__) - const uptr kMadviseRangeBeg = 0x7f0000000000ull; - const uptr kMadviseRangeSize = 0x010000000000ull; -#elif defined(__mips64) - const uptr kMadviseRangeBeg = 0xff00000000ull; - const uptr kMadviseRangeSize = 0x0100000000ull; -#elif defined(__aarch64__) - const uptr kMadviseRangeBeg = 0x7e00000000ull; - const uptr kMadviseRangeSize = 0x0100000000ull; -#endif - NoHugePagesInRegion(MemToShadow(kMadviseRangeBeg), - kMadviseRangeSize * kShadowMultiplier); - // Meta shadow is compressing and we don't flush it, - // so it makes sense to mark it as NOHUGEPAGE to not over-allocate memory. - // On one program it reduces memory consumption from 5GB to 2.5GB. - NoHugePagesInRegion(kMetaShadowBeg, kMetaShadowEnd - kMetaShadowBeg); - if (common_flags()->use_madv_dontdump) - DontDumpShadowMemory(kShadowBeg, kShadowEnd - kShadowBeg); - DPrintf("memory shadow: %zx-%zx (%zuGB)\n", - kShadowBeg, kShadowEnd, - (kShadowEnd - kShadowBeg) >> 30); - - // Map meta shadow. - uptr meta_size = kMetaShadowEnd - kMetaShadowBeg; - uptr meta = - (uptr)MmapFixedNoReserve(kMetaShadowBeg, meta_size, "meta shadow"); - if (meta != kMetaShadowBeg) { - Printf("FATAL: ThreadSanitizer can not mmap the shadow memory\n"); - Printf("FATAL: Make sure to compile with -fPIE and " - "to link with -pie (%p, %p).\n", meta, kMetaShadowBeg); - Die(); - } - if (common_flags()->use_madv_dontdump) - DontDumpShadowMemory(meta, meta_size); - DPrintf("meta shadow: %zx-%zx (%zuGB)\n", - meta, meta + meta_size, meta_size >> 30); - +void InitializeShadowMemoryPlatform() { MapRodata(); } @@ -295,31 +233,6 @@ static void InitDataSeg() { CHECK_LT((uptr)&g_data_start, g_data_end); } -static void CheckAndProtect() { - // Ensure that the binary is indeed compiled with -pie. - MemoryMappingLayout proc_maps(true); - uptr p, end; - while (proc_maps.Next(&p, &end, 0, 0, 0, 0)) { - if (IsAppMem(p)) - continue; - if (p >= kHeapMemEnd && - p < HeapEnd()) - continue; - if (p >= kVdsoBeg) // vdso - break; - Printf("FATAL: ThreadSanitizer: unexpected memory mapping %p-%p\n", p, end); - Die(); - } - - ProtectRange(kLoAppMemEnd, kShadowBeg); - ProtectRange(kShadowEnd, kMetaShadowBeg); - ProtectRange(kMetaShadowEnd, kTraceMemBeg); - // Memory for traces is mapped lazily in MapThreadTrace. - // Protect the whole range for now, so that user does not map something here. - ProtectRange(kTraceMemBeg, kTraceMemEnd); - ProtectRange(kTraceMemEnd, kHeapMemBeg); - ProtectRange(HeapEnd(), kHiAppMemBeg); -} #endif // #ifndef SANITIZER_GO void InitializePlatform() { diff --git a/lib/tsan/rtl/tsan_platform_mac.cc b/lib/tsan/rtl/tsan_platform_mac.cc index 32d340268f..550f9705ed 100644 --- a/lib/tsan/rtl/tsan_platform_mac.cc +++ b/lib/tsan/rtl/tsan_platform_mac.cc @@ -51,28 +51,14 @@ void WriteMemoryProfile(char *buf, uptr buf_size, uptr nthread, uptr nlive) { } #ifndef SANITIZER_GO -void InitializeShadowMemory() { - uptr shadow = (uptr)MmapFixedNoReserve(kShadowBeg, - kShadowEnd - kShadowBeg); - if (shadow != kShadowBeg) { - Printf("FATAL: ThreadSanitizer can not mmap the shadow memory\n"); - Printf("FATAL: Make sure to compile with -fPIE and " - "to link with -pie.\n"); - Die(); - } - if (common_flags()->use_madv_dontdump) - DontDumpShadowMemory(kShadowBeg, kShadowEnd - kShadowBeg); - DPrintf("kShadow %zx-%zx (%zuGB)\n", - kShadowBeg, kShadowEnd, - (kShadowEnd - kShadowBeg) >> 30); - DPrintf("kAppMem %zx-%zx (%zuGB)\n", - kAppMemBeg, kAppMemEnd, - (kAppMemEnd - kAppMemBeg) >> 30); -} +void InitializeShadowMemoryPlatform() { } #endif void InitializePlatform() { DisableCoreDumperIfNecessary(); +#ifndef SANITIZER_GO + CheckAndProtect(); +#endif } #ifndef SANITIZER_GO diff --git a/lib/tsan/rtl/tsan_platform_posix.cc b/lib/tsan/rtl/tsan_platform_posix.cc new file mode 100644 index 0000000000..1782bf1407 --- /dev/null +++ b/lib/tsan/rtl/tsan_platform_posix.cc @@ -0,0 +1,124 @@ +//===-- tsan_platform_posix.cc --------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file is a part of ThreadSanitizer (TSan), a race detector. +// +// POSIX-specific code. +//===----------------------------------------------------------------------===// + +#include "sanitizer_common/sanitizer_platform.h" +#if SANITIZER_POSIX + +#include "sanitizer_common/sanitizer_common.h" +#include "sanitizer_common/sanitizer_libc.h" +#include "sanitizer_common/sanitizer_procmaps.h" +#include "tsan_platform.h" +#include "tsan_rtl.h" + +namespace __tsan { + +#ifndef SANITIZER_GO +void InitializeShadowMemory() { + // Map memory shadow. + uptr shadow = + (uptr)MmapFixedNoReserve(kShadowBeg, kShadowEnd - kShadowBeg, "shadow"); + if (shadow != kShadowBeg) { + Printf("FATAL: ThreadSanitizer can not mmap the shadow memory\n"); + Printf("FATAL: Make sure to compile with -fPIE and " + "to link with -pie (%p, %p).\n", shadow, kShadowBeg); + Die(); + } + // This memory range is used for thread stacks and large user mmaps. + // Frequently a thread uses only a small part of stack and similarly + // a program uses a small part of large mmap. On some programs + // we see 20% memory usage reduction without huge pages for this range. + // FIXME: don't use constants here. +#if defined(__x86_64__) + const uptr kMadviseRangeBeg = 0x7f0000000000ull; + const uptr kMadviseRangeSize = 0x010000000000ull; +#elif defined(__mips64) + const uptr kMadviseRangeBeg = 0xff00000000ull; + const uptr kMadviseRangeSize = 0x0100000000ull; +#elif defined(__aarch64__) + const uptr kMadviseRangeBeg = 0x7e00000000ull; + const uptr kMadviseRangeSize = 0x0100000000ull; +#endif + NoHugePagesInRegion(MemToShadow(kMadviseRangeBeg), + kMadviseRangeSize * kShadowMultiplier); + // Meta shadow is compressing and we don't flush it, + // so it makes sense to mark it as NOHUGEPAGE to not over-allocate memory. + // On one program it reduces memory consumption from 5GB to 2.5GB. + NoHugePagesInRegion(kMetaShadowBeg, kMetaShadowEnd - kMetaShadowBeg); + if (common_flags()->use_madv_dontdump) + DontDumpShadowMemory(kShadowBeg, kShadowEnd - kShadowBeg); + DPrintf("memory shadow: %zx-%zx (%zuGB)\n", + kShadowBeg, kShadowEnd, + (kShadowEnd - kShadowBeg) >> 30); + + // Map meta shadow. + uptr meta_size = kMetaShadowEnd - kMetaShadowBeg; + uptr meta = + (uptr)MmapFixedNoReserve(kMetaShadowBeg, meta_size, "meta shadow"); + if (meta != kMetaShadowBeg) { + Printf("FATAL: ThreadSanitizer can not mmap the shadow memory\n"); + Printf("FATAL: Make sure to compile with -fPIE and " + "to link with -pie (%p, %p).\n", meta, kMetaShadowBeg); + Die(); + } + if (common_flags()->use_madv_dontdump) + DontDumpShadowMemory(meta, meta_size); + DPrintf("meta shadow: %zx-%zx (%zuGB)\n", + meta, meta + meta_size, meta_size >> 30); + + InitializeShadowMemoryPlatform(); +} + +static void ProtectRange(uptr beg, uptr end) { + CHECK_LE(beg, end); + if (beg == end) + return; + if (beg != (uptr)MmapNoAccess(beg, end - beg)) { + Printf("FATAL: ThreadSanitizer can not protect [%zx,%zx]\n", beg, end); + Printf("FATAL: Make sure you are not using unlimited stack\n"); + Die(); + } +} + +void CheckAndProtect() { + // Ensure that the binary is indeed compiled with -pie. + MemoryMappingLayout proc_maps(true); + uptr p, end, prot; + while (proc_maps.Next(&p, &end, 0, 0, 0, &prot)) { + if (IsAppMem(p)) + continue; + if (p >= kHeapMemEnd && + p < HeapEnd()) + continue; + if (prot == 0) // Zero page or mprotected. + continue; + if (p >= kVdsoBeg) // vdso + break; + Printf("FATAL: ThreadSanitizer: unexpected memory mapping %p-%p\n", p, end); + Die(); + } + + ProtectRange(kLoAppMemEnd, kShadowBeg); + ProtectRange(kShadowEnd, kMetaShadowBeg); + ProtectRange(kMetaShadowEnd, kTraceMemBeg); + // Memory for traces is mapped lazily in MapThreadTrace. + // Protect the whole range for now, so that user does not map something here. + ProtectRange(kTraceMemBeg, kTraceMemEnd); + ProtectRange(kTraceMemEnd, kHeapMemBeg); + ProtectRange(HeapEnd(), kHiAppMemBeg); +} +#endif + +} // namespace __tsan + +#endif // SANITIZER_POSIX From 9798c96cf144cfb203756457a0cdb751b498a625 Mon Sep 17 00:00:00 2001 From: Kuba Brecka Date: Wed, 4 Nov 2015 15:09:14 +0000 Subject: [PATCH 36/68] [tsan] Handle libdispatch worker threads on OS X On OS X, GCD worker threads are created without a call to pthread_create. We need to properly register these threads with ThreadCreate and ThreadStart. This patch uses a libpthread API (`pthread_introspection_hook_install`) to get notifications about new threads and about threads that are about to be destroyed. Differential Revision: http://reviews.llvm.org/D14328 git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/trunk@252049 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/tsan/rtl/tsan_clock.cc | 2 -- lib/tsan/rtl/tsan_defs.h | 2 ++ lib/tsan/rtl/tsan_interceptors.cc | 22 ++++++++++------- lib/tsan/rtl/tsan_platform.h | 2 ++ lib/tsan/rtl/tsan_platform_mac.cc | 40 +++++++++++++++++++++++++++++++ lib/tsan/rtl/tsan_rtl_thread.cc | 8 +++++-- 6 files changed, 63 insertions(+), 13 deletions(-) diff --git a/lib/tsan/rtl/tsan_clock.cc b/lib/tsan/rtl/tsan_clock.cc index 59e3de435f..1e2050d1f2 100644 --- a/lib/tsan/rtl/tsan_clock.cc +++ b/lib/tsan/rtl/tsan_clock.cc @@ -90,8 +90,6 @@ namespace __tsan { -const unsigned kInvalidTid = (unsigned)-1; - ThreadClock::ThreadClock(unsigned tid, unsigned reused) : tid_(tid) , reused_(reused + 1) { // 0 has special meaning diff --git a/lib/tsan/rtl/tsan_defs.h b/lib/tsan/rtl/tsan_defs.h index d869d95e08..385e366c39 100644 --- a/lib/tsan/rtl/tsan_defs.h +++ b/lib/tsan/rtl/tsan_defs.h @@ -83,6 +83,8 @@ const bool kCollectHistory = false; const bool kCollectHistory = true; #endif +const unsigned kInvalidTid = (unsigned)-1; + // The following "build consistency" machinery ensures that all source files // are built in the same configuration. Inconsistent builds lead to // hard to debug crashes. diff --git a/lib/tsan/rtl/tsan_interceptors.cc b/lib/tsan/rtl/tsan_interceptors.cc index c9dc34934f..0d9bba5b2f 100644 --- a/lib/tsan/rtl/tsan_interceptors.cc +++ b/lib/tsan/rtl/tsan_interceptors.cc @@ -812,6 +812,18 @@ extern "C" void INTERFACE_ATTRIBUTE __cxa_guard_abort(atomic_uint32_t *g) { atomic_store(g, 0, memory_order_relaxed); } +namespace __tsan { +void DestroyThreadState() { + ThreadState *thr = cur_thread(); + ThreadFinish(thr); + ThreadSignalContext *sctx = thr->signal_ctx; + if (sctx) { + thr->signal_ctx = 0; + UnmapOrDie(sctx, sizeof(*sctx)); + } +} +} // namespace __tsan + static void thread_finalize(void *v) { uptr iter = (uptr)v; if (iter > 1) { @@ -821,15 +833,7 @@ static void thread_finalize(void *v) { } return; } - { - ThreadState *thr = cur_thread(); - ThreadFinish(thr); - ThreadSignalContext *sctx = thr->signal_ctx; - if (sctx) { - thr->signal_ctx = 0; - UnmapOrDie(sctx, sizeof(*sctx)); - } - } + DestroyThreadState(); } diff --git a/lib/tsan/rtl/tsan_platform.h b/lib/tsan/rtl/tsan_platform.h index 87169fc089..57cd86d830 100644 --- a/lib/tsan/rtl/tsan_platform.h +++ b/lib/tsan/rtl/tsan_platform.h @@ -355,6 +355,8 @@ int call_pthread_cancel_with_cleanup(int(*fn)(void *c, void *m, void *abstime), void *c, void *m, void *abstime, void(*cleanup)(void *arg), void *arg); +void DestroyThreadState(); + } // namespace __tsan #endif // TSAN_PLATFORM_H diff --git a/lib/tsan/rtl/tsan_platform_mac.cc b/lib/tsan/rtl/tsan_platform_mac.cc index 550f9705ed..4677adda32 100644 --- a/lib/tsan/rtl/tsan_platform_mac.cc +++ b/lib/tsan/rtl/tsan_platform_mac.cc @@ -54,11 +54,51 @@ void WriteMemoryProfile(char *buf, uptr buf_size, uptr nthread, uptr nlive) { void InitializeShadowMemoryPlatform() { } #endif +// On OS X, GCD worker threads are created without a call to pthread_create. We +// need to properly register these threads with ThreadCreate and ThreadStart. +// These threads don't have a parent thread, as they are created "spuriously". +// We're using a libpthread API that notifies us about a newly created thread. +// The `thread == pthread_self()` check indicates this is actually a worker +// thread. If it's just a regular thread, this hook is called on the parent +// thread. +typedef void (*pthread_introspection_hook_t)(unsigned int event, + pthread_t thread, void *addr, + size_t size); +extern "C" pthread_introspection_hook_t pthread_introspection_hook_install( + pthread_introspection_hook_t hook); +static const uptr PTHREAD_INTROSPECTION_THREAD_CREATE = 1; +static const uptr PTHREAD_INTROSPECTION_THREAD_DESTROY = 4; +static pthread_introspection_hook_t prev_pthread_introspection_hook; +static void my_pthread_introspection_hook(unsigned int event, pthread_t thread, + void *addr, size_t size) { + if (event == PTHREAD_INTROSPECTION_THREAD_CREATE) { + if (thread == pthread_self()) { + // The current thread is a newly created GCD worker thread. + ThreadState *parent_thread_state = nullptr; // No parent. + int tid = ThreadCreate(parent_thread_state, 0, (uptr)thread, true); + CHECK_NE(tid, 0); + ThreadState *thr = cur_thread(); + ThreadStart(thr, tid, GetTid()); + } + } else if (event == PTHREAD_INTROSPECTION_THREAD_DESTROY) { + ThreadState *thr = cur_thread(); + if (thr->tctx->parent_tid == kInvalidTid) { + DestroyThreadState(); + } + } + + if (prev_pthread_introspection_hook != nullptr) + prev_pthread_introspection_hook(event, thread, addr, size); +} + void InitializePlatform() { DisableCoreDumperIfNecessary(); #ifndef SANITIZER_GO CheckAndProtect(); #endif + + prev_pthread_introspection_hook = + pthread_introspection_hook_install(&my_pthread_introspection_hook); } #ifndef SANITIZER_GO diff --git a/lib/tsan/rtl/tsan_rtl_thread.cc b/lib/tsan/rtl/tsan_rtl_thread.cc index 66c78cfdd7..dcae255f76 100644 --- a/lib/tsan/rtl/tsan_rtl_thread.cc +++ b/lib/tsan/rtl/tsan_rtl_thread.cc @@ -55,6 +55,8 @@ void ThreadContext::OnCreated(void *arg) { if (tid == 0) return; OnCreatedArgs *args = static_cast(arg); + if (!args->thr) // GCD workers don't have a parent thread. + return; args->thr->fast_state.IncrementEpoch(); // Can't increment epoch w/o writing to the trace as well. TraceAddEvent(args->thr, args->thr->fast_state, EventTypeMop, 0); @@ -231,8 +233,10 @@ int ThreadCount(ThreadState *thr) { int ThreadCreate(ThreadState *thr, uptr pc, uptr uid, bool detached) { StatInc(thr, StatThreadCreate); OnCreatedArgs args = { thr, pc }; - int tid = ctx->thread_registry->CreateThread(uid, detached, thr->tid, &args); - DPrintf("#%d: ThreadCreate tid=%d uid=%zu\n", thr->tid, tid, uid); + u32 parent_tid = thr ? thr->tid : kInvalidTid; // No parent for GCD workers. + int tid = + ctx->thread_registry->CreateThread(uid, detached, parent_tid, &args); + DPrintf("#%d: ThreadCreate tid=%d uid=%zu\n", parent_tid, tid, uid); StatSet(thr, StatThreadMaxAlive, ctx->thread_registry->GetMaxAliveThreads()); return tid; } From 6d781b8f04e55e68fbe96692eb69376216ddce86 Mon Sep 17 00:00:00 2001 From: Kuba Brecka Date: Wed, 4 Nov 2015 15:43:45 +0000 Subject: [PATCH 37/68] [tsan] Use malloc zone interceptors on OS X, part 1 (refactoring) TSan needs to use a custom malloc zone on OS X, which is already implemented in ASan. This patch is a refactoring patch (NFC) that extracts this from ASan into sanitizer_common, where we can reuse it in TSan. Reviewed at http://reviews.llvm.org/D14330 git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/trunk@252052 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/asan/asan_malloc_mac.cc | 375 ++---------------- lib/sanitizer_common/sanitizer_malloc_mac.inc | 349 ++++++++++++++++ .../Darwin/interface_symbols_darwin.c | 8 - 3 files changed, 388 insertions(+), 344 deletions(-) create mode 100644 lib/sanitizer_common/sanitizer_malloc_mac.inc diff --git a/lib/asan/asan_malloc_mac.cc b/lib/asan/asan_malloc_mac.cc index d7a6307c9b..312c1c34fc 100644 --- a/lib/asan/asan_malloc_mac.cc +++ b/lib/asan/asan_malloc_mac.cc @@ -15,348 +15,51 @@ #include "sanitizer_common/sanitizer_platform.h" #if SANITIZER_MAC -#include -#include -#include -#include -#include - -#include "asan_allocator.h" #include "asan_interceptors.h" -#include "asan_internal.h" #include "asan_report.h" #include "asan_stack.h" #include "asan_stats.h" -#include "sanitizer_common/sanitizer_mac.h" - -// Similar code is used in Google Perftools, -// http://code.google.com/p/google-perftools. - -// ---------------------- Replacement functions ---------------- {{{1 -using namespace __asan; // NOLINT - -// TODO(glider): do we need both zones? -static malloc_zone_t *system_malloc_zone = 0; -static malloc_zone_t asan_zone; - -INTERCEPTOR(malloc_zone_t *, malloc_create_zone, - vm_size_t start_size, unsigned zone_flags) { - ENSURE_ASAN_INITED(); - GET_STACK_TRACE_MALLOC; - uptr page_size = GetPageSizeCached(); - uptr allocated_size = RoundUpTo(sizeof(asan_zone), page_size); - malloc_zone_t *new_zone = - (malloc_zone_t*)asan_memalign(page_size, allocated_size, - &stack, FROM_MALLOC); - internal_memcpy(new_zone, &asan_zone, sizeof(asan_zone)); - new_zone->zone_name = NULL; // The name will be changed anyway. - if (GetMacosVersion() >= MACOS_VERSION_LION) { - // Prevent the client app from overwriting the zone contents. - // Library functions that need to modify the zone will set PROT_WRITE on it. - // This matches the behavior of malloc_create_zone() on OSX 10.7 and higher. - mprotect(new_zone, allocated_size, PROT_READ); - } - return new_zone; -} - -INTERCEPTOR(malloc_zone_t *, malloc_default_zone, void) { - ENSURE_ASAN_INITED(); - return &asan_zone; -} - -INTERCEPTOR(malloc_zone_t *, malloc_default_purgeable_zone, void) { - // FIXME: ASan should support purgeable allocations. - // https://code.google.com/p/address-sanitizer/issues/detail?id=139 - ENSURE_ASAN_INITED(); - return &asan_zone; -} - -INTERCEPTOR(void, malloc_make_purgeable, void *ptr) { - // FIXME: ASan should support purgeable allocations. Ignoring them is fine - // for now. - ENSURE_ASAN_INITED(); -} - -INTERCEPTOR(int, malloc_make_nonpurgeable, void *ptr) { - // FIXME: ASan should support purgeable allocations. Ignoring them is fine - // for now. - ENSURE_ASAN_INITED(); - // Must return 0 if the contents were not purged since the last call to - // malloc_make_purgeable(). - return 0; -} - -INTERCEPTOR(void, malloc_set_zone_name, malloc_zone_t *zone, const char *name) { - ENSURE_ASAN_INITED(); - // Allocate |strlen("asan-") + 1 + internal_strlen(name)| bytes. - size_t buflen = 6 + (name ? internal_strlen(name) : 0); - InternalScopedString new_name(buflen); - if (name && zone->introspect == asan_zone.introspect) { - new_name.append("asan-%s", name); - name = new_name.data(); - } - - // Call the system malloc's implementation for both external and our zones, - // since that appropriately changes VM region protections on the zone. - REAL(malloc_set_zone_name)(zone, name); -} - -INTERCEPTOR(void *, malloc, size_t size) { - ENSURE_ASAN_INITED(); - GET_STACK_TRACE_MALLOC; - void *res = asan_malloc(size, &stack); - return res; -} -INTERCEPTOR(void, free, void *ptr) { - ENSURE_ASAN_INITED(); - if (!ptr) return; - GET_STACK_TRACE_FREE; +using namespace __asan; +#define COMMON_MALLOC_ZONE_NAME "asan" +#define COMMON_MALLOC_ENTER() ENSURE_ASAN_INITED() +#define COMMON_MALLOC_SANITIZER_INITIALIZED asan_inited +#define COMMON_MALLOC_FORCE_LOCK() asan_mz_force_lock() +#define COMMON_MALLOC_FORCE_UNLOCK() asan_mz_force_unlock() +#define COMMON_MALLOC_MEMALIGN(alignment, size) \ + GET_STACK_TRACE_MALLOC; \ + void *p = asan_memalign(alignment, size, &stack, FROM_MALLOC) +#define COMMON_MALLOC_MALLOC(size) \ + GET_STACK_TRACE_MALLOC; \ + void *p = asan_malloc(size, &stack) +#define COMMON_MALLOC_REALLOC(ptr, size) \ + GET_STACK_TRACE_MALLOC; \ + void *p = asan_realloc(ptr, size, &stack); +#define COMMON_MALLOC_CALLOC(count, size) \ + GET_STACK_TRACE_MALLOC; \ + void *p = asan_calloc(count, size, &stack); +#define COMMON_MALLOC_VALLOC(size) \ + GET_STACK_TRACE_MALLOC; \ + void *p = asan_memalign(GetPageSizeCached(), size, &stack, FROM_MALLOC); +#define COMMON_MALLOC_FREE(ptr) \ + GET_STACK_TRACE_FREE; \ asan_free(ptr, &stack, FROM_MALLOC); -} - -INTERCEPTOR(void *, realloc, void *ptr, size_t size) { - ENSURE_ASAN_INITED(); - GET_STACK_TRACE_MALLOC; - return asan_realloc(ptr, size, &stack); -} - -INTERCEPTOR(void *, calloc, size_t nmemb, size_t size) { - ENSURE_ASAN_INITED(); - GET_STACK_TRACE_MALLOC; - return asan_calloc(nmemb, size, &stack); -} - -INTERCEPTOR(void *, valloc, size_t size) { - ENSURE_ASAN_INITED(); - GET_STACK_TRACE_MALLOC; - return asan_memalign(GetPageSizeCached(), size, &stack, FROM_MALLOC); -} - -INTERCEPTOR(size_t, malloc_good_size, size_t size) { - ENSURE_ASAN_INITED(); - return asan_zone.introspect->good_size(&asan_zone, size); -} - -INTERCEPTOR(int, posix_memalign, void **memptr, size_t alignment, size_t size) { - ENSURE_ASAN_INITED(); - CHECK(memptr); - GET_STACK_TRACE_MALLOC; - void *result = asan_memalign(alignment, size, &stack, FROM_MALLOC); - if (result) { - *memptr = result; - return 0; - } - return -1; -} - -namespace { - -// TODO(glider): the __asan_mz_* functions should be united with the Linux -// wrappers, as they are basically copied from there. -extern "C" -SANITIZER_INTERFACE_ATTRIBUTE -size_t __asan_mz_size(malloc_zone_t* zone, const void* ptr) { - return asan_mz_size(ptr); -} - -extern "C" -SANITIZER_INTERFACE_ATTRIBUTE -void *__asan_mz_malloc(malloc_zone_t *zone, uptr size) { - if (UNLIKELY(!asan_inited)) { - CHECK(system_malloc_zone); - return malloc_zone_malloc(system_malloc_zone, size); - } - GET_STACK_TRACE_MALLOC; - return asan_malloc(size, &stack); -} - -extern "C" -SANITIZER_INTERFACE_ATTRIBUTE -void *__asan_mz_calloc(malloc_zone_t *zone, size_t nmemb, size_t size) { - if (UNLIKELY(!asan_inited)) { - // Hack: dlsym calls calloc before REAL(calloc) is retrieved from dlsym. - const size_t kCallocPoolSize = 1024; - static uptr calloc_memory_for_dlsym[kCallocPoolSize]; - static size_t allocated; - size_t size_in_words = ((nmemb * size) + kWordSize - 1) / kWordSize; - void *mem = (void*)&calloc_memory_for_dlsym[allocated]; - allocated += size_in_words; - CHECK(allocated < kCallocPoolSize); - return mem; - } - GET_STACK_TRACE_MALLOC; - return asan_calloc(nmemb, size, &stack); -} - -extern "C" -SANITIZER_INTERFACE_ATTRIBUTE -void *__asan_mz_valloc(malloc_zone_t *zone, size_t size) { - if (UNLIKELY(!asan_inited)) { - CHECK(system_malloc_zone); - return malloc_zone_valloc(system_malloc_zone, size); - } - GET_STACK_TRACE_MALLOC; - return asan_memalign(GetPageSizeCached(), size, &stack, FROM_MALLOC); -} - -#define GET_ZONE_FOR_PTR(ptr) \ - malloc_zone_t *zone_ptr = malloc_zone_from_ptr(ptr); \ - const char *zone_name = (zone_ptr == 0) ? 0 : zone_ptr->zone_name - -void ALWAYS_INLINE free_common(void *context, void *ptr) { - if (!ptr) return; - GET_STACK_TRACE_FREE; - // FIXME: need to retire this flag. - if (!flags()->mac_ignore_invalid_free) { - asan_free(ptr, &stack, FROM_MALLOC); - } else { - GET_ZONE_FOR_PTR(ptr); - WarnMacFreeUnallocated((uptr)ptr, (uptr)zone_ptr, zone_name, &stack); - return; - } -} - -// TODO(glider): the allocation callbacks need to be refactored. -extern "C" -SANITIZER_INTERFACE_ATTRIBUTE -void __asan_mz_free(malloc_zone_t *zone, void *ptr) { - free_common(zone, ptr); -} - -extern "C" -SANITIZER_INTERFACE_ATTRIBUTE -void *__asan_mz_realloc(malloc_zone_t *zone, void *ptr, size_t size) { - if (!ptr) { - GET_STACK_TRACE_MALLOC; - return asan_malloc(size, &stack); - } else { - if (asan_mz_size(ptr)) { - GET_STACK_TRACE_MALLOC; - return asan_realloc(ptr, size, &stack); - } else { - // We can't recover from reallocating an unknown address, because - // this would require reading at most |size| bytes from - // potentially unaccessible memory. - GET_STACK_TRACE_FREE; - GET_ZONE_FOR_PTR(ptr); - ReportMacMzReallocUnknown((uptr)ptr, (uptr)zone_ptr, zone_name, &stack); - } - } -} - -extern "C" -SANITIZER_INTERFACE_ATTRIBUTE -void __asan_mz_destroy(malloc_zone_t* zone) { - // A no-op -- we will not be destroyed! - Report("__asan_mz_destroy() called -- ignoring\n"); -} - -extern "C" -SANITIZER_INTERFACE_ATTRIBUTE -void *__asan_mz_memalign(malloc_zone_t *zone, size_t align, size_t size) { - if (UNLIKELY(!asan_inited)) { - CHECK(system_malloc_zone); - return malloc_zone_memalign(system_malloc_zone, align, size); - } - GET_STACK_TRACE_MALLOC; - return asan_memalign(align, size, &stack, FROM_MALLOC); -} - -// This function is currently unused, and we build with -Werror. -#if 0 -void __asan_mz_free_definite_size( - malloc_zone_t* zone, void *ptr, size_t size) { - // TODO(glider): check that |size| is valid. - UNIMPLEMENTED(); -} -#endif - -kern_return_t mi_enumerator(task_t task, void *, - unsigned type_mask, vm_address_t zone_address, - memory_reader_t reader, - vm_range_recorder_t recorder) { - // Should enumerate all the pointers we have. Seems like a lot of work. - return KERN_FAILURE; -} - -size_t mi_good_size(malloc_zone_t *zone, size_t size) { - // I think it's always safe to return size, but we maybe could do better. - return size; -} - -boolean_t mi_check(malloc_zone_t *zone) { - UNIMPLEMENTED(); -} - -void mi_print(malloc_zone_t *zone, boolean_t verbose) { - UNIMPLEMENTED(); -} - -void mi_log(malloc_zone_t *zone, void *address) { - // I don't think we support anything like this -} - -void mi_force_lock(malloc_zone_t *zone) { - asan_mz_force_lock(); -} - -void mi_force_unlock(malloc_zone_t *zone) { - asan_mz_force_unlock(); -} - -void mi_statistics(malloc_zone_t *zone, malloc_statistics_t *stats) { - AsanMallocStats malloc_stats; - FillMallocStatistics(&malloc_stats); - CHECK(sizeof(malloc_statistics_t) == sizeof(AsanMallocStats)); +#define COMMON_MALLOC_SIZE(ptr) \ + uptr size = asan_mz_size(ptr); +#define COMMON_MALLOC_FILL_STATS(zone, stats) \ + AsanMallocStats malloc_stats; \ + FillMallocStatistics(&malloc_stats); \ + CHECK(sizeof(malloc_statistics_t) == sizeof(AsanMallocStats)); \ internal_memcpy(stats, &malloc_stats, sizeof(malloc_statistics_t)); -} - -boolean_t mi_zone_locked(malloc_zone_t *zone) { - // UNIMPLEMENTED(); - return false; -} - -} // unnamed namespace - -namespace __asan { +#define COMMON_MALLOC_REPORT_UNKNOWN_REALLOC(ptr, zone_ptr, zone_name) \ + GET_STACK_TRACE_FREE; \ + ReportMacMzReallocUnknown((uptr)ptr, (uptr)zone_ptr, zone_name, &stack); +#define COMMON_MALLOC_IGNORE_INVALID_FREE flags()->mac_ignore_invalid_free +#define COMMON_MALLOC_REPORT_FREE_UNALLOCATED(ptr, zone_ptr, zone_name) \ + GET_STACK_TRACE_FREE; \ + WarnMacFreeUnallocated((uptr)ptr, (uptr)zone_ptr, zone_name, &stack); +#define COMMON_MALLOC_NAMESPACE __asan -void ReplaceSystemMalloc() { - static malloc_introspection_t asan_introspection; - // Ok to use internal_memset, these places are not performance-critical. - internal_memset(&asan_introspection, 0, sizeof(asan_introspection)); +#include "sanitizer_common/sanitizer_malloc_mac.inc" - asan_introspection.enumerator = &mi_enumerator; - asan_introspection.good_size = &mi_good_size; - asan_introspection.check = &mi_check; - asan_introspection.print = &mi_print; - asan_introspection.log = &mi_log; - asan_introspection.force_lock = &mi_force_lock; - asan_introspection.force_unlock = &mi_force_unlock; - asan_introspection.statistics = &mi_statistics; - asan_introspection.zone_locked = &mi_zone_locked; - - internal_memset(&asan_zone, 0, sizeof(malloc_zone_t)); - - // Use version 6 for OSX >= 10.6. - asan_zone.version = 6; - asan_zone.zone_name = "asan"; - asan_zone.size = &__asan_mz_size; - asan_zone.malloc = &__asan_mz_malloc; - asan_zone.calloc = &__asan_mz_calloc; - asan_zone.valloc = &__asan_mz_valloc; - asan_zone.free = &__asan_mz_free; - asan_zone.realloc = &__asan_mz_realloc; - asan_zone.destroy = &__asan_mz_destroy; - asan_zone.batch_malloc = 0; - asan_zone.batch_free = 0; - asan_zone.free_definite_size = 0; - asan_zone.memalign = &__asan_mz_memalign; - asan_zone.introspect = &asan_introspection; - - // Register the ASan zone. - malloc_zone_register(&asan_zone); -} -} // namespace __asan - -#endif // SANITIZER_MAC +#endif diff --git a/lib/sanitizer_common/sanitizer_malloc_mac.inc b/lib/sanitizer_common/sanitizer_malloc_mac.inc new file mode 100644 index 0000000000..79dadbc2f6 --- /dev/null +++ b/lib/sanitizer_common/sanitizer_malloc_mac.inc @@ -0,0 +1,349 @@ +//===-- sanitizer_malloc_mac.inc --------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains Mac-specific malloc interceptors and a custom zone +// implementation, which together replace the system allocator. +// +//===----------------------------------------------------------------------===// + +#include "sanitizer_common/sanitizer_platform.h" +#if !SANITIZER_MAC +#error "This file should only be compiled on Darwin." +#endif + +#include +#include +#include +#include +#include + +#include "interception/interception.h" +#include "sanitizer_common/sanitizer_mac.h" + +// Similar code is used in Google Perftools, +// http://code.google.com/p/google-perftools. + +// TODO(glider): do we need both zones? +static malloc_zone_t *system_malloc_zone = 0; +static malloc_zone_t sanitizer_zone; + +INTERCEPTOR(malloc_zone_t *, malloc_create_zone, + vm_size_t start_size, unsigned zone_flags) { + COMMON_MALLOC_ENTER(); + uptr page_size = GetPageSizeCached(); + uptr allocated_size = RoundUpTo(sizeof(sanitizer_zone), page_size); + COMMON_MALLOC_MEMALIGN(page_size, allocated_size); + malloc_zone_t *new_zone = (malloc_zone_t *)p; + internal_memcpy(new_zone, &sanitizer_zone, sizeof(sanitizer_zone)); + new_zone->zone_name = NULL; // The name will be changed anyway. + if (GetMacosVersion() >= MACOS_VERSION_LION) { + // Prevent the client app from overwriting the zone contents. + // Library functions that need to modify the zone will set PROT_WRITE on it. + // This matches the behavior of malloc_create_zone() on OSX 10.7 and higher. + mprotect(new_zone, allocated_size, PROT_READ); + } + return new_zone; +} + +INTERCEPTOR(malloc_zone_t *, malloc_default_zone, void) { + COMMON_MALLOC_ENTER(); + return &sanitizer_zone; +} + +INTERCEPTOR(malloc_zone_t *, malloc_default_purgeable_zone, void) { + // FIXME: ASan should support purgeable allocations. + // https://code.google.com/p/address-sanitizer/issues/detail?id=139 + COMMON_MALLOC_ENTER(); + return &sanitizer_zone; +} + +INTERCEPTOR(void, malloc_make_purgeable, void *ptr) { + // FIXME: ASan should support purgeable allocations. Ignoring them is fine + // for now. + COMMON_MALLOC_ENTER(); +} + +INTERCEPTOR(int, malloc_make_nonpurgeable, void *ptr) { + // FIXME: ASan should support purgeable allocations. Ignoring them is fine + // for now. + COMMON_MALLOC_ENTER(); + // Must return 0 if the contents were not purged since the last call to + // malloc_make_purgeable(). + return 0; +} + +INTERCEPTOR(void, malloc_set_zone_name, malloc_zone_t *zone, const char *name) { + COMMON_MALLOC_ENTER(); + // Allocate |sizeof(COMMON_MALLOC_ZONE_NAME "-") + internal_strlen(name)| bytes. + size_t buflen = + sizeof(COMMON_MALLOC_ZONE_NAME "-") + (name ? internal_strlen(name) : 0); + InternalScopedString new_name(buflen); + if (name && zone->introspect == sanitizer_zone.introspect) { + new_name.append(COMMON_MALLOC_ZONE_NAME "-%s", name); + name = new_name.data(); + } + + // Call the system malloc's implementation for both external and our zones, + // since that appropriately changes VM region protections on the zone. + REAL(malloc_set_zone_name)(zone, name); +} + +INTERCEPTOR(void *, malloc, size_t size) { + COMMON_MALLOC_ENTER(); + COMMON_MALLOC_MALLOC(size); + return p; +} + +INTERCEPTOR(void, free, void *ptr) { + COMMON_MALLOC_ENTER(); + if (!ptr) return; + COMMON_MALLOC_FREE(ptr); +} + +INTERCEPTOR(void *, realloc, void *ptr, size_t size) { + COMMON_MALLOC_ENTER(); + COMMON_MALLOC_REALLOC(ptr, size); + return p; +} + +INTERCEPTOR(void *, calloc, size_t nmemb, size_t size) { + COMMON_MALLOC_ENTER(); + COMMON_MALLOC_CALLOC(nmemb, size); + return p; +} + +INTERCEPTOR(void *, valloc, size_t size) { + COMMON_MALLOC_ENTER(); + COMMON_MALLOC_VALLOC(size); + return p; +} + +INTERCEPTOR(size_t, malloc_good_size, size_t size) { + COMMON_MALLOC_ENTER(); + return sanitizer_zone.introspect->good_size(&sanitizer_zone, size); +} + +INTERCEPTOR(int, posix_memalign, void **memptr, size_t alignment, size_t size) { + COMMON_MALLOC_ENTER(); + CHECK(memptr); + COMMON_MALLOC_MEMALIGN(alignment, size); + if (p) { + *memptr = p; + return 0; + } + return -1; +} + +namespace { + +// TODO(glider): the __sanitizer_mz_* functions should be united with the Linux +// wrappers, as they are basically copied from there. +extern "C" +SANITIZER_INTERFACE_ATTRIBUTE +size_t __sanitizer_mz_size(malloc_zone_t* zone, const void* ptr) { + COMMON_MALLOC_SIZE(ptr); + return size; +} + +extern "C" +SANITIZER_INTERFACE_ATTRIBUTE +void *__sanitizer_mz_malloc(malloc_zone_t *zone, uptr size) { + if (UNLIKELY(!COMMON_MALLOC_SANITIZER_INITIALIZED)) { + CHECK(system_malloc_zone); + return malloc_zone_malloc(system_malloc_zone, size); + } + COMMON_MALLOC_MALLOC(size); + return p; +} + +extern "C" +SANITIZER_INTERFACE_ATTRIBUTE +void *__sanitizer_mz_calloc(malloc_zone_t *zone, size_t nmemb, size_t size) { + if (UNLIKELY(!COMMON_MALLOC_SANITIZER_INITIALIZED)) { + // Hack: dlsym calls calloc before REAL(calloc) is retrieved from dlsym. + const size_t kCallocPoolSize = 1024; + static uptr calloc_memory_for_dlsym[kCallocPoolSize]; + static size_t allocated; + size_t size_in_words = ((nmemb * size) + kWordSize - 1) / kWordSize; + void *mem = (void*)&calloc_memory_for_dlsym[allocated]; + allocated += size_in_words; + CHECK(allocated < kCallocPoolSize); + return mem; + } + COMMON_MALLOC_CALLOC(nmemb, size); + return p; +} + +extern "C" +SANITIZER_INTERFACE_ATTRIBUTE +void *__sanitizer_mz_valloc(malloc_zone_t *zone, size_t size) { + if (UNLIKELY(!COMMON_MALLOC_SANITIZER_INITIALIZED)) { + CHECK(system_malloc_zone); + return malloc_zone_valloc(system_malloc_zone, size); + } + COMMON_MALLOC_VALLOC(size); + return p; +} + +#define GET_ZONE_FOR_PTR(ptr) \ + malloc_zone_t *zone_ptr = malloc_zone_from_ptr(ptr); \ + const char *zone_name = (zone_ptr == 0) ? 0 : zone_ptr->zone_name + +void ALWAYS_INLINE free_common(void *context, void *ptr) { + if (!ptr) return; + // FIXME: need to retire this flag. + if (!COMMON_MALLOC_IGNORE_INVALID_FREE) { + COMMON_MALLOC_FREE(ptr); + } else { + GET_ZONE_FOR_PTR(ptr); + COMMON_MALLOC_REPORT_FREE_UNALLOCATED(ptr, zone_ptr, zone_name); + } +} + +// TODO(glider): the allocation callbacks need to be refactored. +extern "C" +SANITIZER_INTERFACE_ATTRIBUTE +void __sanitizer_mz_free(malloc_zone_t *zone, void *ptr) { + free_common(zone, ptr); +} + +extern "C" +SANITIZER_INTERFACE_ATTRIBUTE +void *__sanitizer_mz_realloc(malloc_zone_t *zone, void *ptr, size_t new_size) { + if (!ptr) { + COMMON_MALLOC_MALLOC(new_size); + return p; + } else { + COMMON_MALLOC_SIZE(ptr); + if (size) { + COMMON_MALLOC_REALLOC(ptr, new_size); + return p; + } else { + // We can't recover from reallocating an unknown address, because + // this would require reading at most |new_size| bytes from + // potentially unaccessible memory. + GET_ZONE_FOR_PTR(ptr); + COMMON_MALLOC_REPORT_UNKNOWN_REALLOC(ptr, zone_ptr, zone_name); + return nullptr; + } + } +} + +extern "C" +SANITIZER_INTERFACE_ATTRIBUTE +void __sanitizer_mz_destroy(malloc_zone_t* zone) { + // A no-op -- we will not be destroyed! + Report("__sanitizer_mz_destroy() called -- ignoring\n"); +} + +extern "C" +SANITIZER_INTERFACE_ATTRIBUTE +void *__sanitizer_mz_memalign(malloc_zone_t *zone, size_t align, size_t size) { + if (UNLIKELY(!COMMON_MALLOC_SANITIZER_INITIALIZED)) { + CHECK(system_malloc_zone); + return malloc_zone_memalign(system_malloc_zone, align, size); + } + COMMON_MALLOC_MEMALIGN(align, size); + return p; +} + +// This function is currently unused, and we build with -Werror. +#if 0 +void __sanitizer_mz_free_definite_size( + malloc_zone_t* zone, void *ptr, size_t size) { + // TODO(glider): check that |size| is valid. + UNIMPLEMENTED(); +} +#endif + +kern_return_t mi_enumerator(task_t task, void *, + unsigned type_mask, vm_address_t zone_address, + memory_reader_t reader, + vm_range_recorder_t recorder) { + // Should enumerate all the pointers we have. Seems like a lot of work. + return KERN_FAILURE; +} + +size_t mi_good_size(malloc_zone_t *zone, size_t size) { + // I think it's always safe to return size, but we maybe could do better. + return size; +} + +boolean_t mi_check(malloc_zone_t *zone) { + UNIMPLEMENTED(); +} + +void mi_print(malloc_zone_t *zone, boolean_t verbose) { + UNIMPLEMENTED(); +} + +void mi_log(malloc_zone_t *zone, void *address) { + // I don't think we support anything like this +} + +void mi_force_lock(malloc_zone_t *zone) { + COMMON_MALLOC_FORCE_LOCK(); +} + +void mi_force_unlock(malloc_zone_t *zone) { + COMMON_MALLOC_FORCE_UNLOCK(); +} + +void mi_statistics(malloc_zone_t *zone, malloc_statistics_t *stats) { + COMMON_MALLOC_FILL_STATS(zone, stats); +} + +boolean_t mi_zone_locked(malloc_zone_t *zone) { + // UNIMPLEMENTED(); + return false; +} + +} // unnamed namespace + +namespace COMMON_MALLOC_NAMESPACE { + +void ReplaceSystemMalloc() { + static malloc_introspection_t sanitizer_zone_introspection; + // Ok to use internal_memset, these places are not performance-critical. + internal_memset(&sanitizer_zone_introspection, 0, + sizeof(sanitizer_zone_introspection)); + + sanitizer_zone_introspection.enumerator = &mi_enumerator; + sanitizer_zone_introspection.good_size = &mi_good_size; + sanitizer_zone_introspection.check = &mi_check; + sanitizer_zone_introspection.print = &mi_print; + sanitizer_zone_introspection.log = &mi_log; + sanitizer_zone_introspection.force_lock = &mi_force_lock; + sanitizer_zone_introspection.force_unlock = &mi_force_unlock; + sanitizer_zone_introspection.statistics = &mi_statistics; + sanitizer_zone_introspection.zone_locked = &mi_zone_locked; + + internal_memset(&sanitizer_zone, 0, sizeof(malloc_zone_t)); + + // Use version 6 for OSX >= 10.6. + sanitizer_zone.version = 6; + sanitizer_zone.zone_name = COMMON_MALLOC_ZONE_NAME; + sanitizer_zone.size = &__sanitizer_mz_size; + sanitizer_zone.malloc = &__sanitizer_mz_malloc; + sanitizer_zone.calloc = &__sanitizer_mz_calloc; + sanitizer_zone.valloc = &__sanitizer_mz_valloc; + sanitizer_zone.free = &__sanitizer_mz_free; + sanitizer_zone.realloc = &__sanitizer_mz_realloc; + sanitizer_zone.destroy = &__sanitizer_mz_destroy; + sanitizer_zone.batch_malloc = 0; + sanitizer_zone.batch_free = 0; + sanitizer_zone.free_definite_size = 0; + sanitizer_zone.memalign = &__sanitizer_mz_memalign; + sanitizer_zone.introspect = &sanitizer_zone_introspection; + + // Register the zone. + malloc_zone_register(&sanitizer_zone); +} + +} // namespace COMMON_MALLOC_NAMESPACE diff --git a/test/asan/TestCases/Darwin/interface_symbols_darwin.c b/test/asan/TestCases/Darwin/interface_symbols_darwin.c index f37072a3ac..9bd32869c9 100644 --- a/test/asan/TestCases/Darwin/interface_symbols_darwin.c +++ b/test/asan/TestCases/Darwin/interface_symbols_darwin.c @@ -43,14 +43,6 @@ // RUN: echo __asan_report_exp_store_n >> %t.interface // RUN: echo __asan_get_current_fake_stack >> %t.interface // RUN: echo __asan_addr_is_in_fake_stack >> %t.interface -// RUN: echo __asan_mz_calloc >> %t.interface -// RUN: echo __asan_mz_destroy >> %t.interface -// RUN: echo __asan_mz_free >> %t.interface -// RUN: echo __asan_mz_malloc >> %t.interface -// RUN: echo __asan_mz_memalign >> %t.interface -// RUN: echo __asan_mz_realloc >> %t.interface -// RUN: echo __asan_mz_size >> %t.interface -// RUN: echo __asan_mz_valloc >> %t.interface // RUN: for i in `jot - 0 10`; do echo __asan_stack_malloc_$i >> %t.interface; done // RUN: for i in `jot - 0 10`; do echo __asan_stack_free_$i >> %t.interface; done From e3abbe5b02dfbc88d3bd356e5e78921d199c094f Mon Sep 17 00:00:00 2001 From: Kuba Brecka Date: Wed, 4 Nov 2015 15:57:38 +0000 Subject: [PATCH 38/68] Whitespace fixup for r252052. NFC. git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/trunk@252053 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/sanitizer_common/sanitizer_malloc_mac.inc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/sanitizer_common/sanitizer_malloc_mac.inc b/lib/sanitizer_common/sanitizer_malloc_mac.inc index 79dadbc2f6..33e9d96b8c 100644 --- a/lib/sanitizer_common/sanitizer_malloc_mac.inc +++ b/lib/sanitizer_common/sanitizer_malloc_mac.inc @@ -80,7 +80,8 @@ INTERCEPTOR(int, malloc_make_nonpurgeable, void *ptr) { INTERCEPTOR(void, malloc_set_zone_name, malloc_zone_t *zone, const char *name) { COMMON_MALLOC_ENTER(); - // Allocate |sizeof(COMMON_MALLOC_ZONE_NAME "-") + internal_strlen(name)| bytes. + // Allocate |sizeof(COMMON_MALLOC_ZONE_NAME "-") + internal_strlen(name)| + // bytes. size_t buflen = sizeof(COMMON_MALLOC_ZONE_NAME "-") + (name ? internal_strlen(name) : 0); InternalScopedString new_name(buflen); From 73a0848e3856b7033ed2372753ac658ed1ea360a Mon Sep 17 00:00:00 2001 From: Mike Aizatsky Date: Wed, 4 Nov 2015 19:56:03 +0000 Subject: [PATCH 39/68] Asan: utility function to determine first wrongly poisoned byte in container. Differential Revision: http://reviews.llvm.org/D14341 git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/trunk@252071 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/sanitizer/common_interface_defs.h | 6 +++++ lib/asan/asan_poisoning.cc | 25 ++++++++++++------- .../sanitizer_interface_internal.h | 5 +++- test/asan/TestCases/contiguous_container.cc | 12 +++++++-- 4 files changed, 36 insertions(+), 12 deletions(-) diff --git a/include/sanitizer/common_interface_defs.h b/include/sanitizer/common_interface_defs.h index 4cba61a49f..b736ed9e52 100644 --- a/include/sanitizer/common_interface_defs.h +++ b/include/sanitizer/common_interface_defs.h @@ -105,6 +105,12 @@ extern "C" { int __sanitizer_verify_contiguous_container(const void *beg, const void *mid, const void *end); + // Similar to __sanitizer_verify_contiguous_container but returns the address + // of the first improperly poisoned byte otherwise. Returns null if the area + // is poisoned properly. + const void *__sanitizer_contiguous_container_find_bad_address( + const void *beg, const void *mid, const void *end); + // Print the stack trace leading to this call. Useful for debugging user code. void __sanitizer_print_stack_trace(); diff --git a/lib/asan/asan_poisoning.cc b/lib/asan/asan_poisoning.cc index 569d359aa4..0082e845fc 100644 --- a/lib/asan/asan_poisoning.cc +++ b/lib/asan/asan_poisoning.cc @@ -375,10 +375,10 @@ void __sanitizer_annotate_contiguous_container(const void *beg_p, } } -int __sanitizer_verify_contiguous_container(const void *beg_p, - const void *mid_p, - const void *end_p) { - if (!flags()->detect_container_overflow) return 1; +const void *__sanitizer_contiguous_container_find_bad_address( + const void *beg_p, const void *mid_p, const void *end_p) { + if (!flags()->detect_container_overflow) + return nullptr; uptr beg = reinterpret_cast(beg_p); uptr end = reinterpret_cast(end_p); uptr mid = reinterpret_cast(mid_p); @@ -395,17 +395,24 @@ int __sanitizer_verify_contiguous_container(const void *beg_p, uptr r3_end = end; for (uptr i = r1_beg; i < r1_end; i++) if (AddressIsPoisoned(i)) - return 0; + return reinterpret_cast(i); for (uptr i = r2_beg; i < mid; i++) if (AddressIsPoisoned(i)) - return 0; + return reinterpret_cast(i); for (uptr i = mid; i < r2_end; i++) if (!AddressIsPoisoned(i)) - return 0; + return reinterpret_cast(i); for (uptr i = r3_beg; i < r3_end; i++) if (!AddressIsPoisoned(i)) - return 0; - return 1; + return reinterpret_cast(i); + return nullptr; +} + +int __sanitizer_verify_contiguous_container(const void *beg_p, + const void *mid_p, + const void *end_p) { + return __sanitizer_contiguous_container_find_bad_address(beg_p, mid_p, + end_p) == nullptr; } extern "C" SANITIZER_INTERFACE_ATTRIBUTE diff --git a/lib/sanitizer_common/sanitizer_interface_internal.h b/lib/sanitizer_common/sanitizer_interface_internal.h index 94d9f4e952..b11ae30106 100644 --- a/lib/sanitizer_common/sanitizer_interface_internal.h +++ b/lib/sanitizer_common/sanitizer_interface_internal.h @@ -53,6 +53,9 @@ extern "C" { SANITIZER_INTERFACE_ATTRIBUTE int __sanitizer_verify_contiguous_container(const void *beg, const void *mid, const void *end); -} // extern "C" + SANITIZER_INTERFACE_ATTRIBUTE + const void *__sanitizer_contiguous_container_find_bad_address( + const void *beg, const void *mid, const void *end); + } // extern "C" #endif // SANITIZER_INTERFACE_INTERNAL_H diff --git a/test/asan/TestCases/contiguous_container.cc b/test/asan/TestCases/contiguous_container.cc index bda0f53dea..3f754562af 100644 --- a/test/asan/TestCases/contiguous_container.cc +++ b/test/asan/TestCases/contiguous_container.cc @@ -26,10 +26,18 @@ void TestContainer(size_t capacity) { for (size_t idx = size; idx < capacity; idx++) assert(__asan_address_is_poisoned(beg + idx)); assert(__sanitizer_verify_contiguous_container(beg, mid, end)); - if (mid != beg) + assert(NULL == + __sanitizer_contiguous_container_find_bad_address(beg, mid, end)); + if (mid != beg) { assert(!__sanitizer_verify_contiguous_container(beg, mid - 1, end)); - if (mid != end) + assert(mid - 1 == __sanitizer_contiguous_container_find_bad_address( + beg, mid - 1, end)); + } + if (mid != end) { assert(!__sanitizer_verify_contiguous_container(beg, mid + 1, end)); + assert(mid == __sanitizer_contiguous_container_find_bad_address( + beg, mid + 1, end)); + } } // Don't forget to unpoison the whole thing before destroing/reallocating. From 766e7c6b61b0207ada838fd31ede7aa2b9bfffef Mon Sep 17 00:00:00 2001 From: Juergen Ributzka Date: Wed, 4 Nov 2015 21:03:12 +0000 Subject: [PATCH 40/68] Revert "Reapply: [asan] On OS X, log reports to syslog and os_trace" Looks like this commit is deadlocking the ASAN tests on the green dragon bot (http://lab.llvm.org:8080/green/job/clang-stage1-cmake-RA/). git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/trunk@252076 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/asan/asan_report.cc | 40 ++++++++---------- lib/asan/tests/asan_test_main.cc | 3 +- lib/sanitizer_common/sanitizer_common.cc | 34 --------------- lib/sanitizer_common/sanitizer_common.h | 19 +-------- .../sanitizer_common_libcdep.cc | 27 +----------- .../sanitizer_common_nolibc.cc | 4 +- lib/sanitizer_common/sanitizer_flags.inc | 2 +- .../sanitizer_linux_libcdep.cc | 24 +++++++++-- lib/sanitizer_common/sanitizer_mac.cc | 41 ------------------- lib/sanitizer_common/sanitizer_printf.cc | 2 +- .../tests/sanitizer_common_test.cc | 24 ----------- lib/tsan/go/buildgo.sh | 1 - test/asan/lit.cfg | 2 - test/ubsan/lit.common.cfg | 1 - 14 files changed, 46 insertions(+), 178 deletions(-) diff --git a/lib/asan/asan_report.cc b/lib/asan/asan_report.cc index 5c266b6532..957ac14eaf 100644 --- a/lib/asan/asan_report.cc +++ b/lib/asan/asan_report.cc @@ -31,7 +31,6 @@ static void (*error_report_callback)(const char*); static char *error_message_buffer = nullptr; static uptr error_message_buffer_pos = 0; static uptr error_message_buffer_size = 0; -static BlockingMutex error_message_buf_mutex(LINKER_INITIALIZED); struct ReportData { uptr pc; @@ -47,21 +46,16 @@ static bool report_happened = false; static ReportData report_data = {}; void AppendToErrorMessageBuffer(const char *buffer) { - BlockingMutexLock l(&error_message_buf_mutex); - if (!error_message_buffer) { - error_message_buffer_size = 1 << 16; - error_message_buffer = - (char*)MmapOrDie(error_message_buffer_size, __func__); - error_message_buffer_pos = 0; + if (error_message_buffer) { + uptr length = internal_strlen(buffer); + CHECK_GE(error_message_buffer_size, error_message_buffer_pos); + uptr remaining = error_message_buffer_size - error_message_buffer_pos; + internal_strncpy(error_message_buffer + error_message_buffer_pos, + buffer, remaining); + error_message_buffer[error_message_buffer_size - 1] = '\0'; + // FIXME: reallocate the buffer instead of truncating the message. + error_message_buffer_pos += Min(remaining, length); } - uptr length = internal_strlen(buffer); - CHECK_GE(error_message_buffer_size, error_message_buffer_pos); - uptr remaining = error_message_buffer_size - error_message_buffer_pos; - internal_strncpy(error_message_buffer + error_message_buffer_pos, - buffer, remaining); - error_message_buffer[error_message_buffer_size - 1] = '\0'; - // FIXME: reallocate the buffer instead of truncating the message. - error_message_buffer_pos += Min(remaining, length); } // ---------------------- Decorator ------------------------------ {{{1 @@ -670,13 +664,8 @@ class ScopedInErrorReport { // Print memory stats. if (flags()->print_stats) __asan_print_accumulated_stats(); - { - BlockingMutexLock l(&error_message_buf_mutex); - LogFullErrorReport(error_message_buffer); - - if (error_report_callback) { - error_report_callback(error_message_buffer); - } + if (error_report_callback) { + error_report_callback(error_message_buffer); } Report("ABORTING\n"); Die(); @@ -1072,8 +1061,13 @@ void __asan_report_error(uptr pc, uptr bp, uptr sp, uptr addr, int is_write, } void NOINLINE __asan_set_error_report_callback(void (*callback)(const char*)) { - BlockingMutexLock l(&error_message_buf_mutex); error_report_callback = callback; + if (callback) { + error_message_buffer_size = 1 << 16; + error_message_buffer = + (char*)MmapOrDie(error_message_buffer_size, __func__); + error_message_buffer_pos = 0; + } } void __asan_describe_address(uptr addr) { diff --git a/lib/asan/tests/asan_test_main.cc b/lib/asan/tests/asan_test_main.cc index cdaf801d91..5958cb8a06 100644 --- a/lib/asan/tests/asan_test_main.cc +++ b/lib/asan/tests/asan_test_main.cc @@ -19,8 +19,7 @@ extern "C" const char* __asan_default_options() { #if SANITIZER_MAC // On Darwin, we default to `abort_on_error=1`, which would make tests run // much slower. Let's override this and run lit tests with 'abort_on_error=0'. - // Also, make sure we do not overwhelm the syslog while testing. - return "symbolize=false:abort_on_error=0:log_to_syslog=0"; + return "symbolize=false:abort_on_error=0"; #else return "symbolize=false"; #endif diff --git a/lib/sanitizer_common/sanitizer_common.cc b/lib/sanitizer_common/sanitizer_common.cc index db734d6286..2fb88688d1 100644 --- a/lib/sanitizer_common/sanitizer_common.cc +++ b/lib/sanitizer_common/sanitizer_common.cc @@ -295,40 +295,6 @@ void ReportErrorSummary(const char *error_type, const AddressInfo &info) { } #endif -// Removes the ANSI escape sequences from the input string (in-place). -void RemoveANSIEscapeSequencesFromString(char *str) { - if (!str) - return; - - // We are going to remove the escape sequences in place. - char *s = str; - char *z = str; - while (*s != '\0') { - CHECK_GE(s, z); - // Skip over ANSI escape sequences with pointer 's'. - if (*s == '\033' && *(s + 1) == '[') { - s = internal_strchrnul(s, 'm'); - if (*s == '\0') { - break; - } - s++; - continue; - } - // 's' now points at a character we want to keep. Copy over the buffer - // content if the escape sequence has been perviously skipped andadvance - // both pointers. - if (s != z) - *z = *s; - - // If we have not seen an escape sequence, just advance both pointers. - z++; - s++; - } - - // Null terminate the string. - *z = '\0'; -} - void LoadedModule::set(const char *module_name, uptr base_address) { clear(); full_name_ = internal_strdup(module_name); diff --git a/lib/sanitizer_common/sanitizer_common.h b/lib/sanitizer_common/sanitizer_common.h index 63c772bc4e..bfd0d6e12a 100644 --- a/lib/sanitizer_common/sanitizer_common.h +++ b/lib/sanitizer_common/sanitizer_common.h @@ -162,7 +162,6 @@ void SetLowLevelAllocateCallback(LowLevelAllocateCallback callback); // IO void RawWrite(const char *buffer); bool ColorizeReports(); -void RemoveANSIEscapeSequencesFromString(char *buffer); void Printf(const char *format, ...); void Report(const char *format, ...); void SetPrintfAndReportCallback(void (*callback)(const char *)); @@ -649,27 +648,13 @@ enum AndroidApiLevel { ANDROID_POST_LOLLIPOP = 23 }; -void WriteToSyslog(const char *buffer); - -#if SANITIZER_MAC -void LogFullErrorReport(const char *error_message_buffer); -#else -INLINE void LogFullErrorReport(const char *error_message_buffer) {} -#endif - -#if SANITIZER_LINUX || SANITIZER_MAC -void WriteOneLineToSyslog(const char *s); -#else -INLINE void WriteOneLineToSyslog(const char *s) {} -#endif - #if SANITIZER_LINUX // Initialize Android logging. Any writes before this are silently lost. void AndroidLogInit(); -bool ShouldLogAfterPrintf(); +void WriteToSyslog(const char *buffer); #else INLINE void AndroidLogInit() {} -INLINE bool ShouldLogAfterPrintf() { return false; } +INLINE void WriteToSyslog(const char *buffer) {} #endif #if SANITIZER_ANDROID diff --git a/lib/sanitizer_common/sanitizer_common_libcdep.cc b/lib/sanitizer_common/sanitizer_common_libcdep.cc index 9095002aa6..1b65bced75 100644 --- a/lib/sanitizer_common/sanitizer_common_libcdep.cc +++ b/lib/sanitizer_common/sanitizer_common_libcdep.cc @@ -12,7 +12,6 @@ //===----------------------------------------------------------------------===// #include "sanitizer_common.h" -#include "sanitizer_allocator_internal.h" #include "sanitizer_flags.h" #include "sanitizer_stackdepot.h" #include "sanitizer_stacktrace.h" @@ -47,7 +46,6 @@ void SetSandboxingCallback(void (*f)()) { } void ReportErrorSummary(const char *error_type, StackTrace *stack) { -#if !SANITIZER_GO if (!common_flags()->print_summary) return; if (stack->size == 0) { @@ -60,7 +58,6 @@ void ReportErrorSummary(const char *error_type, StackTrace *stack) { SymbolizedStack *frame = Symbolizer::GetOrInit()->SymbolizePC(pc); ReportErrorSummary(error_type, frame->info); frame->ClearAll(); -#endif } static void (*SoftRssLimitExceededCallback)(bool exceeded); @@ -119,30 +116,8 @@ void BackgroundThread(void *arg) { } } -void WriteToSyslog(const char *buffer) { - char *copy = internal_strdup(buffer); - char *p = copy; - char *q; - - // Remove color sequences since syslogs cannot print them. - RemoveANSIEscapeSequencesFromString(copy); - - // Print one line at a time. - // syslog, at least on Android, has an implicit message length limit. - do { - q = internal_strchr(p, '\n'); - if (q) - *q = '\0'; - WriteOneLineToSyslog(p); - if (q) - p = q + 1; - } while (q); - InternalFree(copy); -} - void MaybeStartBackgroudThread() { -#if SANITIZER_LINUX && \ - !SANITIZER_GO // Need to implement/test on other platforms. +#if SANITIZER_LINUX // Need to implement/test on other platforms. // Start the background thread if one of the rss limits is given. if (!common_flags()->hard_rss_limit_mb && !common_flags()->soft_rss_limit_mb) return; diff --git a/lib/sanitizer_common/sanitizer_common_nolibc.cc b/lib/sanitizer_common/sanitizer_common_nolibc.cc index 89c17e0797..65d1e37f62 100644 --- a/lib/sanitizer_common/sanitizer_common_nolibc.cc +++ b/lib/sanitizer_common/sanitizer_common_nolibc.cc @@ -18,9 +18,9 @@ namespace __sanitizer { #if SANITIZER_LINUX -bool ShouldLogAfterPrintf() { return false; } -#endif void WriteToSyslog(const char *buffer) {} +#endif + void Abort() { internal__exit(1); } } // namespace __sanitizer diff --git a/lib/sanitizer_common/sanitizer_flags.inc b/lib/sanitizer_common/sanitizer_flags.inc index 3b685db5a5..e742d85466 100644 --- a/lib/sanitizer_common/sanitizer_flags.inc +++ b/lib/sanitizer_common/sanitizer_flags.inc @@ -56,7 +56,7 @@ COMMON_FLAG( "Mention name of executable when reporting error and " "append executable name to logs (as in \"log_path.exe_name.pid\").") COMMON_FLAG( - bool, log_to_syslog, SANITIZER_ANDROID || SANITIZER_MAC, + bool, log_to_syslog, SANITIZER_ANDROID, "Write all sanitizer output to syslog in addition to other means of " "logging.") COMMON_FLAG( diff --git a/lib/sanitizer_common/sanitizer_linux_libcdep.cc b/lib/sanitizer_common/sanitizer_linux_libcdep.cc index 0e2a334209..4b583bfa41 100644 --- a/lib/sanitizer_common/sanitizer_linux_libcdep.cc +++ b/lib/sanitizer_common/sanitizer_linux_libcdep.cc @@ -507,16 +507,16 @@ void AndroidLogInit() { atomic_store(&android_log_initialized, 1, memory_order_release); } -bool ShouldLogAfterPrintf() { +static bool IsSyslogAvailable() { return atomic_load(&android_log_initialized, memory_order_acquire); } #else void AndroidLogInit() {} -bool ShouldLogAfterPrintf() { return true; } +static bool IsSyslogAvailable() { return true; } #endif // SANITIZER_ANDROID -void WriteOneLineToSyslog(const char *s) { +static void WriteOneLineToSyslog(const char *s) { #if SANITIZER_ANDROID &&__ANDROID_API__ < 21 __android_log_write(ANDROID_LOG_INFO, NULL, s); #else @@ -524,6 +524,24 @@ void WriteOneLineToSyslog(const char *s) { #endif } +void WriteToSyslog(const char *buffer) { + if (!IsSyslogAvailable()) + return; + char *copy = internal_strdup(buffer); + char *p = copy; + char *q; + // syslog, at least on Android, has an implicit message length limit. + // Print one line at a time. + do { + q = internal_strchr(p, '\n'); + if (q) + *q = '\0'; + WriteOneLineToSyslog(p); + if (q) + p = q + 1; + } while (q); + InternalFree(copy); +} #endif // SANITIZER_LINUX } // namespace __sanitizer diff --git a/lib/sanitizer_common/sanitizer_mac.cc b/lib/sanitizer_common/sanitizer_mac.cc index 951a48a713..3151cf8b91 100644 --- a/lib/sanitizer_common/sanitizer_mac.cc +++ b/lib/sanitizer_common/sanitizer_mac.cc @@ -36,14 +36,12 @@ extern char **environ; #endif -#include #include #include #include #include #include #include -#include #include #include #include @@ -373,45 +371,6 @@ uptr GetRSS() { return info.resident_size; } -static BlockingMutex syslog_lock(LINKER_INITIALIZED); - -void WriteOneLineToSyslog(const char *s) { - syslog_lock.CheckLocked(); - asl_log(nullptr, nullptr, ASL_LEVEL_ERR, "%s", s); -} - -void LogFullErrorReport(const char *buffer) { - // Log with os_trace. This will make it into the crash log. - if (GetMacosVersion() >= MACOS_VERSION_MAVERICKS) { - // os_trace requires the message (format parameter) to be a string literal. - if (internal_strncmp(SanitizerToolName, "AddressSanitizer", - sizeof("AddressSanitizer") - 1) == 0) - os_trace("Address Sanitizer reported a failure."); - else if (internal_strncmp(SanitizerToolName, "UndefinedBehaviorSanitizer", - sizeof("UndefinedBehaviorSanitizer") - 1) == 0) - os_trace("Undefined Behavior Sanitizer reported a failure."); - else if (internal_strncmp(SanitizerToolName, "ThreadSanitizer", - sizeof("ThreadSanitizer") - 1) == 0) - os_trace("Thread Sanitizer reported a failure."); - else - os_trace("Sanitizer tool reported a failure."); - - if (common_flags()->log_to_syslog) - os_trace("Consult syslog for more information."); - } - - // Log to syslog. - // The logging on OS X may call pthread_create so we need the threading - // environment to be fully initialized. Also, this should never be called when - // holding the thread registry lock since that may result in a deadlock. If - // the reporting thread holds the thread registry mutex, and asl_log waits - // for GCD to dispatch a new thread, the process will deadlock, because the - // pthread_create wrapper needs to acquire the lock as well. - BlockingMutexLock l(&syslog_lock); - if (common_flags()->log_to_syslog) - WriteToSyslog(buffer); -} - void *internal_start_thread(void (*func)(void *arg), void *arg) { return 0; } void internal_join_thread(void *th) { } diff --git a/lib/sanitizer_common/sanitizer_printf.cc b/lib/sanitizer_common/sanitizer_printf.cc index 2794e667e6..5f4725ec1d 100644 --- a/lib/sanitizer_common/sanitizer_printf.cc +++ b/lib/sanitizer_common/sanitizer_printf.cc @@ -278,7 +278,7 @@ static void SharedPrintfCode(bool append_pid, const char *format, # undef CHECK_NEEDED_LENGTH } RawWrite(buffer); - if (common_flags()->log_to_syslog && ShouldLogAfterPrintf()) + if (common_flags()->log_to_syslog) WriteToSyslog(buffer); CallPrintfAndReportCallback(buffer); // If we had mapped any memory, clean up. diff --git a/lib/sanitizer_common/tests/sanitizer_common_test.cc b/lib/sanitizer_common/tests/sanitizer_common_test.cc index 6fc308ad14..c1bb797db2 100644 --- a/lib/sanitizer_common/tests/sanitizer_common_test.cc +++ b/lib/sanitizer_common/tests/sanitizer_common_test.cc @@ -208,30 +208,6 @@ TEST(SanitizerCommon, StripPathPrefix) { EXPECT_STREQ("file.h", StripPathPrefix("/usr/lib/./file.h", "/usr/lib/")); } -TEST(SanitizerCommon, RemoveANSIEscapeSequencesFromString) { - RemoveANSIEscapeSequencesFromString(nullptr); - const char *buffs[22] = { - "Default", "Default", - "\033[95mLight magenta", "Light magenta", - "\033[30mBlack\033[32mGreen\033[90mGray", "BlackGreenGray", - "\033[106mLight cyan \033[107mWhite ", "Light cyan White ", - "\033[31mHello\033[0m World", "Hello World", - "\033[38;5;82mHello \033[38;5;198mWorld", "Hello World", - "123[653456789012", "123[653456789012", - "Normal \033[5mBlink \033[25mNormal", "Normal Blink Normal", - "\033[106m\033[107m", "", - "", "", - " ", " ", - }; - - for (size_t i = 0; i < ARRAY_SIZE(buffs); i+=2) { - char *buffer_copy = internal_strdup(buffs[i]); - RemoveANSIEscapeSequencesFromString(buffer_copy); - EXPECT_STREQ(buffer_copy, buffs[i+1]); - InternalFree(buffer_copy); - } -} - TEST(SanitizerCommon, InternalScopedString) { InternalScopedString str(10); EXPECT_EQ(0U, str.length()); diff --git a/lib/tsan/go/buildgo.sh b/lib/tsan/go/buildgo.sh index 8c89d8fe68..a7e12f18c3 100755 --- a/lib/tsan/go/buildgo.sh +++ b/lib/tsan/go/buildgo.sh @@ -20,7 +20,6 @@ SRCS=" ../rtl/tsan_sync.cc ../../sanitizer_common/sanitizer_allocator.cc ../../sanitizer_common/sanitizer_common.cc - ../../sanitizer_common/sanitizer_common_libcdep.cc ../../sanitizer_common/sanitizer_deadlock_detector2.cc ../../sanitizer_common/sanitizer_flag_parser.cc ../../sanitizer_common/sanitizer_flags.cc diff --git a/test/asan/lit.cfg b/test/asan/lit.cfg index 835547090a..fd99f66996 100644 --- a/test/asan/lit.cfg +++ b/test/asan/lit.cfg @@ -34,9 +34,7 @@ default_asan_opts = '' if config.host_os == 'Darwin': # On Darwin, we default to `abort_on_error=1`, which would make tests run # much slower. Let's override this and run lit tests with 'abort_on_error=0'. - # Also, make sure we do not overwhelm the syslog while testing. default_asan_opts = 'abort_on_error=0' - default_asan_opts += ':log_to_syslog=0' if default_asan_opts: config.environment['ASAN_OPTIONS'] = default_asan_opts default_asan_opts += ':' diff --git a/test/ubsan/lit.common.cfg b/test/ubsan/lit.common.cfg index e50862983d..8e84406664 100644 --- a/test/ubsan/lit.common.cfg +++ b/test/ubsan/lit.common.cfg @@ -42,7 +42,6 @@ if config.host_os == 'Darwin': # On Darwin, we default to `abort_on_error=1`, which would make tests run # much slower. Let's override this and run lit tests with 'abort_on_error=0'. default_ubsan_opts += ['abort_on_error=0'] - default_ubsan_opts += ['log_to_syslog=0'] default_ubsan_opts_str = ':'.join(default_ubsan_opts) if default_ubsan_opts_str: config.environment['UBSAN_OPTIONS'] = default_ubsan_opts_str From 4dc8693946cb2b5ea0bf48038324957a44f4e12b Mon Sep 17 00:00:00 2001 From: Alexey Samsonov Date: Thu, 5 Nov 2015 00:00:36 +0000 Subject: [PATCH 41/68] [TSan] Fix mmap/mmap64 interceptor signature. mmap() offset argument has type off_t, not unsigned. off_t is usually 64-bit on 64-bit Linux. git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/trunk@252103 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/tsan/rtl/tsan_interceptors.cc | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/tsan/rtl/tsan_interceptors.cc b/lib/tsan/rtl/tsan_interceptors.cc index 0d9bba5b2f..eb25cfdf7e 100644 --- a/lib/tsan/rtl/tsan_interceptors.cc +++ b/lib/tsan/rtl/tsan_interceptors.cc @@ -701,8 +701,8 @@ static bool fix_mmap_addr(void **addr, long_t sz, int flags) { return true; } -TSAN_INTERCEPTOR(void*, mmap, void *addr, long_t sz, int prot, - int flags, int fd, unsigned off) { +TSAN_INTERCEPTOR(void *, mmap, void *addr, SIZE_T sz, int prot, int flags, + int fd, OFF_T off) { SCOPED_TSAN_INTERCEPTOR(mmap, addr, sz, prot, flags, fd, off); if (!fix_mmap_addr(&addr, sz, flags)) return MAP_FAILED; @@ -716,8 +716,8 @@ TSAN_INTERCEPTOR(void*, mmap, void *addr, long_t sz, int prot, } #if SANITIZER_LINUX -TSAN_INTERCEPTOR(void*, mmap64, void *addr, long_t sz, int prot, - int flags, int fd, u64 off) { +TSAN_INTERCEPTOR(void *, mmap64, void *addr, SIZE_T sz, int prot, int flags, + int fd, OFF64_T off) { SCOPED_TSAN_INTERCEPTOR(mmap64, addr, sz, prot, flags, fd, off); if (!fix_mmap_addr(&addr, sz, flags)) return MAP_FAILED; From 438a247012e5a2d3bd9fe6d95c52b1c52dda4511 Mon Sep 17 00:00:00 2001 From: Alexey Samsonov Date: Thu, 5 Nov 2015 01:16:48 +0000 Subject: [PATCH 42/68] [Sanitizer] Use ReportMmapFailureAndDie() in all applicable mmap variants on Posix. git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/trunk@252121 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/sanitizer_common/sanitizer_common.cc | 6 +++--- lib/sanitizer_common/sanitizer_common.h | 2 +- lib/sanitizer_common/sanitizer_posix.cc | 18 +++++++----------- lib/sanitizer_common/sanitizer_win.cc | 2 +- 4 files changed, 12 insertions(+), 16 deletions(-) diff --git a/lib/sanitizer_common/sanitizer_common.cc b/lib/sanitizer_common/sanitizer_common.cc index 2fb88688d1..b40a457c0b 100644 --- a/lib/sanitizer_common/sanitizer_common.cc +++ b/lib/sanitizer_common/sanitizer_common.cc @@ -164,7 +164,7 @@ void NORETURN CheckFailed(const char *file, int line, const char *cond, } void NORETURN ReportMmapFailureAndDie(uptr size, const char *mem_type, - error_t err) { + const char *mmap_type, error_t err) { static int recursion_count; if (recursion_count) { // The Report() and CHECK calls below may call mmap recursively and fail. @@ -174,8 +174,8 @@ void NORETURN ReportMmapFailureAndDie(uptr size, const char *mem_type, } recursion_count++; Report("ERROR: %s failed to " - "allocate 0x%zx (%zd) bytes of %s (error code: %d)\n", - SanitizerToolName, size, size, mem_type, err); + "%s 0x%zx (%zd) bytes of %s (error code: %d)\n", + SanitizerToolName, mmap_type, size, size, mem_type, err); DumpProcessMap(); UNREACHABLE("unable to mmap"); } diff --git a/lib/sanitizer_common/sanitizer_common.h b/lib/sanitizer_common/sanitizer_common.h index bfd0d6e12a..43cd2d0e8c 100644 --- a/lib/sanitizer_common/sanitizer_common.h +++ b/lib/sanitizer_common/sanitizer_common.h @@ -309,7 +309,7 @@ void NORETURN Die(); void NORETURN CheckFailed(const char *file, int line, const char *cond, u64 v1, u64 v2); void NORETURN ReportMmapFailureAndDie(uptr size, const char *mem_type, - error_t err); + const char *mmap_type, error_t err); // Set the name of the current thread to 'name', return true on succees. // The name may be truncated to a system-dependent limit. diff --git a/lib/sanitizer_common/sanitizer_posix.cc b/lib/sanitizer_common/sanitizer_posix.cc index d61fee1fc5..9ad66bec2a 100644 --- a/lib/sanitizer_common/sanitizer_posix.cc +++ b/lib/sanitizer_common/sanitizer_posix.cc @@ -119,7 +119,7 @@ void *MmapOrDie(uptr size, const char *mem_type) { MAP_PRIVATE | MAP_ANON, -1, 0); int reserrno; if (internal_iserror(res, &reserrno)) - ReportMmapFailureAndDie(size, mem_type, reserrno); + ReportMmapFailureAndDie(size, mem_type, "allocate", reserrno); IncreaseTotalMmap(size); return (void *)res; } @@ -143,12 +143,8 @@ void *MmapNoReserveOrDie(uptr size, const char *mem_type) { MAP_PRIVATE | MAP_ANON | MAP_NORESERVE, -1, 0); int reserrno; - if (internal_iserror(p, &reserrno)) { - Report("ERROR: %s failed to " - "allocate noreserve 0x%zx (%zd) bytes for '%s' (errno: %d)\n", - SanitizerToolName, size, size, mem_type, reserrno); - CHECK("unable to mmap" && 0); - } + if (internal_iserror(p, &reserrno)) + ReportMmapFailureAndDie(size, mem_type, "allocate noreserve", reserrno); IncreaseTotalMmap(size); return (void *)p; } @@ -162,10 +158,10 @@ void *MmapFixedOrDie(uptr fixed_addr, uptr size) { -1, 0); int reserrno; if (internal_iserror(p, &reserrno)) { - Report("ERROR: %s failed to " - "allocate 0x%zx (%zd) bytes at address %zx (errno: %d)\n", - SanitizerToolName, size, size, fixed_addr, reserrno); - CHECK("unable to mmap" && 0); + char mem_type[30]; + internal_snprintf(mem_type, sizeof(mem_type), "memory at address 0x%zx", + fixed_addr); + ReportMmapFailureAndDie(size, mem_type, "allocate", reserrno); } IncreaseTotalMmap(size); return (void *)p; diff --git a/lib/sanitizer_common/sanitizer_win.cc b/lib/sanitizer_common/sanitizer_win.cc index dca5a6da1c..bcebce0b29 100644 --- a/lib/sanitizer_common/sanitizer_win.cc +++ b/lib/sanitizer_common/sanitizer_win.cc @@ -86,7 +86,7 @@ void GetThreadStackTopAndBottom(bool at_initialization, uptr *stack_top, void *MmapOrDie(uptr size, const char *mem_type) { void *rv = VirtualAlloc(0, size, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE); if (rv == 0) - ReportMmapFailureAndDie(size, mem_type, GetLastError()); + ReportMmapFailureAndDie(size, mem_type, "allocate", GetLastError()); return rv; } From e387c400041957b4d75e46ffae0dfb83bf16404a Mon Sep 17 00:00:00 2001 From: Kuba Brecka Date: Thu, 5 Nov 2015 10:31:21 +0000 Subject: [PATCH 43/68] [tsan] Use malloc zone interceptors on OS X, part 2 TSan needs to use a custom malloc zone on OS X, which is already implemented in ASan. This patch uses the sanitizer_common implementation in `sanitizer_malloc_mac.inc` for TSan as well. Reviewed at http://reviews.llvm.org/D14330 git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/trunk@252155 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/tsan/CMakeLists.txt | 1 + lib/tsan/rtl/tsan_interceptors.cc | 14 +++---- lib/tsan/rtl/tsan_malloc_mac.cc | 59 +++++++++++++++++++++++++++++ lib/tsan/rtl/tsan_mman.h | 1 + lib/tsan/rtl/tsan_platform_linux.cc | 4 ++ lib/tsan/rtl/tsan_rtl.cc | 1 + 6 files changed, 72 insertions(+), 8 deletions(-) create mode 100644 lib/tsan/rtl/tsan_malloc_mac.cc diff --git a/lib/tsan/CMakeLists.txt b/lib/tsan/CMakeLists.txt index a9cfa14e67..6971a0fee1 100644 --- a/lib/tsan/CMakeLists.txt +++ b/lib/tsan/CMakeLists.txt @@ -26,6 +26,7 @@ set(TSAN_SOURCES rtl/tsan_interface_atomic.cc rtl/tsan_interface.cc rtl/tsan_interface_java.cc + rtl/tsan_malloc_mac.cc rtl/tsan_md5.cc rtl/tsan_mman.cc rtl/tsan_mutex.cc diff --git a/lib/tsan/rtl/tsan_interceptors.cc b/lib/tsan/rtl/tsan_interceptors.cc index eb25cfdf7e..26fa8b985a 100644 --- a/lib/tsan/rtl/tsan_interceptors.cc +++ b/lib/tsan/rtl/tsan_interceptors.cc @@ -97,8 +97,8 @@ extern "C" int pthread_sigmask(int how, const __sanitizer_sigset_t *set, // REAL(sigfillset) defined in common interceptors. DECLARE_REAL(int, sigfillset, __sanitizer_sigset_t *set) DECLARE_REAL(int, fflush, __sanitizer_FILE *fp) -DECLARE_REAL(void *, malloc, uptr size) -DECLARE_REAL(void, free, void *ptr) +DECLARE_REAL_AND_INTERCEPTOR(void *, malloc, uptr size) +DECLARE_REAL_AND_INTERCEPTOR(void, free, void *ptr) extern "C" void *pthread_self(); extern "C" void _exit(int status); extern "C" int *__errno_location(); @@ -534,6 +534,7 @@ TSAN_INTERCEPTOR(void, siglongjmp, uptr *env, int val) { REAL(siglongjmp)(env, val); } +#if !SANITIZER_MAC TSAN_INTERCEPTOR(void*, malloc, uptr size) { if (cur_thread()->in_symbolizer) return __libc_malloc(size); @@ -546,12 +547,10 @@ TSAN_INTERCEPTOR(void*, malloc, uptr size) { return p; } -#if !SANITIZER_MAC TSAN_INTERCEPTOR(void*, __libc_memalign, uptr align, uptr sz) { SCOPED_TSAN_INTERCEPTOR(__libc_memalign, align, sz); return user_alloc(thr, pc, sz, align); } -#endif TSAN_INTERCEPTOR(void*, calloc, uptr size, uptr n) { if (cur_thread()->in_symbolizer) @@ -588,7 +587,6 @@ TSAN_INTERCEPTOR(void, free, void *p) { user_free(thr, pc, p); } -#if !SANITIZER_MAC TSAN_INTERCEPTOR(void, cfree, void *p) { if (p == 0) return; @@ -598,9 +596,7 @@ TSAN_INTERCEPTOR(void, cfree, void *p) { SCOPED_INTERCEPTOR_RAW(cfree, p); user_free(thr, pc, p); } -#endif -#if !SANITIZER_MAC TSAN_INTERCEPTOR(uptr, malloc_usable_size, void *p) { SCOPED_INTERCEPTOR_RAW(malloc_usable_size, p); return user_alloc_usable_size(p); @@ -760,12 +756,12 @@ TSAN_INTERCEPTOR(void*, aligned_alloc, uptr align, uptr sz) { SCOPED_INTERCEPTOR_RAW(memalign, align, sz); return user_alloc(thr, pc, sz, align); } -#endif TSAN_INTERCEPTOR(void*, valloc, uptr sz) { SCOPED_INTERCEPTOR_RAW(valloc, sz); return user_alloc(thr, pc, sz, GetPageSizeCached()); } +#endif #if SANITIZER_LINUX TSAN_INTERCEPTOR(void*, pvalloc, uptr sz) { @@ -778,11 +774,13 @@ TSAN_INTERCEPTOR(void*, pvalloc, uptr sz) { #define TSAN_MAYBE_INTERCEPT_PVALLOC #endif +#if !SANITIZER_MAC TSAN_INTERCEPTOR(int, posix_memalign, void **memptr, uptr align, uptr sz) { SCOPED_INTERCEPTOR_RAW(posix_memalign, memptr, align, sz); *memptr = user_alloc(thr, pc, sz, align); return 0; } +#endif // Used in thread-safe function static initialization. extern "C" int INTERFACE_ATTRIBUTE __cxa_guard_acquire(atomic_uint32_t *g) { diff --git a/lib/tsan/rtl/tsan_malloc_mac.cc b/lib/tsan/rtl/tsan_malloc_mac.cc new file mode 100644 index 0000000000..6319fdf603 --- /dev/null +++ b/lib/tsan/rtl/tsan_malloc_mac.cc @@ -0,0 +1,59 @@ +//===-- tsan_malloc_mac.cc ------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file is a part of ThreadSanitizer (TSan), a race detector. +// +// Mac-specific malloc interception. +//===----------------------------------------------------------------------===// + +#include "sanitizer_common/sanitizer_platform.h" +#if SANITIZER_MAC + +#include "tsan_interceptors.h" +#include "tsan_stack_trace.h" + +using namespace __tsan; +#define COMMON_MALLOC_ZONE_NAME "tsan" +#define COMMON_MALLOC_ENTER() +#define COMMON_MALLOC_SANITIZER_INITIALIZED (cur_thread()->is_inited) +#define COMMON_MALLOC_FORCE_LOCK() +#define COMMON_MALLOC_FORCE_UNLOCK() +#define COMMON_MALLOC_MEMALIGN(alignment, size) \ + void *p = \ + user_alloc(cur_thread(), StackTrace::GetCurrentPc(), size, alignment) +#define COMMON_MALLOC_MALLOC(size) \ + SCOPED_INTERCEPTOR_RAW(malloc, size); \ + void *p = user_alloc(thr, pc, size) +#define COMMON_MALLOC_REALLOC(ptr, size) \ + SCOPED_INTERCEPTOR_RAW(realloc, ptr, size); \ + void *p = user_realloc(thr, pc, ptr, size); +#define COMMON_MALLOC_CALLOC(count, size) \ + SCOPED_INTERCEPTOR_RAW(calloc, size, count); \ + void *p = user_calloc(thr, pc, size, count); +#define COMMON_MALLOC_VALLOC(size) \ + SCOPED_INTERCEPTOR_RAW(valloc, size); \ + void *p = user_alloc(thr, pc, size, GetPageSizeCached()); +#define COMMON_MALLOC_FREE(ptr) \ + SCOPED_INTERCEPTOR_RAW(free, ptr); \ + user_free(thr, pc, ptr); +#define COMMON_MALLOC_SIZE(ptr) \ + uptr size = user_alloc_usable_size(ptr); +#define COMMON_MALLOC_FILL_STATS(zone, stats) +#define COMMON_MALLOC_REPORT_UNKNOWN_REALLOC(ptr, zone_ptr, zone_name) \ + (void)zone_name; \ + Report("mz_realloc(%p) -- attempting to realloc unallocated memory.\n", ptr); +#define COMMON_MALLOC_IGNORE_INVALID_FREE false +#define COMMON_MALLOC_REPORT_FREE_UNALLOCATED(ptr, zone_ptr, zone_name) \ + (void)zone_name; \ + Report("free_common(%p) -- attempting to free unallocated memory.\n", ptr); +#define COMMON_MALLOC_NAMESPACE __tsan + +#include "sanitizer_common/sanitizer_malloc_mac.inc" + +#endif diff --git a/lib/tsan/rtl/tsan_mman.h b/lib/tsan/rtl/tsan_mman.h index 5ff956d827..b419b58ca4 100644 --- a/lib/tsan/rtl/tsan_mman.h +++ b/lib/tsan/rtl/tsan_mman.h @@ -20,6 +20,7 @@ namespace __tsan { const uptr kDefaultAlignment = 16; void InitializeAllocator(); +void ReplaceSystemMalloc(); void AllocatorThreadStart(ThreadState *thr); void AllocatorThreadFinish(ThreadState *thr); void AllocatorPrintStats(); diff --git a/lib/tsan/rtl/tsan_platform_linux.cc b/lib/tsan/rtl/tsan_platform_linux.cc index 65c7b8bcc5..f6c704051c 100644 --- a/lib/tsan/rtl/tsan_platform_linux.cc +++ b/lib/tsan/rtl/tsan_platform_linux.cc @@ -331,6 +331,10 @@ int call_pthread_cancel_with_cleanup(int(*fn)(void *c, void *m, } #endif +#ifndef SANITIZER_GO +void ReplaceSystemMalloc() { } +#endif + } // namespace __tsan #endif // SANITIZER_LINUX || SANITIZER_FREEBSD diff --git a/lib/tsan/rtl/tsan_rtl.cc b/lib/tsan/rtl/tsan_rtl.cc index 24ccc51a21..33b419c78c 100644 --- a/lib/tsan/rtl/tsan_rtl.cc +++ b/lib/tsan/rtl/tsan_rtl.cc @@ -325,6 +325,7 @@ void Initialize(ThreadState *thr) { CheckVMASize(); #ifndef SANITIZER_GO InitializeAllocator(); + ReplaceSystemMalloc(); #endif InitializeInterceptors(); CheckShadowMapping(); From 29bf03d9354ed3bf0c0e5033e4d39ff6d3ac6612 Mon Sep 17 00:00:00 2001 From: Kuba Brecka Date: Thu, 5 Nov 2015 13:54:50 +0000 Subject: [PATCH 44/68] [tsan] Alternative ThreadState storage for OS X This implements a "poor man's TLV" to be used for TSan's ThreadState on OS X. Based on the fact that `pthread_self()` is always available and reliable and returns a valid pointer to memory, we'll use the shadow memory of this pointer as a thread-local storage. No user code should ever read/write to this internal libpthread structure, so it's safe to use it for this purpose. We lazily allocate the ThreadState object and store the pointer here. Differential Revision: http://reviews.llvm.org/D14288 git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/trunk@252159 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/tsan/rtl/tsan_interceptors.cc | 1 + lib/tsan/rtl/tsan_platform_mac.cc | 61 +++++++++++++++++++++++++++++++ lib/tsan/rtl/tsan_rtl.cc | 2 +- lib/tsan/rtl/tsan_rtl.h | 8 +++- 4 files changed, 70 insertions(+), 2 deletions(-) diff --git a/lib/tsan/rtl/tsan_interceptors.cc b/lib/tsan/rtl/tsan_interceptors.cc index 26fa8b985a..3df07e79dd 100644 --- a/lib/tsan/rtl/tsan_interceptors.cc +++ b/lib/tsan/rtl/tsan_interceptors.cc @@ -819,6 +819,7 @@ void DestroyThreadState() { thr->signal_ctx = 0; UnmapOrDie(sctx, sizeof(*sctx)); } + cur_thread_finalize(); } } // namespace __tsan diff --git a/lib/tsan/rtl/tsan_platform_mac.cc b/lib/tsan/rtl/tsan_platform_mac.cc index 4677adda32..446d790019 100644 --- a/lib/tsan/rtl/tsan_platform_mac.cc +++ b/lib/tsan/rtl/tsan_platform_mac.cc @@ -15,8 +15,10 @@ #include "sanitizer_common/sanitizer_platform.h" #if SANITIZER_MAC +#include "sanitizer_common/sanitizer_atomic.h" #include "sanitizer_common/sanitizer_common.h" #include "sanitizer_common/sanitizer_libc.h" +#include "sanitizer_common/sanitizer_posix.h" #include "sanitizer_common/sanitizer_procmaps.h" #include "tsan_platform.h" #include "tsan_rtl.h" @@ -40,6 +42,62 @@ namespace __tsan { +static void *SignalSafeGetOrAllocate(uptr *dst, uptr size) { + atomic_uintptr_t *a = (atomic_uintptr_t *)dst; + void *val = (void *)atomic_load_relaxed(a); + atomic_signal_fence(memory_order_acquire); // Turns the previous load into + // acquire wrt signals. + if (UNLIKELY(val == nullptr)) { + val = (void *)internal_mmap(nullptr, size, PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_ANON, -1, 0); + CHECK(val); + void *cmp = nullptr; + if (!atomic_compare_exchange_strong(a, (uintptr_t *)&cmp, (uintptr_t)val, + memory_order_acq_rel)) { + internal_munmap(val, size); + val = cmp; + } + } + return val; +} + +#ifndef SANITIZER_GO +// On OS X, accessing TLVs via __thread or manually by using pthread_key_* is +// problematic, because there are several places where interceptors are called +// when TLVs are not accessible (early process startup, thread cleanup, ...). +// The following provides a "poor man's TLV" implementation, where we use the +// shadow memory of the pointer returned by pthread_self() to store a pointer to +// the ThreadState object. The main thread's ThreadState pointer is stored +// separately in a static variable, because we need to access it even before the +// shadow memory is set up. +static uptr main_thread_identity = 0; +static ThreadState *main_thread_state = nullptr; + +ThreadState *cur_thread() { + ThreadState **fake_tls; + uptr thread_identity = (uptr)pthread_self(); + if (thread_identity == main_thread_identity || main_thread_identity == 0) { + fake_tls = &main_thread_state; + } else { + fake_tls = (ThreadState **)MemToShadow(thread_identity); + } + ThreadState *thr = (ThreadState *)SignalSafeGetOrAllocate( + (uptr *)fake_tls, sizeof(ThreadState)); + return thr; +} + +// TODO(kuba.brecka): This is not async-signal-safe. In particular, we call +// munmap first and then clear `fake_tls`; if we receive a signal in between, +// handler will try to access the unmapped ThreadState. +void cur_thread_finalize() { + uptr thread_identity = (uptr)pthread_self(); + CHECK_NE(thread_identity, main_thread_identity); + ThreadState **fake_tls = (ThreadState **)MemToShadow(thread_identity); + internal_munmap(*fake_tls, sizeof(ThreadState)); + *fake_tls = nullptr; +} +#endif + uptr GetShadowMemoryConsumption() { return 0; } @@ -95,6 +153,9 @@ void InitializePlatform() { DisableCoreDumperIfNecessary(); #ifndef SANITIZER_GO CheckAndProtect(); + + CHECK_EQ(main_thread_identity, 0); + main_thread_identity = (uptr)pthread_self(); #endif prev_pthread_introspection_hook = diff --git a/lib/tsan/rtl/tsan_rtl.cc b/lib/tsan/rtl/tsan_rtl.cc index 33b419c78c..05d530e982 100644 --- a/lib/tsan/rtl/tsan_rtl.cc +++ b/lib/tsan/rtl/tsan_rtl.cc @@ -44,7 +44,7 @@ extern "C" void __tsan_resume() { namespace __tsan { -#ifndef SANITIZER_GO +#if !defined(SANITIZER_GO) && !SANITIZER_MAC THREADLOCAL char cur_thread_placeholder[sizeof(ThreadState)] ALIGNED(64); #endif static char ctx_placeholder[sizeof(Context)] ALIGNED(64); diff --git a/lib/tsan/rtl/tsan_rtl.h b/lib/tsan/rtl/tsan_rtl.h index 2618405757..2e6be3ff06 100644 --- a/lib/tsan/rtl/tsan_rtl.h +++ b/lib/tsan/rtl/tsan_rtl.h @@ -410,12 +410,18 @@ struct ThreadState { }; #ifndef SANITIZER_GO +#if SANITIZER_MAC +ThreadState *cur_thread(); +void cur_thread_finalize(); +#else __attribute__((tls_model("initial-exec"))) extern THREADLOCAL char cur_thread_placeholder[]; INLINE ThreadState *cur_thread() { return reinterpret_cast(&cur_thread_placeholder); } -#endif +INLINE void cur_thread_finalize() { } +#endif // SANITIZER_MAC +#endif // SANITIZER_GO class ThreadContext : public ThreadContextBase { public: From b33423ee8897f5f1eacb6d400216fd99db39f153 Mon Sep 17 00:00:00 2001 From: Kuba Brecka Date: Thu, 5 Nov 2015 13:59:07 +0000 Subject: [PATCH 45/68] [tsan] Fix pthread_once interceptor for OS X TSan has a re-implementation of `pthread_once` in its interceptor, which assumes that the `pthread_once_t *once_control` pointer is actually pointing to a "storage" which is zero-initialized and used for the atomic operations. However, that's not true on OS X, where pthread_once_t is a structure, that contains a header (with a magic value) and the actual storage follows after that. This patch skips the header to make the interceptor work on OS X. Differential Revision: http://reviews.llvm.org/D14379 git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/trunk@252160 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/tsan/rtl/tsan_interceptors.cc | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/lib/tsan/rtl/tsan_interceptors.cc b/lib/tsan/rtl/tsan_interceptors.cc index 3df07e79dd..f270f6764a 100644 --- a/lib/tsan/rtl/tsan_interceptors.cc +++ b/lib/tsan/rtl/tsan_interceptors.cc @@ -1293,7 +1293,11 @@ TSAN_INTERCEPTOR(int, pthread_once, void *o, void (*f)()) { SCOPED_INTERCEPTOR_RAW(pthread_once, o, f); if (o == 0 || f == 0) return EINVAL; - atomic_uint32_t *a = static_cast(o); + atomic_uint32_t *a; + if (!SANITIZER_MAC) + a = static_cast(o); + else // On OS X, pthread_once_t has a header with a long-sized signature. + a = static_cast((void *)((char *)o + sizeof(long))); u32 v = atomic_load(a, memory_order_acquire); if (v == 0 && atomic_compare_exchange_strong(a, &v, 1, memory_order_relaxed)) { From 3c0131759856fff5e408b2d47b5f22959e2e70a1 Mon Sep 17 00:00:00 2001 From: Kuba Brecka Date: Thu, 5 Nov 2015 14:01:53 +0000 Subject: [PATCH 46/68] [tsan] Allow memmove interceptor to be used when TSan is not initialized A call to memmove is used early during new thread initialization on OS X. This patch uses the `COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED` check, similarly to how we deal with other early-used interceptors. Differential Revision: http://reviews.llvm.org/D14377 git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/trunk@252161 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/tsan/rtl/tsan_interceptors.cc | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/lib/tsan/rtl/tsan_interceptors.cc b/lib/tsan/rtl/tsan_interceptors.cc index f270f6764a..7d2194d836 100644 --- a/lib/tsan/rtl/tsan_interceptors.cc +++ b/lib/tsan/rtl/tsan_interceptors.cc @@ -630,9 +630,11 @@ TSAN_INTERCEPTOR(void*, memcpy, void *dst, const void *src, uptr size) { } TSAN_INTERCEPTOR(void*, memmove, void *dst, void *src, uptr n) { - SCOPED_TSAN_INTERCEPTOR(memmove, dst, src, n); - MemoryAccessRange(thr, pc, (uptr)dst, n, true); - MemoryAccessRange(thr, pc, (uptr)src, n, false); + if (!COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED) { + SCOPED_TSAN_INTERCEPTOR(memmove, dst, src, n); + MemoryAccessRange(thr, pc, (uptr)dst, n, true); + MemoryAccessRange(thr, pc, (uptr)src, n, false); + } return REAL(memmove)(dst, src, n); } From 26de8b759260e649154696ac8f3907df7cd574b7 Mon Sep 17 00:00:00 2001 From: Kuba Brecka Date: Thu, 5 Nov 2015 14:03:26 +0000 Subject: [PATCH 47/68] [tsan] Fix the memcpy interceptor to be memmove compatible on OS X On OS X, memcpy and memmove are actually aliases of the same implementation, which means the interceptor of memcpy is also invoked when memmove is called. The current implementation of the interceptor uses `internal_memcpy` to perform the actual memory operation, which can produce an incorrect result when memmove semantics are expected. Let's call `internal_memmove` instead. Differential Revision: http://reviews.llvm.org/D14336 git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/trunk@252162 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/tsan/rtl/tsan_interceptors.cc | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/lib/tsan/rtl/tsan_interceptors.cc b/lib/tsan/rtl/tsan_interceptors.cc index 7d2194d836..8308afb7c2 100644 --- a/lib/tsan/rtl/tsan_interceptors.cc +++ b/lib/tsan/rtl/tsan_interceptors.cc @@ -626,7 +626,10 @@ TSAN_INTERCEPTOR(void*, memcpy, void *dst, const void *src, uptr size) { MemoryAccessRange(thr, pc, (uptr)dst, size, true); MemoryAccessRange(thr, pc, (uptr)src, size, false); } - return internal_memcpy(dst, src, size); + // On OS X, calling internal_memcpy here will cause memory corruptions, + // because memcpy and memmove are actually aliases of the same implementation. + // We need to use internal_memmove here. + return internal_memmove(dst, src, size); } TSAN_INTERCEPTOR(void*, memmove, void *dst, void *src, uptr n) { From ecb0485c829a444d60e516c236d51348b5ade1ba Mon Sep 17 00:00:00 2001 From: Kuba Brecka Date: Thu, 5 Nov 2015 14:16:42 +0000 Subject: [PATCH 48/68] Lint warning fixup for r252160 ("[tsan] Fix pthread_once interceptor for OS X"). git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/trunk@252163 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/tsan/rtl/tsan_interceptors.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/tsan/rtl/tsan_interceptors.cc b/lib/tsan/rtl/tsan_interceptors.cc index 8308afb7c2..5470f34b62 100644 --- a/lib/tsan/rtl/tsan_interceptors.cc +++ b/lib/tsan/rtl/tsan_interceptors.cc @@ -1302,7 +1302,7 @@ TSAN_INTERCEPTOR(int, pthread_once, void *o, void (*f)()) { if (!SANITIZER_MAC) a = static_cast(o); else // On OS X, pthread_once_t has a header with a long-sized signature. - a = static_cast((void *)((char *)o + sizeof(long))); + a = static_cast((void *)((char *)o + sizeof(long_t))); u32 v = atomic_load(a, memory_order_acquire); if (v == 0 && atomic_compare_exchange_strong(a, &v, 1, memory_order_relaxed)) { From cdfcc2bfe34cb45a336884f4b35377e7fd91047e Mon Sep 17 00:00:00 2001 From: Kuba Brecka Date: Thu, 5 Nov 2015 14:32:56 +0000 Subject: [PATCH 49/68] [tsan] Fix build warnings on OS X Fixing `tsan_interceptors.cc`, which on OS X produces a bunch of warnings about unused constants and functions. Differential Revision: http://reviews.llvm.org/D14381 git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/trunk@252165 91177308-0d34-0410-b5e6-96231b3b80d8 --- .../sanitizer_platform_interceptors.h | 2 +- lib/tsan/rtl/tsan_interceptors.cc | 12 +++++++++++- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/lib/sanitizer_common/sanitizer_platform_interceptors.h b/lib/sanitizer_common/sanitizer_platform_interceptors.h index a96941b578..89bfe98897 100644 --- a/lib/sanitizer_common/sanitizer_platform_interceptors.h +++ b/lib/sanitizer_common/sanitizer_platform_interceptors.h @@ -220,7 +220,7 @@ // FIXME: getline seems to be available on OSX 10.7 #define SANITIZER_INTERCEPT_GETLINE SI_FREEBSD || SI_LINUX_NOT_ANDROID -#define SANITIZER_INTERCEPT__EXIT SI_LINUX || SI_FREEBSD +#define SANITIZER_INTERCEPT__EXIT SI_LINUX || SI_FREEBSD || SI_MAC #define SANITIZER_INTERCEPT_PHTREAD_MUTEX SI_NOT_WINDOWS #define SANITIZER_INTERCEPT_PTHREAD_SETNAME_NP \ diff --git a/lib/tsan/rtl/tsan_interceptors.cc b/lib/tsan/rtl/tsan_interceptors.cc index 5470f34b62..8be04795d7 100644 --- a/lib/tsan/rtl/tsan_interceptors.cc +++ b/lib/tsan/rtl/tsan_interceptors.cc @@ -115,7 +115,9 @@ const int PTHREAD_MUTEX_RECURSIVE_NP = 1; const int EINVAL = 22; const int EBUSY = 16; const int EOWNERDEAD = 130; +#if !SANITIZER_MAC const int EPOLL_CTL_ADD = 1; +#endif const int SIGILL = 4; const int SIGABRT = 6; const int SIGFPE = 8; @@ -130,7 +132,9 @@ const int SIGBUS = 7; const int SIGSYS = 31; #endif void *const MAP_FAILED = (void*)-1; +#if !SANITIZER_MAC const int PTHREAD_BARRIER_SERIAL_THREAD = -1; +#endif const int MAP_FIXED = 0x10; typedef long long_t; // NOLINT @@ -385,6 +389,7 @@ static int setup_at_exit_wrapper(ThreadState *thr, uptr pc, void(*f)(), return res; } +#if !SANITIZER_MAC static void on_exit_wrapper(int status, void *arg) { ThreadState *thr = cur_thread(); uptr pc = 0; @@ -394,7 +399,6 @@ static void on_exit_wrapper(int status, void *arg) { __libc_free(ctx); } -#if !SANITIZER_MAC TSAN_INTERCEPTOR(int, on_exit, void(*f)(int, void*), void *arg) { if (cur_thread()->in_symbolizer) return 0; @@ -2198,6 +2202,7 @@ struct TsanInterceptorContext { const uptr pc; }; +#if !SANITIZER_MAC static void HandleRecvmsg(ThreadState *thr, uptr pc, __sanitizer_msghdr *msg) { int fds[64]; @@ -2205,6 +2210,7 @@ static void HandleRecvmsg(ThreadState *thr, uptr pc, for (int i = 0; i < cnt; i++) FdEventCreate(thr, pc, fds[i]); } +#endif #include "sanitizer_common/sanitizer_platform_interceptors.h" // Causes interceptor recursion (getaddrinfo() and fopen()) @@ -2355,6 +2361,7 @@ struct ScopedSyscall { } }; +#if !SANITIZER_MAC static void syscall_access_range(uptr pc, uptr p, uptr s, bool write) { TSAN_SYSCALL(); MemoryAccessRange(thr, pc, p, s, write); @@ -2408,6 +2415,7 @@ static void syscall_post_fork(uptr pc, int pid) { ForkParentAfter(thr, pc); } } +#endif #define COMMON_SYSCALL_PRE_READ_RANGE(p, s) \ syscall_access_range(GET_CALLER_PC(), (uptr)(p), (uptr)(s), false) @@ -2458,10 +2466,12 @@ static void finalize(void *arg) { Die(); } +#if !SANITIZER_MAC static void unreachable() { Report("FATAL: ThreadSanitizer: unreachable called\n"); Die(); } +#endif void InitializeInterceptors() { #if !SANITIZER_MAC From aaf82144351bf1c75adc127e8eb8b3e4a5fd93ea Mon Sep 17 00:00:00 2001 From: Sergey Dmitrouk Date: Thu, 5 Nov 2015 18:36:42 +0000 Subject: [PATCH 50/68] [compiler-rt][aarch64] New tests for 128-bit floating-point builtins, fixes of tests and __fixuint Summary: The following tests for 128-bit floating-point type behaved in a strange way, thought it were bugs, but seem to be mistakes in tests: * `fixtfsi` test checked for `0x80000001` as a value returned for number less than can be represented, while `LONG_MIN` should be returned on saturation; * `fixunstfdi` wasn't enabled for AArch64, only for PPC, but there is nothing PPC specific in that test; * `multf3` tried to underflow multiplication by producing result with 16383 exponent, while there are still 112 bits of fraction plus implicit bit, so resultant exponent should be 16497. Tests for some other builtins didn't exist: * `fixtfdi` * `fixtfti` * `fixunstfti` They were made by copying similar files and adjusting for wider types and adding/removing some reasonable/extra checks. Also `__fixuint` seems to have off by one error, updated tests to catch this case. Reviewers: rengolin, zatrazz, howard.hinnant, t.p.northover, jmolloy, enefaim Subscribers: aemerson, llvm-commits, rengolin Differential Revision: http://reviews.llvm.org/D14187 git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/trunk@252180 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/builtins/fp_fixuint_impl.inc | 2 +- test/builtins/Unit/fixtfdi_test.c | 71 ++++++++++++++++++ test/builtins/Unit/fixtfsi_test.c | 2 +- test/builtins/Unit/fixtfti_test.c | 83 +++++++++++++++++++++ test/builtins/Unit/fixunsdfdi_test.c | 3 + test/builtins/Unit/fixunsdfsi_test.c | 2 + test/builtins/Unit/fixunsdfti_test.c | 3 + test/builtins/Unit/fixunssfdi_test.c | 2 + test/builtins/Unit/fixunssfsi_test.c | 2 + test/builtins/Unit/fixunstfdi_test.c | 8 ++- test/builtins/Unit/fixunstfsi_test.c | 3 + test/builtins/Unit/fixunstfti_test.c | 103 +++++++++++++++++++++++++++ test/builtins/Unit/multf3_test.c | 2 +- 13 files changed, 280 insertions(+), 6 deletions(-) create mode 100644 test/builtins/Unit/fixtfdi_test.c create mode 100644 test/builtins/Unit/fixtfti_test.c create mode 100644 test/builtins/Unit/fixunstfti_test.c diff --git a/lib/builtins/fp_fixuint_impl.inc b/lib/builtins/fp_fixuint_impl.inc index b223c63840..d68ccf27a7 100644 --- a/lib/builtins/fp_fixuint_impl.inc +++ b/lib/builtins/fp_fixuint_impl.inc @@ -27,7 +27,7 @@ static __inline fixuint_t __fixuint(fp_t a) { return 0; // If the value is too large for the integer type, saturate. - if ((unsigned)exponent > sizeof(fixuint_t) * CHAR_BIT) + if ((unsigned)exponent >= sizeof(fixuint_t) * CHAR_BIT) return ~(fixuint_t)0; // If 0 <= exponent < significandBits, right shift to get the result. diff --git a/test/builtins/Unit/fixtfdi_test.c b/test/builtins/Unit/fixtfdi_test.c new file mode 100644 index 0000000000..cc25becb2f --- /dev/null +++ b/test/builtins/Unit/fixtfdi_test.c @@ -0,0 +1,71 @@ +//===--------------- fixtfdi_test.c - Test __fixtfdi ----------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file tests __fixtfdi for the compiler_rt library. +// +//===----------------------------------------------------------------------===// + +#include "int_lib.h" +#include + +#if __LDBL_MANT_DIG__ == 113 + +#include "fp_test.h" + +di_int __fixtfdi(long double a); + +int test__fixtfdi(long double a, di_int expected) +{ + di_int x = __fixtfdi(a); + int ret = (x != expected); + + if (ret) + { + printf("error in test__fixtfdi(%.20Lf) = %llX, " + "expected %llX\n", a, x, expected); + } + return ret; +} + +char assumption_1[sizeof(long double) * CHAR_BIT == 128] = {0}; + +#endif + +int main() +{ +#if __LDBL_MANT_DIG__ == 113 + if (test__fixtfdi(makeInf128(), 0x7fffffffffffffffLL)) + return 1; + if (test__fixtfdi(0, 0x0)) + return 1; + if (test__fixtfdi(0x1.23456789abcdefp+5L, 0x24LL)) + return 1; + if (test__fixtfdi(0x1.23456789abcdefp-3L, 0x0LL)) + return 1; + if (test__fixtfdi(0x1.23456789abcdef12345678p+20L, 0x123456LL)) + return 1; + if (test__fixtfdi(0x1.23456789abcdef12345678p+40L, 0x123456789abLL)) + return 1; + if (test__fixtfdi(0x1.23456789abcdef12345678p+60L, 0x123456789abcdef1LL)) + return 1; + if (test__fixtfdi(0x1.23456789abcdefp+256L, 0x7fffffffffffffffLL)) + return 1; + if (test__fixtfdi(-0x1.23456789abcdefp+20L, 0xffffffffffedcbaaLL)) + return 1; + if (test__fixtfdi(-0x1.23456789abcdefp+40L, 0xfffffedcba987655LL)) + return 1; + if (test__fixtfdi(-0x1.23456789abcdefp+256L, 0x8000000000000000LL)) + return 1; + +#else + printf("skipped\n"); + +#endif + return 0; +} diff --git a/test/builtins/Unit/fixtfsi_test.c b/test/builtins/Unit/fixtfsi_test.c index 45ad0d2437..1da516bd07 100644 --- a/test/builtins/Unit/fixtfsi_test.c +++ b/test/builtins/Unit/fixtfsi_test.c @@ -54,7 +54,7 @@ int main() return 1; if (test__fixtfsi(-0x1.23456789abcdefp+20, 0xffedcbaa)) return 1; - if (test__fixtfsi(-0x1.23456789abcdefp+40, 0x80000001)) + if (test__fixtfsi(-0x1.23456789abcdefp+40, 0x80000000)) return 1; #else diff --git a/test/builtins/Unit/fixtfti_test.c b/test/builtins/Unit/fixtfti_test.c new file mode 100644 index 0000000000..52184ca624 --- /dev/null +++ b/test/builtins/Unit/fixtfti_test.c @@ -0,0 +1,83 @@ +//===--------------- fixtfti_test.c - Test __fixtfti ----------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file tests __fixtfti for the compiler_rt library. +// +//===----------------------------------------------------------------------===// + +#include "int_lib.h" +#include + +#if __LDBL_MANT_DIG__ == 113 + +#include "fp_test.h" + +ti_int __fixtfti(long double a); + +int test__fixtfti(long double a, ti_int expected) +{ + ti_int x = __fixtfti(a); + int ret = (x != expected); + + if (ret) + { + twords xt; + xt.all = x; + + twords expectedt; + expectedt.all = expected; + + printf("error in test__fixtfti(%.20Lf) = 0x%.16llX%.16llX, " + "expected 0x%.16llX%.16llX\n", + a, xt.s.high, xt.s.low, expectedt.s.high, expectedt.s.low); + } + return ret; +} + +char assumption_1[sizeof(long double) * CHAR_BIT == 128] = {0}; + +#endif + +int main() +{ +#if __LDBL_MANT_DIG__ == 113 + if (test__fixtfti(makeInf128(), make_ti(0x7fffffffffffffffLL, + 0xffffffffffffffffLL))) + return 1; + if (test__fixtfti(0, make_ti(0x0LL, 0x0LL))) + return 1; + if (test__fixtfti(0x1.23456789abcdefp+5L, make_ti(0x0LL, 0x24LL))) + return 1; + if (test__fixtfti(0x1.23456789abcdefp-3L, make_ti(0x0LL, 0x0LL))) + return 1; + if (test__fixtfti(0x1.23456789abcdef12345678p+20L, + make_ti(0x0LL, 0x123456LL))) + return 1; + if (test__fixtfti(0x1.23456789abcdef123456789abcdep+112L, + make_ti(0x123456789abcdLL, 0xef123456789abcdeLL))) + return 1; + if (test__fixtfti(-0x1.23456789abcdef123456789abcdep+112L, + make_ti(0xFFFEDCBA98765432LL, 0x10EDCBA987654322LL))) + return 1; + if (test__fixtfti(0x1.23456789abcdefp+256L, make_ti(0x7fffffffffffffffLL, + 0xffffffffffffffffLL))) + return 1; + if (test__fixtfti(-0x1.23456789abcdefp+20L, make_ti(0xffffffffffffffffLL, + 0xffffffffffedcbaaLL))) + return 1; + if (test__fixtfti(-0x1.23456789abcdefp+256L, make_ti(0x8000000000000000LL, + 0x0))) + return 1; + +#else + printf("skipped\n"); + +#endif + return 0; +} diff --git a/test/builtins/Unit/fixunsdfdi_test.c b/test/builtins/Unit/fixunsdfdi_test.c index 3998482876..1ddc5340b0 100644 --- a/test/builtins/Unit/fixunsdfdi_test.c +++ b/test/builtins/Unit/fixunsdfdi_test.c @@ -95,6 +95,9 @@ int main() if (test__fixunsdfdi(0x1.FFFFFFFFFFFFEp+62, 0x7FFFFFFFFFFFF800LL)) return 1; + if (test__fixunsdfdi(0x1.p+64, 0xFFFFFFFFFFFFFFFFLL)) + return 1; + #if !TARGET_LIBGCC if (test__fixunsdfdi(-0x1.FFFFFFFFFFFFFp+62, 0)) return 1; diff --git a/test/builtins/Unit/fixunsdfsi_test.c b/test/builtins/Unit/fixunsdfsi_test.c index 551fc88a52..8d3d6304f4 100644 --- a/test/builtins/Unit/fixunsdfsi_test.c +++ b/test/builtins/Unit/fixunsdfsi_test.c @@ -75,6 +75,8 @@ int main() if (test__fixunsdfsi(0x1.000000p+31, 0x80000000)) return 1; + if (test__fixunsdfsi(0x1.000000p+32, 0xFFFFFFFF)) + return 1; if (test__fixunsdfsi(0x1.FFFFFEp+31, 0xFFFFFF00)) return 1; if (test__fixunsdfsi(0x1.FFFFFEp+30, 0x7FFFFF80)) diff --git a/test/builtins/Unit/fixunsdfti_test.c b/test/builtins/Unit/fixunsdfti_test.c index e1aa56d763..0298fb9e94 100644 --- a/test/builtins/Unit/fixunsdfti_test.c +++ b/test/builtins/Unit/fixunsdfti_test.c @@ -115,6 +115,9 @@ int main() return 1; if (test__fixunsdfti(0x1.FFFFFFFFFFFFEp+126, make_ti(0x7FFFFFFFFFFFF800LL, 0))) return 1; + if (test__fixunsdfti(0x1.0000000000000p+128, make_ti(0xFFFFFFFFFFFFFFFFLL, + 0xFFFFFFFFFFFFFFFFLL))) + return 1; #if !TARGET_LIBGCC if (test__fixunsdfti(-0x1.FFFFFFFFFFFFFp+62, 0)) diff --git a/test/builtins/Unit/fixunssfdi_test.c b/test/builtins/Unit/fixunssfdi_test.c index 812457a002..166153cb5b 100644 --- a/test/builtins/Unit/fixunssfdi_test.c +++ b/test/builtins/Unit/fixunssfdi_test.c @@ -79,6 +79,8 @@ int main() return 1; if (test__fixunssfdi(0x1.000000p+63F, 0x8000000000000000LL)) return 1; + if (test__fixunssfdi(0x1.000000p+64F, 0xFFFFFFFFFFFFFFFFLL)) + return 1; if (test__fixunssfdi(0x1.FFFFFEp+62F, 0x7FFFFF8000000000LL)) return 1; if (test__fixunssfdi(0x1.FFFFFCp+62F, 0x7FFFFF0000000000LL)) diff --git a/test/builtins/Unit/fixunssfsi_test.c b/test/builtins/Unit/fixunssfsi_test.c index 94a8b0867e..17293e4385 100644 --- a/test/builtins/Unit/fixunssfsi_test.c +++ b/test/builtins/Unit/fixunssfsi_test.c @@ -75,6 +75,8 @@ int main() if (test__fixunssfsi(0x1.000000p+31F, 0x80000000)) return 1; + if (test__fixunssfsi(0x1.000000p+32F, 0xFFFFFFFF)) + return 1; if (test__fixunssfsi(0x1.FFFFFEp+31F, 0xFFFFFF00)) return 1; if (test__fixunssfsi(0x1.FFFFFEp+30F, 0x7FFFFF80)) diff --git a/test/builtins/Unit/fixunstfdi_test.c b/test/builtins/Unit/fixunstfdi_test.c index 60ea503d27..817c59b2d5 100644 --- a/test/builtins/Unit/fixunstfdi_test.c +++ b/test/builtins/Unit/fixunstfdi_test.c @@ -13,14 +13,14 @@ #include -#if _ARCH_PPC +#if _ARCH_PPC || __aarch64__ #include "int_lib.h" // Returns: convert a to a unsigned long long, rounding toward zero. // Negative values all become zero. -// Assumption: long double is a ppc 128 bit floating point type +// Assumption: long double is a 128 bit floating point type // du_int is a 64 bit integral type // value in long double is representable in du_int or is negative // (no range checking performed) @@ -44,7 +44,7 @@ char assumption_3[sizeof(long double)*CHAR_BIT == 128] = {0}; int main() { -#if _ARCH_PPC +#if _ARCH_PPC || __aarch64__ if (test__fixunstfdi(0.0, 0)) return 1; @@ -107,6 +107,8 @@ int main() return 1; if (test__fixunstfdi(0x1.FFFFFFFFFFFFFFF8p+62L, 0x7FFFFFFFFFFFFFFELL)) return 1; + if (test__fixunstfdi(0x1.p+64L, 0xFFFFFFFFFFFFFFFFLL)) + return 1; if (test__fixunstfdi(-0x1.0000000000000000p+63L, 0)) return 1; diff --git a/test/builtins/Unit/fixunstfsi_test.c b/test/builtins/Unit/fixunstfsi_test.c index 4bf8fdec60..13ed779522 100644 --- a/test/builtins/Unit/fixunstfsi_test.c +++ b/test/builtins/Unit/fixunstfsi_test.c @@ -56,6 +56,9 @@ int main() if (test__fixunstfsi(-0x1.23456789abcdefp+3, UINT32_C(0x0))) return 1; + if (test__fixunstfsi(0x1.p+32, 0xFFFFFFFFLL)) + return 1; + #else printf("skipped\n"); diff --git a/test/builtins/Unit/fixunstfti_test.c b/test/builtins/Unit/fixunstfti_test.c new file mode 100644 index 0000000000..60a0982b62 --- /dev/null +++ b/test/builtins/Unit/fixunstfti_test.c @@ -0,0 +1,103 @@ +//===-- fixunstfti_test.c - Test __fixunstfti -----------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file tests __fixunstfti for the compiler_rt library. +// +//===----------------------------------------------------------------------===// + +#include + +#if __LDBL_MANT_DIG__ == 113 + +#include "fp_test.h" +#include "int_lib.h" + +// Returns: convert a to a unsigned long long, rounding toward zero. +// Negative values all become zero. + +// Assumption: long double is a 128 bit floating point type +// tu_int is a 128 bit integral type +// value in long double is representable in tu_int or is negative +// (no range checking performed) + +COMPILER_RT_ABI tu_int __fixunstfti(long double a); + +int test__fixunstfti(long double a, tu_int expected) +{ + tu_int x = __fixunstfti(a); + if (x != expected) + { + twords xt; + xt.all = x; + + twords expectedt; + expectedt.all = expected; + + printf("error in __fixunstfti(%.20Lf) = 0x%.16llX%.16llX, " + "expected 0x%.16llX%.16llX\n", + a, xt.s.high, xt.s.low, expectedt.s.high, expectedt.s.low); + } + return x != expected; +} + +char assumption_1[sizeof(tu_int) == 4*sizeof(su_int)] = {0}; +char assumption_2[sizeof(tu_int)*CHAR_BIT == 128] = {0}; +char assumption_3[sizeof(long double)*CHAR_BIT == 128] = {0}; + +#endif + +int main() +{ +#if __LDBL_MANT_DIG__ == 113 + if (test__fixunstfti(makeInf128(), make_ti(0xffffffffffffffffLL, + 0xffffffffffffffffLL))) + return 1; + + if (test__fixunstfti(0.0, 0)) + return 1; + + if (test__fixunstfti(0.5, 0)) + return 1; + if (test__fixunstfti(0.99, 0)) + return 1; + if (test__fixunstfti(1.0, 1)) + return 1; + if (test__fixunstfti(1.5, 1)) + return 1; + if (test__fixunstfti(1.99, 1)) + return 1; + if (test__fixunstfti(2.0, 2)) + return 1; + if (test__fixunstfti(2.01, 2)) + return 1; + if (test__fixunstfti(-0.01, 0)) + return 1; + if (test__fixunstfti(-0.99, 0)) + return 1; + + if (test__fixunstfti(0x1.p+128, make_ti(0xffffffffffffffffLL, + 0xffffffffffffffffLL))) + return 1; + + if (test__fixunstfti(0x1.FFFFFEp+126, make_ti(0x7fffff8000000000LL, 0x0))) + return 1; + if (test__fixunstfti(0x1.FFFFFEp+127, make_ti(0xffffff0000000000LL, 0x0))) + return 1; + if (test__fixunstfti(0x1.FFFFFEp+128, make_ti(0xffffffffffffffffLL, + 0xffffffffffffffffLL))) + return 1; + if (test__fixunstfti(0x1.FFFFFEp+129, make_ti(0xffffffffffffffffLL, + 0xffffffffffffffffLL))) + return 1; + +#else + printf("skipped\n"); +#endif + return 0; +} diff --git a/test/builtins/Unit/multf3_test.c b/test/builtins/Unit/multf3_test.c index 98a8f7a323..42147550c7 100644 --- a/test/builtins/Unit/multf3_test.c +++ b/test/builtins/Unit/multf3_test.c @@ -82,7 +82,7 @@ int main() return 1; // underflow if (test__multf3(0x1.23456734245345p-10000L, - 0x1.edcba524498724p-6383L, + 0x1.edcba524498724p-6497L, UINT64_C(0x0), UINT64_C(0x0))) return 1; From 1c591077573491e8082cde9c790f935d7a2a3a88 Mon Sep 17 00:00:00 2001 From: Kuba Brecka Date: Fri, 6 Nov 2015 08:16:24 +0000 Subject: [PATCH 51/68] Trying to fix the FreeBSD build breakage due to r251916. http://lab.llvm.org:8011/builders/sanitizer_x86_64-freebsd/builds/6395 git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/trunk@252277 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/tsan/rtl/tsan_interceptors.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/tsan/rtl/tsan_interceptors.cc b/lib/tsan/rtl/tsan_interceptors.cc index 8be04795d7..800c7bd98b 100644 --- a/lib/tsan/rtl/tsan_interceptors.cc +++ b/lib/tsan/rtl/tsan_interceptors.cc @@ -2144,7 +2144,7 @@ TSAN_INTERCEPTOR(int, vfork, int fake) { return WRAP(fork)(fake); } -#if SANITIZER_LINUX +#if !SANITIZER_MAC typedef int (*dl_iterate_phdr_cb_t)(__sanitizer_dl_phdr_info *info, SIZE_T size, void *data); struct dl_iterate_phdr_data { From ebc821f9271012b54c438438af319da8581b695b Mon Sep 17 00:00:00 2001 From: Kuba Brecka Date: Fri, 6 Nov 2015 11:05:53 +0000 Subject: [PATCH 52/68] [tsan] Replace pthread_yield with sched_yield in lit tests OS X doesn't have `pthread_yield`. Let's use `sched_yield` instead. Differential Revision: http://reviews.llvm.org/D14428 git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/trunk@252283 91177308-0d34-0410-b5e6-96231b3b80d8 --- test/tsan/atomic_free3.cc | 2 +- test/tsan/real_deadlock_detector_stress_test.cc | 2 +- test/tsan/signal_errno.cc | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/test/tsan/atomic_free3.cc b/test/tsan/atomic_free3.cc index 753671bd11..f2875aeb65 100644 --- a/test/tsan/atomic_free3.cc +++ b/test/tsan/atomic_free3.cc @@ -13,7 +13,7 @@ int main() { pthread_t t; pthread_create(&t, 0, Thread, a); while (__atomic_load_n(a, __ATOMIC_RELAXED) == 0) - pthread_yield(); + sched_yield(); delete a; pthread_join(t, 0); } diff --git a/test/tsan/real_deadlock_detector_stress_test.cc b/test/tsan/real_deadlock_detector_stress_test.cc index 67c878f450..5576f12589 100644 --- a/test/tsan/real_deadlock_detector_stress_test.cc +++ b/test/tsan/real_deadlock_detector_stress_test.cc @@ -59,7 +59,7 @@ void *Thread(void *seed) { for (;;) { int old = __atomic_load_n(&m->state, __ATOMIC_RELAXED); if (old == kStateLocked) { - pthread_yield(); + sched_yield(); continue; } int newv = old + 1; diff --git a/test/tsan/signal_errno.cc b/test/tsan/signal_errno.cc index 8305e84930..5354cdeeb7 100644 --- a/test/tsan/signal_errno.cc +++ b/test/tsan/signal_errno.cc @@ -24,7 +24,7 @@ static __attribute__((noinline)) void loop() { volatile char *p = (char*)malloc(1); p[0] = 0; free((void*)p); - pthread_yield(); + sched_yield(); } } From b83dae99aa09ba8db402c58156864b963542c840 Mon Sep 17 00:00:00 2001 From: Kuba Brecka Date: Fri, 6 Nov 2015 11:07:26 +0000 Subject: [PATCH 53/68] [tsan] Enable new/delete C++ interceptors for OS X This patch adds `tsan_new_delete.cc` into the OS X build. Differential Revision: http://reviews.llvm.org/D14424 git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/trunk@252284 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/tsan/CMakeLists.txt | 2 +- lib/tsan/rtl/tsan_new_delete.cc | 8 ++++++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/lib/tsan/CMakeLists.txt b/lib/tsan/CMakeLists.txt index 6971a0fee1..cbfca5ce28 100644 --- a/lib/tsan/CMakeLists.txt +++ b/lib/tsan/CMakeLists.txt @@ -92,7 +92,7 @@ if(APPLE) SHARED OS ${TSAN_SUPPORTED_OS} ARCHS ${TSAN_SUPPORTED_ARCH} - SOURCES ${TSAN_SOURCES} + SOURCES ${TSAN_SOURCES} ${TSAN_CXX_SOURCES} OBJECT_LIBS RTInterception RTSanitizerCommon RTSanitizerCommonLibc diff --git a/lib/tsan/rtl/tsan_new_delete.cc b/lib/tsan/rtl/tsan_new_delete.cc index d3ac472b7d..18ba9082c4 100644 --- a/lib/tsan/rtl/tsan_new_delete.cc +++ b/lib/tsan/rtl/tsan_new_delete.cc @@ -12,6 +12,7 @@ // Interceptors for operators new and delete. //===----------------------------------------------------------------------===// #include "sanitizer_common/sanitizer_internal_defs.h" +#include "interception/interception.h" #include "tsan_interceptors.h" using namespace __tsan; // NOLINT @@ -20,6 +21,13 @@ namespace std { struct nothrow_t {}; } // namespace std +DECLARE_REAL(void *, malloc, uptr size) +DECLARE_REAL(void, free, void *ptr) +#if SANITIZER_MAC +#define __libc_malloc REAL(malloc) +#define __libc_free REAL(free) +#endif + #define OPERATOR_NEW_BODY(mangled_name) \ if (cur_thread()->in_symbolizer) \ return __libc_malloc(size); \ From dfcf188919fce22ee3b100f1d772f3fec10f4383 Mon Sep 17 00:00:00 2001 From: Dmitry Vyukov Date: Fri, 6 Nov 2015 11:52:24 +0000 Subject: [PATCH 54/68] tsan: make invisible test barrier portable The current implementation does not work on darwin and can have issues with other OSes in future. See http://reviews.llvm.org/D14427 Make it portable once and for all (minus usleep call). Reviewed in: http://reviews.llvm.org/D14434 git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/trunk@252292 91177308-0d34-0410-b5e6-96231b3b80d8 --- test/tsan/test.h | 37 +++++++++++++++++-------------------- test/tsan/thread_name2.cc | 2 +- 2 files changed, 18 insertions(+), 21 deletions(-) diff --git a/test/tsan/test.h b/test/tsan/test.h index 6af33a139b..adc44bbe96 100644 --- a/test/tsan/test.h +++ b/test/tsan/test.h @@ -8,32 +8,29 @@ // TSan-invisible barrier. // Tests use it to establish necessary execution order in a way that does not // interfere with tsan (does not establish synchronization between threads). -__typeof(pthread_barrier_wait) *barrier_wait; +// 8 lsb is thread count, the remaining are count of entered threads. +typedef unsigned long long invisible_barrier_t; -void barrier_init(pthread_barrier_t *barrier, unsigned count) { -#if defined(__FreeBSD__) - static const char libpthread_name[] = "libpthread.so"; -#else - static const char libpthread_name[] = "libpthread.so.0"; -#endif +void barrier_init(invisible_barrier_t *barrier, unsigned count) { + if (count >= (1 << 8)) + exit(fprintf(stderr, "barrier_init: count is too large (%d)\n", count)); + *barrier = count; +} - if (barrier_wait == 0) { - void *h = dlopen(libpthread_name, RTLD_LAZY); - if (h == 0) { - fprintf(stderr, "failed to dlopen %s, exiting\n", libpthread_name); - exit(1); - } - barrier_wait = (__typeof(barrier_wait))dlsym(h, "pthread_barrier_wait"); - if (barrier_wait == 0) { - fprintf(stderr, "failed to resolve pthread_barrier_wait, exiting\n"); - exit(1); - } +void barrier_wait(invisible_barrier_t *barrier) { + unsigned old = __atomic_fetch_add(barrier, 1 << 8, __ATOMIC_RELAXED); + unsigned old_epoch = (old >> 8) / (old & 0xff); + for (;;) { + unsigned cur = __atomic_load_n(barrier, __ATOMIC_RELAXED); + unsigned cur_epoch = (cur >> 8) / (cur & 0xff); + if (cur_epoch != old_epoch) + return; + usleep(1000); } - pthread_barrier_init(barrier, 0, count); } // Default instance of the barrier, but a test can declare more manually. -pthread_barrier_t barrier; +invisible_barrier_t barrier; void print_address(void *address) { // On FreeBSD, the %p conversion specifier works as 0x%x and thus does not match diff --git a/test/tsan/thread_name2.cc b/test/tsan/thread_name2.cc index a44f4b9d32..93387dab2b 100644 --- a/test/tsan/thread_name2.cc +++ b/test/tsan/thread_name2.cc @@ -6,7 +6,7 @@ #define pthread_setname_np pthread_set_name_np #endif -int Global; +long long Global; void *Thread1(void *x) { barrier_wait(&barrier); From 08bd93adee55727aa1c393fbb970913714d77563 Mon Sep 17 00:00:00 2001 From: Kuba Brecka Date: Fri, 6 Nov 2015 15:05:34 +0000 Subject: [PATCH 55/68] [tsan] Add Darwin support for lit tests This patch enables running lit tests on OS X: 1) Simply enable tests for Darwin (they were restricted to Linux and FreeBSD). 2) Disable using instrumented libcxx (libcxx_tsan) on Darwin. 3) On Darwin, override abort_on_error=0, otherwise all tests would generate crash logs and take much longer to process. Differential Revision: http://reviews.llvm.org/D14439 git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/trunk@252309 91177308-0d34-0410-b5e6-96231b3b80d8 --- test/tsan/lit.cfg | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/test/tsan/lit.cfg b/test/tsan/lit.cfg index 092fa43be3..b0c6671832 100644 --- a/test/tsan/lit.cfg +++ b/test/tsan/lit.cfg @@ -20,6 +20,11 @@ config.test_source_root = os.path.dirname(__file__) # Setup environment variables for running ThreadSanitizer. tsan_options = "atexit_sleep_ms=0" +if config.host_os == 'Darwin': + # On Darwin, we default to `abort_on_error=1`, which would make tests run + # much slower. Let's override this and run lit tests with 'abort_on_error=0'. + tsan_options += ':abort_on_error=0' + config.environment['TSAN_OPTIONS'] = tsan_options # GCC driver doesn't add necessary compile/link flags with -fsanitize=thread. @@ -34,7 +39,8 @@ clang_tsan_cflags = ["-fsanitize=thread", "-m64"] + config.debug_info_flags + extra_cflags clang_tsan_cxxflags = config.cxx_mode_flags + clang_tsan_cflags # Add additional flags if we're using instrumented libc++. -if config.has_libcxx: +# Instrumented libcxx currently not supported on Darwin. +if config.has_libcxx and config.host_os != 'Darwin': # FIXME: Dehardcode this path somehow. libcxx_path = os.path.join(config.compiler_rt_obj_root, "lib", "tsan", "libcxx_tsan") @@ -60,8 +66,8 @@ config.substitutions.append( ("%deflake ", os.path.join(os.path.dirname(__file__ # Default test suffixes. config.suffixes = ['.c', '.cc', '.cpp'] -# ThreadSanitizer tests are currently supported on FreeBSD and Linux only. -if config.host_os not in ['FreeBSD', 'Linux']: +# ThreadSanitizer tests are currently supported on FreeBSD, Linux and Darwin. +if config.host_os not in ['FreeBSD', 'Linux', 'Darwin']: config.unsupported = True # Allow tests to use REQUIRES=stable-runtime. For use when you cannot use XFAIL From f6ea2d83dfe178255e8afd09ba98138105d45c77 Mon Sep 17 00:00:00 2001 From: angelsl Date: Sat, 24 Oct 2015 01:01:19 +0800 Subject: [PATCH 56/68] Rust: Add triple.mk Based on 1957424e9f575e13bd09a8f7be84a7b9c738b015 (vadimcn) --- make/platform/triple.mk | 66 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 66 insertions(+) create mode 100644 make/platform/triple.mk diff --git a/make/platform/triple.mk b/make/platform/triple.mk new file mode 100644 index 0000000000..792e806200 --- /dev/null +++ b/make/platform/triple.mk @@ -0,0 +1,66 @@ +# This "platform" file is intended for building compiler-rt using gcc. +# The actual target platform is selected by setting the TargetTriple variable to the corresponding LLVM triple. + +Description := Static runtime libraries for platforms selected by 'TargetTriple' + +# Provide defaults for the required vars +ifndef CC + CC := gcc +endif +ifndef CFLAGS + CFLAGS := -Wall -O3 +endif + +Configs := builtins + +Arch := $(word 1,$(subst -, ,$(TargetTriple))) +ifeq ($(Arch),i686) + Arch := i386 +else ifeq ($(Arch),arm) +ifneq (,$(findstring ios,$(TargetTriple))) + Arch := armv7 +else ifneq (,$(findstring android,$(TargetTriple))) + Arch := armv7 +endif +endif + +# Filter out stuff that gcc cannot compile (these are only needed for clang-generated code anywasys). +CommonFunctions_gcc := $(filter-out atomic enable_execute_stack,$(CommonFunctions)) + +# Filter out stuff which is not available on specific target +# For example, sync_fetch_and_add_4 uses Thumb instructions, which are unavailable +# when building for arm-linux-androideabi +ifeq ($(TargetTriple),arm-linux-androideabi) + ArchDisabledFunctions := \ + sync_fetch_and_add_4 \ + sync_fetch_and_sub_4 \ + sync_fetch_and_and_4 \ + sync_fetch_and_or_4 \ + sync_fetch_and_xor_4 \ + sync_fetch_and_nand_4 \ + sync_fetch_and_max_4 \ + sync_fetch_and_umax_4 \ + sync_fetch_and_min_4 \ + sync_fetch_and_umin_4 \ + sync_fetch_and_add_8 \ + sync_fetch_and_sub_8 \ + sync_fetch_and_and_8 \ + sync_fetch_and_or_8 \ + sync_fetch_and_xor_8 \ + sync_fetch_and_nand_8 \ + sync_fetch_and_max_8 \ + sync_fetch_and_umax_8 \ + sync_fetch_and_min_8 \ + sync_fetch_and_umin_8 +endif + +# Clear cache is builtin on aarch64-apple-ios +# arm64 and aarch64 are synonims, but iOS targets usually use arm64 (history reasons) +ifeq (aarch64-apple-ios,$(subst arm64,aarch64,$(TargetTriple))) +CommonDisabledFunctions := clear_cache +endif + +ArchEnabledFunctions := $(filter-out $(ArchDisabledFunctions),$(value ArchFunctions.$(Arch))) +CommonEnabledFunctions := $(filter-out $(CommonDisabledFunctions),$(CommonFunctions_gcc)) + +FUNCTIONS.builtins := $(CommonEnabledFunctions) $(ArchEnabledFunctions) From 01b893b2cb1f39366aa16b48a58abc3870f093c0 Mon Sep 17 00:00:00 2001 From: angelsl Date: Sat, 24 Oct 2015 01:20:27 +0800 Subject: [PATCH 57/68] Rust: triple.mk: properly filter out Clang-specific atomic* builtins --- make/platform/triple.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/make/platform/triple.mk b/make/platform/triple.mk index 792e806200..061faa7f96 100644 --- a/make/platform/triple.mk +++ b/make/platform/triple.mk @@ -25,7 +25,7 @@ endif endif # Filter out stuff that gcc cannot compile (these are only needed for clang-generated code anywasys). -CommonFunctions_gcc := $(filter-out atomic enable_execute_stack,$(CommonFunctions)) +CommonFunctions_gcc := $(filter-out atomic% enable_execute_stack,$(CommonFunctions)) # Filter out stuff which is not available on specific target # For example, sync_fetch_and_add_4 uses Thumb instructions, which are unavailable From 8d4ca037848f184ee9518508207071efb9451398 Mon Sep 17 00:00:00 2001 From: angelsl Date: Wed, 28 Oct 2015 10:51:12 +0800 Subject: [PATCH 58/68] Rust: delete other platforms' makefiles to prevent conflicts clang_linux.mk was complaining on AArch64. These makefiles create targets that are never used anyway, so let's remove them. --- make/platform/clang_darwin.mk | 566 ------------------ make/platform/clang_darwin_test_input.c | 15 - make/platform/clang_linux.mk | 90 --- make/platform/clang_linux_test_input.c | 4 - make/platform/clang_macho_embedded.mk | 297 --------- .../clang_macho_embedded_test_input.c | 0 make/platform/darwin_bni.mk | 135 ----- make/platform/multi_arch.mk | 15 - 8 files changed, 1122 deletions(-) delete mode 100644 make/platform/clang_darwin.mk delete mode 100644 make/platform/clang_darwin_test_input.c delete mode 100644 make/platform/clang_linux.mk delete mode 100644 make/platform/clang_linux_test_input.c delete mode 100644 make/platform/clang_macho_embedded.mk delete mode 100644 make/platform/clang_macho_embedded_test_input.c delete mode 100644 make/platform/darwin_bni.mk delete mode 100644 make/platform/multi_arch.mk diff --git a/make/platform/clang_darwin.mk b/make/platform/clang_darwin.mk deleted file mode 100644 index dff26943be..0000000000 --- a/make/platform/clang_darwin.mk +++ /dev/null @@ -1,566 +0,0 @@ -# These are the functions which clang needs when it is targeting a previous -# version of the OS. The issue is that the backend may use functions which were -# not present in the libgcc that shipped on the platform. In such cases, we link -# with a version of the library which contains private_extern definitions of all -# the extra functions which might be referenced. - -Description := Static runtime libraries for clang/Darwin. - -# A function that ensures we don't try to build for architectures and SDKs -# that we don't have working toolchains for. Arguments: -# (1): List of architectures -# (2): Library name -# (3): SDK path -# The result is a possibly empty subset of the architectures from argument 1. -CheckArches = \ - $(shell \ - result=""; \ - if [ "X$(3)" != X ]; then \ - for arch in $(1); do \ - if $(LD) -v 2>&1 | grep "configured to support" \ - | tr ' ' '\n' | grep "^$$arch$$" >/dev/null 2>/dev/null; then \ - if $(CC) -arch $$arch \ - -integrated-as \ - $(ProjSrcRoot)/make/platform/clang_darwin_test_input.c \ - -isysroot $(3) \ - -o /dev/null > /dev/null 2> /dev/null; then \ - result="$$result$$arch "; \ - else \ - printf 1>&2 \ - "warning: clang_darwin.mk: dropping arch '$$arch' from lib '$(2)'"; \ - printf 1>&2 " (clang or system libraries do not support it)\n"; \ - fi; \ - else \ - printf 1>&2 \ - "warning: clang_darwin.mk: dropping arch '$$arch' from lib '$(2)'";\ - printf 1>&2 " (ld does not support it)\n"; \ - fi; \ - done; \ - fi; \ - echo $$result) - -XCRun = \ - $(shell \ - result=`xcrun -find $(1) 2> /dev/null`; \ - if [ "$$?" != "0" ]; then result=$(1); fi; \ - echo $$result) -# Prefer building with the internal SDKs. -XCRunSdkPath = \ - $(shell \ - result=`xcrun --sdk $(1).internal --show-sdk-path 2> /dev/null`; \ - if [ "$$?" != "0" ]; then \ - result=`xcrun --sdk $(1) --show-sdk-path 2> /dev/null`; \ - if [ "$$?" != "0" ]; then result=""; fi; \ - fi; \ - echo $$result) -### - -CC := $(call XCRun,clang) -LD := $(shell $(CC) -print-prog-name=ld) -AR := $(call XCRun,ar) -RANLIB := $(call XCRun,ranlib) -STRIP := $(call XCRun,strip) -LIPO := $(call XCRun,lipo) -DSYMUTIL := $(call XCRun,dsymutil) - -OSX_SDK := $(call XCRunSdkPath,macosx) -IOS_SDK := $(call XCRunSdkPath,iphoneos) -IOSSIM_SDK := $(call XCRunSdkPath,iphonesimulator) - -Configs := -UniversalArchs := - -# Configuration solely for providing access to an eprintf symbol, which may -# still be referenced from Darwin system headers. This symbol is only ever -# needed on i386. -Configs += eprintf -UniversalArchs.eprintf := $(call CheckArches,i386,eprintf,$(OSX_SDK)) - -# Configuration for targeting 10.4. We need a few functions missing from -# libgcc_s.10.4.dylib. We only build x86 slices since clang doesn't really -# support targeting PowerPC. -Configs += 10.4 -UniversalArchs.10.4 := $(call CheckArches,i386 x86_64,10.4,$(OSX_SDK)) - -# Configuration for targeting iOS for a couple of functions that didn't -# make it into libSystem. -Configs += ios -UniversalArchs.ios := $(call CheckArches,i386 x86_64,ios,$(IOSSIM_SDK)) -UniversalArchs.ios += $(call CheckArches,armv7 arm64,ios,$(IOS_SDK)) - -# Configuration for targeting OSX. These functions may not be in libSystem -# so we should provide our own. -Configs += osx -UniversalArchs.osx := $(call CheckArches,i386 x86_64 x86_64h,osx,$(OSX_SDK)) - -# Configuration for use with kernel/kexts. -Configs += cc_kext -UniversalArchs.cc_kext := $(call CheckArches,i386 x86_64 x86_64h,cc_kext,$(OSX_SDK)) - -# Configuration for use with iOS kernel/kexts -Configs += cc_kext_ios -UniversalArchs.cc_kext_ios += $(call CheckArches,armv7,cc_kext_ios,$(IOS_SDK)) - -# Configurations which define the profiling support functions. -Configs += profile_osx -UniversalArchs.profile_osx := $(call CheckArches,i386 x86_64 x86_64h,profile_osx,$(OSX_SDK)) -Configs += profile_ios -UniversalArchs.profile_ios := $(call CheckArches,i386 x86_64,profile_ios,$(IOSSIM_SDK)) -UniversalArchs.profile_ios += $(call CheckArches,armv7 arm64,profile_ios,$(IOS_SDK)) - -# Configurations which define the ASAN support functions. -Configs += asan_osx_dynamic -UniversalArchs.asan_osx_dynamic := $(call CheckArches,i386 x86_64 x86_64h,asan_osx_dynamic,$(OSX_SDK)) - -Configs += asan_iossim_dynamic -UniversalArchs.asan_iossim_dynamic := $(call CheckArches,i386 x86_64,asan_iossim_dynamic,$(IOSSIM_SDK)) - -Configs += ubsan_osx_dynamic -UniversalArchs.ubsan_osx_dynamic := $(call CheckArches,i386 x86_64 x86_64h,ubsan_osx_dynamic,$(OSX_SDK)) - -Configs += ubsan_iossim_dynamic -UniversalArchs.ubsan_iossim_dynamic := $(call CheckArches,i386 x86_64,ubsan_iossim_dynamic,$(IOSSIM_SDK)) - -# Darwin 10.6 has a bug in cctools that makes it unable to use ranlib on our ARM -# object files. If we are on that platform, strip out all ARM archs. We still -# build the libraries themselves so that Clang can find them where it expects -# them, even though they might not have an expected slice. -ifneq ($(shell test -x /usr/bin/sw_vers && sw_vers -productVersion | grep 10.6),) -UniversalArchs.ios := $(filter-out armv7, $(UniversalArchs.ios)) -UniversalArchs.cc_kext_ios := $(filter-out armv7, $(UniversalArchs.cc_kext_ios)) -UniversalArchs.profile_ios := $(filter-out armv7, $(UniversalArchs.profile_ios)) -endif - -# If RC_SUPPORTED_ARCHS is defined, treat it as a list of the architectures we -# are intended to support and limit what we try to build to that. -ifneq ($(RC_SUPPORTED_ARCHS),) -$(foreach config,$(Configs),\ - $(call Set,UniversalArchs.$(config),\ - $(filter $(RC_SUPPORTED_ARCHS),$(UniversalArchs.$(config))))) -endif - -# Remove empty configs if we end up dropping all the requested -# archs for a particular config. -$(foreach config,$(Configs),\ - $(if $(strip $(UniversalArchs.$(config))),,\ - $(call Set,Configs,$(filter-out $(config),$(Configs))))) - -### - -# Forcibly strip off any -arch, as that totally breaks our universal support. -override CC := $(subst -arch ,-arch_,$(CC)) -override CC := $(patsubst -arch_%,,$(CC)) - -CFLAGS := -Wall -Werror -O3 -fomit-frame-pointer - -# Always set deployment target arguments for every build, these libraries should -# never depend on the environmental overrides. We simply set them to minimum -# supported deployment target -- nothing in the compiler-rt libraries should -# actually depend on the deployment target. -OSX_DEPLOYMENT_ARGS := -mmacosx-version-min=10.4 -IOS_DEPLOYMENT_ARGS := -mios-version-min=1.0 -IOS6_DEPLOYMENT_ARGS := -mios-version-min=6.0 -IOSSIM_DEPLOYMENT_ARGS := -mios-simulator-version-min=1.0 - -OSX_DEPLOYMENT_ARGS += -isysroot $(OSX_SDK) -IOS_DEPLOYMENT_ARGS += -isysroot $(IOS_SDK) -IOS6_DEPLOYMENT_ARGS += -isysroot $(IOS_SDK) -IOSSIM_DEPLOYMENT_ARGS += -isysroot $(IOSSIM_SDK) - -CFLAGS.eprintf := $(CFLAGS) $(OSX_DEPLOYMENT_ARGS) -CFLAGS.10.4 := $(CFLAGS) $(OSX_DEPLOYMENT_ARGS) - -SANITIZER_MACOSX_DEPLOYMENT_ARGS := -mmacosx-version-min=10.7 -SANITIZER_IOSSIM_DEPLOYMENT_ARGS := -mios-simulator-version-min=7.0 \ - -isysroot $(IOSSIM_SDK) -SANITIZER_CFLAGS := -fno-builtin -gline-tables-only -stdlib=libc++ - -CFLAGS.asan_osx_dynamic := \ - $(CFLAGS) $(SANITIZER_MACOSX_DEPLOYMENT_ARGS) \ - $(SANITIZER_CFLAGS) \ - -DMAC_INTERPOSE_FUNCTIONS=1 \ - -DASAN_DYNAMIC=1 - -CFLAGS.asan_iossim_dynamic := \ - $(CFLAGS) $(SANITIZER_IOSSIM_DEPLOYMENT_ARGS) \ - $(SANITIZER_CFLAGS) \ - -DMAC_INTERPOSE_FUNCTIONS=1 \ - -DASAN_DYNAMIC=1 - -CFLAGS.ubsan_osx_dynamic := \ - $(CFLAGS) $(SANITIZER_MACOSX_DEPLOYMENT_ARGS) \ - $(SANITIZER_CFLAGS) - -CFLAGS.ubsan_iossim_dynamic := \ - $(CFLAGS) $(SANITIZER_IOSSIM_DEPLOYMENT_ARGS) \ - $(SANITIZER_CFLAGS) - - -CFLAGS.ios.i386 := $(CFLAGS) $(IOSSIM_DEPLOYMENT_ARGS) -CFLAGS.ios.x86_64 := $(CFLAGS) $(IOSSIM_DEPLOYMENT_ARGS) -CFLAGS.ios.armv7 := $(CFLAGS) $(IOS_DEPLOYMENT_ARGS) -CFLAGS.ios.armv7k := $(CFLAGS) $(IOS_DEPLOYMENT_ARGS) -CFLAGS.ios.armv7s := $(CFLAGS) $(IOS_DEPLOYMENT_ARGS) -CFLAGS.ios.arm64 := $(CFLAGS) $(IOS6_DEPLOYMENT_ARGS) -CFLAGS.osx.i386 := $(CFLAGS) $(OSX_DEPLOYMENT_ARGS) -CFLAGS.osx.x86_64 := $(CFLAGS) $(OSX_DEPLOYMENT_ARGS) -CFLAGS.osx.x86_64h := $(CFLAGS) $(OSX_DEPLOYMENT_ARGS) -CFLAGS.cc_kext.i386 := $(CFLAGS) $(OSX_DEPLOYMENT_ARGS) -CFLAGS.cc_kext.x86_64 := $(CFLAGS) $(OSX_DEPLOYMENT_ARGS) -CFLAGS.cc_kext.x86_64h := $(CFLAGS) $(OSX_DEPLOYMENT_ARGS) -CFLAGS.cc_kext_ios.armv7 := $(CFLAGS) $(IOS6_DEPLOYMENT_ARGS) -CFLAGS.cc_kext_ios.armv7k := $(CFLAGS) $(IOS6_DEPLOYMENT_ARGS) -CFLAGS.cc_kext_ios.armv7s := $(CFLAGS) $(IOS6_DEPLOYMENT_ARGS) -CFLAGS.cc_kext_ios.arm64 := $(CFLAGS) $(IOS6_DEPLOYMENT_ARGS) -CFLAGS.profile_osx.i386 := $(CFLAGS) $(OSX_DEPLOYMENT_ARGS) -CFLAGS.profile_osx.x86_64 := $(CFLAGS) $(OSX_DEPLOYMENT_ARGS) -CFLAGS.profile_osx.x86_64h := $(CFLAGS) $(OSX_DEPLOYMENT_ARGS) -CFLAGS.profile_ios.i386 := $(CFLAGS) $(IOSSIM_DEPLOYMENT_ARGS) -CFLAGS.profile_ios.x86_64 := $(CFLAGS) $(IOSSIM_DEPLOYMENT_ARGS) -CFLAGS.profile_ios.armv7 := $(CFLAGS) $(IOS_DEPLOYMENT_ARGS) -CFLAGS.profile_ios.armv7k := $(CFLAGS) $(IOS_DEPLOYMENT_ARGS) -CFLAGS.profile_ios.armv7s := $(CFLAGS) $(IOS_DEPLOYMENT_ARGS) -CFLAGS.profile_ios.arm64 := $(CFLAGS) $(IOS6_DEPLOYMENT_ARGS) - -SANITIZER_LDFLAGS := -stdlib=libc++ -lc++ -lc++abi - -SHARED_LIBRARY.asan_osx_dynamic := 1 -LDFLAGS.asan_osx_dynamic := $(SANITIZER_LDFLAGS) -install_name @rpath/libclang_rt.asan_osx_dynamic.dylib \ - $(SANITIZER_MACOSX_DEPLOYMENT_ARGS) - -SHARED_LIBRARY.asan_iossim_dynamic := 1 -LDFLAGS.asan_iossim_dynamic := $(SANITIZER_LDFLAGS) -install_name @rpath/libclang_rt.asan_iossim_dynamic.dylib \ - -Wl,-ios_simulator_version_min,7.0.0 $(SANITIZER_IOSSIM_DEPLOYMENT_ARGS) - -SHARED_LIBRARY.ubsan_osx_dynamic := 1 -LDFLAGS.ubsan_osx_dynamic := $(SANITIZER_LDFLAGS) -install_name @rpath/libclang_rt.ubsan_osx_dynamic.dylib \ - $(SANITIZER_MACOSX_DEPLOYMENT_ARGS) - -SHARED_LIBRARY.ubsan_iossim_dynamic := 1 -LDFLAGS.ubsan_iossim_dynamic := $(SANITIZER_LDFLAGS) -install_name @rpath/libclang_rt.ubsan_iossim_dynamic.dylib \ - -Wl,-ios_simulator_version_min,7.0.0 $(SANITIZER_IOSSIM_DEPLOYMENT_ARGS) - -ifneq ($(OSX_SDK),) -CFLAGS.asan_osx_dynamic += -isysroot $(OSX_SDK) -LDFLAGS.asan_osx_dynamic += -isysroot $(OSX_SDK) -CFLAGS.ubsan_osx_dynamic += -isysroot $(OSX_SDK) -LDFLAGS.ubsan_osx_dynamic += -isysroot $(OSX_SDK) -endif - -ATOMIC_FUNCTIONS := \ - atomic_flag_clear \ - atomic_flag_clear_explicit \ - atomic_flag_test_and_set \ - atomic_flag_test_and_set_explicit \ - atomic_signal_fence \ - atomic_thread_fence - -FP16_FUNCTIONS := \ - extendhfsf2 \ - truncdfhf2 \ - truncsfhf2 - -FUNCTIONS.eprintf := eprintf -FUNCTIONS.10.4 := eprintf floatundidf floatundisf floatundixf - -FUNCTIONS.ios := divmodsi4 udivmodsi4 mulosi4 mulodi4 muloti4 \ - $(ATOMIC_FUNCTIONS) $(FP16_FUNCTIONS) -# On x86, the divmod functions reference divsi. -FUNCTIONS.ios.i386 := $(FUNCTIONS.ios) \ - divsi3 udivsi3 -FUNCTIONS.ios.x86_64 := $(FUNCTIONS.ios.i386) -FUNCTIONS.ios.arm64 := mulsc3 muldc3 divsc3 divdc3 udivti3 umodti3 \ - $(ATOMIC_FUNCTIONS) - -FUNCTIONS.osx := mulosi4 mulodi4 muloti4 $(ATOMIC_FUNCTIONS) $(FP16_FUNCTIONS) - -FUNCTIONS.profile_osx := GCDAProfiling InstrProfiling InstrProfilingBuffer \ - InstrProfilingFile InstrProfilingPlatformDarwin \ - InstrProfilingRuntime InstrProfilingUtil -FUNCTIONS.profile_ios := $(FUNCTIONS.profile_osx) - -FUNCTIONS.asan_osx_dynamic := $(AsanFunctions) $(AsanCXXFunctions) \ - $(InterceptionFunctions) \ - $(SanitizerCommonFunctions) \ - $(AsanDynamicFunctions) \ - $(UbsanFunctions) $(UbsanCXXFunctions) - -FUNCTIONS.asan_iossim_dynamic := $(AsanFunctions) $(AsanCXXFunctions) \ - $(InterceptionFunctions) \ - $(SanitizerCommonFunctions) \ - $(AsanDynamicFunctions) \ - $(UbsanFunctions) $(UbsanCXXFunctions) - -FUNCTIONS.ubsan_osx_dynamic := $(UbsanFunctions) $(UbsanCXXFunctions) \ - $(SanitizerCommonFunctions) \ - $(UbsanStandaloneFunctions) - -FUNCTIONS.ubsan_iossim_dynamic := $(UbsanFunctions) $(UbsanCXXFunctions) \ - $(SanitizerCommonFunctions) \ - $(UbsanStandaloneFunctions) - -CCKEXT_PROFILE_FUNCTIONS := \ - InstrProfiling \ - InstrProfilingBuffer \ - InstrProfilingPlatformDarwin - -CCKEXT_COMMON_FUNCTIONS := \ - $(CCKEXT_PROFILE_FUNCTIONS) \ - absvdi2 \ - absvsi2 \ - addvdi3 \ - addvsi3 \ - ashldi3 \ - ashrdi3 \ - bswapdi2 \ - bswapsi2 \ - clzdi2 \ - clzsi2 \ - cmpdi2 \ - ctzdi2 \ - ctzsi2 \ - divdc3 \ - divdi3 \ - divsc3 \ - divmodsi4 \ - udivmodsi4 \ - do_global_dtors \ - eprintf \ - extendhfsf2 \ - ffsdi2 \ - fixdfdi \ - fixsfdi \ - fixunsdfdi \ - fixunsdfsi \ - fixunssfdi \ - fixunssfsi \ - floatdidf \ - floatdisf \ - floatundidf \ - floatundisf \ - gcc_bcmp \ - lshrdi3 \ - moddi3 \ - muldc3 \ - muldi3 \ - mulsc3 \ - mulvdi3 \ - mulvsi3 \ - negdi2 \ - negvdi2 \ - negvsi2 \ - paritydi2 \ - paritysi2 \ - popcountdi2 \ - popcountsi2 \ - powidf2 \ - powisf2 \ - subvdi3 \ - subvsi3 \ - truncdfhf2 \ - truncsfhf2 \ - ucmpdi2 \ - udiv_w_sdiv \ - udivdi3 \ - udivmoddi4 \ - umoddi3 - -CCKEXT_ARM_FUNCTIONS := $(CCKEXT_COMMON_FUNCTIONS) \ - adddf3 \ - addsf3 \ - aeabi_cdcmpeq \ - aeabi_cdrcmple \ - aeabi_cfcmpeq \ - aeabi_cfrcmple \ - aeabi_dcmpeq \ - aeabi_dcmpge \ - aeabi_dcmpgt \ - aeabi_dcmple \ - aeabi_dcmplt \ - aeabi_drsub \ - aeabi_fcmpeq \ - aeabi_fcmpge \ - aeabi_fcmpgt \ - aeabi_fcmple \ - aeabi_fcmplt \ - aeabi_frsub \ - aeabi_idivmod \ - aeabi_uidivmod \ - cmpdf2 \ - cmpsf2 \ - div0 \ - divdf3 \ - divsf3 \ - divsi3 \ - extendsfdf2 \ - ffssi2 \ - fixdfsi \ - fixsfsi \ - floatsidf \ - floatsisf \ - floatunsidf \ - floatunsisf \ - comparedf2 \ - comparesf2 \ - modsi3 \ - muldf3 \ - mulsf3 \ - mulodi4 \ - negdf2 \ - negsf2 \ - subdf3 \ - subsf3 \ - switch16 \ - switch32 \ - switch8 \ - switchu8 \ - truncdfsf2 \ - udivsi3 \ - umodsi3 \ - unorddf2 \ - unordsf2 - -CCKEXT_ARMVFP_FUNCTIONS := $(CCKEXT_ARM_FUNCTIONS) \ - adddf3vfp \ - addsf3vfp \ - divdf3vfp \ - divsf3vfp \ - eqdf2vfp \ - eqsf2vfp \ - extendsfdf2vfp \ - fixdfsivfp \ - fixsfsivfp \ - fixunsdfsivfp \ - fixunssfsivfp \ - floatsidfvfp \ - floatsisfvfp \ - floatunssidfvfp \ - floatunssisfvfp \ - gedf2vfp \ - gesf2vfp \ - gtdf2vfp \ - gtsf2vfp \ - ledf2vfp \ - lesf2vfp \ - ltdf2vfp \ - ltsf2vfp \ - muldf3vfp \ - mulsf3vfp \ - nedf2vfp \ - nesf2vfp \ - subdf3vfp \ - subsf3vfp \ - truncdfsf2vfp \ - unorddf2vfp \ - unordsf2vfp - -CCKEXT_ARM64_FUNCTIONS := \ - $(CCKEXT_PROFILE_FUNCTIONS) \ - divdc3 \ - divsc3 \ - muldc3 \ - mulsc3 \ - udivti3 \ - umodti3 - -FUNCTIONS.cc_kext_ios.armv7 := $(CCKEXT_ARMVFP_FUNCTIONS) -FUNCTIONS.cc_kext_ios.armv7k := $(CCKEXT_ARMVFP_FUNCTIONS) -FUNCTIONS.cc_kext_ios.armv7s := $(CCKEXT_ARMVFP_FUNCTIONS) -FUNCTIONS.cc_kext_ios.arm64 := $(CCKEXT_ARM64_FUNCTIONS) - -CCKEXT_X86_FUNCTIONS := $(CCKEXT_COMMON_FUNCTIONS) \ - divxc3 \ - fixunsxfdi \ - fixunsxfsi \ - fixxfdi \ - floatdixf \ - floatundixf \ - mulxc3 \ - powixf2 - -FUNCTIONS.cc_kext.i386 := $(CCKEXT_X86_FUNCTIONS) \ - ffssi2 \ - i686.get_pc_thunk.eax \ - i686.get_pc_thunk.ebp \ - i686.get_pc_thunk.ebx \ - i686.get_pc_thunk.ecx \ - i686.get_pc_thunk.edi \ - i686.get_pc_thunk.edx \ - i686.get_pc_thunk.esi - -FUNCTIONS.cc_kext.x86_64 := $(CCKEXT_X86_FUNCTIONS) \ - absvti2 \ - addvti3 \ - ashlti3 \ - ashrti3 \ - clzti2 \ - cmpti2 \ - ctzti2 \ - divti3 \ - ffsti2 \ - fixdfti \ - fixsfti \ - fixunsdfti \ - fixunssfti \ - fixunsxfti \ - fixxfti \ - floattidf \ - floattisf \ - floattixf \ - floatuntidf \ - floatuntisf \ - floatuntixf \ - lshrti3 \ - modti3 \ - multi3 \ - mulvti3 \ - negti2 \ - negvti2 \ - parityti2 \ - popcountti2 \ - subvti3 \ - ucmpti2 \ - udivmodti4 \ - udivti3 \ - umodti3 - -FUNCTIONS.cc_kext.x86_64h := $(FUNCTIONS.cc_kext.x86_64) - -# FIXME: Currently, compiler-rt is missing implementations for a number of the -# functions that need to go into libcc_kext.a. Filter them out for now. -CCKEXT_MISSING_FUNCTIONS := \ - cmpdf2 cmpsf2 div0 \ - ffssi2 \ - udiv_w_sdiv unorddf2 unordsf2 bswapdi2 \ - bswapsi2 \ - gcc_bcmp \ - do_global_dtors \ - i686.get_pc_thunk.eax i686.get_pc_thunk.ebp i686.get_pc_thunk.ebx \ - i686.get_pc_thunk.ecx i686.get_pc_thunk.edi i686.get_pc_thunk.edx \ - i686.get_pc_thunk.esi \ - aeabi_cdcmpeq aeabi_cdrcmple aeabi_cfcmpeq aeabi_cfrcmple aeabi_dcmpeq \ - aeabi_dcmpge aeabi_dcmpgt aeabi_dcmple aeabi_dcmplt aeabi_drsub aeabi_fcmpeq \ - aeabi_fcmpge aeabi_fcmpgt aeabi_fcmple aeabi_fcmplt aeabi_frsub aeabi_idivmod \ - aeabi_uidivmod - -FUNCTIONS.cc_kext_ios.armv7 := \ - $(filter-out $(CCKEXT_MISSING_FUNCTIONS),$(FUNCTIONS.cc_kext_ios.armv7)) -FUNCTIONS.cc_kext_ios.armv7k := \ - $(filter-out $(CCKEXT_MISSING_FUNCTIONS),$(FUNCTIONS.cc_kext_ios.armv7k)) -FUNCTIONS.cc_kext_ios.armv7s := \ - $(filter-out $(CCKEXT_MISSING_FUNCTIONS),$(FUNCTIONS.cc_kext_ios.armv7s)) -FUNCTIONS.cc_kext_ios.arm64 := \ - $(filter-out $(CCKEXT_MISSING_FUNCTIONS),$(FUNCTIONS.cc_kext_ios.arm64)) -FUNCTIONS.cc_kext.i386 := \ - $(filter-out $(CCKEXT_MISSING_FUNCTIONS),$(FUNCTIONS.cc_kext.i386)) -FUNCTIONS.cc_kext.x86_64 := \ - $(filter-out $(CCKEXT_MISSING_FUNCTIONS),$(FUNCTIONS.cc_kext.x86_64)) -FUNCTIONS.cc_kext.x86_64h := \ - $(filter-out $(CCKEXT_MISSING_FUNCTIONS),$(FUNCTIONS.cc_kext.x86_64h)) - -KERNEL_USE.cc_kext := 1 -KERNEL_USE.cc_kext_ios := 1 - -VISIBILITY_HIDDEN := 1 - -SHARED_LIBRARY_SUFFIX := dylib diff --git a/make/platform/clang_darwin_test_input.c b/make/platform/clang_darwin_test_input.c deleted file mode 100644 index b406a28a63..0000000000 --- a/make/platform/clang_darwin_test_input.c +++ /dev/null @@ -1,15 +0,0 @@ -/* Include the headers we use in int_lib.h, to verify that they work. */ - -#include -#include -#include -#include -#include - -// Force us to link at least one symbol in a system library -// to detect systems where we don't have those for a given -// architecture. -int main(int argc, const char **argv) { - int x; - memcpy(&x,&argc,sizeof(int)); -} diff --git a/make/platform/clang_linux.mk b/make/platform/clang_linux.mk deleted file mode 100644 index 7b109d56c0..0000000000 --- a/make/platform/clang_linux.mk +++ /dev/null @@ -1,90 +0,0 @@ -Description := Static runtime libraries for clang/Linux. - -### - -CC := clang -Arch := unknown -Configs := - -# We don't currently have any general purpose way to target architectures other -# than the compiler defaults (because there is no generalized way to invoke -# cross compilers). For now, we just find the target architecture of the -# compiler and only define configurations we know that compiler can generate. -CompilerTargetTriple := $(shell \ - LANG=C $(CC) -v 2>&1 | grep 'Target:' | cut -d' ' -f2) -ifeq ($(CompilerTargetTriple),) -$(error "unable to infer compiler target triple for $(CC)") -endif - -# Only define configs if we detected a linux target. -ifneq ($(findstring -linux-,$(CompilerTargetTriple)),) - -# Define configs only if arch in triple is i386 or x86_64 -CompilerTargetArch := $(firstword $(subst -, ,$(CompilerTargetTriple))) -ifeq ($(call contains,i386 x86_64,$(CompilerTargetArch)),true) - -# TryCompile compiler source flags -# Returns exit code of running a compiler invocation. -TryCompile = \ - $(shell \ - cflags=""; \ - for flag in $(3); do \ - cflags="$$cflags $$flag"; \ - done; \ - $(1) $$cflags $(2) -o /dev/null > /dev/null 2> /dev/null ; \ - echo $$?) - -test_source = $(ProjSrcRoot)/make/platform/clang_linux_test_input.c -ifeq ($(CompilerTargetArch),i386) - SupportedArches := i386 - ifeq ($(call TryCompile,$(CC),$(test_source),-m64),0) - SupportedArches += x86_64 - endif -else - SupportedArches := x86_64 - ifeq ($(call TryCompile,$(CC),$(test_source),-m32),0) - SupportedArches += i386 - endif -endif - -# Build runtime libraries for i386. -ifeq ($(call contains,$(SupportedArches),i386),true) -Configs += builtins-i386 profile-i386 -Arch.builtins-i386 := i386 -Arch.profile-i386 := i386 -endif - -# Build runtime libraries for x86_64. -ifeq ($(call contains,$(SupportedArches),x86_64),true) -Configs += builtins-x86_64 profile-x86_64 -Arch.builtins-x86_64 := x86_64 -Arch.profile-x86_64 := x86_64 -endif - -endif - -endif - -### - -CFLAGS := -Wall -Werror -O3 -fomit-frame-pointer - -CFLAGS.builtins-i386 := $(CFLAGS) -m32 -CFLAGS.builtins-x86_64 := $(CFLAGS) -m64 -CFLAGS.profile-i386 := $(CFLAGS) -m32 -CFLAGS.profile-x86_64 := $(CFLAGS) -m64 - -FUNCTIONS.builtins-i386 := $(CommonFunctions) $(ArchFunctions.i386) -FUNCTIONS.builtins-x86_64 := $(CommonFunctions) $(ArchFunctions.x86_64) -FUNCTIONS.profile-i386 := GCDAProfiling InstrProfiling InstrProfilingBuffer \ - InstrProfilingFile InstrProfilingPlatformOther \ - InstrProfilingRuntime InstrProfilingUtil -FUNCTIONS.profile-x86_64 := $(FUNCTIONS.profile-i386) - -# Always use optimized variants. -OPTIMIZED := 1 - -# We don't need to use visibility hidden on Linux. -VISIBILITY_HIDDEN := 0 - -SHARED_LIBRARY_SUFFIX := so diff --git a/make/platform/clang_linux_test_input.c b/make/platform/clang_linux_test_input.c deleted file mode 100644 index e65ce9860a..0000000000 --- a/make/platform/clang_linux_test_input.c +++ /dev/null @@ -1,4 +0,0 @@ -// This file is used to check if we can produce working executables -// for i386 and x86_64 archs on Linux. -#include -int main(){} diff --git a/make/platform/clang_macho_embedded.mk b/make/platform/clang_macho_embedded.mk deleted file mode 100644 index d7870d491f..0000000000 --- a/make/platform/clang_macho_embedded.mk +++ /dev/null @@ -1,297 +0,0 @@ -# These are the functions which clang needs when it is targeting a previous -# version of the OS. The issue is that the backend may use functions which were -# not present in the libgcc that shipped on the platform. In such cases, we link -# with a version of the library which contains private_extern definitions of all -# the extra functions which might be referenced. - -Description := Static runtime libraries for embedded clang/Darwin - -# A function that ensures we don't try to build for architectures that we -# don't have working toolchains for. -CheckArches = \ - $(shell \ - result=""; \ - for arch in $(1); do \ - if $(CC) -arch $$arch -c \ - -integrated-as \ - $(ProjSrcRoot)/make/platform/clang_macho_embedded_test_input.c \ - -o /dev/null > /dev/null 2> /dev/null; then \ - result="$$result$$arch "; \ - else \ - printf 1>&2 \ - "warning: clang_macho_embedded.mk: dropping arch '$$arch' from lib '$(2)'\n"; \ - fi; \ - done; \ - echo $$result) - -XCRun = \ - $(shell \ - result=`xcrun -find $(1) 2> /dev/null`; \ - if [ "$$?" != "0" ]; then result=$(1); fi; \ - echo $$result) - -### - -CC := $(call XCRun,clang) -AR := $(call XCRun,ar) -RANLIB := $(call XCRun,ranlib) -STRIP := $(call XCRun,strip) -LIPO := $(call XCRun,lipo) -DSYMUTIL := $(call XCRun,dsymutil) - -Configs := -UniversalArchs := - -# Soft-float version of the runtime. No floating-point instructions will be used -# and the ABI (out of necessity) passes floating values in normal registers: -# non-VFP variant of the AAPCS. -UniversalArchs.soft_static := $(call CheckArches,armv6m armv7m armv7em armv7,soft_static) -Configs += $(if $(UniversalArchs.soft_static),soft_static) - -# Hard-float version of the runtime. On ARM VFP instructions and registers are -# allowed, and floating point values get passed in them. VFP variant of the -# AAPCS. -UniversalArchs.hard_static := $(call CheckArches,armv7em armv7 i386 x86_64,hard_static) -Configs += $(if $(UniversalArchs.hard_static),hard_static) - -UniversalArchs.soft_pic := $(call CheckArches,armv6m armv7m armv7em armv7,soft_pic) -Configs += $(if $(UniversalArchs.soft_pic),soft_pic) - -UniversalArchs.hard_pic := $(call CheckArches,armv7em armv7 i386 x86_64,hard_pic) -Configs += $(if $(UniversalArchs.hard_pic),hard_pic) - -CFLAGS := -Wall -Werror -Oz -fomit-frame-pointer -ffreestanding - -PIC_CFLAGS := -fPIC -STATIC_CFLAGS := -static - -CFLAGS_SOFT := -mfloat-abi=soft -CFLAGS_HARD := -mfloat-abi=hard - -CFLAGS_ARMV7 := -target thumbv7-apple-darwin-eabi -CFLAGS_I386 := -march=pentium - -CFLAGS.soft_static := $(CFLAGS) $(STATIC_CFLAGS) $(CFLAGS_SOFT) -CFLAGS.hard_static := $(CFLAGS) $(STATIC_CFLAGS) $(CFLAGS_HARD) -CFLAGS.soft_pic := $(CFLAGS) $(PIC_CFLAGS) $(CFLAGS_SOFT) -CFLAGS.hard_pic := $(CFLAGS) $(PIC_CFLAGS) $(CFLAGS_HARD) - -CFLAGS.soft_static.armv7 := $(CFLAGS.soft_static) $(CFLAGS_ARMV7) -CFLAGS.hard_static.armv7 := $(CFLAGS.hard_static) $(CFLAGS_ARMV7) -CFLAGS.soft_pic.armv7 := $(CFLAGS.soft_pic) $(CFLAGS_ARMV7) -CFLAGS.hard_pic.armv7 := $(CFLAGS.hard_pic) $(CFLAGS_ARMV7) - -# x86 platforms ignore -mfloat-abi options and complain about doing so. Despite -# this they're hard-float. -CFLAGS.hard_static.i386 := $(CFLAGS) $(STATIC_CFLAGS) $(CFLAGS_I386) -CFLAGS.hard_pic.i386 := $(CFLAGS) $(PIC_CFLAGS) $(CFLAGS_I386) -CFLAGS.hard_static.x86_64 := $(CFLAGS) $(STATIC_CFLAGS) -CFLAGS.hard_pic.x86_64 := $(CFLAGS) $(PIC_CFLAGS) - -# Functions not wanted: -# + eprintf is obsolete anyway -# + *vfp: designed for Thumb1 CPUs with VFPv2 - -COMMON_FUNCTIONS := \ - absvdi2 \ - absvsi2 \ - addvdi3 \ - addvsi3 \ - ashldi3 \ - ashrdi3 \ - bswapdi2 \ - bswapsi2 \ - clzdi2 \ - clzsi2 \ - cmpdi2 \ - ctzdi2 \ - ctzsi2 \ - divdc3 \ - divdi3 \ - divsc3 \ - divmodsi4 \ - udivmodsi4 \ - do_global_dtors \ - ffsdi2 \ - fixdfdi \ - fixsfdi \ - fixunsdfdi \ - fixunsdfsi \ - fixunssfdi \ - fixunssfsi \ - floatdidf \ - floatdisf \ - floatundidf \ - floatundisf \ - gcc_bcmp \ - lshrdi3 \ - moddi3 \ - muldc3 \ - muldi3 \ - mulsc3 \ - mulvdi3 \ - mulvsi3 \ - negdi2 \ - negvdi2 \ - negvsi2 \ - paritydi2 \ - paritysi2 \ - popcountdi2 \ - popcountsi2 \ - powidf2 \ - powisf2 \ - subvdi3 \ - subvsi3 \ - ucmpdi2 \ - udiv_w_sdiv \ - udivdi3 \ - udivmoddi4 \ - umoddi3 \ - adddf3 \ - addsf3 \ - cmpdf2 \ - cmpsf2 \ - div0 \ - divdf3 \ - divsf3 \ - divsi3 \ - extendsfdf2 \ - extendhfsf2 \ - ffssi2 \ - fixdfsi \ - fixsfsi \ - floatsidf \ - floatsisf \ - floatunsidf \ - floatunsisf \ - comparedf2 \ - comparesf2 \ - modsi3 \ - muldf3 \ - mulsf3 \ - negdf2 \ - negsf2 \ - subdf3 \ - subsf3 \ - truncdfhf2 \ - truncdfsf2 \ - truncsfhf2 \ - udivsi3 \ - umodsi3 \ - unorddf2 \ - unordsf2 \ - atomic_flag_clear \ - atomic_flag_clear_explicit \ - atomic_flag_test_and_set \ - atomic_flag_test_and_set_explicit \ - atomic_signal_fence \ - atomic_thread_fence - -ARM_FUNCTIONS := \ - aeabi_cdcmpeq \ - aeabi_cdrcmple \ - aeabi_cfcmpeq \ - aeabi_cfrcmple \ - aeabi_dcmpeq \ - aeabi_dcmpge \ - aeabi_dcmpgt \ - aeabi_dcmple \ - aeabi_dcmplt \ - aeabi_drsub \ - aeabi_fcmpeq \ - aeabi_fcmpge \ - aeabi_fcmpgt \ - aeabi_fcmple \ - aeabi_fcmplt \ - aeabi_frsub \ - aeabi_idivmod \ - aeabi_uidivmod \ - -# ARM Assembly implementation which requires Thumb2 (i.e. won't work on v6M). -THUMB2_FUNCTIONS := \ - switch16 \ - switch32 \ - switch8 \ - switchu8 \ - sync_fetch_and_add_4 \ - sync_fetch_and_sub_4 \ - sync_fetch_and_and_4 \ - sync_fetch_and_or_4 \ - sync_fetch_and_xor_4 \ - sync_fetch_and_nand_4 \ - sync_fetch_and_max_4 \ - sync_fetch_and_umax_4 \ - sync_fetch_and_min_4 \ - sync_fetch_and_umin_4 \ - sync_fetch_and_add_8 \ - sync_fetch_and_sub_8 \ - sync_fetch_and_and_8 \ - sync_fetch_and_or_8 \ - sync_fetch_and_xor_8 \ - sync_fetch_and_nand_8 \ - sync_fetch_and_max_8 \ - sync_fetch_and_umax_8 \ - sync_fetch_and_min_8 \ - sync_fetch_and_umin_8 - -I386_FUNCTIONS := \ - i686.get_pc_thunk.eax \ - i686.get_pc_thunk.ebp \ - i686.get_pc_thunk.ebx \ - i686.get_pc_thunk.ecx \ - i686.get_pc_thunk.edi \ - i686.get_pc_thunk.edx \ - i686.get_pc_thunk.esi - -# FIXME: Currently, compiler-rt is missing implementations for a number of the -# functions. Filter them out for now. -MISSING_FUNCTIONS := \ - cmpdf2 cmpsf2 div0 \ - ffssi2 \ - udiv_w_sdiv unorddf2 unordsf2 bswapdi2 \ - bswapsi2 \ - gcc_bcmp \ - do_global_dtors \ - i686.get_pc_thunk.eax i686.get_pc_thunk.ebp i686.get_pc_thunk.ebx \ - i686.get_pc_thunk.ecx i686.get_pc_thunk.edi i686.get_pc_thunk.edx \ - i686.get_pc_thunk.esi \ - aeabi_cdcmpeq aeabi_cdrcmple aeabi_cfcmpeq aeabi_cfrcmple aeabi_dcmpeq \ - aeabi_dcmpge aeabi_dcmpgt aeabi_dcmple aeabi_dcmplt aeabi_drsub \ - aeabi_fcmpeq \ aeabi_fcmpge aeabi_fcmpgt aeabi_fcmple aeabi_fcmplt \ - aeabi_frsub aeabi_idivmod aeabi_uidivmod - -FUNCTIONS_ARMV6M := $(COMMON_FUNCTIONS) $(ARM_FUNCTIONS) -FUNCTIONS_ARM_ALL := $(COMMON_FUNCTIONS) $(ARM_FUNCTIONS) $(THUMB2_FUNCTIONS) -FUNCTIONS_I386 := $(COMMON_FUNCTIONS) $(I386_FUNCTIONS) -FUNCTIONS_X86_64 := $(COMMON_FUNCTIONS) - -FUNCTIONS_ARMV6M := \ - $(filter-out $(MISSING_FUNCTIONS),$(FUNCTIONS_ARMV6M)) -FUNCTIONS_ARM_ALL := \ - $(filter-out $(MISSING_FUNCTIONS),$(FUNCTIONS_ARM_ALL)) -FUNCTIONS_I386 := \ - $(filter-out $(MISSING_FUNCTIONS),$(FUNCTIONS_I386)) -FUNCTIONS_X86_64 := \ - $(filter-out $(MISSING_FUNCTIONS),$(FUNCTIONS_X86_64)) - -FUNCTIONS.soft_static.armv6m := $(FUNCTIONS_ARMV6M) -FUNCTIONS.soft_pic.armv6m := $(FUNCTIONS_ARMV6M) - -FUNCTIONS.soft_static.armv7m := $(FUNCTIONS_ARM_ALL) -FUNCTIONS.soft_pic.armv7m := $(FUNCTIONS_ARM_ALL) - -FUNCTIONS.soft_static.armv7em := $(FUNCTIONS_ARM_ALL) -FUNCTIONS.hard_static.armv7em := $(FUNCTIONS_ARM_ALL) -FUNCTIONS.soft_pic.armv7em := $(FUNCTIONS_ARM_ALL) -FUNCTIONS.hard_pic.armv7em := $(FUNCTIONS_ARM_ALL) - -FUNCTIONS.soft_static.armv7 := $(FUNCTIONS_ARM_ALL) -FUNCTIONS.hard_static.armv7 := $(FUNCTIONS_ARM_ALL) -FUNCTIONS.soft_pic.armv7 := $(FUNCTIONS_ARM_ALL) -FUNCTIONS.hard_pic.armv7 := $(FUNCTIONS_ARM_ALL) - -FUNCTIONS.hard_static.i386 := $(FUNCTIONS_I386) -FUNCTIONS.hard_pic.i386 := $(FUNCTIONS_I386) - -FUNCTIONS.hard_static.x86_64 := $(FUNCTIONS_X86_64) -FUNCTIONS.hard_pic.x86_64 := $(FUNCTIONS_X86_64) diff --git a/make/platform/clang_macho_embedded_test_input.c b/make/platform/clang_macho_embedded_test_input.c deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/make/platform/darwin_bni.mk b/make/platform/darwin_bni.mk deleted file mode 100644 index 8e066e8e31..0000000000 --- a/make/platform/darwin_bni.mk +++ /dev/null @@ -1,135 +0,0 @@ - -Description := Target for Darwin using an Apple-style build. - -Configs := Debug Release Profile Static - -# We override this with RC_ARCHS because B&I may want to build on an ARCH we -# haven't explicitly defined support for. If all goes well, this will just work -# and the resulting lib will just have generic versions for anything unknown. -UniversalArchs := $(RC_ARCHS) - -ifneq (,$(SDKROOT)) - override CC := $(shell xcrun -sdk $(SDKROOT) -find clang || echo "false") - AR := $(shell xcrun -sdk $(SDKROOT) -find ar || echo "false") - RANLIB := $(shell xcrun -sdk $(SDKROOT) -find ranlib || echo "false") - STRIP := $(shell xcrun -sdk $(SDKROOT) -find strip || echo "false") - LIPO := $(shell xcrun -sdk $(SDKROOT) -find lipo || echo "false") - DSYMUTIL := $(shell xcrun -sdk $(SDKROOT) -find dsymutil || echo "false") -endif - -ifneq ($(IPHONEOS_DEPLOYMENT_TARGET),) - DEPLOYMENT_FLAGS := -miphoneos-version-min=$(IPHONEOS_DEPLOYMENT_TARGET) -else - ifneq ($(MACOSX_DEPLOYMENT_TARGET),) - DEPLOYMENT_FLAGS := -mmacosx-version-min=$(MACOSX_DEPLOYMENT_TARGET) - endif -endif - -ifneq (,$(SDKROOT)) - DEPLOYMENT_FLAGS += -isysroot $(SDKROOT) -endif - -CFLAGS := -Wall -Os -fomit-frame-pointer -g $(DEPLOYMENT_FLAGS) -CFLAGS.Static := $(CFLAGS) -static -DYLIB_FLAGS := $(DEPLOYMENT_FLAGS) \ - -Xarch_arm -Wl,-alias_list,$(SRCROOT)/lib/builtins/arm/softfloat-alias.list - -VISIBILITY_HIDDEN := 0 -VISIBILITY_HIDDEN.Static := 1 - - -FUNCTIONS := absvdi2 absvsi2 addvdi3 addvsi3 ashldi3 ashrdi3 \ - clzdi2 clzsi2 cmpdi2 ctzdi2 ctzsi2 \ - divdc3 divdi3 divsc3 ffsdi2 \ - fixdfdi fixsfdi fixunsdfdi fixunsdfsi fixunssfdi \ - fixunssfsi floatdidf floatdisf floatundidf floatundisf \ - gcc_personality_v0 lshrdi3 moddi3 muldc3 muldi3 mulosi4 \ - mulodi4 muloti4 mulsc3 mulvdi3 mulvsi3 negdi2 negvdi2 negvsi2 \ - paritydi2 paritysi2 popcountdi2 popcountsi2 powidf2 \ - powisf2 subvdi3 subvsi3 ucmpdi2 udivdi3 \ - udivmoddi4 umoddi3 apple_versioning eprintf atomic \ - atomic_flag_clear atomic_flag_clear_explicit \ - atomic_flag_test_and_set atomic_flag_test_and_set_explicit \ - atomic_signal_fence atomic_thread_fence \ - extendhfsf2 truncdfhf2 truncsfhf2 - -FUNCTIONS.i386 := $(FUNCTIONS) \ - divxc3 fixunsxfdi fixunsxfsi fixxfdi floatdixf \ - floatundixf mulxc3 powixf2 clear_cache \ - enable_execute_stack -FUNCTIONS.ppc := $(FUNCTIONS) \ - divtc3 fixtfdi fixunstfdi floatditf floatunditf \ - gcc_qadd gcc_qdiv gcc_qmul gcc_qsub multc3 \ - powitf2 restFP saveFP trampoline_setup \ - clear_cache enable_execute_stack -FUNCTIONS.x86_64 := $(FUNCTIONS) \ - absvti2 addvti3 ashlti3 ashrti3 clzti2 cmpti2 \ - ctzti2 divti3 divxc3 ffsti2 fixdfti fixsfti \ - fixunsdfti fixunssfti fixunsxfdi fixunsxfsi \ - fixunsxfti fixxfdi fixxfti floatdixf floattidf \ - floattisf floattixf floatundixf floatuntidf \ - floatuntisf floatuntixf lshrti3 modti3 multi3 \ - muloti4 mulvti3 mulxc3 negti2 negvti2 parityti2 \ - popcountti2 powixf2 subvti3 ucmpti2 udivmodti4 \ - udivti3 umodti3 clear_cache enable_execute_stack - -FUNCTIONS.armv4t := $(FUNCTIONS) - -FUNCTIONS.armv5 := $(FUNCTIONS) \ - adddf3 addsf3 bswapdi2 bswapsi2 \ - comparedf2 comparesf2 extendsfdf2 \ - divdf3 divsf3 \ - fixdfsi fixsfsi fixunsdfsi fixunssfsi \ - floatsidf floatsisf floatunsidf floatunsisf \ - muldf3 mulsf3 \ - negdf2 negsf2 \ - truncdfsf2 \ - modsi3 umodsi3 udivsi3 divsi3 udivmodsi4 divmodsi4 \ - switch8 switchu8 switch16 switch32 \ - sync_synchronize - -FUNCTIONS.armv6 := $(FUNCTIONS) \ - comparedf2 comparesf2 \ - adddf3vfp addsf3vfp bswapdi2 bswapsi2 divdf3vfp \ - divsf3vfp eqdf2vfp eqsf2vfp extendsfdf2vfp \ - fixdfsivfp fixsfsivfp fixunsdfsivfp fixunssfsivfp \ - floatsidfvfp floatsisfvfp floatunssidfvfp floatunssisfvfp \ - gedf2vfp gesf2vfp gtdf2vfp gtsf2vfp \ - ledf2vfp lesf2vfp ltdf2vfp ltsf2vfp \ - muldf3vfp mulsf3vfp \ - nedf2vfp nesf2vfp \ - subdf3vfp subsf3vfp truncdfsf2vfp unorddf2vfp unordsf2vfp \ - modsi3 umodsi3 udivsi3 divsi3 udivmodsi4 divmodsi4 \ - switch8 switchu8 switch16 switch32 \ - restore_vfp_d8_d15_regs save_vfp_d8_d15_regs \ - sync_synchronize - -FUNCTIONS.armv7 := $(FUNCTIONS) \ - comparedf2 comparesf2 \ - adddf3vfp addsf3vfp bswapdi2 bswapsi2 divdf3vfp \ - divsf3vfp eqdf2vfp eqsf2vfp extendsfdf2vfp \ - fixdfsivfp fixsfsivfp fixunsdfsivfp fixunssfsivfp \ - floatsidfvfp floatsisfvfp floatunssidfvfp floatunssisfvfp \ - gedf2vfp gesf2vfp gtdf2vfp gtsf2vfp \ - ledf2vfp lesf2vfp ltdf2vfp ltsf2vfp \ - muldf3vfp mulsf3vfp \ - nedf2vfp nesf2vfp \ - subdf3vfp subsf3vfp truncdfsf2vfp unorddf2vfp unordsf2vfp \ - modsi3 umodsi3 udivsi3 divsi3 udivmodsi4 divmodsi4 - -FUNCTIONS.armv7s := $(FUNCTIONS.armv7) - -FUNCTIONS.arm64 := divti3 modti3 \ - udivmodti4 \ - udivti3 umodti3 \ - mulsc3 muldc3 \ - powisf2 powidf2 \ - clzti2 \ - fixdfti fixsfti \ - fixunsdfti fixunssfti fixunssfti \ - floattidf floattisf floatuntidf floatuntisf \ - gcc_personality_v0 atomic \ - atomic_flag_clear atomic_flag_clear_explicit \ - atomic_flag_test_and_set \ - atomic_flag_test_and_set_explicit \ - atomic_signal_fence atomic_thread_fence diff --git a/make/platform/multi_arch.mk b/make/platform/multi_arch.mk deleted file mode 100644 index fe6ac4be0e..0000000000 --- a/make/platform/multi_arch.mk +++ /dev/null @@ -1,15 +0,0 @@ -Description := Example configuration for build two libraries for separate \ -architectures. - -Configs := m32 m64 -Arch := i386 -Arch.m64 := x86_64 - -CC := clang - -CFLAGS := -Wall -Werror -CFLAGS.m32 := $(CFLAGS) -m32 -O3 -CFLAGS.m64 := $(CFLAGS) -m64 -O3 - -FUNCTIONS := moddi3 floatundixf udivdi3 -FUNCTIONS.m64 := $(FUNCTIONS) lshrdi3 From 540b0942b7a8556fa316d86b8458706267ad749c Mon Sep 17 00:00:00 2001 From: angelsl Date: Sat, 24 Oct 2015 01:02:01 +0800 Subject: [PATCH 59/68] Rust: Enable MSVC build --- lib/builtins/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/builtins/CMakeLists.txt b/lib/builtins/CMakeLists.txt index 08929048ed..df4e2523cf 100644 --- a/lib/builtins/CMakeLists.txt +++ b/lib/builtins/CMakeLists.txt @@ -349,7 +349,7 @@ if (APPLE) add_subdirectory(Darwin-excludes) add_subdirectory(macho_embedded) darwin_add_builtin_libraries(${BUILTIN_SUPPORTED_OS}) -elseif (NOT WIN32 OR MINGW) +else () foreach (arch ${BUILTIN_SUPPORTED_ARCH}) if (CAN_TARGET_${arch}) # Filter out generic versions of routines that are re-implemented in From a4b1f78283db06dc5bbec6abaab7a93086697c44 Mon Sep 17 00:00:00 2001 From: angelsl Date: Sat, 24 Oct 2015 01:21:15 +0800 Subject: [PATCH 60/68] Rust: Silence -fPIC warnings on Windows Based on 44f2671fe87099a76510ec316a01644789aec689 (vadimcn) --- make/config.mk | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/make/config.mk b/make/config.mk index 094fd160f9..0998aca0de 100644 --- a/make/config.mk +++ b/make/config.mk @@ -44,6 +44,6 @@ endif ### # Common compiler options COMMON_INCLUDES=-I${ProjSrcRoot}/lib -I${ProjSrcRoot}/include -COMMON_CXXFLAGS=-std=c++11 -fno-exceptions -fPIC -funwind-tables $(COMMON_INCLUDES) -COMMON_CFLAGS=-fPIC $(COMMON_INCLUDES) +COMMON_CXXFLAGS=-std=c++11 -fno-exceptions -funwind-tables $(COMMON_INCLUDES) +COMMON_CFLAGS=$(COMMON_INCLUDES) COMMON_ASMFLAGS=$(COMMON_INCLUDES) From b97188b982800366714162201833aefe2893fe78 Mon Sep 17 00:00:00 2001 From: angelsl Date: Sat, 31 Oct 2015 02:33:55 +0800 Subject: [PATCH 61/68] Rust: fix MSVC-built lib pulling in other lib files --- lib/builtins/CMakeLists.txt | 9 ++++++++- lib/builtins/int_math.h | 4 +++- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/lib/builtins/CMakeLists.txt b/lib/builtins/CMakeLists.txt index df4e2523cf..97249ea730 100644 --- a/lib/builtins/CMakeLists.txt +++ b/lib/builtins/CMakeLists.txt @@ -363,11 +363,18 @@ else () endif () endforeach () + # Rust: don't insert a reference to MSVCRT.lib/etc + if (MSVC) + set(_cflags -Zl) + else () + set(_cflags -std=c99) + endif () + add_compiler_rt_runtime(clang_rt.builtins STATIC ARCHS ${arch} SOURCES ${${arch}_SOURCES} - CFLAGS "-std=c99" + CFLAGS ${_cflags} PARENT_TARGET builtins) endif () endforeach () diff --git a/lib/builtins/int_math.h b/lib/builtins/int_math.h index fc81fb7f02..9a8b751e44 100644 --- a/lib/builtins/int_math.h +++ b/lib/builtins/int_math.h @@ -28,7 +28,9 @@ #if defined(_MSC_VER) && !defined(__clang__) #include #include -#include +// Rust: need to upstream this +// don't include ymath.h, it's not needed + pulls in the C++ stdlib for some reason +// #include #endif #if defined(_MSC_VER) && !defined(__clang__) From ba1ad133573910af55be99d68ec5f05d447d9d95 Mon Sep 17 00:00:00 2001 From: angelsl Date: Tue, 27 Oct 2015 18:24:03 +0800 Subject: [PATCH 62/68] Rust: fix clear_cache ARM ASM --- lib/builtins/clear_cache.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/builtins/clear_cache.c b/lib/builtins/clear_cache.c index ede7659a05..863eb818fc 100644 --- a/lib/builtins/clear_cache.c +++ b/lib/builtins/clear_cache.c @@ -104,7 +104,7 @@ void __clear_cache(void *start, void *end) { const register int flags __asm("r2") = 0; const register int syscall_nr __asm("r7") = __ARM_NR_cacheflush; __asm __volatile("svc 0x0" : "=r"(start_reg) - : "r"(syscall_nr), "r"(start_reg), "r"(end_reg), "r"(flags) : "r0"); + : "r"(syscall_nr), "r"(start_reg), "r"(end_reg), "r"(flags)); if (start_reg != 0) { compilerrt_abort(); } From 280acc0f49634092a8af93ace80960216874639a Mon Sep 17 00:00:00 2001 From: angelsl Date: Tue, 27 Oct 2015 18:24:34 +0800 Subject: [PATCH 63/68] Rust: cleanup macros leaked from pthread.h on Android --- lib/builtins/emutls.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/lib/builtins/emutls.c b/lib/builtins/emutls.c index 09e79568bd..d4678e9ebc 100644 --- a/lib/builtins/emutls.c +++ b/lib/builtins/emutls.c @@ -8,6 +8,15 @@ * ===----------------------------------------------------------------------=== */ #include + +// Rust-specific change +// One of the headers included by pthread.h in Android #defines si_int to +// something else. Remove this definition, as we use si_int internally to +// mean int. +#ifdef si_int +#undef si_int +#endif + #include #include #include From 3d5277f7a4d78d8e70d7823f3564d7f41e82a3b0 Mon Sep 17 00:00:00 2001 From: angelsl Date: Wed, 28 Oct 2015 15:20:06 +0800 Subject: [PATCH 64/68] Rust: Fix clear_cache on MIPS --- lib/builtins/clear_cache.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/lib/builtins/clear_cache.c b/lib/builtins/clear_cache.c index 863eb818fc..5e3fcccd23 100644 --- a/lib/builtins/clear_cache.c +++ b/lib/builtins/clear_cache.c @@ -24,9 +24,13 @@ #endif #if defined(__mips__) + #include + // Rust: For some strange reason __USE_MISC isn't being defined so + // we don't get the definition of syscall. Force it to be defined. + #define __USE_MISC + #include #include #include - #include #if defined(__ANDROID__) && defined(__LP64__) /* * clear_mips_cache - Invalidates instruction cache for Mips. From 12954864101c4aefdb130fecd5572ca8a247fa16 Mon Sep 17 00:00:00 2001 From: angelsl Date: Wed, 28 Oct 2015 15:20:31 +0800 Subject: [PATCH 65/68] Rust: Add back endianness check via Linux endian.h for old GCC on MIPS --- lib/builtins/int_endianness.h | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/lib/builtins/int_endianness.h b/lib/builtins/int_endianness.h index 7995ddbb95..92511e6a15 100644 --- a/lib/builtins/int_endianness.h +++ b/lib/builtins/int_endianness.h @@ -105,6 +105,19 @@ #endif /* Windows */ +#if defined(__linux__) +#include + +#if __BYTE_ORDER == __BIG_ENDIAN +#define _YUGA_LITTLE_ENDIAN 0 +#define _YUGA_BIG_ENDIAN 1 +#elif __BYTE_ORDER == __LITTLE_ENDIAN +#define _YUGA_LITTLE_ENDIAN 1 +#define _YUGA_BIG_ENDIAN 0 +#endif /* __BYTE_ORDER */ + +#endif /* GNU/Linux */ + #endif /* Clang or GCC. */ /* . */ From 961d2bfb65f3d0a098894c935574d64e743ed7f0 Mon Sep 17 00:00:00 2001 From: angelsl Date: Wed, 28 Oct 2015 15:21:02 +0800 Subject: [PATCH 66/68] Rust: Disable emutls on MIPS; old GCC can't take it --- make/platform/triple.mk | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/make/platform/triple.mk b/make/platform/triple.mk index 061faa7f96..7e3450e395 100644 --- a/make/platform/triple.mk +++ b/make/platform/triple.mk @@ -54,6 +54,12 @@ ifeq ($(TargetTriple),arm-linux-androideabi) sync_fetch_and_umin_8 endif +# Disable emutls on MIPS +# Rust uses GCC 4.4 to cross-compile, which doesn't have some builtins +ifneq (,$(findstring mips,$(TargetTriple))) + CommonDisabledFunctions := emutls +endif + # Clear cache is builtin on aarch64-apple-ios # arm64 and aarch64 are synonims, but iOS targets usually use arm64 (history reasons) ifeq (aarch64-apple-ios,$(subst arm64,aarch64,$(TargetTriple))) From 5b9c754678225af6a9d5c0001f74307250d8a05e Mon Sep 17 00:00:00 2001 From: angelsl Date: Sat, 31 Oct 2015 01:50:58 +0800 Subject: [PATCH 67/68] Rust: disable emutls on Windows MinGW --- make/platform/triple.mk | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/make/platform/triple.mk b/make/platform/triple.mk index 7e3450e395..0d68b2eafd 100644 --- a/make/platform/triple.mk +++ b/make/platform/triple.mk @@ -60,6 +60,12 @@ ifneq (,$(findstring mips,$(TargetTriple))) CommonDisabledFunctions := emutls endif +# Disable emutls on Windows +# emutls works on POSIX only as it uses pthreads +ifneq (,$(findstring windows,$(TargetTriple))) + CommonDisabledFunctions := emutls +endif + # Clear cache is builtin on aarch64-apple-ios # arm64 and aarch64 are synonims, but iOS targets usually use arm64 (history reasons) ifeq (aarch64-apple-ios,$(subst arm64,aarch64,$(TargetTriple))) From b6087e82ba1384c4af3adf2dc68e92316f0d4caf Mon Sep 17 00:00:00 2001 From: Valerii Hiora Date: Fri, 23 May 2014 15:09:39 +0300 Subject: [PATCH 68/68] Rust: Support for SJ/LJ unwinding (arm) --- lib/builtins/gcc_personality_v0.c | 65 ++++++++++++++++++++++--------- 1 file changed, 47 insertions(+), 18 deletions(-) diff --git a/lib/builtins/gcc_personality_v0.c b/lib/builtins/gcc_personality_v0.c index 331dc2bea2..afe643c4bd 100644 --- a/lib/builtins/gcc_personality_v0.c +++ b/lib/builtins/gcc_personality_v0.c @@ -164,8 +164,6 @@ __gcc_personality_v0(int version, _Unwind_Action actions, return _URC_CONTINUE_UNWIND; uintptr_t pc = _Unwind_GetIP(context)-1; - uintptr_t funcStart = _Unwind_GetRegionStart(context); - uintptr_t pcOffset = pc - funcStart; /* Parse LSDA header. */ uint8_t lpStartEncoding = *lsda++; @@ -176,17 +174,43 @@ __gcc_personality_v0(int version, _Unwind_Action actions, if (ttypeEncoding != DW_EH_PE_omit) { readULEB128(&lsda); } - /* Walk call-site table looking for range that includes current PC. */ + + uintptr_t resumeIp = 0; uint8_t callSiteEncoding = *lsda++; uint32_t callSiteTableLength = readULEB128(&lsda); - const uint8_t* callSiteTableStart = lsda; - const uint8_t* callSiteTableEnd = callSiteTableStart + callSiteTableLength; - const uint8_t* p=callSiteTableStart; - while (p < callSiteTableEnd) { - uintptr_t start = readEncodedPointer(&p, callSiteEncoding); - uintptr_t length = readEncodedPointer(&p, callSiteEncoding); - uintptr_t landingPad = readEncodedPointer(&p, callSiteEncoding); - readULEB128(&p); /* action value not used for C code */ + const uint8_t* callSite = lsda; + +#if defined(__USING_SJLJ_EXCEPTIONS__) + (void)callSiteEncoding; + (void)callSiteTableLength; + /* The given "IP" is an index into the call-site table, with two + exceptions -- -1 means no-action, and 0 means terminate. But + since we're using uleb128 values, we've not got random access + to the array. */ + if ((int) pc <= 0) { + return _URC_CONTINUE_UNWIND; + } else { + uintptr_t csLp; + do { + csLp = readULEB128(&callSite); + readULEB128(&callSite); // skip cs action + } while (--pc); + + /* Can never have null landing pad for sjlj -- that would have + been indicated by a -1 call site index. */ + resumeIp = csLp + 1; + } +#else + /* Walk call-site table looking for range that includes current PC. */ + uintptr_t funcStart = _Unwind_GetRegionStart(context); + uintptr_t pcOffset = pc - funcStart; + const uint8_t* callSiteTableEnd = callSite + callSiteTableLength; + + while (callSite < callSiteTableEnd) { + uintptr_t start = readEncodedPointer(&callSite, callSiteEncoding); + uintptr_t length = readEncodedPointer(&callSite, callSiteEncoding); + uintptr_t landingPad = readEncodedPointer(&callSite, callSiteEncoding); + readULEB128(&callSite); /* action value not used for C code */ if ( landingPad == 0 ) continue; /* no landing pad for this entry */ if ( (start <= pcOffset) && (pcOffset < (start+length)) ) { @@ -195,15 +219,20 @@ __gcc_personality_v0(int version, _Unwind_Action actions, * at landing pad. The landing pad is created by the compiler * to take two parameters in registers. */ - _Unwind_SetGR(context, __builtin_eh_return_data_regno(0), - (uintptr_t)exceptionObject); - _Unwind_SetGR(context, __builtin_eh_return_data_regno(1), 0); - _Unwind_SetIP(context, (funcStart + landingPad)); - return _URC_INSTALL_CONTEXT; + resumeIp = funcStart + landingPad; + break; } } +#endif // SJ/LJ - /* No landing pad found, continue unwinding. */ - return _URC_CONTINUE_UNWIND; + if (resumeIp == 0) { + return _URC_CONTINUE_UNWIND; + } else { + _Unwind_SetGR(context, __builtin_eh_return_data_regno(0), + (uintptr_t)exceptionObject); + _Unwind_SetGR(context, __builtin_eh_return_data_regno(1), 0); + _Unwind_SetIP(context, resumeIp); + return _URC_INSTALL_CONTEXT; + } }