Update aosp/master compiler-rt for rebase to r233350

Change-Id: I5f20256ce73ec7b5956f742b4062f850bf11b667
diff --git a/CMakeLists.txt b/CMakeLists.txt
index f348585..d65b396 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -160,8 +160,6 @@
 
 set(COMPILER_RT_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR})
 set(COMPILER_RT_BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR})
-# Setup custom SDK sysroots.
-set(COMPILER_RT_LINUX_SDK_SYSROOT ${COMPILER_RT_SOURCE_DIR}/SDKs/linux)
 
 # We support running instrumented tests when we're not cross compiling
 # and target a UNIX-like system or Windows.
@@ -302,15 +300,22 @@
   set(SANITIZER_MIN_OSX_VERSION 10.7)
   set(CMAKE_OSX_DEPLOYMENT_TARGET "") # We're setting the flag manually below.
   set(DARWIN_osx_CFLAGS -mmacosx-version-min=${SANITIZER_MIN_OSX_VERSION}
-    -isysroot ${OSX_SDK_DIR} -stdlib=libc++)
+    -stdlib=libc++)
   set(DARWIN_iossim_CFLAGS
+    -stdlib=libc++
     -mios-simulator-version-min=7.0 -isysroot ${IOSSIM_SDK_DIR})
   set(DARWIN_osx_LINKFLAGS -mmacosx-version-min=${SANITIZER_MIN_OSX_VERSION}
-    -isysroot ${OSX_SDK_DIR} -stdlib=libc++)
+    -stdlib=libc++ -lc++)
   set(DARWIN_iossim_LINKFLAGS
+    -stdlib=libc++ -lc++
     -Wl,-ios_simulator_version_min,7.0.0
     -mios-simulator-version-min=7.0
     -isysroot ${IOSSIM_SDK_DIR})
+
+  if(OSX_SDK_DIR)
+    list(APPEND DARWIN_osx_CFLAGS -isysroot ${OSX_SDK_DIR})
+    list(APPEND DARWIN_osx_LINKFLAGS -isysroot ${OSX_SDK_DIR})
+  endif()
 endif()
 
 add_subdirectory(include)
diff --git a/LICENSE.TXT b/LICENSE.TXT
index aee8347..aa4115e 100644
--- a/LICENSE.TXT
+++ b/LICENSE.TXT
@@ -14,7 +14,7 @@
 University of Illinois/NCSA
 Open Source License
 
-Copyright (c) 2009-2014 by the contributors listed in CREDITS.TXT
+Copyright (c) 2009-2015 by the contributors listed in CREDITS.TXT
 
 All rights reserved.
 
@@ -55,7 +55,7 @@
 
 ==============================================================================
 
-Copyright (c) 2009-2014 by the contributors listed in CREDITS.TXT
+Copyright (c) 2009-2015 by the contributors listed in CREDITS.TXT
 
 Permission is hereby granted, free of charge, to any person obtaining a copy
 of this software and associated documentation files (the "Software"), to deal
diff --git a/SDKs/README.txt b/SDKs/README.txt
deleted file mode 100644
index b95575e..0000000
--- a/SDKs/README.txt
+++ /dev/null
@@ -1,9 +0,0 @@
-It is often convenient to be able to build compiler-rt libraries for a certain
-platform without having a full SDK or development environment installed.
-
-This makes it easy for users to build a compiler which can target a number of
-different platforms, without having to actively maintain full development
-environments for those platforms.
-
-Since compiler-rt's libraries typically have minimal interaction with the
-system, we achieve this by stubbing out the SDKs of certain platforms.
diff --git a/SDKs/linux/README.txt b/SDKs/linux/README.txt
deleted file mode 100644
index aa0604a..0000000
--- a/SDKs/linux/README.txt
+++ /dev/null
@@ -1,2 +0,0 @@
-This is a stub SDK for Linux. Currently, this has only been tested on i386 and
-x86_64 using the Clang compiler.
diff --git a/SDKs/linux/usr/include/endian.h b/SDKs/linux/usr/include/endian.h
deleted file mode 100644
index 95528db..0000000
--- a/SDKs/linux/usr/include/endian.h
+++ /dev/null
@@ -1,29 +0,0 @@
-/* ===-- endian.h - stub SDK header for compiler-rt -------------------------===
- *
- *                     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 is a stub SDK header file. This file is not part of the interface of
- * this library nor an official version of the appropriate SDK header. It is
- * intended only to stub the features of this header required by compiler-rt.
- *
- * ===-----------------------------------------------------------------------===
- */
-
-#ifndef __ENDIAN_H__
-#define __ENDIAN_H__
-
-#define __LITTLE_ENDIAN 1234
-#define __BIG_ENDIAN 4321
-
-#if defined(__LITTLE_ENDIAN__) || defined(__ORDER_LITTLE_ENDIAN__)
-#define __BYTE_ORDER __LITTLE_ENDIAN
-#else
-#define __BYTE_ORDER __BIG_ENDIAN
-#endif
-
-#endif /* __ENDIAN_H__ */
diff --git a/SDKs/linux/usr/include/fcntl.h b/SDKs/linux/usr/include/fcntl.h
deleted file mode 100644
index a5f91e3..0000000
--- a/SDKs/linux/usr/include/fcntl.h
+++ /dev/null
@@ -1,17 +0,0 @@
-/* ===-- fcntl.h - stub SDK header for compiler-rt --------------------------===
- *
- *                     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 is a stub SDK header file. This file is not part of the interface of
- * this library nor an official version of the appropriate SDK header. It is
- * intended only to stub the features of this header required by compiler-rt.
- *
- * ===-----------------------------------------------------------------------===
- */
-
-#include <sys/fcntl.h>
diff --git a/SDKs/linux/usr/include/limits.h b/SDKs/linux/usr/include/limits.h
deleted file mode 100644
index 5495a78..0000000
--- a/SDKs/linux/usr/include/limits.h
+++ /dev/null
@@ -1,23 +0,0 @@
-/* ===-- limits.h - stub SDK header for compiler-rt -------------------------===
- *
- *                     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 is a stub SDK header file. This file is not part of the interface of
- * this library nor an official version of the appropriate SDK header. It is
- * intended only to stub the features of this header required by compiler-rt.
- *
- * ===-----------------------------------------------------------------------===
- */
-
-#ifndef __LIMITS_H__
-#define __LIMITS_H__
-
-/* This is only here as a landing pad for the include_next from the compiler's
-   built-in limits.h. */
-
-#endif /* __LIMITS_H__ */
diff --git a/SDKs/linux/usr/include/stdio.h b/SDKs/linux/usr/include/stdio.h
deleted file mode 100644
index e2161da..0000000
--- a/SDKs/linux/usr/include/stdio.h
+++ /dev/null
@@ -1,44 +0,0 @@
-/* ===-- stdio.h - stub SDK header for compiler-rt --------------------------===
- *
- *                     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 is a stub SDK header file. This file is not part of the interface of
- * this library nor an official version of the appropriate SDK header. It is
- * intended only to stub the features of this header required by compiler-rt.
- *
- * ===-----------------------------------------------------------------------===
- */
-
-#ifndef __STDIO_H__
-#define __STDIO_H__
-
-typedef __SIZE_TYPE__ size_t;
-
-struct _IO_FILE;
-typedef struct _IO_FILE FILE;
-
-extern struct _IO_FILE *stdin;
-extern struct _IO_FILE *stdout;
-extern struct _IO_FILE *stderr;
-
-#define	SEEK_SET	0	/* set file offset to offset */
-#define	SEEK_CUR	1	/* set file offset to current plus offset */
-#define	SEEK_END	2	/* set file offset to EOF plus offset */
-
-extern int fclose(FILE *);
-extern int fflush(FILE *);
-extern FILE *fopen(const char * restrict, const char * restrict);
-extern FILE *fdopen(int, const char * restrict);
-extern int fprintf(FILE * restrict, const char * restrict, ...);
-extern int fputc(int, FILE *);
-extern size_t fwrite(const void * restrict, size_t, size_t, FILE * restrict);
-extern size_t fread(void * restrict, size_t, size_t, FILE * restrict);
-extern long ftell(FILE *);
-extern int fseek(FILE *, long, int);
-
-#endif /* __STDIO_H__ */
diff --git a/SDKs/linux/usr/include/stdlib.h b/SDKs/linux/usr/include/stdlib.h
deleted file mode 100644
index 966b29d..0000000
--- a/SDKs/linux/usr/include/stdlib.h
+++ /dev/null
@@ -1,36 +0,0 @@
-/* ===-- stdlib.h - stub SDK header for compiler-rt -------------------------===
- *
- *                     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 is a stub SDK header file. This file is not part of the interface of
- * this library nor an official version of the appropriate SDK header. It is
- * intended only to stub the features of this header required by compiler-rt.
- *
- * ===-----------------------------------------------------------------------===
- */
-
-#ifndef __STDLIB_H__
-#define __STDLIB_H__
-
-#define NULL ((void *)0)
-
-typedef __SIZE_TYPE__ size_t;
-
-void abort(void) __attribute__((__nothrow__)) __attribute__((__noreturn__));
-int atexit(void (*)(void)) __attribute__((__nothrow__));
-int atoi(const char *) __attribute__((__nothrow__));
-void free(void *) __attribute__((__nothrow__));
-char *getenv(const char *) __attribute__((__nothrow__))
-  __attribute__((__nonnull__(1)));
-  __attribute__((__warn_unused_result__));
-void *malloc(size_t) __attribute__((__nothrow__)) __attribute((__malloc__))
-     __attribute__((__warn_unused_result__));
-void *realloc(void *, size_t) __attribute__((__nothrow__)) __attribute((__malloc__))
-     __attribute__((__warn_unused_result__));
-
-#endif /* __STDLIB_H__ */
diff --git a/SDKs/linux/usr/include/string.h b/SDKs/linux/usr/include/string.h
deleted file mode 100644
index c7da1f5..0000000
--- a/SDKs/linux/usr/include/string.h
+++ /dev/null
@@ -1,31 +0,0 @@
-/* ===-- string.h - stub SDK header for compiler-rt -------------------------===
- *
- *                     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 is a stub SDK header file. This file is not part of the interface of
- * this library nor an official version of the appropriate SDK header. It is
- * intended only to stub the features of this header required by compiler-rt.
- *
- * ===-----------------------------------------------------------------------===
- */
-
-#ifndef __STRING_H__
-#define __STRING_H__
-
-typedef __SIZE_TYPE__ size_t;
-
-int memcmp(const void *, const void *, size_t);
-void *memcpy(void *, const void *, size_t);
-void *memset(void *, int, size_t);
-char *strcat(char *, const char *);
-char *strcpy(char *, const char *);
-char *strdup(const char *);
-size_t strlen(const char *);
-char *strncpy(char *, const char *, size_t);
-
-#endif /* __STRING_H__ */
diff --git a/SDKs/linux/usr/include/sys/fcntl.h b/SDKs/linux/usr/include/sys/fcntl.h
deleted file mode 100644
index 1512bf9..0000000
--- a/SDKs/linux/usr/include/sys/fcntl.h
+++ /dev/null
@@ -1,29 +0,0 @@
-/* ===-- fcntl.h - stub SDK header for compiler-rt --------------------------===
- *
- *                     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 is a stub SDK header file. This file is not part of the interface of
- * this library nor an official version of the appropriate SDK header. It is
- * intended only to stub the features of this header required by compiler-rt.
- *
- * ===-----------------------------------------------------------------------===
- */
-
-#ifndef _SYS_FCNTL_H_
-#define _SYS_FCNTL_H_
-
-#define O_RDONLY   0x0000
-#define O_WRONLY   0x0001
-#define O_RDWR     0x0002
-#define O_ACCMODE  0x0003
-
-#define O_CREAT    0x0200
-
-int open(const char *, int, ...);
-
-#endif /* _SYS_FCNTL_H_ */
diff --git a/SDKs/linux/usr/include/sys/mman.h b/SDKs/linux/usr/include/sys/mman.h
deleted file mode 100644
index bfb7f8b..0000000
--- a/SDKs/linux/usr/include/sys/mman.h
+++ /dev/null
@@ -1,47 +0,0 @@
-/* ===-- limits.h - stub SDK header for compiler-rt -------------------------===
- *
- *                     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 is a stub SDK header file. This file is not part of the interface of
- * this library nor an official version of the appropriate SDK header. It is
- * intended only to stub the features of this header required by compiler-rt.
- *
- * ===-----------------------------------------------------------------------===
- */
-
-#ifndef __SYS_MMAN_H__
-#define __SYS_MMAN_H__
-
-typedef __SIZE_TYPE__ size_t;
-
-#define PROT_NONE     0x00
-#define PROT_READ     0x01
-#define PROT_WRITE    0x02
-#define PROT_EXEC     0x04
-
-#define MAP_SHARED    0x0001
-#define MAP_PRIVATE   0x0002
-
-#define MAP_FILE      0x0000
-#define MAP_ANON      0x1000
-
-#define MS_ASYNC      0x0001
-#define MS_INVALIDATE 0x0002
-#define MS_SYNC       0x0010
-
-extern void *mmap(void *addr, size_t len, int prot, int flags, int fd,
-                  long long offset)
-  __attribute__((__nothrow__));
-extern int munmap(void *addr, size_t len)
-  __attribute__((__nothrow__));
-extern int msync(void *addr, size_t len, int flags)
-  __attribute__((__nothrow__));
-extern int mprotect (void *__addr, size_t __len, int __prot)
-  __attribute__((__nothrow__));
-
-#endif /* __SYS_MMAN_H__ */
diff --git a/SDKs/linux/usr/include/sys/stat.h b/SDKs/linux/usr/include/sys/stat.h
deleted file mode 100644
index 0449fdd..0000000
--- a/SDKs/linux/usr/include/sys/stat.h
+++ /dev/null
@@ -1,24 +0,0 @@
-/* ===-- stat.h - stub SDK header for compiler-rt ---------------------------===
- *
- *                     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 is a stub SDK header file. This file is not part of the interface of
- * this library nor an official version of the appropriate SDK header. It is
- * intended only to stub the features of this header required by compiler-rt.
- *
- * ===-----------------------------------------------------------------------===
- */
-
-#ifndef __SYS_STAT_H__
-#define __SYS_STAT_H__
-
-typedef unsigned int mode_t;
-
-int mkdir(const char *, mode_t);
-
-#endif /* __SYS_STAT_H__ */
diff --git a/SDKs/linux/usr/include/sys/types.h b/SDKs/linux/usr/include/sys/types.h
deleted file mode 100644
index 10e74bb..0000000
--- a/SDKs/linux/usr/include/sys/types.h
+++ /dev/null
@@ -1,20 +0,0 @@
-/* ===-- stat.h - stub SDK header for compiler-rt ---------------------------===
- *
- *                     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 is a stub SDK header file. This file is not part of the interface of
- * this library nor an official version of the appropriate SDK header. It is
- * intended only to stub the features of this header required by compiler-rt.
- *
- * ===-----------------------------------------------------------------------===
- */
-
-#ifndef __SYS_TYPES_H__
-#define __SYS_TYPES_H__
-
-#endif /* __SYS_TYPES_H__ */
diff --git a/SDKs/linux/usr/include/unistd.h b/SDKs/linux/usr/include/unistd.h
deleted file mode 100644
index 773b081..0000000
--- a/SDKs/linux/usr/include/unistd.h
+++ /dev/null
@@ -1,26 +0,0 @@
-/* ===-- unistd.h - stub SDK header for compiler-rt -------------------------===
- *
- *                     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 is a stub SDK header file. This file is not part of the interface of
- * this library nor an official version of the appropriate SDK header. It is
- * intended only to stub the features of this header required by compiler-rt.
- *
- * ===-----------------------------------------------------------------------===
- */
-
-#ifndef __UNISTD_H__
-#define __UNISTD_H__
-
-enum {
-  _SC_PAGESIZE = 30
-};
-
-extern long int sysconf (int __name) __attribute__ ((__nothrow__));
-
-#endif /* __UNISTD_H__ */
diff --git a/cmake/Modules/CompilerRTCompile.cmake b/cmake/Modules/CompilerRTCompile.cmake
index de73ccf..c883e43 100644
--- a/cmake/Modules/CompilerRTCompile.cmake
+++ b/cmake/Modules/CompilerRTCompile.cmake
@@ -1,5 +1,31 @@
 include(LLVMParseArguments)
 
+# On Windows, CMAKE_*_FLAGS are built for MSVC but we use the GCC clang.exe,
+# which uses completely different flags. Translate some common flag types, and
+# drop the rest.
+function(translate_msvc_cflags out_flags msvc_flags)
+  # Insert an empty string in the list to simplify processing.
+  set(msvc_flags ";${msvc_flags}")
+
+  # Canonicalize /flag to -flag.
+  string(REPLACE ";/" ";-" msvc_flags "${msvc_flags}")
+
+  # Make space separated -D and -U flags into joined flags.
+  string(REGEX REPLACE ";-\([DU]\);" ";-\\1" msvc_flags "${msvc_flags}")
+
+  set(clang_flags "")
+  foreach(flag ${msvc_flags})
+    if ("${flag}" MATCHES "^-[DU]")
+      # Pass through basic command line macro definitions (-DNDEBUG).
+      list(APPEND clang_flags "${flag}")
+    elseif ("${flag}" MATCHES "^-O[2x]")
+      # Canonicalize normal optimization flags to -O2.
+      list(APPEND clang_flags "-O2")
+    endif()
+  endforeach()
+  set(${out_flags} "${clang_flags}" PARENT_SCOPE)
+endfunction()
+
 # Compile a source into an object file with COMPILER_RT_TEST_COMPILER using
 # a provided compile flags and dependenices.
 # clang_compile(<object> <source>
@@ -20,13 +46,11 @@
   else()
     string(REPLACE " " ";" global_flags "${CMAKE_C_FLAGS}")
   endif()
-  # On Windows, CMAKE_*_FLAGS are built for MSVC but we use the GCC clang.exe
-  # which doesn't support flags starting with "/smth". Replace those with
-  # "-smth" equivalents.
-  if(MSVC)
-    string(REGEX REPLACE "^/" "-" global_flags "${global_flags}")
-    string(REPLACE ";/" ";-" global_flags "${global_flags}")
+
+  if (MSVC)
+    translate_msvc_cflags(global_flags "${global_flags}")
   endif()
+
   # Ignore unknown warnings. CMAKE_CXX_FLAGS may contain GCC-specific options
   # which are not supported by Clang.
   list(APPEND global_flags -Wno-unknown-warning-option)
diff --git a/cmake/config-ix.cmake b/cmake/config-ix.cmake
index 9c4c8de..f52639b 100644
--- a/cmake/config-ix.cmake
+++ b/cmake/config-ix.cmake
@@ -161,10 +161,11 @@
   if("${LLVM_NATIVE_ARCH}" STREQUAL "X86")
     if(NOT MSVC)
       test_target_arch(x86_64 "" "-m64")
+      # FIXME: We build runtimes for both i686 and i386, as "clang -m32" may
+      # target different variant than "$CMAKE_C_COMPILER -m32". This part should
+      # be gone after we resolve PR14109.
       test_target_arch(i686 __i686__ "-m32")
-      if(NOT CAN_TARGET_i686)
-        test_target_arch(i386 __i386__ "-m32")
-      endif()
+      test_target_arch(i386 __i386__ "-m32")
     else()
       test_target_arch(i386 "" "")
     endif()
@@ -220,14 +221,14 @@
 # Architectures supported by compiler-rt libraries.
 filter_available_targets(SANITIZER_COMMON_SUPPORTED_ARCH
   x86_64 i386 i686 powerpc64 powerpc64le arm aarch64 mips mips64 mipsel mips64el)
-filter_available_targets(ASAN_SUPPORTED_ARCH
-  x86_64 i386 i686 powerpc64 powerpc64le arm mips mipsel mips64 mips64el)
-filter_available_targets(DFSAN_SUPPORTED_ARCH x86_64 mips64 mips64el)
-filter_available_targets(LSAN_SUPPORTED_ARCH x86_64 mips64 mips64el)
 # LSan common files should be available on all architectures supported
 # by other sanitizers (even if they build into dummy object files).
 filter_available_targets(LSAN_COMMON_SUPPORTED_ARCH
   ${SANITIZER_COMMON_SUPPORTED_ARCH})
+filter_available_targets(ASAN_SUPPORTED_ARCH
+  x86_64 i386 i686 powerpc64 powerpc64le arm mips mipsel mips64 mips64el)
+filter_available_targets(DFSAN_SUPPORTED_ARCH x86_64 mips64 mips64el)
+filter_available_targets(LSAN_SUPPORTED_ARCH x86_64 mips64 mips64el)
 filter_available_targets(MSAN_SUPPORTED_ARCH x86_64 mips64 mips64el)
 filter_available_targets(PROFILE_SUPPORTED_ARCH x86_64 i386 i686 arm mips mips64
   mipsel mips64el aarch64 powerpc64 powerpc64le)
@@ -276,13 +277,6 @@
   set(COMPILER_RT_HAS_LSAN FALSE)
 endif()
 
-if (COMPILER_RT_HAS_SANITIZER_COMMON AND LSAN_COMMON_SUPPORTED_ARCH AND
-    OS_NAME MATCHES "Darwin|Linux|FreeBSD|Android")
-  set(COMPILER_RT_HAS_LSAN_COMMON TRUE)
-else()
-  set(COMPILER_RT_HAS_LSAN_COMMON FALSE)
-endif()
-
 if (COMPILER_RT_HAS_SANITIZER_COMMON AND MSAN_SUPPORTED_ARCH AND
     OS_NAME MATCHES "Linux")
   set(COMPILER_RT_HAS_MSAN TRUE)
diff --git a/include/sanitizer/coverage_interface.h b/include/sanitizer/coverage_interface.h
index 88a7e48..404b71e 100644
--- a/include/sanitizer/coverage_interface.h
+++ b/include/sanitizer/coverage_interface.h
@@ -39,6 +39,23 @@
   // Some of the entries in *data will be zero.
   uintptr_t __sanitizer_get_coverage_guards(uintptr_t **data);
 
+  // The coverage instrumentation may optionally provide imprecise counters.
+  // Rather than exposing the counter values to the user we instead map
+  // the counters to a bitset.
+  // Every counter is associated with 8 bits in the bitset.
+  // We define 8 value ranges: 1, 2, 3, 4-7, 8-15, 16-31, 32-127, 128+
+  // The i-th bit is set to 1 if the counter value is in the i-th range.
+  // This counter-based coverage implementation is *not* thread-safe.
+
+  // Returns the number of registered coverage counters.
+  uintptr_t __sanitizer_get_number_of_counters();
+  // Updates the counter 'bitset', clears the counters and returns the number of
+  // new bits in 'bitset'.
+  // If 'bitset' is nullptr, only clears the counters.
+  // Otherwise 'bitset' should be at least
+  // __sanitizer_get_number_of_counters bytes long and 8-aligned.
+  uintptr_t
+  __sanitizer_update_counter_bitset_and_clear_counters(uint8_t *bitset);
 #ifdef __cplusplus
 }  // extern "C"
 #endif
diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt
index 6929e68..91a7037 100644
--- a/lib/CMakeLists.txt
+++ b/lib/CMakeLists.txt
@@ -7,6 +7,7 @@
 if(COMPILER_RT_HAS_SANITIZER_COMMON)
   add_subdirectory(interception)
   add_subdirectory(sanitizer_common)
+  add_subdirectory(lsan)
 endif()
 
 if(COMPILER_RT_HAS_ASAN)
@@ -19,10 +20,6 @@
   add_subdirectory(dfsan)
 endif()
 
-if(COMPILER_RT_HAS_LSAN OR COMPILER_RT_HAS_LSAN_COMMON)
-  add_subdirectory(lsan)
-endif()
-
 if(COMPILER_RT_HAS_MSAN)
   add_subdirectory(msan)
 endif()
diff --git a/lib/asan/Android.mk b/lib/asan/Android.mk
index 4314c02..ccb4545 100644
--- a/lib/asan/Android.mk
+++ b/lib/asan/Android.mk
@@ -79,6 +79,7 @@
   ../sanitizer_common/sanitizer_symbolizer_libbacktrace.cc \
   ../sanitizer_common/sanitizer_symbolizer_libcdep.cc \
   ../sanitizer_common/sanitizer_symbolizer_posix_libcdep.cc \
+  ../sanitizer_common/sanitizer_symbolizer_process_libcdep.cc \
   ../sanitizer_common/sanitizer_symbolizer_win.cc \
   ../sanitizer_common/sanitizer_thread_registry.cc \
   ../sanitizer_common/sanitizer_tls_get_addr.cc \
diff --git a/lib/asan/CMakeLists.txt b/lib/asan/CMakeLists.txt
index 90cb6f8..8b771fb 100644
--- a/lib/asan/CMakeLists.txt
+++ b/lib/asan/CMakeLists.txt
@@ -106,12 +106,8 @@
     set(ASAN_COMMON_RUNTIME_OBJECTS
       $<TARGET_OBJECTS:RTInterception.${arch}>
       $<TARGET_OBJECTS:RTSanitizerCommon.${arch}>
-      $<TARGET_OBJECTS:RTSanitizerCommonLibc.${arch}>)
-    if(NOT WIN32)
-      # We can't build Leak Sanitizer on Windows yet.
-      list(APPEND ASAN_COMMON_RUNTIME_OBJECTS
-           $<TARGET_OBJECTS:RTLSanCommon.${arch}>)
-    endif()
+      $<TARGET_OBJECTS:RTSanitizerCommonLibc.${arch}>
+      $<TARGET_OBJECTS:RTLSanCommon.${arch}>)
 
     add_compiler_rt_runtime(clang_rt.asan-${arch} ${arch} STATIC
       SOURCES $<TARGET_OBJECTS:RTAsan_preinit.${arch}>
diff --git a/lib/asan/asan_globals.cc b/lib/asan/asan_globals.cc
index 853a181..8906d1e 100644
--- a/lib/asan/asan_globals.cc
+++ b/lib/asan/asan_globals.cc
@@ -212,20 +212,6 @@
   }
 }
 
-#if SANITIZER_WINDOWS  // Should only be called on Windows.
-SANITIZER_INTERFACE_ATTRIBUTE
-void UnregisterGlobalsInRange(void *beg, void *end) {
-  if (!flags()->report_globals)
-    return;
-  BlockingMutexLock lock(&mu_for_globals);
-  for (ListOfGlobals *l = list_of_all_globals; l; l = l->next) {
-    void *address = (void *)l->g->beg;
-    if (beg <= address && address < end)
-      UnregisterGlobal(l->g);
-  }
-}
-#endif
-
 }  // namespace __asan
 
 // ---------------------- Interface ---------------- {{{1
diff --git a/lib/asan/asan_interceptors.cc b/lib/asan/asan_interceptors.cc
index df57696..585181c 100644
--- a/lib/asan/asan_interceptors.cc
+++ b/lib/asan/asan_interceptors.cc
@@ -65,7 +65,7 @@
       }                                                                 \
       if (!suppressed) {                                                \
         GET_CURRENT_PC_BP_SP;                                           \
-        __asan_report_error(pc, bp, sp, __bad, isWrite, __size);        \
+        __asan_report_error(pc, bp, sp, __bad, isWrite, __size, 0);     \
       }                                                                 \
     }                                                                   \
   } while (0)
@@ -120,17 +120,6 @@
 DECLARE_REAL_AND_INTERCEPTOR(void *, malloc, uptr)
 DECLARE_REAL_AND_INTERCEPTOR(void, free, void *)
 
-#if !SANITIZER_MAC
-#define ASAN_INTERCEPT_FUNC(name)                                        \
-  do {                                                                   \
-    if ((!INTERCEPT_FUNCTION(name) || !REAL(name)))                      \
-      VReport(1, "AddressSanitizer: failed to intercept '" #name "'\n"); \
-  } while (0)
-#else
-// OS X interceptors don't need to be initialized with INTERCEPT_FUNCTION.
-#define ASAN_INTERCEPT_FUNC(name)
-#endif  // SANITIZER_MAC
-
 #define ASAN_INTERCEPTOR_ENTER(ctx, func)                                      \
   AsanInterceptorContext _ctx = {#func};                                       \
   ctx = (void *)&_ctx;                                                         \
@@ -206,12 +195,6 @@
 };
 
 static thread_return_t THREAD_CALLING_CONV asan_thread_start(void *arg) {
-#if SANITIZER_WINDOWS
-  // FIXME: this is a bandaid fix for PR22025.
-  AsanThread *t = (AsanThread*)arg;
-  SetCurrentThread(t);
-  return t->ThreadStart(GetTid(), /* signal_thread_is_registered */ nullptr);
-#else
   ThreadStartParam *param = reinterpret_cast<ThreadStartParam *>(arg);
   AsanThread *t = nullptr;
   while ((t = reinterpret_cast<AsanThread *>(
@@ -219,7 +202,6 @@
     internal_sched_yield();
   SetCurrentThread(t);
   return t->ThreadStart(GetTid(), &param->is_registered);
-#endif
 }
 
 #if ASAN_INTERCEPT_PTHREAD_CREATE
@@ -363,30 +345,6 @@
 }
 #endif
 
-#if SANITIZER_WINDOWS
-INTERCEPTOR_WINAPI(void, RaiseException, void *a, void *b, void *c, void *d) {
-  CHECK(REAL(RaiseException));
-  __asan_handle_no_return();
-  REAL(RaiseException)(a, b, c, d);
-}
-
-INTERCEPTOR(int, _except_handler3, void *a, void *b, void *c, void *d) {
-  CHECK(REAL(_except_handler3));
-  __asan_handle_no_return();
-  return REAL(_except_handler3)(a, b, c, d);
-}
-
-#if ASAN_DYNAMIC
-// This handler is named differently in -MT and -MD CRTs.
-#define _except_handler4 _except_handler4_common
-#endif
-INTERCEPTOR(int, _except_handler4, void *a, void *b, void *c, void *d) {
-  CHECK(REAL(_except_handler4));
-  __asan_handle_no_return();
-  return REAL(_except_handler4)(a, b, c, d);
-}
-#endif
-
 static inline int CharCmp(unsigned char c1, unsigned char c2) {
   return (c1 == c2) ? 0 : (c1 < c2) ? -1 : 1;
 }
@@ -813,36 +771,6 @@
 }
 #endif  // ASAN_INTERCEPT_FORK
 
-#if SANITIZER_WINDOWS
-INTERCEPTOR_WINAPI(DWORD, CreateThread,
-                   void* security, uptr stack_size,
-                   DWORD (__stdcall *start_routine)(void*), void* arg,
-                   DWORD thr_flags, void* tid) {
-  // Strict init-order checking is thread-hostile.
-  if (flags()->strict_init_order)
-    StopInitOrderChecking();
-  GET_STACK_TRACE_THREAD;
-  // FIXME: The CreateThread interceptor is not the same as a pthread_create
-  // one.  This is a bandaid fix for PR22025.
-  bool detached = false;  // FIXME: how can we determine it on Windows?
-  u32 current_tid = GetCurrentTidOrInvalid();
-  AsanThread *t =
-        AsanThread::Create(start_routine, arg, current_tid, &stack, detached);
-  return REAL(CreateThread)(security, stack_size,
-                            asan_thread_start, t, thr_flags, tid);
-}
-
-namespace __asan {
-void InitializeWindowsInterceptors() {
-  ASAN_INTERCEPT_FUNC(CreateThread);
-  ASAN_INTERCEPT_FUNC(RaiseException);
-  ASAN_INTERCEPT_FUNC(_except_handler3);
-  ASAN_INTERCEPT_FUNC(_except_handler4);
-}
-
-}  // namespace __asan
-#endif
-
 // ---------------------- InitializeAsanInterceptors ---------------- {{{1
 namespace __asan {
 void InitializeAsanInterceptors() {
@@ -925,10 +853,7 @@
   ASAN_INTERCEPT_FUNC(fork);
 #endif
 
-  // Some Windows-specific interceptors.
-#if SANITIZER_WINDOWS
-  InitializeWindowsInterceptors();
-#endif
+  InitializePlatformInterceptors();
 
   VReport(1, "AddressSanitizer: libc interceptors initialized\n");
 }
diff --git a/lib/asan/asan_interceptors.h b/lib/asan/asan_interceptors.h
index ee3b82a..488ada7 100644
--- a/lib/asan/asan_interceptors.h
+++ b/lib/asan/asan_interceptors.h
@@ -92,9 +92,21 @@
 DECLARE_REAL(int, sigaction, int signum, const struct sigaction *act,
                              struct sigaction *oldact)
 
+#if !SANITIZER_MAC
+#define ASAN_INTERCEPT_FUNC(name)                                        \
+  do {                                                                   \
+    if ((!INTERCEPT_FUNCTION(name) || !REAL(name)))                      \
+      VReport(1, "AddressSanitizer: failed to intercept '" #name "'\n"); \
+  } while (0)
+#else
+// OS X interceptors don't need to be initialized with INTERCEPT_FUNCTION.
+#define ASAN_INTERCEPT_FUNC(name)
+#endif  // SANITIZER_MAC
+
 namespace __asan {
 
 void InitializeAsanInterceptors();
+void InitializePlatformInterceptors();
 
 #define ENSURE_ASAN_INITED() do { \
   CHECK(!asan_init_is_running); \
diff --git a/lib/asan/asan_interface_internal.h b/lib/asan/asan_interface_internal.h
index ea7540f..8ed4ee3 100644
--- a/lib/asan/asan_interface_internal.h
+++ b/lib/asan/asan_interface_internal.h
@@ -128,7 +128,7 @@
 
   SANITIZER_INTERFACE_ATTRIBUTE
   void __asan_report_error(uptr pc, uptr bp, uptr sp,
-                           uptr addr, int is_write, uptr access_size);
+                           uptr addr, int is_write, uptr access_size, u32 exp);
 
   SANITIZER_INTERFACE_ATTRIBUTE
   int __asan_set_error_exit_code(int exit_code);
@@ -165,6 +165,21 @@
   SANITIZER_INTERFACE_ATTRIBUTE void __asan_loadN(uptr p, uptr size);
   SANITIZER_INTERFACE_ATTRIBUTE void __asan_storeN(uptr p, uptr size);
 
+  SANITIZER_INTERFACE_ATTRIBUTE void __asan_exp_load1(uptr p, u32 exp);
+  SANITIZER_INTERFACE_ATTRIBUTE void __asan_exp_load2(uptr p, u32 exp);
+  SANITIZER_INTERFACE_ATTRIBUTE void __asan_exp_load4(uptr p, u32 exp);
+  SANITIZER_INTERFACE_ATTRIBUTE void __asan_exp_load8(uptr p, u32 exp);
+  SANITIZER_INTERFACE_ATTRIBUTE void __asan_exp_load16(uptr p, u32 exp);
+  SANITIZER_INTERFACE_ATTRIBUTE void __asan_exp_store1(uptr p, u32 exp);
+  SANITIZER_INTERFACE_ATTRIBUTE void __asan_exp_store2(uptr p, u32 exp);
+  SANITIZER_INTERFACE_ATTRIBUTE void __asan_exp_store4(uptr p, u32 exp);
+  SANITIZER_INTERFACE_ATTRIBUTE void __asan_exp_store8(uptr p, u32 exp);
+  SANITIZER_INTERFACE_ATTRIBUTE void __asan_exp_store16(uptr p, u32 exp);
+  SANITIZER_INTERFACE_ATTRIBUTE void __asan_exp_loadN(uptr p, uptr size,
+                                                      u32 exp);
+  SANITIZER_INTERFACE_ATTRIBUTE void __asan_exp_storeN(uptr p, uptr size,
+                                                       u32 exp);
+
   SANITIZER_INTERFACE_ATTRIBUTE
       void* __asan_memcpy(void *dst, const void *src, uptr size);
   SANITIZER_INTERFACE_ATTRIBUTE
diff --git a/lib/asan/asan_internal.h b/lib/asan/asan_internal.h
index ffd3ff8..394e460 100644
--- a/lib/asan/asan_internal.h
+++ b/lib/asan/asan_internal.h
@@ -62,21 +62,6 @@
 class AsanThread;
 using __sanitizer::StackTrace;
 
-struct SignalContext {
-  void *context;
-  uptr addr;
-  uptr pc;
-  uptr sp;
-  uptr bp;
-
-  SignalContext(void *context, uptr addr, uptr pc, uptr sp, uptr bp) :
-      context(context), addr(addr), pc(pc), sp(sp), bp(bp) {
-  }
-
-  // Creates signal context in a platform-specific manner.
-  static SignalContext Create(void *siginfo, void *context);
-};
-
 void AsanInitFromRtl();
 
 // asan_rtl.cc
@@ -90,7 +75,6 @@
 void AsanCheckDynamicRTPrereqs();
 void AsanCheckIncompatibleRT();
 
-void GetPcSpBp(void *context, uptr *pc, uptr *sp, uptr *bp);
 void AsanOnSIGSEGV(int, void *siginfo, void *context);
 
 void DisableReexec();
diff --git a/lib/asan/asan_linux.cc b/lib/asan/asan_linux.cc
index 8e8bafd..f4f187f 100644
--- a/lib/asan/asan_linux.cc
+++ b/lib/asan/asan_linux.cc
@@ -68,6 +68,8 @@
 
 namespace __asan {
 
+void InitializePlatformInterceptors() {}
+
 void DisableReexec() {
   // No need to re-exec on Linux.
 }
@@ -152,78 +154,6 @@
 }
 #endif  // SANITIZER_ANDROID
 
-void GetPcSpBp(void *context, uptr *pc, uptr *sp, uptr *bp) {
-#if defined(__arm__)
-  ucontext_t *ucontext = (ucontext_t*)context;
-  *pc = ucontext->uc_mcontext.arm_pc;
-  *bp = ucontext->uc_mcontext.arm_fp;
-  *sp = ucontext->uc_mcontext.arm_sp;
-#elif defined(__aarch64__)
-  ucontext_t *ucontext = (ucontext_t*)context;
-  *pc = ucontext->uc_mcontext.pc;
-  *bp = ucontext->uc_mcontext.regs[29];
-  *sp = ucontext->uc_mcontext.sp;
-#elif defined(__hppa__)
-  ucontext_t *ucontext = (ucontext_t*)context;
-  *pc = ucontext->uc_mcontext.sc_iaoq[0];
-  /* GCC uses %r3 whenever a frame pointer is needed.  */
-  *bp = ucontext->uc_mcontext.sc_gr[3];
-  *sp = ucontext->uc_mcontext.sc_gr[30];
-#elif defined(__x86_64__)
-# if SANITIZER_FREEBSD
-  ucontext_t *ucontext = (ucontext_t*)context;
-  *pc = ucontext->uc_mcontext.mc_rip;
-  *bp = ucontext->uc_mcontext.mc_rbp;
-  *sp = ucontext->uc_mcontext.mc_rsp;
-# else
-  ucontext_t *ucontext = (ucontext_t*)context;
-  *pc = ucontext->uc_mcontext.gregs[REG_RIP];
-  *bp = ucontext->uc_mcontext.gregs[REG_RBP];
-  *sp = ucontext->uc_mcontext.gregs[REG_RSP];
-# endif
-#elif defined(__i386__)
-# if SANITIZER_FREEBSD
-  ucontext_t *ucontext = (ucontext_t*)context;
-  *pc = ucontext->uc_mcontext.mc_eip;
-  *bp = ucontext->uc_mcontext.mc_ebp;
-  *sp = ucontext->uc_mcontext.mc_esp;
-# else
-  ucontext_t *ucontext = (ucontext_t*)context;
-  *pc = ucontext->uc_mcontext.gregs[REG_EIP];
-  *bp = ucontext->uc_mcontext.gregs[REG_EBP];
-  *sp = ucontext->uc_mcontext.gregs[REG_ESP];
-# endif
-#elif defined(__powerpc__) || defined(__powerpc64__)
-  ucontext_t *ucontext = (ucontext_t*)context;
-  *pc = ucontext->uc_mcontext.regs->nip;
-  *sp = ucontext->uc_mcontext.regs->gpr[PT_R1];
-  // The powerpc{,64}-linux ABIs do not specify r31 as the frame
-  // pointer, but GCC always uses r31 when we need a frame pointer.
-  *bp = ucontext->uc_mcontext.regs->gpr[PT_R31];
-#elif defined(__sparc__)
-  ucontext_t *ucontext = (ucontext_t*)context;
-  uptr *stk_ptr;
-# if defined (__arch64__)
-  *pc = ucontext->uc_mcontext.mc_gregs[MC_PC];
-  *sp = ucontext->uc_mcontext.mc_gregs[MC_O6];
-  stk_ptr = (uptr *) (*sp + 2047);
-  *bp = stk_ptr[15];
-# else
-  *pc = ucontext->uc_mcontext.gregs[REG_PC];
-  *sp = ucontext->uc_mcontext.gregs[REG_O6];
-  stk_ptr = (uptr *) *sp;
-  *bp = stk_ptr[15];
-# endif
-#elif defined(__mips__)
-  ucontext_t *ucontext = (ucontext_t*)context;
-  *pc = ucontext->uc_mcontext.gregs[31];
-  *bp = ucontext->uc_mcontext.gregs[30];
-  *sp = ucontext->uc_mcontext.gregs[29];
-#else
-# error "Unsupported arch"
-#endif
-}
-
 void AsanPlatformThreadInit() {
   // Nothing here for now.
 }
diff --git a/lib/asan/asan_mac.cc b/lib/asan/asan_mac.cc
index b353686..b2618d7 100644
--- a/lib/asan/asan_mac.cc
+++ b/lib/asan/asan_mac.cc
@@ -40,19 +40,7 @@
 
 namespace __asan {
 
-void GetPcSpBp(void *context, uptr *pc, uptr *sp, uptr *bp) {
-  ucontext_t *ucontext = (ucontext_t*)context;
-# if SANITIZER_WORDSIZE == 64
-  *pc = ucontext->uc_mcontext->__ss.__rip;
-  *bp = ucontext->uc_mcontext->__ss.__rbp;
-  *sp = ucontext->uc_mcontext->__ss.__rsp;
-# else
-  *pc = ucontext->uc_mcontext->__ss.__eip;
-  *bp = ucontext->uc_mcontext->__ss.__ebp;
-  *sp = ucontext->uc_mcontext->__ss.__esp;
-# endif  // SANITIZER_WORDSIZE
-}
-
+void InitializePlatformInterceptors() {}
 
 bool PlatformHasDifferentMemcpyAndMemmove() {
   // On OS X 10.7 memcpy() and memmove() are both resolved
diff --git a/lib/asan/asan_poisoning.cc b/lib/asan/asan_poisoning.cc
index e2b1f4d..569d359 100644
--- a/lib/asan/asan_poisoning.cc
+++ b/lib/asan/asan_poisoning.cc
@@ -112,7 +112,7 @@
   if (!flags()->allow_user_poisoning || size == 0) return;
   uptr beg_addr = (uptr)addr;
   uptr end_addr = beg_addr + size;
-  VPrintf(1, "Trying to poison memory region [%p, %p)\n", (void *)beg_addr,
+  VPrintf(3, "Trying to poison memory region [%p, %p)\n", (void *)beg_addr,
           (void *)end_addr);
   ShadowSegmentEndpoint beg(beg_addr);
   ShadowSegmentEndpoint end(end_addr);
@@ -152,7 +152,7 @@
   if (!flags()->allow_user_poisoning || size == 0) return;
   uptr beg_addr = (uptr)addr;
   uptr end_addr = beg_addr + size;
-  VPrintf(1, "Trying to unpoison memory region [%p, %p)\n", (void *)beg_addr,
+  VPrintf(3, "Trying to unpoison memory region [%p, %p)\n", (void *)beg_addr,
           (void *)end_addr);
   ShadowSegmentEndpoint beg(beg_addr);
   ShadowSegmentEndpoint end(end_addr);
@@ -218,7 +218,7 @@
         __asan::AddressIsPoisoned(__p + __size - 1))) {       \
       GET_CURRENT_PC_BP_SP;                                   \
       uptr __bad = __asan_region_is_poisoned(__p, __size);    \
-      __asan_report_error(pc, bp, sp, __bad, isWrite, __size);\
+      __asan_report_error(pc, bp, sp, __bad, isWrite, __size, 0);\
     }                                                         \
   } while (false);                                            \
 
diff --git a/lib/asan/asan_posix.cc b/lib/asan/asan_posix.cc
index ad31458..4652dde 100644
--- a/lib/asan/asan_posix.cc
+++ b/lib/asan/asan_posix.cc
@@ -32,13 +32,6 @@
 
 namespace __asan {
 
-SignalContext SignalContext::Create(void *siginfo, void *context) {
-  uptr addr = (uptr)((siginfo_t*)siginfo)->si_addr;
-  uptr pc, sp, bp;
-  GetPcSpBp(context, &pc, &sp, &bp);
-  return SignalContext(context, addr, pc, sp, bp);
-}
-
 void AsanOnSIGSEGV(int, void *siginfo, void *context) {
   ScopedDeadlySignal signal_scope(GetCurrentThread());
   int code = (int)((siginfo_t*)siginfo)->si_code;
diff --git a/lib/asan/asan_report.cc b/lib/asan/asan_report.cc
index ad75262..c1c340c 100644
--- a/lib/asan/asan_report.cc
+++ b/lib/asan/asan_report.cc
@@ -939,9 +939,18 @@
 using namespace __asan;  // NOLINT
 
 void __asan_report_error(uptr pc, uptr bp, uptr sp, uptr addr, int is_write,
-                         uptr access_size) {
+                         uptr access_size, u32 exp) {
   ENABLE_FRAME_POINTER;
 
+  // Optimization experiments.
+  // The experiments can be used to evaluate potential optimizations that remove
+  // instrumentation (assess false negatives). Instead of completely removing
+  // some instrumentation, compiler can emit special calls into runtime
+  // (e.g. __asan_report_exp_load1 instead of __asan_report_load1) and pass
+  // mask of experiments (exp).
+  // The reaction to a non-zero value of exp is to be defined.
+  (void)exp;
+
   // Determine the error type.
   const char *bug_descr = "unknown-crash";
   if (AddrIsInMem(addr)) {
diff --git a/lib/asan/asan_rtl.cc b/lib/asan/asan_rtl.cc
index 9126e71..f346615 100644
--- a/lib/asan/asan_rtl.cc
+++ b/lib/asan/asan_rtl.cc
@@ -112,11 +112,15 @@
 // -------------------------- Run-time entry ------------------- {{{1
 // exported functions
 #define ASAN_REPORT_ERROR(type, is_write, size)                     \
-extern "C" NOINLINE INTERFACE_ATTRIBUTE                        \
-void __asan_report_ ## type ## size(uptr addr);                \
-void __asan_report_ ## type ## size(uptr addr) {               \
+extern "C" NOINLINE INTERFACE_ATTRIBUTE                             \
+void __asan_report_ ## type ## size(uptr addr) {                    \
   GET_CALLER_PC_BP_SP;                                              \
-  __asan_report_error(pc, bp, sp, addr, is_write, size);            \
+  __asan_report_error(pc, bp, sp, addr, is_write, size, 0);         \
+}                                                                   \
+extern "C" NOINLINE INTERFACE_ATTRIBUTE                             \
+void __asan_report_exp_ ## type ## size(uptr addr, u32 exp) {       \
+  GET_CALLER_PC_BP_SP;                                              \
+  __asan_report_error(pc, bp, sp, addr, is_write, size, exp);       \
 }
 
 ASAN_REPORT_ERROR(load, false, 1)
@@ -132,18 +136,20 @@
 
 #define ASAN_REPORT_ERROR_N(type, is_write)                    \
 extern "C" NOINLINE INTERFACE_ATTRIBUTE                        \
-void __asan_report_ ## type ## _n(uptr addr, uptr size);       \
 void __asan_report_ ## type ## _n(uptr addr, uptr size) {      \
   GET_CALLER_PC_BP_SP;                                         \
-  __asan_report_error(pc, bp, sp, addr, is_write, size);       \
+  __asan_report_error(pc, bp, sp, addr, is_write, size, 0);    \
+}                                                              \
+extern "C" NOINLINE INTERFACE_ATTRIBUTE                        \
+void __asan_report_exp_ ## type ## _n(uptr addr, uptr size, u32 exp) {      \
+  GET_CALLER_PC_BP_SP;                                                      \
+  __asan_report_error(pc, bp, sp, addr, is_write, size, exp);               \
 }
 
 ASAN_REPORT_ERROR_N(load, false)
 ASAN_REPORT_ERROR_N(store, true)
 
-#define ASAN_MEMORY_ACCESS_CALLBACK(type, is_write, size)                      \
-  extern "C" NOINLINE INTERFACE_ATTRIBUTE void __asan_##type##size(uptr addr); \
-  void __asan_##type##size(uptr addr) {                                        \
+#define ASAN_MEMORY_ACCESS_CALLBACK_BODY(type, is_write, size, exp_arg)        \
     uptr sp = MEM_TO_SHADOW(addr);                                             \
     uptr s = size <= SHADOW_GRANULARITY ? *reinterpret_cast<u8 *>(sp)          \
                                         : *reinterpret_cast<u16 *>(sp);        \
@@ -155,10 +161,19 @@
           *__asan_test_only_reported_buggy_pointer = addr;                     \
         } else {                                                               \
           GET_CALLER_PC_BP_SP;                                                 \
-          __asan_report_error(pc, bp, sp, addr, is_write, size);               \
+          __asan_report_error(pc, bp, sp, addr, is_write, size, exp_arg);      \
         }                                                                      \
       }                                                                        \
-    }                                                                          \
+    }
+
+#define ASAN_MEMORY_ACCESS_CALLBACK(type, is_write, size)                      \
+  extern "C" NOINLINE INTERFACE_ATTRIBUTE                                      \
+  void __asan_##type##size(uptr addr) {                                        \
+    ASAN_MEMORY_ACCESS_CALLBACK_BODY(type, is_write, size, 0)                  \
+  }                                                                            \
+  extern "C" NOINLINE INTERFACE_ATTRIBUTE                                      \
+  void __asan_exp_##type##size(uptr addr, u32 exp) {                           \
+    ASAN_MEMORY_ACCESS_CALLBACK_BODY(type, is_write, size, exp)                \
   }
 
 ASAN_MEMORY_ACCESS_CALLBACK(load, false, 1)
@@ -173,18 +188,38 @@
 ASAN_MEMORY_ACCESS_CALLBACK(store, true, 16)
 
 extern "C"
-NOINLINE INTERFACE_ATTRIBUTE void __asan_loadN(uptr addr, uptr size) {
+NOINLINE INTERFACE_ATTRIBUTE
+void __asan_loadN(uptr addr, uptr size) {
   if (__asan_region_is_poisoned(addr, size)) {
     GET_CALLER_PC_BP_SP;
-    __asan_report_error(pc, bp, sp, addr, false, size);
+    __asan_report_error(pc, bp, sp, addr, false, size, 0);
   }
 }
 
 extern "C"
-NOINLINE INTERFACE_ATTRIBUTE void __asan_storeN(uptr addr, uptr size) {
+NOINLINE INTERFACE_ATTRIBUTE
+void __asan_exp_loadN(uptr addr, uptr size, u32 exp) {
   if (__asan_region_is_poisoned(addr, size)) {
     GET_CALLER_PC_BP_SP;
-    __asan_report_error(pc, bp, sp, addr, true, size);
+    __asan_report_error(pc, bp, sp, addr, false, size, exp);
+  }
+}
+
+extern "C"
+NOINLINE INTERFACE_ATTRIBUTE
+void __asan_storeN(uptr addr, uptr size) {
+  if (__asan_region_is_poisoned(addr, size)) {
+    GET_CALLER_PC_BP_SP;
+    __asan_report_error(pc, bp, sp, addr, true, size, 0);
+  }
+}
+
+extern "C"
+NOINLINE INTERFACE_ATTRIBUTE
+void __asan_exp_storeN(uptr addr, uptr size, u32 exp) {
+  if (__asan_region_is_poisoned(addr, size)) {
+    GET_CALLER_PC_BP_SP;
+    __asan_report_error(pc, bp, sp, addr, true, size, exp);
   }
 }
 
@@ -203,26 +238,40 @@
     case 3: __asan_report_load4(0); break;
     case 4: __asan_report_load8(0); break;
     case 5: __asan_report_load16(0); break;
-    case 6: __asan_report_store1(0); break;
-    case 7: __asan_report_store2(0); break;
-    case 8: __asan_report_store4(0); break;
-    case 9: __asan_report_store8(0); break;
-    case 10: __asan_report_store16(0); break;
-    case 12: __asan_register_globals(0, 0); break;
-    case 13: __asan_unregister_globals(0, 0); break;
-    case 14: __asan_set_death_callback(0); break;
-    case 15: __asan_set_error_report_callback(0); break;
-    case 16: __asan_handle_no_return(); break;
-    case 17: __asan_address_is_poisoned(0); break;
-    case 25: __asan_poison_memory_region(0, 0); break;
-    case 26: __asan_unpoison_memory_region(0, 0); break;
-    case 27: __asan_set_error_exit_code(0); break;
-    case 30: __asan_before_dynamic_init(0); break;
-    case 31: __asan_after_dynamic_init(); break;
-    case 32: __asan_poison_stack_memory(0, 0); break;
-    case 33: __asan_unpoison_stack_memory(0, 0); break;
-    case 34: __asan_region_is_poisoned(0, 0); break;
-    case 35: __asan_describe_address(0); break;
+    case 6: __asan_report_load_n(0, 0); break;
+    case 7: __asan_report_store1(0); break;
+    case 8: __asan_report_store2(0); break;
+    case 9: __asan_report_store4(0); break;
+    case 10: __asan_report_store8(0); break;
+    case 11: __asan_report_store16(0); break;
+    case 12: __asan_report_store_n(0, 0); break;
+    case 13: __asan_report_exp_load1(0, 0); break;
+    case 14: __asan_report_exp_load2(0, 0); break;
+    case 15: __asan_report_exp_load4(0, 0); break;
+    case 16: __asan_report_exp_load8(0, 0); break;
+    case 17: __asan_report_exp_load16(0, 0); break;
+    case 18: __asan_report_exp_load_n(0, 0, 0); break;
+    case 19: __asan_report_exp_store1(0, 0); break;
+    case 20: __asan_report_exp_store2(0, 0); break;
+    case 21: __asan_report_exp_store4(0, 0); break;
+    case 22: __asan_report_exp_store8(0, 0); break;
+    case 23: __asan_report_exp_store16(0, 0); break;
+    case 24: __asan_report_exp_store_n(0, 0, 0); break;
+    case 25: __asan_register_globals(0, 0); break;
+    case 26: __asan_unregister_globals(0, 0); break;
+    case 27: __asan_set_death_callback(0); break;
+    case 28: __asan_set_error_report_callback(0); break;
+    case 29: __asan_handle_no_return(); break;
+    case 30: __asan_address_is_poisoned(0); break;
+    case 31: __asan_poison_memory_region(0, 0); break;
+    case 32: __asan_unpoison_memory_region(0, 0); break;
+    case 33: __asan_set_error_exit_code(0); break;
+    case 34: __asan_before_dynamic_init(0); break;
+    case 35: __asan_after_dynamic_init(); break;
+    case 36: __asan_poison_stack_memory(0, 0); break;
+    case 37: __asan_unpoison_stack_memory(0, 0); break;
+    case 38: __asan_region_is_poisoned(0, 0); break;
+    case 39: __asan_describe_address(0); break;
   }
 }
 
diff --git a/lib/asan/asan_suppressions.cc b/lib/asan/asan_suppressions.cc
index 3f76e20..41887b5 100644
--- a/lib/asan/asan_suppressions.cc
+++ b/lib/asan/asan_suppressions.cc
@@ -81,14 +81,10 @@
     uptr addr = stack->trace[i];
 
     if (suppression_ctx->HasSuppressionType(kInterceptorViaLibrary)) {
-      const char *module_name;
-      uptr module_offset;
       // Match "interceptor_via_lib" suppressions.
-      if (symbolizer->GetModuleNameAndOffsetForPC(addr, &module_name,
-                                                  &module_offset) &&
-          suppression_ctx->Match(module_name, kInterceptorViaLibrary, &s)) {
-        return true;
-      }
+      if (const char *module_name = symbolizer->GetModuleNameForPc(addr))
+        if (suppression_ctx->Match(module_name, kInterceptorViaLibrary, &s))
+          return true;
     }
 
     if (suppression_ctx->HasSuppressionType(kInterceptorViaFunction)) {
diff --git a/lib/asan/asan_win.cc b/lib/asan/asan_win.cc
index 5b1d0da..addb3d4 100644
--- a/lib/asan/asan_win.cc
+++ b/lib/asan/asan_win.cc
@@ -22,10 +22,13 @@
 #include "asan_interceptors.h"
 #include "asan_internal.h"
 #include "asan_report.h"
+#include "asan_stack.h"
 #include "asan_thread.h"
 #include "sanitizer_common/sanitizer_libc.h"
 #include "sanitizer_common/sanitizer_mutex.h"
 
+using namespace __asan;  // NOLINT
+
 extern "C" {
 SANITIZER_INTERFACE_ATTRIBUTE
 int __asan_should_detect_stack_use_after_return() {
@@ -33,6 +36,7 @@
   return __asan_option_detect_stack_use_after_return;
 }
 
+// -------------------- A workaround for the abscence of weak symbols ----- {{{
 // We don't have a direct equivalent of weak symbols when using MSVC, but we can
 // use the /alternatename directive to tell the linker to default a specific
 // symbol to a specific value, which works nicely for allocator hooks and
@@ -47,11 +51,105 @@
 #pragma comment(linker, "/alternatename:___asan_default_options=___asan_default_default_options")    // NOLINT
 #pragma comment(linker, "/alternatename:___asan_default_suppressions=___asan_default_default_suppressions")    // NOLINT
 #pragma comment(linker, "/alternatename:___asan_on_error=___asan_default_on_error")                  // NOLINT
+// }}}
 }  // extern "C"
 
+// ---------------------- Windows-specific inteceptors ---------------- {{{
+INTERCEPTOR_WINAPI(void, RaiseException, void *a, void *b, void *c, void *d) {
+  CHECK(REAL(RaiseException));
+  __asan_handle_no_return();
+  REAL(RaiseException)(a, b, c, d);
+}
+
+INTERCEPTOR(int, _except_handler3, void *a, void *b, void *c, void *d) {
+  CHECK(REAL(_except_handler3));
+  __asan_handle_no_return();
+  return REAL(_except_handler3)(a, b, c, d);
+}
+
+#if ASAN_DYNAMIC
+// This handler is named differently in -MT and -MD CRTs.
+#define _except_handler4 _except_handler4_common
+#endif
+INTERCEPTOR(int, _except_handler4, void *a, void *b, void *c, void *d) {
+  CHECK(REAL(_except_handler4));
+  __asan_handle_no_return();
+  return REAL(_except_handler4)(a, b, c, d);
+}
+
+static thread_return_t THREAD_CALLING_CONV asan_thread_start(void *arg) {
+  AsanThread *t = (AsanThread*)arg;
+  SetCurrentThread(t);
+  return t->ThreadStart(GetTid(), /* signal_thread_is_registered */ nullptr);
+}
+
+INTERCEPTOR_WINAPI(DWORD, CreateThread,
+                   void* security, uptr stack_size,
+                   DWORD (__stdcall *start_routine)(void*), void* arg,
+                   DWORD thr_flags, void* tid) {
+  // Strict init-order checking is thread-hostile.
+  if (flags()->strict_init_order)
+    StopInitOrderChecking();
+  GET_STACK_TRACE_THREAD;
+  // FIXME: The CreateThread interceptor is not the same as a pthread_create
+  // one.  This is a bandaid fix for PR22025.
+  bool detached = false;  // FIXME: how can we determine it on Windows?
+  u32 current_tid = GetCurrentTidOrInvalid();
+  AsanThread *t =
+        AsanThread::Create(start_routine, arg, current_tid, &stack, detached);
+  return REAL(CreateThread)(security, stack_size,
+                            asan_thread_start, t, thr_flags, tid);
+}
+
+namespace {
+BlockingMutex mu_for_thread_tracking(LINKER_INITIALIZED);
+
+void EnsureWorkerThreadRegistered() {
+  // FIXME: GetCurrentThread relies on TSD, which might not play well with
+  // system thread pools.  We might want to use something like reference
+  // counting to zero out GetCurrentThread() underlying storage when the last
+  // work item finishes?  Or can we disable reclaiming of threads in the pool?
+  BlockingMutexLock l(&mu_for_thread_tracking);
+  if (__asan::GetCurrentThread())
+    return;
+
+  AsanThread *t = AsanThread::Create(
+      /* start_routine */ nullptr, /* arg */ nullptr,
+      /* parent_tid */ -1, /* stack */ nullptr, /* detached */ true);
+  t->Init();
+  asanThreadRegistry().StartThread(t->tid(), 0, 0);
+  SetCurrentThread(t);
+}
+}  // namespace
+
+INTERCEPTOR_WINAPI(DWORD, NtWaitForWorkViaWorkerFactory, DWORD a, DWORD b) {
+  // NtWaitForWorkViaWorkerFactory is called from system worker pool threads to
+  // query work scheduled by BindIoCompletionCallback, QueueUserWorkItem, etc.
+  // System worker pool threads are created at arbitraty point in time and
+  // without using CreateThread, so we wrap NtWaitForWorkViaWorkerFactory
+  // instead and don't register a specific parent_tid/stack.
+  EnsureWorkerThreadRegistered();
+  return REAL(NtWaitForWorkViaWorkerFactory)(a, b);
+}
+
+// }}}
+
 namespace __asan {
 
-// ---------------------- TSD ---------------- {{{1
+void InitializePlatformInterceptors() {
+  ASAN_INTERCEPT_FUNC(CreateThread);
+  ASAN_INTERCEPT_FUNC(RaiseException);
+  ASAN_INTERCEPT_FUNC(_except_handler3);
+  ASAN_INTERCEPT_FUNC(_except_handler4);
+
+  // NtWaitForWorkViaWorkerFactory is always linked dynamically.
+  CHECK(::__interception::OverrideFunction(
+      "NtWaitForWorkViaWorkerFactory",
+      (uptr)WRAP(NtWaitForWorkViaWorkerFactory),
+      (uptr *)&REAL(NtWaitForWorkViaWorkerFactory)));
+}
+
+// ---------------------- TSD ---------------- {{{
 static bool tsd_key_inited = false;
 
 static __declspec(thread) void *fake_tsd = 0;
@@ -74,7 +172,9 @@
 void PlatformTSDDtor(void *tsd) {
   AsanThread::TSDDtor(tsd);
 }
-// ---------------------- Various stuff ---------------- {{{1
+// }}}
+
+// ---------------------- Various stuff ---------------- {{{
 void DisableReexec() {
   // No need to re-exec on Windows.
 }
@@ -108,23 +208,6 @@
 
 static LPTOP_LEVEL_EXCEPTION_FILTER default_seh_handler;
 
-SignalContext SignalContext::Create(void *siginfo, void *context) {
-  EXCEPTION_RECORD *exception_record = (EXCEPTION_RECORD*)siginfo;
-  CONTEXT *context_record = (CONTEXT*)context;
-
-  uptr pc = (uptr)exception_record->ExceptionAddress;
-#ifdef _WIN64
-  uptr bp = (uptr)context_record->Rbp;
-  uptr sp = (uptr)context_record->Rsp;
-#else
-  uptr bp = (uptr)context_record->Ebp;
-  uptr sp = (uptr)context_record->Esp;
-#endif
-  uptr access_addr = exception_record->ExceptionInformation[1];
-
-  return SignalContext(context, access_addr, pc, sp, bp);
-}
-
 static long WINAPI SEHHandler(EXCEPTION_POINTERS *info) {
   EXCEPTION_RECORD *exception_record = info->ExceptionRecord;
   CONTEXT *context = info->ContextRecord;
@@ -177,7 +260,7 @@
 static __declspec(allocate(".CRT$XIZ"))
     int (*__intercept_seh)() = __asan_set_seh_filter;
 #endif
-
+// }}}
 }  // namespace __asan
 
 #endif  // _WIN32
diff --git a/lib/asan/asan_win_dll_thunk.cc b/lib/asan/asan_win_dll_thunk.cc
index 7b94302..0c363fe 100644
--- a/lib/asan/asan_win_dll_thunk.cc
+++ b/lib/asan/asan_win_dll_thunk.cc
@@ -319,6 +319,8 @@
 INTERFACE_FUNCTION(__sanitizer_ptr_sub)
 INTERFACE_FUNCTION(__sanitizer_report_error_summary)
 INTERFACE_FUNCTION(__sanitizer_reset_coverage)
+INTERFACE_FUNCTION(__sanitizer_get_number_of_counters)
+INTERFACE_FUNCTION(__sanitizer_update_counter_bitset_and_clear_counters)
 INTERFACE_FUNCTION(__sanitizer_sandbox_on_notify)
 INTERFACE_FUNCTION(__sanitizer_set_death_callback)
 INTERFACE_FUNCTION(__sanitizer_set_report_path)
diff --git a/lib/asan/asan_win_dynamic_runtime_thunk.cc b/lib/asan/asan_win_dynamic_runtime_thunk.cc
index 1945614..d59f9f5 100644
--- a/lib/asan/asan_win_dynamic_runtime_thunk.cc
+++ b/lib/asan/asan_win_dynamic_runtime_thunk.cc
@@ -15,7 +15,8 @@
 //
 // This includes:
 //  - forwarding the detect_stack_use_after_return runtime option
-//  - installing a custom SEH handler
+//  - working around deficiencies of the MD runtime
+//  - installing a custom SEH handlerx
 //
 //===----------------------------------------------------------------------===//
 
@@ -24,9 +25,13 @@
 // simplifies the build procedure.
 #ifdef ASAN_DYNAMIC_RUNTIME_THUNK
 #include <windows.h>
-#include <psapi.h>
 
-extern "C" {
+// First, declare CRT sections we'll be using in this file
+#pragma section(".CRT$XID", long, read)  // NOLINT
+#pragma section(".CRT$XIZ", long, read)  // NOLINT
+#pragma section(".CRT$XTW", long, read)  // NOLINT
+#pragma section(".CRT$XTY", long, read)  // NOLINT
+
 ////////////////////////////////////////////////////////////////////////////////
 // Define a copy of __asan_option_detect_stack_use_after_return that should be
 // used when linking an MD runtime with a set of object files on Windows.
@@ -38,82 +43,55 @@
 // with a MT or MD runtime and we don't want to use ugly __imp_ names on Windows
 // just to work around this issue, let's clone the a variable that is
 // constant after initialization anyways.
+extern "C" {
 __declspec(dllimport) int __asan_should_detect_stack_use_after_return();
 int __asan_option_detect_stack_use_after_return =
     __asan_should_detect_stack_use_after_return();
 }
 
 ////////////////////////////////////////////////////////////////////////////////
-// For some reason, the MD CRT doesn't call the C/C++ terminators as MT does.
-// To work around this, for each DLL we schedule a call to
-// UnregisterGlobalsInRange atexit() specifying the address range of the DLL
-// image to unregister globals in that range.   We don't do the same
-// for the main module (.exe) as the asan_globals.cc allocator is destroyed
-// by the time UnregisterGlobalsInRange is executed.
-// See PR22545 for the details.
-namespace __asan {
-__declspec(dllimport)
-void UnregisterGlobalsInRange(void *beg, void *end);
-}
+// For some reason, the MD CRT doesn't call the C/C++ terminators during on DLL
+// unload or on exit.  ASan relies on LLVM global_dtors to call
+// __asan_unregister_globals on these events, which unfortunately doesn't work
+// with the MD runtime, see PR22545 for the details.
+// To work around this, for each DLL we schedule a call to UnregisterGlobals
+// using atexit() that calls a small subset of C terminators
+// where LLVM global_dtors is placed.  Fingers crossed, no other C terminators
+// are there.
+extern "C" void __cdecl _initterm(void *a, void *b);
 
 namespace {
-void *this_module_base, *this_module_end;
+__declspec(allocate(".CRT$XTW")) void* before_global_dtors = 0;
+__declspec(allocate(".CRT$XTY")) void* after_global_dtors = 0;
 
 void UnregisterGlobals() {
-  __asan::UnregisterGlobalsInRange(this_module_base, this_module_end);
+  _initterm(&before_global_dtors, &after_global_dtors);
 }
 
 int ScheduleUnregisterGlobals() {
-  HMODULE this_module = 0;
-  // Increments the reference counter of the DLL module, so need to call
-  // FreeLibrary later.
-  if (!GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS,
-                         (LPCTSTR)&UnregisterGlobals, &this_module))
-    return 1;
-
-  // Skip the main module.
-  if (this_module == GetModuleHandle(0))
-    return 0;
-
-  MODULEINFO mi;
-  bool success =
-      GetModuleInformation(GetCurrentProcess(), this_module, &mi, sizeof(mi));
-  if (!FreeLibrary(this_module))
-    return 2;
-  if (!success)
-    return 3;
-
-  this_module_base = mi.lpBaseOfDll;
-  this_module_end = (char*)mi.lpBaseOfDll + mi.SizeOfImage;
-
   return atexit(UnregisterGlobals);
 }
+
+// We need to call 'atexit(UnregisterGlobals);' as early as possible, but after
+// atexit() is initialized (.CRT$XIC).  As this is executed before C++
+// initializers (think ctors for globals), UnregisterGlobals gets executed after
+// dtors for C++ globals.
+__declspec(allocate(".CRT$XID"))
+int (*__asan_schedule_unregister_globals)() = ScheduleUnregisterGlobals;
+
 }  // namespace
 
-///////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
 // ASan SEH handling.
-extern "C" __declspec(dllimport) int __asan_set_seh_filter();
-static int SetSEHFilter() { return __asan_set_seh_filter(); }
-
-///////////////////////////////////////////////////////////////////////////////
-// We schedule some work at start-up by placing callbacks to our code to the
-// list of CRT C initializers.
-//
-// First, declare sections we'll be using:
-#pragma section(".CRT$XID", long, read)  // NOLINT
-#pragma section(".CRT$XIZ", long, read)  // NOLINT
-
-// We need to call 'atexit(UnregisterGlobals);' after atexit() is initialized
-// (.CRT$XIC) but before the C++ constructors (.CRT$XCA).
-__declspec(allocate(".CRT$XID"))
-static int (*__asan_schedule_unregister_globals)() = ScheduleUnregisterGlobals;
-
 // We need to set the ASan-specific SEH handler at the end of CRT initialization
 // of each module (see also asan_win.cc).
-//
+extern "C" {
+__declspec(dllimport) int __asan_set_seh_filter();
+static int SetSEHFilter() { return __asan_set_seh_filter(); }
+
 // Unfortunately, putting a pointer to __asan_set_seh_filter into
 // __asan_intercept_seh gets optimized out, so we have to use an extra function.
-extern "C" __declspec(allocate(".CRT$XIZ"))
-int (*__asan_seh_interceptor)() = SetSEHFilter;
+__declspec(allocate(".CRT$XIZ")) int (*__asan_seh_interceptor)() = SetSEHFilter;
+}
 
 #endif // ASAN_DYNAMIC_RUNTIME_THUNK
diff --git a/lib/asan/scripts/asan_symbolize.py b/lib/asan/scripts/asan_symbolize.py
index 59fceaa..b9d3ad3 100755
--- a/lib/asan/scripts/asan_symbolize.py
+++ b/lib/asan/scripts/asan_symbolize.py
@@ -23,6 +23,7 @@
 binary_name_filter = None
 fix_filename_patterns = None
 logfile = sys.stdin
+allow_system_symbolizer = True
 
 # FIXME: merge the code that calls fix_filename().
 def fix_filename(file_name):
@@ -392,6 +393,8 @@
           [BreakpadSymbolizerFactory(binary), self.llvm_symbolizers[binary]])
     result = symbolizers[binary].symbolize(addr, binary, offset)
     if result is None:
+      if not allow_system_symbolizer:
+        raise Exception('Failed to launch or use llvm-symbolizer.')
       # Initialize system symbolizer only if other symbolizers failed.
       symbolizers[binary].append_symbolizer(
           SystemSymbolizerFactory(self.system, addr, binary))
diff --git a/lib/asan/tests/asan_asm_test.cc b/lib/asan/tests/asan_asm_test.cc
index 1d8b04d..200de2c 100644
--- a/lib/asan/tests/asan_asm_test.cc
+++ b/lib/asan/tests/asan_asm_test.cc
@@ -232,7 +232,7 @@
   long magic = 0x1234;
   long r = 0x0;
 
-#if defined(__x86_64__)
+#if defined(__x86_64__) && !defined(__ILP32__)
   __asm__("xorq %%rax, %%rax  \n\t"
           "movq (%[p]), %%rax \n\t"
           "sete %%al          \n\t"
@@ -248,7 +248,7 @@
           : [r] "=r"(r)
           : [p] "r"(&magic)
           : "eax", "memory");
-#endif // defined(__x86_64__)
+#endif // defined(__x86_64__) && !defined(__ILP32__)
 
   ASSERT_EQ(0x1, r);
 }
diff --git a/lib/asan/tests/asan_test.cc b/lib/asan/tests/asan_test.cc
index 952b05e..aa08080 100644
--- a/lib/asan/tests/asan_test.cc
+++ b/lib/asan/tests/asan_test.cc
@@ -31,13 +31,13 @@
 
 template<typename T>
 NOINLINE void uaf_test(int size, int off) {
-  char *p = (char *)malloc_aaa(size);
+  void *p = malloc_aaa(size);
   free_aaa(p);
   for (int i = 1; i < 100; i++)
     free_aaa(malloc_aaa(i));
   fprintf(stderr, "writing %ld byte(s) at %p with offset %d\n",
           (long)sizeof(T), p, off);
-  asan_write((T*)(p + off));
+  asan_write((T *)((char *)p + off));
 }
 
 TEST(AddressSanitizer, HasFeatureAddressSanitizerTest) {
@@ -436,10 +436,10 @@
 
 void DoubleFree() {
   int *x = (int*)malloc(100 * sizeof(int));
-  fprintf(stderr, "DoubleFree: x=%p\n", x);
+  fprintf(stderr, "DoubleFree: x=%p\n", (void *)x);
   free(x);
   free(x);
-  fprintf(stderr, "should have failed in the second free(%p)\n", x);
+  fprintf(stderr, "should have failed in the second free(%p)\n", (void *)x);
   abort();
 }
 
@@ -569,17 +569,6 @@
 }
 
 #if !defined(_WIN32)  // Only basic longjmp is available on Windows.
-NOINLINE void BuiltinLongJmpFunc1(jmp_buf buf) {
-  // create three red zones for these two stack objects.
-  int a;
-  int b;
-
-  int *A = Ident(&a);
-  int *B = Ident(&b);
-  *A = *B;
-  __builtin_longjmp((void**)buf, 1);
-}
-
 NOINLINE void UnderscopeLongJmpFunc1(jmp_buf buf) {
   // create three red zones for these two stack objects.
   int a;
@@ -605,6 +594,17 @@
 #if !defined(__ANDROID__) && !defined(__arm__) && \
     !defined(__powerpc64__) && !defined(__powerpc__) && \
     !defined(__aarch64__)
+NOINLINE void BuiltinLongJmpFunc1(jmp_buf buf) {
+  // create three red zones for these two stack objects.
+  int a;
+  int b;
+
+  int *A = Ident(&a);
+  int *B = Ident(&b);
+  *A = *B;
+  __builtin_longjmp((void**)buf, 1);
+}
+
 // Does not work on Power and ARM:
 // https://code.google.com/p/address-sanitizer/issues/detail?id=185
 TEST(AddressSanitizer, BuiltinLongJmpTest) {
@@ -1243,7 +1243,7 @@
   const size_t kAllocSize = (1 << 28) - 1024;
   size_t total_size = 0;
   while (true) {
-    char *x = (char*)malloc(kAllocSize);
+    void *x = malloc(kAllocSize);
     memset(x, 0, kAllocSize);
     total_size += kAllocSize;
     fprintf(stderr, "total: %ldM %p\n", (long)total_size >> 20, x);
diff --git a/lib/builtins/clear_cache.c b/lib/builtins/clear_cache.c
index 8dc0fb1..ede7659 100644
--- a/lib/builtins/clear_cache.c
+++ b/lib/builtins/clear_cache.c
@@ -9,11 +9,12 @@
  */
 
 #include "int_lib.h"
+#include <stddef.h>
 
 #if __APPLE__
   #include <libkern/OSCacheControl.h>
 #endif
-#if defined(__FreeBSD__) && defined(__arm__)
+#if (defined(__FreeBSD__) || defined(__Bitrig__)) && defined(__arm__)
   #include <sys/types.h>
   #include <machine/sysarch.h>
 #endif
@@ -25,6 +26,7 @@
 #if defined(__mips__)
   #include <sys/cachectl.h>
   #include <sys/syscall.h>
+  #include <unistd.h>
   #if defined(__ANDROID__) && defined(__LP64__)
     /*
      * clear_mips_cache - Invalidates instruction cache for Mips.
@@ -89,7 +91,7 @@
  * so there is nothing to do
  */
 #elif defined(__arm__) && !defined(__APPLE__)
-    #if defined(__FreeBSD__) || defined(__NetBSD__)
+    #if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__Bitrig__)
         struct arm_sync_icache_args arg;
 
         arg.addr = (uintptr_t)start;
@@ -126,6 +128,7 @@
 #elif defined(__aarch64__) && !defined(__APPLE__)
   uint64_t xstart = (uint64_t)(uintptr_t) start;
   uint64_t xend = (uint64_t)(uintptr_t) end;
+  uint64_t addr;
 
   // Get Cache Type Info
   uint64_t ctr_el0;
@@ -136,12 +139,12 @@
    * uintptr_t in case this runs in an IPL32 environment.
    */
   const size_t dcache_line_size = 4 << ((ctr_el0 >> 16) & 15);
-  for (uint64_t addr = xstart; addr < xend; addr += dcache_line_size)
+  for (addr = xstart; addr < xend; addr += dcache_line_size)
     __asm __volatile("dc cvau, %0" :: "r"(addr));
   __asm __volatile("dsb ish");
 
   const size_t icache_line_size = 4 << ((ctr_el0 >> 0) & 15);
-  for (uint64_t addr = xstart; addr < xend; addr += icache_line_size)
+  for (addr = xstart; addr < xend; addr += icache_line_size)
     __asm __volatile("ic ivau, %0" :: "r"(addr));
   __asm __volatile("isb sy");
 #else
diff --git a/lib/builtins/fixdfdi.c b/lib/builtins/fixdfdi.c
index 86f9f6c..67b124a 100644
--- a/lib/builtins/fixdfdi.c
+++ b/lib/builtins/fixdfdi.c
@@ -6,40 +6,17 @@
  * Source Licenses. See LICENSE.TXT for details.
  *
  * ===----------------------------------------------------------------------===
- *
- * This file implements __fixdfdi for the compiler_rt library.
- *
- * ===----------------------------------------------------------------------===
  */
 
-#include "int_lib.h"
-
-/* Returns: convert a to a signed long long, rounding toward zero. */
-
-/* Assumption: double is a IEEE 64 bit floating point type 
- *            su_int is a 32 bit integral type
- *            value in double is representable in di_int (no range checking performed)
- */
-
-/* seee eeee eeee mmmm mmmm mmmm mmmm mmmm | mmmm mmmm mmmm mmmm mmmm mmmm mmmm mmmm */
-
+#define DOUBLE_PRECISION
+#include "fp_lib.h"
 ARM_EABI_FNALIAS(d2lz, fixdfdi)
 
+typedef di_int fixint_t;
+typedef du_int fixuint_t;
+#include "fp_fixint_impl.inc"
+
 COMPILER_RT_ABI di_int
-__fixdfdi(double a)
-{
-    double_bits fb;
-    fb.f = a;
-    int e = ((fb.u.s.high & 0x7FF00000) >> 20) - 1023;
-    if (e < 0)
-        return 0;
-    di_int s = (si_int)(fb.u.s.high & 0x80000000) >> 31;
-    dwords r;
-    r.s.high = (fb.u.s.high & 0x000FFFFF) | 0x00100000;
-    r.s.low = fb.u.s.low;
-    if (e > 52)
-        r.all <<= (e - 52);
-    else
-        r.all >>= (52 - e);
-    return (r.all ^ s) - s;
-} 
+__fixdfdi(fp_t a) {
+    return __fixint(a);
+}
diff --git a/lib/builtins/fixdfsi.c b/lib/builtins/fixdfsi.c
index 88b2ff5..704e65b 100644
--- a/lib/builtins/fixdfsi.c
+++ b/lib/builtins/fixdfsi.c
@@ -1,50 +1,22 @@
-//===-- lib/fixdfsi.c - Double-precision -> integer conversion ----*- C -*-===//
-//
-//                     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 implements double-precision to integer conversion for the
-// compiler-rt library.  No range checking is performed; the behavior of this
-// conversion is undefined for out of range values in the C standard.
-//
-//===----------------------------------------------------------------------===//
+/* ===-- fixdfsi.c - Implement __fixdfsi -----------------------------------===
+ *
+ *                     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.
+ *
+ * ===----------------------------------------------------------------------===
+ */
 
 #define DOUBLE_PRECISION
 #include "fp_lib.h"
-
-#include "int_lib.h"
+typedef si_int fixint_t;
+typedef su_int fixuint_t;
+#include "fp_fixint_impl.inc"
 
 ARM_EABI_FNALIAS(d2iz, fixdfsi)
 
-COMPILER_RT_ABI int
+COMPILER_RT_ABI si_int
 __fixdfsi(fp_t a) {
-    
-    // Break a into sign, exponent, significand
-    const rep_t aRep = toRep(a);
-    const rep_t aAbs = aRep & absMask;
-    const int sign = aRep & signBit ? -1 : 1;
-    const int exponent = (aAbs >> significandBits) - exponentBias;
-    const rep_t significand = (aAbs & significandMask) | implicitBit;
-    
-    // If 0 < exponent < significandBits, right shift to get the result.
-    if ((unsigned int)exponent < significandBits) {
-        return sign * (significand >> (significandBits - exponent));
-    }
-    
-    // If exponent is negative, the result is zero.
-    else if (exponent < 0) {
-        return 0;
-    }
-    
-    // If significandBits < exponent, left shift to get the result.  This shift
-    // may end up being larger than the type width, which incurs undefined
-    // behavior, but the conversion itself is undefined in that case, so
-    // whatever the compiler decides to do is fine.
-    else {
-        return sign * (significand << (exponent - significandBits));
-    }
+    return __fixint(a);
 }
diff --git a/lib/builtins/fixdfti.c b/lib/builtins/fixdfti.c
index 2c27f4b..aaf225e 100644
--- a/lib/builtins/fixdfti.c
+++ b/lib/builtins/fixdfti.c
@@ -6,40 +6,21 @@
  * Source Licenses. See LICENSE.TXT for details.
  *
  * ===----------------------------------------------------------------------===
- *
- * This file implements __fixdfti for the compiler_rt library.
- *
- * ===----------------------------------------------------------------------===
  */
 
 #include "int_lib.h"
 
 #ifdef CRT_HAS_128BIT
+#define DOUBLE_PRECISION
+#include "fp_lib.h"
 
-/* Returns: convert a to a signed long long, rounding toward zero. */
-
-/* Assumption: double is a IEEE 64 bit floating point type 
- *             su_int is a 32 bit integral type
- *             value in double is representable in ti_int (no range checking performed)
- */
-
-/* seee eeee eeee mmmm mmmm mmmm mmmm mmmm | mmmm mmmm mmmm mmmm mmmm mmmm mmmm mmmm */
+typedef ti_int fixint_t;
+typedef tu_int fixuint_t;
+#include "fp_fixint_impl.inc"
 
 COMPILER_RT_ABI ti_int
-__fixdfti(double a)
-{
-    double_bits fb;
-    fb.f = a;
-    int e = ((fb.u.s.high & 0x7FF00000) >> 20) - 1023;
-    if (e < 0)
-        return 0;
-    ti_int s = (si_int)(fb.u.s.high & 0x80000000) >> 31;
-    ti_int r = 0x0010000000000000uLL | (0x000FFFFFFFFFFFFFuLL & fb.u.all);
-    if (e > 52)
-        r <<= (e - 52);
-    else
-        r >>= (52 - e);
-    return (r ^ s) - s;
+__fixdfti(fp_t a) {
+    return __fixint(a);
 }
 
 #endif /* CRT_HAS_128BIT */
diff --git a/lib/builtins/fixsfdi.c b/lib/builtins/fixsfdi.c
index 4f6cfdd..835ff85 100644
--- a/lib/builtins/fixsfdi.c
+++ b/lib/builtins/fixsfdi.c
@@ -1,43 +1,23 @@
 /* ===-- fixsfdi.c - Implement __fixsfdi -----------------------------------===
  *
- *                    The LLVM Compiler Infrastructure
+ *                     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 implements __fixsfdi for the compiler_rt library.
- *
- * ===----------------------------------------------------------------------===
  */
 
-#include "int_lib.h"
-
-/* Returns: convert a to a signed long long, rounding toward zero. */
-
-/* Assumption: float is a IEEE 32 bit floating point type 
- *             su_int is a 32 bit integral type
- *             value in float is representable in di_int (no range checking performed)
- */
-
-/* seee eeee emmm mmmm mmmm mmmm mmmm mmmm */
+#define SINGLE_PRECISION
+#include "fp_lib.h"
 
 ARM_EABI_FNALIAS(f2lz, fixsfdi)
 
+typedef di_int fixint_t;
+typedef du_int fixuint_t;
+#include "fp_fixint_impl.inc"
+
 COMPILER_RT_ABI di_int
-__fixsfdi(float a)
-{
-    float_bits fb;
-    fb.f = a;
-    int e = ((fb.u & 0x7F800000) >> 23) - 127;
-    if (e < 0)
-        return 0;
-    di_int s = (si_int)(fb.u & 0x80000000) >> 31;
-    di_int r = (fb.u & 0x007FFFFF) | 0x00800000;
-    if (e > 23)
-        r <<= (e - 23);
-    else
-        r >>= (23 - e);
-    return (r ^ s) - s;
+__fixsfdi(fp_t a) {
+    return __fixint(a);
 }
diff --git a/lib/builtins/fixsfsi.c b/lib/builtins/fixsfsi.c
index e3cc42d..f045536 100644
--- a/lib/builtins/fixsfsi.c
+++ b/lib/builtins/fixsfsi.c
@@ -1,47 +1,22 @@
-//===-- lib/fixsfsi.c - Single-precision -> integer conversion ----*- C -*-===//
-//
-//                     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 implements single-precision to integer conversion for the
-// compiler-rt library.  No range checking is performed; the behavior of this
-// conversion is undefined for out of range values in the C standard.
-//
-//===----------------------------------------------------------------------===//
+/* ===-- fixsfsi.c - Implement __fixsfsi -----------------------------------===
+ *
+ *                     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.
+ *
+ * ===----------------------------------------------------------------------===
+ */
 
 #define SINGLE_PRECISION
 #include "fp_lib.h"
+typedef si_int fixint_t;
+typedef su_int fixuint_t;
+#include "fp_fixint_impl.inc"
 
 ARM_EABI_FNALIAS(f2iz, fixsfsi)
 
-COMPILER_RT_ABI int
+COMPILER_RT_ABI si_int
 __fixsfsi(fp_t a) {
-    // Break a into sign, exponent, significand
-    const rep_t aRep = toRep(a);
-    const rep_t aAbs = aRep & absMask;
-    const int sign = aRep & signBit ? -1 : 1;
-    const int exponent = (aAbs >> significandBits) - exponentBias;
-    const rep_t significand = (aAbs & significandMask) | implicitBit;
-    
-    // If 0 < exponent < significandBits, right shift to get the result.
-    if ((unsigned int)exponent < significandBits) {
-        return sign * (significand >> (significandBits - exponent));
-    }
-    
-    // If exponent is negative, the result is zero.
-    else if (exponent < 0) {
-        return 0;
-    }
-    
-    // If significandBits < exponent, left shift to get the result.  This shift
-    // may end up being larger than the type width, which incurs undefined
-    // behavior, but the conversion itself is undefined in that case, so
-    // whatever the compiler decides to do is fine.
-    else {
-        return sign * (significand << (exponent - significandBits));
-    }
+    return __fixint(a);
 }
diff --git a/lib/builtins/fixsfti.c b/lib/builtins/fixsfti.c
index 6a1a1c6..3a159b3 100644
--- a/lib/builtins/fixsfti.c
+++ b/lib/builtins/fixsfti.c
@@ -6,40 +6,21 @@
  * Source Licenses. See LICENSE.TXT for details.
  *
  * ===----------------------------------------------------------------------===
- *
- * This file implements __fixsfti for the compiler_rt library.
- *
- * ===----------------------------------------------------------------------===
  */
 
 #include "int_lib.h"
 
 #ifdef CRT_HAS_128BIT
+#define SINGLE_PRECISION
+#include "fp_lib.h"
 
-/* Returns: convert a to a signed long long, rounding toward zero. */
-
-/* Assumption: float is a IEEE 32 bit floating point type 
- *             su_int is a 32 bit integral type
- *             value in float is representable in ti_int (no range checking performed)
- */
-
-/* seee eeee emmm mmmm mmmm mmmm mmmm mmmm */
+typedef ti_int fixint_t;
+typedef tu_int fixuint_t;
+#include "fp_fixint_impl.inc"
 
 COMPILER_RT_ABI ti_int
-__fixsfti(float a)
-{
-    float_bits fb;
-    fb.f = a;
-    int e = ((fb.u & 0x7F800000) >> 23) - 127;
-    if (e < 0)
-        return 0;
-    ti_int s = (si_int)(fb.u & 0x80000000) >> 31;
-    ti_int r = (fb.u & 0x007FFFFF) | 0x00800000;
-    if (e > 23)
-        r <<= (e - 23);
-    else
-        r >>= (23 - e);
-    return (r ^ s) - s;
+__fixsfti(fp_t a) {
+    return __fixint(a);
 }
 
 #endif /* CRT_HAS_128BIT */
diff --git a/lib/builtins/fixtfdi.c b/lib/builtins/fixtfdi.c
new file mode 100644
index 0000000..bc9dea1
--- /dev/null
+++ b/lib/builtins/fixtfdi.c
@@ -0,0 +1,23 @@
+/* ===-- fixtfdi.c - Implement __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.
+ *
+ * ===----------------------------------------------------------------------===
+ */
+
+#define QUAD_PRECISION
+#include "fp_lib.h"
+
+#if defined(CRT_HAS_128BIT) && defined(CRT_LDBL_128BIT)
+typedef di_int fixint_t;
+typedef du_int fixuint_t;
+#include "fp_fixint_impl.inc"
+
+COMPILER_RT_ABI di_int
+__fixtfdi(fp_t a) {
+    return __fixint(a);
+}
+#endif
diff --git a/lib/builtins/fixtfsi.c b/lib/builtins/fixtfsi.c
new file mode 100644
index 0000000..feb3de8
--- /dev/null
+++ b/lib/builtins/fixtfsi.c
@@ -0,0 +1,23 @@
+/* ===-- fixtfsi.c - Implement __fixtfsi -----------------------------------===
+ *
+ *                     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.
+ *
+ * ===----------------------------------------------------------------------===
+ */
+
+#define QUAD_PRECISION
+#include "fp_lib.h"
+
+#if defined(CRT_HAS_128BIT) && defined(CRT_LDBL_128BIT)
+typedef si_int fixint_t;
+typedef su_int fixuint_t;
+#include "fp_fixint_impl.inc"
+
+COMPILER_RT_ABI si_int
+__fixtfsi(fp_t a) {
+    return __fixint(a);
+}
+#endif
diff --git a/lib/builtins/fixtfti.c b/lib/builtins/fixtfti.c
new file mode 100644
index 0000000..ee4ada8
--- /dev/null
+++ b/lib/builtins/fixtfti.c
@@ -0,0 +1,23 @@
+/* ===-- fixtfti.c - Implement __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.
+ *
+ * ===----------------------------------------------------------------------===
+ */
+
+#define QUAD_PRECISION
+#include "fp_lib.h"
+
+#if defined(CRT_HAS_128BIT) && defined(CRT_LDBL_128BIT)
+typedef ti_int fixint_t;
+typedef tu_int fixuint_t;
+#include "fp_fixint_impl.inc"
+
+COMPILER_RT_ABI ti_int
+__fixtfti(fp_t a) {
+    return __fixint(a);
+}
+#endif
diff --git a/lib/builtins/fixunsdfdi.c b/lib/builtins/fixunsdfdi.c
index 9e63713..f4f689e 100644
--- a/lib/builtins/fixunsdfdi.c
+++ b/lib/builtins/fixunsdfdi.c
@@ -6,42 +6,16 @@
  * Source Licenses. See LICENSE.TXT for details.
  *
  * ===----------------------------------------------------------------------===
- *
- * This file implements __fixunsdfdi for the compiler_rt library.
- *
- * ===----------------------------------------------------------------------===
  */
 
-#include "int_lib.h"
-
-/* Returns: convert a to a unsigned long long, rounding toward zero.
- *          Negative values all become zero.
- */
-
-/* Assumption: double is a IEEE 64 bit floating point type 
- *             du_int is a 64 bit integral type
- *             value in double is representable in du_int or is negative 
- *                 (no range checking performed)
- */
-
-/* seee eeee eeee mmmm mmmm mmmm mmmm mmmm | mmmm mmmm mmmm mmmm mmmm mmmm mmmm mmmm */
+#define DOUBLE_PRECISION
+#include "fp_lib.h"
+typedef du_int fixuint_t;
+#include "fp_fixuint_impl.inc"
 
 ARM_EABI_FNALIAS(d2ulz, fixunsdfdi)
 
 COMPILER_RT_ABI du_int
-__fixunsdfdi(double a)
-{
-    double_bits fb;
-    fb.f = a;
-    int e = ((fb.u.s.high & 0x7FF00000) >> 20) - 1023;
-    if (e < 0 || (fb.u.s.high & 0x80000000))
-        return 0;
-    udwords r;
-    r.s.high = (fb.u.s.high & 0x000FFFFF) | 0x00100000;
-    r.s.low = fb.u.s.low;
-    if (e > 52)
-        r.all <<= (e - 52);
-    else
-        r.all >>= (52 - e);
-    return r.all;
+__fixunsdfdi(fp_t a) {
+    return __fixuint(a);
 }
diff --git a/lib/builtins/fixunsdfsi.c b/lib/builtins/fixunsdfsi.c
index c6a3c75..232d342 100644
--- a/lib/builtins/fixunsdfsi.c
+++ b/lib/builtins/fixunsdfsi.c
@@ -6,39 +6,16 @@
  * Source Licenses. See LICENSE.TXT for details.
  *
  * ===----------------------------------------------------------------------===
- *
- * This file implements __fixunsdfsi for the compiler_rt library.
- *
- * ===----------------------------------------------------------------------===
  */
 
-#include "int_lib.h"
-
-/* Returns: convert a to a unsigned int, rounding toward zero.
- *          Negative values all become zero.
- */
-
-/* Assumption: double is a IEEE 64 bit floating point type 
- *             su_int is a 32 bit integral type
- *             value in double is representable in su_int or is negative 
- *                 (no range checking performed)
- */
-
-/* seee eeee eeee mmmm mmmm mmmm mmmm mmmm | mmmm mmmm mmmm mmmm mmmm mmmm mmmm mmmm */
+#define DOUBLE_PRECISION
+#include "fp_lib.h"
+typedef su_int fixuint_t;
+#include "fp_fixuint_impl.inc"
 
 ARM_EABI_FNALIAS(d2uiz, fixunsdfsi)
 
 COMPILER_RT_ABI su_int
-__fixunsdfsi(double a)
-{
-    double_bits fb;
-    fb.f = a;
-    int e = ((fb.u.s.high & 0x7FF00000) >> 20) - 1023;
-    if (e < 0 || (fb.u.s.high & 0x80000000))
-        return 0;
-    return (
-                0x80000000u                      |
-                ((fb.u.s.high & 0x000FFFFF) << 11) |
-                (fb.u.s.low >> 21)
-           ) >> (31 - e);
+__fixunsdfsi(fp_t a) {
+    return __fixuint(a);
 }
diff --git a/lib/builtins/fixunsdfti.c b/lib/builtins/fixunsdfti.c
index cc6c84f..c3d7df9 100644
--- a/lib/builtins/fixunsdfti.c
+++ b/lib/builtins/fixunsdfti.c
@@ -6,42 +6,18 @@
  * Source Licenses. See LICENSE.TXT for details.
  *
  * ===----------------------------------------------------------------------===
- *
- * This file implements __fixunsdfti for the compiler_rt library.
- *
- * ===----------------------------------------------------------------------===
  */
 
 #include "int_lib.h"
 
 #ifdef CRT_HAS_128BIT
-
-/* Returns: convert a to a unsigned long long, rounding toward zero.
- *          Negative values all become zero.
- */
-
-/* Assumption: double is a IEEE 64 bit floating point type 
- *             tu_int is a 64 bit integral type
- *             value in double is representable in tu_int or is negative 
- *                 (no range checking performed)
- */
-
-/* seee eeee eeee mmmm mmmm mmmm mmmm mmmm | mmmm mmmm mmmm mmmm mmmm mmmm mmmm mmmm */
+#define DOUBLE_PRECISION
+#include "fp_lib.h"
+typedef tu_int fixuint_t;
+#include "fp_fixuint_impl.inc"
 
 COMPILER_RT_ABI tu_int
-__fixunsdfti(double a)
-{
-    double_bits fb;
-    fb.f = a;
-    int e = ((fb.u.s.high & 0x7FF00000) >> 20) - 1023;
-    if (e < 0 || (fb.u.s.high & 0x80000000))
-        return 0;
-    tu_int r = 0x0010000000000000uLL | (fb.u.all & 0x000FFFFFFFFFFFFFuLL);
-    if (e > 52)
-        r <<= (e - 52);
-    else
-        r >>= (52 - e);
-    return r;
+__fixunsdftti(fp_t a) {
+    return __fixuint(a);
 }
-
 #endif /* CRT_HAS_128BIT */
diff --git a/lib/builtins/fixunssfdi.c b/lib/builtins/fixunssfdi.c
index 69d5952..cd21cfd 100644
--- a/lib/builtins/fixunssfdi.c
+++ b/lib/builtins/fixunssfdi.c
@@ -6,39 +6,16 @@
  * Source Licenses. See LICENSE.TXT for details.
  *
  * ===----------------------------------------------------------------------===
- *
- * This file implements __fixunssfdi for the compiler_rt library.
- *
- * ===----------------------------------------------------------------------===
  */
 
-#include "int_lib.h"
-/* Returns: convert a to a unsigned long long, rounding toward zero.
- *          Negative values all become zero.
- */
-
-/* Assumption: float is a IEEE 32 bit floating point type 
- *             du_int is a 64 bit integral type
- *             value in float is representable in du_int or is negative 
- *                 (no range checking performed)
- */
-
-/* seee eeee emmm mmmm mmmm mmmm mmmm mmmm */
+#define SINGLE_PRECISION
+#include "fp_lib.h"
+typedef du_int fixuint_t;
+#include "fp_fixuint_impl.inc"
 
 ARM_EABI_FNALIAS(f2ulz, fixunssfdi)
 
 COMPILER_RT_ABI du_int
-__fixunssfdi(float a)
-{
-    float_bits fb;
-    fb.f = a;
-    int e = ((fb.u & 0x7F800000) >> 23) - 127;
-    if (e < 0 || (fb.u & 0x80000000))
-        return 0;
-    du_int r = (fb.u & 0x007FFFFF) | 0x00800000;
-    if (e > 23)
-        r <<= (e - 23);
-    else
-        r >>= (23 - e);
-    return r;
+__fixunssfdi(fp_t a) {
+    return __fixuint(a);
 }
diff --git a/lib/builtins/fixunssfsi.c b/lib/builtins/fixunssfsi.c
index e034139..cc2b05b 100644
--- a/lib/builtins/fixunssfsi.c
+++ b/lib/builtins/fixunssfsi.c
@@ -12,34 +12,14 @@
  * ===----------------------------------------------------------------------===
  */
 
-#include "int_lib.h"
-
-/* Returns: convert a to a unsigned int, rounding toward zero.
- *          Negative values all become zero.
- */
-
-/* Assumption: float is a IEEE 32 bit floating point type 
- *             su_int is a 32 bit integral type
- *             value in float is representable in su_int or is negative 
- *                 (no range checking performed)
- */
-
-/* seee eeee emmm mmmm mmmm mmmm mmmm mmmm */
+#define SINGLE_PRECISION
+#include "fp_lib.h"
+typedef su_int fixuint_t;
+#include "fp_fixuint_impl.inc"
 
 ARM_EABI_FNALIAS(f2uiz, fixunssfsi)
 
 COMPILER_RT_ABI su_int
-__fixunssfsi(float a)
-{
-    float_bits fb;
-    fb.f = a;
-    int e = ((fb.u & 0x7F800000) >> 23) - 127;
-    if (e < 0 || (fb.u & 0x80000000))
-        return 0;
-    su_int r = (fb.u & 0x007FFFFF) | 0x00800000;
-    if (e > 23)
-        r <<= (e - 23);
-    else
-        r >>= (23 - e);
-    return r;
+__fixunssfsi(fp_t a) {
+    return __fixuint(a);
 }
diff --git a/lib/builtins/fixunssfti.c b/lib/builtins/fixunssfti.c
index 4da9e24..862d7bd 100644
--- a/lib/builtins/fixunssfti.c
+++ b/lib/builtins/fixunssfti.c
@@ -12,36 +12,15 @@
  * ===----------------------------------------------------------------------===
  */
 
-#include "int_lib.h"
+#define SINGLE_PRECISION
+#include "fp_lib.h"
 
-#ifdef CRT_HAS_128BIT
-
-/* Returns: convert a to a unsigned long long, rounding toward zero.
- *          Negative values all become zero.
- */
-
-/* Assumption: float is a IEEE 32 bit floating point type 
- *             tu_int is a 64 bit integral type
- *             value in float is representable in tu_int or is negative 
- *                 (no range checking performed)
- */
-
-/* seee eeee emmm mmmm mmmm mmmm mmmm mmmm */
+#if defined(CRT_HAS_128BIT)
+typedef tu_int fixuint_t;
+#include "fp_fixuint_impl.inc"
 
 COMPILER_RT_ABI tu_int
-__fixunssfti(float a)
-{
-    float_bits fb;
-    fb.f = a;
-    int e = ((fb.u & 0x7F800000) >> 23) - 127;
-    if (e < 0 || (fb.u & 0x80000000))
-        return 0;
-    tu_int r = (fb.u & 0x007FFFFF) | 0x00800000;
-    if (e > 23)
-        r <<= (e - 23);
-    else
-        r >>= (23 - e);
-    return r;
+__fixunssfti(fp_t a) {
+    return __fixuint(a);
 }
-
-#endif /* CRT_HAS_128BIT */
+#endif
diff --git a/lib/builtins/fixunstfdi.c b/lib/builtins/fixunstfdi.c
new file mode 100644
index 0000000..b2995f6
--- /dev/null
+++ b/lib/builtins/fixunstfdi.c
@@ -0,0 +1,22 @@
+/* ===-- fixunstfdi.c - Implement __fixunstfdi -----------------------------===
+ *
+ *                     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.
+ *
+ * ===----------------------------------------------------------------------===
+ */
+
+#define QUAD_PRECISION
+#include "fp_lib.h"
+
+#if defined(CRT_HAS_128BIT) && defined(CRT_LDBL_128BIT)
+typedef du_int fixuint_t;
+#include "fp_fixuint_impl.inc"
+
+COMPILER_RT_ABI du_int
+__fixunstfdi(fp_t a) {
+    return __fixuint(a);
+}
+#endif
diff --git a/lib/builtins/fixunstfsi.c b/lib/builtins/fixunstfsi.c
new file mode 100644
index 0000000..b5d3f6a
--- /dev/null
+++ b/lib/builtins/fixunstfsi.c
@@ -0,0 +1,22 @@
+/* ===-- fixunstfsi.c - Implement __fixunstfsi -----------------------------===
+ *
+ *                     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.
+ *
+ * ===----------------------------------------------------------------------===
+ */
+
+#define QUAD_PRECISION
+#include "fp_lib.h"
+
+#if defined(CRT_HAS_128BIT) && defined(CRT_LDBL_128BIT)
+typedef su_int fixuint_t;
+#include "fp_fixuint_impl.inc"
+
+COMPILER_RT_ABI su_int
+__fixunstfsi(fp_t a) {
+    return __fixuint(a);
+}
+#endif
diff --git a/lib/builtins/fixunstfti.c b/lib/builtins/fixunstfti.c
new file mode 100644
index 0000000..22ff9df
--- /dev/null
+++ b/lib/builtins/fixunstfti.c
@@ -0,0 +1,22 @@
+/* ===-- fixunstfsi.c - Implement __fixunstfsi -----------------------------===
+ *
+ *                     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.
+ *
+ * ===----------------------------------------------------------------------===
+ */
+
+#define QUAD_PRECISION
+#include "fp_lib.h"
+
+#if defined(CRT_HAS_128BIT) && defined(CRT_LDBL_128BIT)
+typedef tu_int fixuint_t;
+#include "fp_fixuint_impl.inc"
+
+COMPILER_RT_ABI tu_int
+__fixunstfti(fp_t a) {
+    return __fixuint(a);
+}
+#endif
diff --git a/lib/builtins/fixunsxfdi.c b/lib/builtins/fixunsxfdi.c
index 7224d46..075304e 100644
--- a/lib/builtins/fixunsxfdi.c
+++ b/lib/builtins/fixunsxfdi.c
@@ -38,6 +38,8 @@
     int e = (fb.u.high.s.low & 0x00007FFF) - 16383;
     if (e < 0 || (fb.u.high.s.low & 0x00008000))
         return 0;
+    if ((unsigned)e > sizeof(du_int) * CHAR_BIT)
+        return ~(du_int)0;
     return fb.u.low.all >> (63 - e);
 }
 
diff --git a/lib/builtins/fixunsxfsi.c b/lib/builtins/fixunsxfsi.c
index df0a18e..c3c70f7 100644
--- a/lib/builtins/fixunsxfsi.c
+++ b/lib/builtins/fixunsxfsi.c
@@ -23,7 +23,6 @@
 /* Assumption: long double is an intel 80 bit floating point type padded with 6 bytes
  *             su_int is a 32 bit integral type
  *             value in long double is representable in su_int or is negative 
- *                 (no range checking performed)
  */
 
 /* gggg gggg gggg gggg gggg gggg gggg gggg | gggg gggg gggg gggg seee eeee eeee eeee |
@@ -38,6 +37,8 @@
     int e = (fb.u.high.s.low & 0x00007FFF) - 16383;
     if (e < 0 || (fb.u.high.s.low & 0x00008000))
         return 0;
+    if ((unsigned)e > sizeof(su_int) * CHAR_BIT)
+        return ~(su_int)0;
     return fb.u.low.s.high >> (31 - e);
 }
 
diff --git a/lib/builtins/fixunsxfti.c b/lib/builtins/fixunsxfti.c
index 42e5073..fb39d00 100644
--- a/lib/builtins/fixunsxfti.c
+++ b/lib/builtins/fixunsxfti.c
@@ -21,9 +21,8 @@
  */
 
 /* Assumption: long double is an intel 80 bit floating point type padded with 6 bytes
- *             tu_int is a 64 bit integral 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)
  */
 
 /* gggg gggg gggg gggg gggg gggg gggg gggg | gggg gggg gggg gggg seee eeee eeee eeee |
@@ -38,6 +37,8 @@
     int e = (fb.u.high.s.low & 0x00007FFF) - 16383;
     if (e < 0 || (fb.u.high.s.low & 0x00008000))
         return 0;
+    if ((unsigned)e > sizeof(tu_int) * CHAR_BIT)
+        return ~(tu_int)0;
     tu_int r = fb.u.low.all;
     if (e > 63)
         r <<= (e - 63);
diff --git a/lib/builtins/fixxfdi.c b/lib/builtins/fixxfdi.c
index afc79d8..011787f 100644
--- a/lib/builtins/fixxfdi.c
+++ b/lib/builtins/fixxfdi.c
@@ -19,7 +19,7 @@
 /* Returns: convert a to a signed long long, rounding toward zero. */
 
 /* Assumption: long double is an intel 80 bit floating point type padded with 6 bytes
- *             su_int is a 32 bit integral type
+ *             di_int is a 64 bit integral type
  *             value in long double is representable in di_int (no range checking performed)
  */
 
@@ -30,11 +30,15 @@
 COMPILER_RT_ABI di_int
 __fixxfdi(long double a)
 {
+    const di_int di_max = (di_int)((~(du_int)0) / 2);
+    const di_int di_min = -di_max - 1;
     long_double_bits fb;
     fb.f = a;
     int e = (fb.u.high.s.low & 0x00007FFF) - 16383;
     if (e < 0)
         return 0;
+    if ((unsigned)e >= sizeof(di_int) * CHAR_BIT)
+        return a > 0 ? di_max : di_min;
     di_int s = -(si_int)((fb.u.high.s.low & 0x00008000) >> 15);
     di_int r = fb.u.low.all;
     r = (du_int)r >> (63 - e);
diff --git a/lib/builtins/fixxfti.c b/lib/builtins/fixxfti.c
index 3d0a279..968a4f0 100644
--- a/lib/builtins/fixxfti.c
+++ b/lib/builtins/fixxfti.c
@@ -19,8 +19,8 @@
 /* Returns: convert a to a signed long long, rounding toward zero. */
 
 /* Assumption: long double is an intel 80 bit floating point type padded with 6 bytes
- *             su_int is a 32 bit integral type
- *             value in long double is representable in ti_int (no range checking performed)
+ *             ti_int is a 128 bit integral type
+ *             value in long double is representable in ti_int
  */
 
 /* gggg gggg gggg gggg gggg gggg gggg gggg | gggg gggg gggg gggg seee eeee eeee eeee |
@@ -30,6 +30,8 @@
 COMPILER_RT_ABI ti_int
 __fixxfti(long double a)
 {
+    const ti_int ti_max = (ti_int)((~(tu_int)0) / 2);
+    const ti_int ti_min = -ti_max - 1;
     long_double_bits fb;
     fb.f = a;
     int e = (fb.u.high.s.low & 0x00007FFF) - 16383;
@@ -37,6 +39,8 @@
         return 0;
     ti_int s = -(si_int)((fb.u.high.s.low & 0x00008000) >> 15);
     ti_int r = fb.u.low.all;
+    if ((unsigned)e >= sizeof(ti_int) * CHAR_BIT)
+        return a > 0 ? ti_max : ti_min;
     if (e > 63)
         r <<= (e - 63);
     else
diff --git a/lib/builtins/fp_fixint_impl.inc b/lib/builtins/fp_fixint_impl.inc
new file mode 100644
index 0000000..035e87c
--- /dev/null
+++ b/lib/builtins/fp_fixint_impl.inc
@@ -0,0 +1,41 @@
+//===-- lib/fixdfsi.c - Double-precision -> integer conversion ----*- C -*-===//
+//
+//                     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 implements float to integer conversion for the
+// compiler-rt library.
+//
+//===----------------------------------------------------------------------===//
+
+#include "fp_lib.h"
+
+static inline fixint_t __fixint(fp_t a) {
+    const fixint_t fixint_max = (fixint_t)((~(fixuint_t)0) / 2);
+    const fixint_t fixint_min = -fixint_max - 1;
+    // Break a into sign, exponent, significand
+    const rep_t aRep = toRep(a);
+    const rep_t aAbs = aRep & absMask;
+    const fixint_t sign = aRep & signBit ? -1 : 1;
+    const int exponent = (aAbs >> significandBits) - exponentBias;
+    const rep_t significand = (aAbs & significandMask) | implicitBit;
+
+    // If exponent is negative, the result is zero.
+    if (exponent < 0)
+        return 0;
+
+    // If the value is too large for the integer type, saturate.
+    if ((unsigned)exponent >= sizeof(fixint_t) * CHAR_BIT)
+        return sign == 1 ? fixint_max : fixint_min;
+
+    // If 0 <= exponent < significandBits, right shift to get the result.
+    // Otherwise, shift left.
+    if (exponent < significandBits)
+        return sign * (significand >> (significandBits - exponent));
+    else
+        return sign * ((fixint_t)significand << (exponent - significandBits));
+}
diff --git a/lib/builtins/fp_fixuint_impl.inc b/lib/builtins/fp_fixuint_impl.inc
new file mode 100644
index 0000000..5fefab0
--- /dev/null
+++ b/lib/builtins/fp_fixuint_impl.inc
@@ -0,0 +1,39 @@
+//===-- lib/fixdfsi.c - Double-precision -> integer conversion ----*- C -*-===//
+//
+//                     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 implements float to unsigned integer conversion for the
+// compiler-rt library.
+//
+//===----------------------------------------------------------------------===//
+
+#include "fp_lib.h"
+
+static inline fixuint_t __fixuint(fp_t a) {
+    // Break a into sign, exponent, significand
+    const rep_t aRep = toRep(a);
+    const rep_t aAbs = aRep & absMask;
+    const int sign = aRep & signBit ? -1 : 1;
+    const int exponent = (aAbs >> significandBits) - exponentBias;
+    const rep_t significand = (aAbs & significandMask) | implicitBit;
+
+    // If either the value or the exponent is negative, the result is zero.
+    if (sign == -1 || exponent < 0)
+        return 0;
+
+    // If the value is too large for the integer type, saturate.
+    if ((unsigned)exponent > sizeof(fixuint_t) * CHAR_BIT)
+        return ~(fixuint_t)0;
+
+    // If 0 <= exponent < significandBits, right shift to get the result.
+    // Otherwise, shift left.
+    if (exponent < significandBits)
+        return significand >> (significandBits - exponent);
+    else
+        return (fixuint_t)significand << (exponent - significandBits);
+}
diff --git a/lib/dfsan/dfsan.cc b/lib/dfsan/dfsan.cc
index de5b2ce..5a8da38 100644
--- a/lib/dfsan/dfsan.cc
+++ b/lib/dfsan/dfsan.cc
@@ -333,7 +333,7 @@
 
 static void dfsan_fini() {
   if (internal_strcmp(flags().dump_labels_at_exit, "") != 0) {
-    fd_t fd = OpenFile(flags().dump_labels_at_exit, true /* write */);
+    fd_t fd = OpenFile(flags().dump_labels_at_exit, WrOnly);
     if (fd == kInvalidFd) {
       Report("WARNING: DataFlowSanitizer: unable to open output file %s\n",
              flags().dump_labels_at_exit);
diff --git a/lib/interception/interception.h b/lib/interception/interception.h
index 5257325..9e9aca2 100644
--- a/lib/interception/interception.h
+++ b/lib/interception/interception.h
@@ -219,7 +219,6 @@
     namespace __interception { \
       FUNC_TYPE(func) PTR_TO_REAL(func); \
     } \
-    DECLARE_WRAPPER_WINAPI(ret_type, func, __VA_ARGS__) \
     extern "C" \
     INTERCEPTOR_ATTRIBUTE \
     ret_type __stdcall WRAP(func)(__VA_ARGS__)
diff --git a/lib/interception/interception_win.cc b/lib/interception/interception_win.cc
index cd241c3..19cf184 100644
--- a/lib/interception/interception_win.cc
+++ b/lib/interception/interception_win.cc
@@ -84,6 +84,7 @@
         cursor += 2;
         continue;
       case '\xE9':  // E9 XX YY ZZ WW = jmp WWZZYYXX
+      case '\xB8':  // B8 XX YY ZZ WW = mov eax, WWZZYYXX
         cursor += 5;
         continue;
     }
@@ -182,10 +183,14 @@
 }
 
 static const void **InterestingDLLsAvailable() {
-  const char *InterestingDLLs[] = {"kernel32.dll",
-                                   "msvcr110.dll", // VS2012
-                                   "msvcr120.dll", // VS2013
-                                   NULL};
+  const char *InterestingDLLs[] = {
+    "kernel32.dll",
+    "msvcr110.dll", // VS2012
+    "msvcr120.dll", // VS2013
+    // NTDLL should go last as it exports some functions that we should override
+    // in the CRT [presumably only used internally].
+    "ntdll.dll", NULL
+  };
   static void *result[ARRAY_SIZE(InterestingDLLs)] = { 0 };
   if (!result[0]) {
     for (size_t i = 0, j = 0; InterestingDLLs[i]; ++i) {
diff --git a/lib/lsan/lsan_common.cc b/lib/lsan/lsan_common.cc
index a6119af..8ac2ae0 100644
--- a/lib/lsan/lsan_common.cc
+++ b/lib/lsan/lsan_common.cc
@@ -435,13 +435,11 @@
   Suppression *s = nullptr;
 
   // Suppress by module name.
-  const char *module_name;
-  uptr module_offset;
   SuppressionContext *suppressions = GetSuppressionContext();
-  if (Symbolizer::GetOrInit()->GetModuleNameAndOffsetForPC(addr, &module_name,
-                                                           &module_offset) &&
-      suppressions->Match(module_name, kSuppressionLeak, &s))
-    return s;
+  if (const char *module_name =
+          Symbolizer::GetOrInit()->GetModuleNameForPc(addr))
+    if (suppressions->Match(module_name, kSuppressionLeak, &s))
+      return s;
 
   // Suppress by file or function name.
   SymbolizedStack *frames = Symbolizer::GetOrInit()->SymbolizePC(addr);
diff --git a/lib/msan/tests/CMakeLists.txt b/lib/msan/tests/CMakeLists.txt
index e008bd3..4bc8254 100644
--- a/lib/msan/tests/CMakeLists.txt
+++ b/lib/msan/tests/CMakeLists.txt
@@ -33,6 +33,7 @@
   -Wno-deprecated-declarations
   -Wno-unused-variable
   -Wno-zero-length-array
+  -Wno-uninitialized
   -Werror=sign-compare
 )
 set(MSAN_UNITTEST_INSTRUMENTED_CFLAGS
diff --git a/lib/profile/InstrProfilingFile.c b/lib/profile/InstrProfilingFile.c
index daa3094..d9acbbe 100644
--- a/lib/profile/InstrProfilingFile.c
+++ b/lib/profile/InstrProfilingFile.c
@@ -8,10 +8,10 @@
 \*===----------------------------------------------------------------------===*/
 
 #include "InstrProfiling.h"
+#include <errno.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
-#include <sys/errno.h>
 
 #define UNCONST(ptr) ((void *)(uintptr_t)(ptr))
 
diff --git a/lib/sanitizer_common/CMakeLists.txt b/lib/sanitizer_common/CMakeLists.txt
index 6eb6ca8..5b32b6a 100644
--- a/lib/sanitizer_common/CMakeLists.txt
+++ b/lib/sanitizer_common/CMakeLists.txt
@@ -27,6 +27,7 @@
   sanitizer_suppressions.cc
   sanitizer_symbolizer.cc
   sanitizer_symbolizer_libbacktrace.cc
+  sanitizer_symbolizer_mac.cc
   sanitizer_symbolizer_win.cc
   sanitizer_tls_get_addr.cc
   sanitizer_thread_registry.cc
@@ -42,6 +43,7 @@
   sanitizer_stoptheworld_linux_libcdep.cc
   sanitizer_symbolizer_libcdep.cc
   sanitizer_symbolizer_posix_libcdep.cc
+  sanitizer_symbolizer_process_libcdep.cc
   sanitizer_unwind_posix_libcdep.cc)
 
 # Explicitly list all sanitizer_common headers. Not all of these are
@@ -91,7 +93,10 @@
   sanitizer_stoptheworld.h
   sanitizer_suppressions.h
   sanitizer_symbolizer.h
+  sanitizer_symbolizer_internal.h
   sanitizer_symbolizer_libbacktrace.h
+  sanitizer_symbolizer_mac.h
+  sanitizer_symbolizer_win.h
   sanitizer_syscall_generic.inc
   sanitizer_syscall_linux_x86_64.inc
   sanitizer_thread_registry.h)
@@ -137,12 +142,6 @@
       DEFS ${SANITIZER_COMMON_DEFINITIONS})
     list(APPEND SANITIZER_RUNTIME_LIBRARIES RTSanitizerCommon.${arch}
                                             RTSanitizerCommonLibc.${arch})
-    add_compiler_rt_runtime(clang_rt.san-${arch} ${arch} STATIC
-      SOURCES $<TARGET_OBJECTS:RTSanitizerCommon.${arch}>
-              $<TARGET_OBJECTS:RTSanitizerCommonLibc.${arch}>
-      CFLAGS ${SANITIZER_CFLAGS}
-      DEFS ${SANITIZER_COMMON_DEFINITIONS})
-    add_dependencies(sanitizer_common clang_rt.san-${arch})
   endforeach()
 endif()
 
diff --git a/lib/sanitizer_common/sanitizer_common.cc b/lib/sanitizer_common/sanitizer_common.cc
index 4be3c7a..956fc99 100644
--- a/lib/sanitizer_common/sanitizer_common.cc
+++ b/lib/sanitizer_common/sanitizer_common.cc
@@ -16,6 +16,8 @@
 #include "sanitizer_flags.h"
 #include "sanitizer_libc.h"
 #include "sanitizer_placement_new.h"
+#include "sanitizer_stacktrace_printer.h"
+#include "sanitizer_symbolizer.h"
 
 namespace __sanitizer {
 
@@ -56,7 +58,7 @@
   }
 
   internal_snprintf(full_path, kMaxPathLength, "%s.%zu", path_prefix, pid);
-  uptr openrv = OpenFile(full_path, true);
+  uptr openrv = OpenFile(full_path, WrOnly);
   if (internal_iserror(openrv)) {
     const char *ErrorMsgPrefix = "ERROR: Can't open file: ";
     internal_write(kStderrFd, ErrorMsgPrefix, internal_strlen(ErrorMsgPrefix));
@@ -142,7 +144,7 @@
   *buff_size = 0;
   // The files we usually open are not seekable, so try different buffer sizes.
   for (uptr size = kMinFileLen; size <= max_len; size *= 2) {
-    uptr openrv = OpenFile(file_name, /*write*/ false);
+    uptr openrv = OpenFile(file_name, RdOnly);
     if (internal_iserror(openrv, errno_p)) return 0;
     fd_t fd = openrv;
     UnmapOrDie(*buff, *buff_size);
@@ -206,12 +208,12 @@
                             const char *strip_path_prefix) {
   if (filepath == 0) return 0;
   if (strip_path_prefix == 0) return filepath;
-  const char *pos = internal_strstr(filepath, strip_path_prefix);
-  if (pos == 0) return filepath;
-  pos += internal_strlen(strip_path_prefix);
-  if (pos[0] == '.' && pos[1] == '/')
-    pos += 2;
-  return pos;
+  const char *res = filepath;
+  if (const char *pos = internal_strstr(filepath, strip_path_prefix))
+    res = pos + internal_strlen(strip_path_prefix);
+  if (res[0] == '.' && res[1] == '/')
+    res += 2;
+  return res;
 }
 
 const char *StripModuleName(const char *module) {
@@ -230,17 +232,16 @@
   __sanitizer_report_error_summary(buff.data());
 }
 
-void ReportErrorSummary(const char *error_type, const char *file,
-                        int line, const char *function) {
+#ifndef SANITIZER_GO
+void ReportErrorSummary(const char *error_type, const AddressInfo &info) {
   if (!common_flags()->print_summary)
     return;
   InternalScopedString buff(kMaxSummaryLength);
-  buff.append("%s %s:%d %s", error_type,
-              file ? StripPathPrefix(file, common_flags()->strip_path_prefix)
-                   : "??",
-              line, function ? function : "??");
+  buff.append("%s ", error_type);
+  RenderFrame(&buff, "%L %F", 0, info, common_flags()->strip_path_prefix);
   ReportErrorSummary(buff.data());
 }
+#endif
 
 LoadedModule::LoadedModule(const char *module_name, uptr base_address) {
   full_name_ = internal_strdup(module_name);
diff --git a/lib/sanitizer_common/sanitizer_common.h b/lib/sanitizer_common/sanitizer_common.h
index ff13ef1..0dfa815 100644
--- a/lib/sanitizer_common/sanitizer_common.h
+++ b/lib/sanitizer_common/sanitizer_common.h
@@ -25,6 +25,7 @@
 
 namespace __sanitizer {
 struct StackTrace;
+struct AddressInfo;
 
 // Constants.
 const uptr kWordSize = SANITIZER_WORDSIZE / 8;
@@ -186,7 +187,13 @@
 extern uptr stoptheworld_tracer_pid;
 extern uptr stoptheworld_tracer_ppid;
 
-uptr OpenFile(const char *filename, bool write);
+enum FileAccessMode {
+  RdOnly,
+  WrOnly,
+  RdWr
+};
+
+uptr OpenFile(const char *filename, FileAccessMode mode);
 // Opens the file 'file_name" and reads up to 'max_len' bytes.
 // The resulting buffer is mmaped and stored in '*buff'.
 // The size of the mmaped region is stored in '*buff_size',
@@ -215,6 +222,11 @@
 bool SetEnv(const char *name, const char *value);
 const char *GetPwd();
 char *FindPathToBinary(const char *name);
+bool IsPathSeparator(const char c);
+bool IsAbsolutePath(const char *path);
+
+// Returns the path to the main executable.
+uptr ReadBinaryName(/*out*/char *buf, uptr buf_len);
 u32 GetUid();
 void ReExec();
 bool StackSizeIsUnlimited();
@@ -288,9 +300,9 @@
 // and pass it to __sanitizer_report_error_summary.
 void ReportErrorSummary(const char *error_message);
 // Same as above, but construct error_message as:
-//   error_type file:line function
-void ReportErrorSummary(const char *error_type, const char *file,
-                        int line, const char *function);
+//   error_type file:line[:column][ function]
+void ReportErrorSummary(const char *error_type, const AddressInfo &info);
+// Same as above, but obtains AddressInfo by symbolizing top stack trace frame.
 void ReportErrorSummary(const char *error_type, StackTrace *trace);
 
 // Math
@@ -439,11 +451,15 @@
   const T *data() const {
     return data_;
   }
+  T *data() {
+    return data_;
+  }
   uptr capacity() const {
     return capacity_;
   }
 
   void clear() { size_ = 0; }
+  bool empty() const { return size() == 0; }
 
  private:
   void Resize(uptr new_capacity) {
@@ -532,6 +548,7 @@
 // executable or a shared object).
 class LoadedModule {
  public:
+  LoadedModule() : full_name_(nullptr), base_address_(0) {}
   LoadedModule(const char *module_name, uptr base_address);
   void clear();
   void addAddressRange(uptr beg, uptr end, bool executable);
@@ -607,6 +624,23 @@
 #endif
 }
 
+struct SignalContext {
+  void *context;
+  uptr addr;
+  uptr pc;
+  uptr sp;
+  uptr bp;
+
+  SignalContext(void *context, uptr addr, uptr pc, uptr sp, uptr bp) :
+      context(context), addr(addr), pc(pc), sp(sp), bp(bp) {
+  }
+
+  // Creates signal context in a platform-specific manner.
+  static SignalContext Create(void *siginfo, void *context);
+};
+
+void GetPcSpBp(void *context, uptr *pc, uptr *sp, uptr *bp);
+
 }  // namespace __sanitizer
 
 inline void *operator new(__sanitizer::operator_new_size_type size,
diff --git a/lib/sanitizer_common/sanitizer_common_libcdep.cc b/lib/sanitizer_common/sanitizer_common_libcdep.cc
index 17ef689..9622e60 100644
--- a/lib/sanitizer_common/sanitizer_common_libcdep.cc
+++ b/lib/sanitizer_common/sanitizer_common_libcdep.cc
@@ -44,20 +44,16 @@
 void ReportErrorSummary(const char *error_type, StackTrace *stack) {
   if (!common_flags()->print_summary)
     return;
-#if !SANITIZER_GO
-  if (stack->size > 0 && Symbolizer::GetOrInit()->CanReturnFileLineInfo()) {
-    // Currently, we include the first stack frame into the report summary.
-    // Maybe sometimes we need to choose another frame (e.g. skip memcpy/etc).
-    uptr pc = StackTrace::GetPreviousInstructionPc(stack->trace[0]);
-    SymbolizedStack *frame = Symbolizer::GetOrInit()->SymbolizePC(pc);
-    const AddressInfo &ai = frame->info;
-    ReportErrorSummary(error_type, ai.file, ai.line, ai.function);
-    frame->ClearAll();
+  if (stack->size == 0) {
+    ReportErrorSummary(error_type);
+    return;
   }
-#else
-  AddressInfo ai;
-  ReportErrorSummary(error_type, ai.file, ai.line, ai.function);
-#endif
+  // Currently, we include the first stack frame into the report summary.
+  // Maybe sometimes we need to choose another frame (e.g. skip memcpy/etc).
+  uptr pc = StackTrace::GetPreviousInstructionPc(stack->trace[0]);
+  SymbolizedStack *frame = Symbolizer::GetOrInit()->SymbolizePC(pc);
+  ReportErrorSummary(error_type, frame->info);
+  frame->ClearAll();
 }
 
 static void (*SoftRssLimitExceededCallback)(bool exceeded);
diff --git a/lib/sanitizer_common/sanitizer_coverage_libcdep.cc b/lib/sanitizer_common/sanitizer_coverage_libcdep.cc
index 49887b1..94863c6 100644
--- a/lib/sanitizer_common/sanitizer_coverage_libcdep.cc
+++ b/lib/sanitizer_common/sanitizer_coverage_libcdep.cc
@@ -24,8 +24,12 @@
 //    and atomically set Guard to -Guard.
 //  - __sanitizer_cov_dump: dump the coverage data to disk.
 //  For every module of the current process that has coverage data
-//  this will create a file module_name.PID.sancov. The file format is simple:
-//  it's just a sorted sequence of 4-byte offsets in the module.
+//  this will create a file module_name.PID.sancov.
+//
+// The file format is simple: the first 8 bytes is the magic,
+// one of 0xC0BFFFFFFFFFFF64 and 0xC0BFFFFFFFFFFF32. The last byte of the
+// magic defines the size of the following offsets.
+// The rest of the data is the offsets in the module.
 //
 // Eventually, this coverage implementation should be obsoleted by a more
 // powerful general purpose Clang/LLVM coverage instrumentation.
@@ -43,6 +47,9 @@
 #include "sanitizer_symbolizer.h"
 #include "sanitizer_flags.h"
 
+static const u64 kMagic64 = 0xC0BFFFFFFFFFFF64ULL;
+static const u64 kMagic32 = 0xC0BFFFFFFFFFFF32ULL;
+
 static atomic_uint32_t dump_once_guard;  // Ensure that CovDump runs only once.
 
 static atomic_uintptr_t coverage_counter;
@@ -77,21 +84,32 @@
                  uptr cache_size);
   void DumpCallerCalleePairs();
   void DumpTrace();
+  void DumpAsBitSet();
+  void DumpCounters();
+  void DumpOffsets();
+  void DumpAll();
 
   ALWAYS_INLINE
   void TraceBasicBlock(s32 *id);
 
   void InitializeGuardArray(s32 *guards);
-  void InitializeGuards(s32 *guards, uptr n, const char *module_name);
+  void InitializeGuards(s32 *guards, uptr n, const char *module_name,
+                        uptr caller_pc);
+  void InitializeCounters(u8 *counters, uptr n);
   void ReinitializeGuards();
+  uptr GetNumberOf8bitCounters();
+  uptr Update8bitCounterBitsetAndClearCounters(u8 *bitset);
 
   uptr *data();
   uptr size();
 
  private:
+  void DirectOpen();
+  void UpdateModuleNameVec(uptr caller_pc, uptr range_beg, uptr range_end);
+
   // Maximal size pc array may ever grow.
   // We MmapNoReserve this space to ensure that the array is contiguous.
-  static const uptr kPcArrayMaxSize = FIRST_32_SECOND_64(1 << 24, 1 << 27);
+  static const uptr kPcArrayMaxSize = FIRST_32_SECOND_64(1 << 26, 1 << 27);
   // The amount file mapping for the pc array is grown by.
   static const uptr kPcArrayMmapSize = 64 * 1024;
 
@@ -110,8 +128,22 @@
   // Vector of coverage guard arrays, protected by mu.
   InternalMmapVectorNoCtor<s32*> guard_array_vec;
 
-  // Vector of module (compilation unit) names.
-  InternalMmapVectorNoCtor<const char*> comp_unit_name_vec;
+  struct NamedPcRange {
+    const char *copied_module_name;
+    uptr beg, end; // elements [beg,end) in pc_array.
+  };
+
+  // Vector of module and compilation unit pc ranges.
+  InternalMmapVectorNoCtor<NamedPcRange> comp_unit_name_vec;
+  InternalMmapVectorNoCtor<NamedPcRange> module_name_vec;
+
+  struct CounterAndSize {
+    u8 *counters;
+    uptr n;
+  };
+
+  InternalMmapVectorNoCtor<CounterAndSize> counters_vec;
+  uptr num_8bit_counters;
 
   // Caller-Callee (cc) array, size and current index.
   static const uptr kCcArrayMaxSize = FIRST_32_SECOND_64(1 << 18, 1 << 24);
@@ -133,8 +165,6 @@
   static const uptr kTrPcArrayMaxSize    = FIRST_32_SECOND_64(1 << 22, 1 << 27);
 
   StaticSpinMutex mu;
-
-  void DirectOpen();
 };
 
 static CoverageData coverage_data;
@@ -145,9 +175,9 @@
   InternalScopedString path(kMaxPathLength);
   internal_snprintf((char *)path.data(), path.size(), "%s/%zd.sancov.raw",
                     coverage_dir, internal_getpid());
-  pc_fd = OpenFile(path.data(), true);
+  pc_fd = OpenFile(path.data(), RdWr);
   if (internal_iserror(pc_fd)) {
-    Report(" Coverage: failed to open %s for writing\n", path.data());
+    Report(" Coverage: failed to open %s for reading/writing\n", path.data());
     Die();
   }
 
@@ -184,6 +214,8 @@
            GetMmapGranularity());
   tr_event_array_size = kTrEventArrayMaxSize;
   tr_event_pointer = tr_event_array;
+
+  num_8bit_counters = 0;
 }
 
 void CoverageData::InitializeGuardArray(s32 *guards) {
@@ -289,16 +321,70 @@
   atomic_store(&pc_array_size, size, memory_order_release);
 }
 
+void CoverageData::InitializeCounters(u8 *counters, uptr n) {
+  if (!counters) return;
+  CHECK_EQ(reinterpret_cast<uptr>(counters) % 16, 0);
+  n = RoundUpTo(n, 16); // The compiler must ensure that counters is 16-aligned.
+  SpinMutexLock l(&mu);
+  counters_vec.push_back({counters, n});
+  num_8bit_counters += n;
+}
+
+void CoverageData::UpdateModuleNameVec(uptr caller_pc, uptr range_beg,
+                                       uptr range_end) {
+  auto sym = Symbolizer::GetOrInit();
+  if (!sym)
+    return;
+  const char *module_name = sym->GetModuleNameForPc(caller_pc);
+  if (!module_name) return;
+  if (module_name_vec.empty() ||
+      internal_strcmp(module_name_vec.back().copied_module_name, module_name))
+    module_name_vec.push_back(
+        {internal_strdup(module_name), range_beg, range_end});
+  else
+    module_name_vec.back().end = range_end;
+}
+
 void CoverageData::InitializeGuards(s32 *guards, uptr n,
-                                    const char *module_name) {
+                                    const char *comp_unit_name,
+                                    uptr caller_pc) {
   // The array 'guards' has n+1 elements, we use the element zero
   // to store 'n'.
   CHECK_LT(n, 1 << 30);
   guards[0] = static_cast<s32>(n);
   InitializeGuardArray(guards);
   SpinMutexLock l(&mu);
-  comp_unit_name_vec.push_back(module_name);
+  uptr range_end = atomic_load(&pc_array_index, memory_order_relaxed);
+  uptr range_beg = range_end - n;
+  comp_unit_name_vec.push_back({comp_unit_name, range_beg, range_end});
   guard_array_vec.push_back(guards);
+  UpdateModuleNameVec(caller_pc, range_beg, range_end);
+}
+
+static const uptr kBundleCounterBits = 16;
+
+// When coverage_order_pcs==true and SANITIZER_WORDSIZE==64
+// we insert the global counter into the first 16 bits of the PC.
+uptr BundlePcAndCounter(uptr pc, uptr counter) {
+  if (SANITIZER_WORDSIZE != 64 || !common_flags()->coverage_order_pcs)
+    return pc;
+  static const uptr kMaxCounter = (1 << kBundleCounterBits) - 1;
+  if (counter > kMaxCounter)
+    counter = kMaxCounter;
+  CHECK_EQ(0, pc >> (SANITIZER_WORDSIZE - kBundleCounterBits));
+  return pc | (counter << (SANITIZER_WORDSIZE - kBundleCounterBits));
+}
+
+uptr UnbundlePc(uptr bundle) {
+  if (SANITIZER_WORDSIZE != 64 || !common_flags()->coverage_order_pcs)
+    return bundle;
+  return (bundle << kBundleCounterBits) >> kBundleCounterBits;
+}
+
+uptr UnbundleCounter(uptr bundle) {
+  if (SANITIZER_WORDSIZE != 64 || !common_flags()->coverage_order_pcs)
+    return 0;
+  return bundle >> (SANITIZER_WORDSIZE - kBundleCounterBits);
 }
 
 // If guard is negative, atomically set it to -guard and store the PC in
@@ -316,8 +402,8 @@
     return;  // May happen after fork when pc_array_index becomes 0.
   CHECK_LT(idx * sizeof(uptr),
            atomic_load(&pc_array_size, memory_order_acquire));
-  pc_array[idx] = pc;
-  atomic_fetch_add(&coverage_counter, 1, memory_order_relaxed);
+  uptr counter = atomic_fetch_add(&coverage_counter, 1, memory_order_relaxed);
+  pc_array[idx] = BundlePcAndCounter(pc, counter);
 }
 
 // Registers a pair caller=>callee.
@@ -354,6 +440,64 @@
   }
 }
 
+uptr CoverageData::GetNumberOf8bitCounters() {
+  return num_8bit_counters;
+}
+
+// Map every 8bit counter to a 8-bit bitset and clear the counter.
+uptr CoverageData::Update8bitCounterBitsetAndClearCounters(u8 *bitset) {
+  uptr num_new_bits = 0;
+  uptr cur = 0;
+  // For better speed we map 8 counters to 8 bytes of bitset at once.
+  static const uptr kBatchSize = 8;
+  CHECK_EQ(reinterpret_cast<uptr>(bitset) % kBatchSize, 0);
+  for (uptr i = 0, len = counters_vec.size(); i < len; i++) {
+    u8 *c = counters_vec[i].counters;
+    uptr n = counters_vec[i].n;
+    CHECK_EQ(n % 16, 0);
+    CHECK_EQ(cur % kBatchSize, 0);
+    CHECK_EQ(reinterpret_cast<uptr>(c) % kBatchSize, 0);
+    if (!bitset) {
+      internal_bzero_aligned16(c, n);
+      cur += n;
+      continue;
+    }
+    for (uptr j = 0; j < n; j += kBatchSize, cur += kBatchSize) {
+      CHECK_LT(cur, num_8bit_counters);
+      u64 *pc64 = reinterpret_cast<u64*>(c + j);
+      u64 *pb64 = reinterpret_cast<u64*>(bitset + cur);
+      u64 c64 = *pc64;
+      u64 old_bits_64 = *pb64;
+      u64 new_bits_64 = old_bits_64;
+      if (c64) {
+        *pc64 = 0;
+        for (uptr k = 0; k < kBatchSize; k++) {
+          u64 x = (c64 >> (8 * k)) & 0xff;
+          if (x) {
+            u64 bit = 0;
+            /**/ if (x >= 128) bit = 128;
+            else if (x >= 32) bit = 64;
+            else if (x >= 16) bit = 32;
+            else if (x >= 8) bit = 16;
+            else if (x >= 4) bit = 8;
+            else if (x >= 3) bit = 4;
+            else if (x >= 2) bit = 2;
+            else if (x >= 1) bit = 1;
+            u64 mask = bit << (8 * k);
+            if (!(new_bits_64 & mask)) {
+              num_new_bits++;
+              new_bits_64 |= mask;
+            }
+          }
+        }
+        *pb64 = new_bits_64;
+      }
+    }
+  }
+  CHECK_EQ(cur, num_8bit_counters);
+  return num_new_bits;
+}
+
 uptr *CoverageData::data() {
   return pc_array;
 }
@@ -413,23 +557,23 @@
 // If packed = true and name == 0: <pid>.<sancov>.<packed>.
 // If packed = true and name != 0: <name>.<sancov>.<packed> (name is
 // user-supplied).
-static int CovOpenFile(bool packed, const char *name,
-                       const char *extension = "sancov") {
-  InternalScopedString path(kMaxPathLength);
+static int CovOpenFile(InternalScopedString *path, bool packed,
+                       const char *name, const char *extension = "sancov") {
+  path->clear();
   if (!packed) {
     CHECK(name);
-    path.append("%s/%s.%zd.%s", coverage_dir, name, internal_getpid(),
+    path->append("%s/%s.%zd.%s", coverage_dir, name, internal_getpid(),
                 extension);
   } else {
     if (!name)
-      path.append("%s/%zd.%s.packed", coverage_dir, internal_getpid(),
+      path->append("%s/%zd.%s.packed", coverage_dir, internal_getpid(),
                   extension);
     else
-      path.append("%s/%s.%s.packed", coverage_dir, name, extension);
+      path->append("%s/%s.%s.packed", coverage_dir, name, extension);
   }
-  uptr fd = OpenFile(path.data(), true);
+  uptr fd = OpenFile(path->data(), WrOnly);
   if (internal_iserror(fd)) {
-    Report(" SanitizerCoverage: failed to open %s for writing\n", path.data());
+    Report(" SanitizerCoverage: failed to open %s for writing\n", path->data());
     return -1;
   }
   return fd;
@@ -446,24 +590,25 @@
   for (uptr i = 0, n = size(); i < n; i++) {
     const char *module_name = "<unknown>";
     uptr module_address = 0;
-    sym->GetModuleNameAndOffsetForPC(pc_array[i], &module_name,
+    sym->GetModuleNameAndOffsetForPC(UnbundlePc(pc_array[i]), &module_name,
                                      &module_address);
     out.append("%s 0x%zx\n", module_name, module_address);
   }
-  int fd = CovOpenFile(false, "trace-points");
+  InternalScopedString path(kMaxPathLength);
+  int fd = CovOpenFile(&path, false, "trace-points");
   if (fd < 0) return;
   internal_write(fd, out.data(), out.length());
   internal_close(fd);
 
-  fd = CovOpenFile(false, "trace-compunits");
+  fd = CovOpenFile(&path, false, "trace-compunits");
   if (fd < 0) return;
   out.clear();
   for (uptr i = 0; i < comp_unit_name_vec.size(); i++)
-    out.append("%s\n", comp_unit_name_vec[i]);
+    out.append("%s\n", comp_unit_name_vec[i].copied_module_name);
   internal_write(fd, out.data(), out.length());
   internal_close(fd);
 
-  fd = CovOpenFile(false, "trace-events");
+  fd = CovOpenFile(&path, false, "trace-events");
   if (fd < 0) return;
   uptr bytes_to_write = max_idx * sizeof(tr_event_array[0]);
   u8 *event_bytes = reinterpret_cast<u8*>(tr_event_array);
@@ -514,7 +659,8 @@
                  callee_module_address);
     }
   }
-  int fd = CovOpenFile(false, "caller-callee");
+  InternalScopedString path(kMaxPathLength);
+  int fd = CovOpenFile(&path, false, "caller-callee");
   if (fd < 0) return;
   internal_write(fd, out.data(), out.length());
   internal_close(fd);
@@ -534,86 +680,124 @@
   tr_event_pointer++;
 }
 
-static void CovDumpAsBitSet() {
-  if (!common_flags()->coverage_bitset) return;
-  if (!coverage_data.size()) return;
-  int fd = CovOpenFile(/* packed */false, "combined", "bitset-sancov");
-  if (fd < 0) return;
-  uptr n = coverage_data.size();
-  uptr n_set_bits = 0;
-  InternalScopedBuffer<char> out(n);
-  for (uptr i = 0; i < n; i++) {
-    uptr pc = coverage_data.data()[i];
-    out[i] = pc ? '1' : '0';
-    if (pc)
-      n_set_bits++;
+void CoverageData::DumpCounters() {
+  if (!common_flags()->coverage_counters) return;
+  uptr n = coverage_data.GetNumberOf8bitCounters();
+  if (!n) return;
+  InternalScopedBuffer<u8> bitset(n);
+  coverage_data.Update8bitCounterBitsetAndClearCounters(bitset.data());
+  InternalScopedString path(kMaxPathLength);
+
+  for (uptr m = 0; m < module_name_vec.size(); m++) {
+    auto r = module_name_vec[m];
+    CHECK(r.copied_module_name);
+    CHECK_LE(r.beg, r.end);
+    CHECK_LE(r.end, size());
+    const char *base_name = StripModuleName(r.copied_module_name);
+    int fd =
+        CovOpenFile(&path, /* packed */ false, base_name, "counters-sancov");
+    if (fd < 0) return;
+    internal_write(fd, bitset.data() + r.beg, r.end - r.beg);
+    internal_close(fd);
+    VReport(1, " CovDump: %zd counters written for '%s'\n", r.end - r.beg,
+            base_name);
   }
-  internal_write(fd, out.data(), n);
-  internal_close(fd);
-  VReport(1, " CovDump: bitset of %zd bits written, %zd bits are set\n", n,
-          n_set_bits);
 }
 
-// Dump the coverage on disk.
-static void CovDump() {
-  if (!coverage_enabled || common_flags()->coverage_direct) return;
-#if !SANITIZER_WINDOWS
-  if (atomic_fetch_add(&dump_once_guard, 1, memory_order_relaxed))
-    return;
-  CovDumpAsBitSet();
-  coverage_data.DumpTrace();
-  if (!common_flags()->coverage_pcs) return;
-  uptr size = coverage_data.size();
-  InternalMmapVector<u32> offsets(size);
-  uptr *vb = coverage_data.data();
-  uptr *ve = vb + size;
-  SortArray(vb, size);
-  MemoryMappingLayout proc_maps(/*cache_enabled*/true);
-  uptr mb, me, off, prot;
-  InternalScopedString module(kMaxPathLength);
+void CoverageData::DumpAsBitSet() {
+  if (!common_flags()->coverage_bitset) return;
+  if (!size()) return;
+  InternalScopedBuffer<char> out(size());
   InternalScopedString path(kMaxPathLength);
-  for (int i = 0;
-       proc_maps.Next(&mb, &me, &off, module.data(), module.size(), &prot);
-       i++) {
-    if ((prot & MemoryMappingLayout::kProtectionExecute) == 0)
-      continue;
-    while (vb < ve && *vb < mb) vb++;
-    if (vb >= ve) break;
-    if (*vb < me) {
-      offsets.clear();
-      const uptr *old_vb = vb;
-      CHECK_LE(off, *vb);
-      for (; vb < ve && *vb < me; vb++) {
-        uptr diff = *vb - (i ? mb : 0) + off;
-        CHECK_LE(diff, 0xffffffffU);
-        offsets.push_back(static_cast<u32>(diff));
+  for (uptr m = 0; m < module_name_vec.size(); m++) {
+    uptr n_set_bits = 0;
+    auto r = module_name_vec[m];
+    CHECK(r.copied_module_name);
+    CHECK_LE(r.beg, r.end);
+    CHECK_LE(r.end, size());
+    for (uptr i = r.beg; i < r.end; i++) {
+      uptr pc = UnbundlePc(pc_array[i]);
+      out[i] = pc ? '1' : '0';
+      if (pc)
+        n_set_bits++;
+    }
+    const char *base_name = StripModuleName(r.copied_module_name);
+    int fd = CovOpenFile(&path, /* packed */ false, base_name, "bitset-sancov");
+    if (fd < 0) return;
+    internal_write(fd, out.data() + r.beg, r.end - r.beg);
+    internal_close(fd);
+    VReport(1,
+            " CovDump: bitset of %zd bits written for '%s', %zd bits are set\n",
+            r.end - r.beg, base_name, n_set_bits);
+  }
+}
+
+void CoverageData::DumpOffsets() {
+  auto sym = Symbolizer::GetOrInit();
+  if (!common_flags()->coverage_pcs) return;
+  CHECK_NE(sym, nullptr);
+  InternalMmapVector<uptr> offsets(0);
+  InternalScopedString path(kMaxPathLength);
+  for (uptr m = 0; m < module_name_vec.size(); m++) {
+    offsets.clear();
+    uptr num_words_for_magic = SANITIZER_WORDSIZE == 64 ? 1 : 2;
+    for (uptr i = 0; i < num_words_for_magic; i++)
+      offsets.push_back(0);
+    auto r = module_name_vec[m];
+    CHECK(r.copied_module_name);
+    CHECK_LE(r.beg, r.end);
+    CHECK_LE(r.end, size());
+    for (uptr i = r.beg; i < r.end; i++) {
+      uptr pc = UnbundlePc(pc_array[i]);
+      uptr counter = UnbundleCounter(pc_array[i]);
+      if (!pc) continue; // Not visited.
+      const char *unused;
+      uptr offset = 0;
+      sym->GetModuleNameAndOffsetForPC(pc, &unused, &offset);
+      offsets.push_back(BundlePcAndCounter(offset, counter));
+    }
+
+    CHECK_GE(offsets.size(), num_words_for_magic);
+    SortArray(offsets.data(), offsets.size());
+    for (uptr i = 0; i < offsets.size(); i++)
+      offsets[i] = UnbundlePc(offsets[i]);
+
+    uptr num_offsets = offsets.size() - num_words_for_magic;
+    u64 *magic_p = reinterpret_cast<u64*>(offsets.data());
+    CHECK_EQ(*magic_p, 0ULL);
+    // FIXME: we may want to write 32-bit offsets even in 64-mode
+    // if all the offsets are small enough.
+    *magic_p = SANITIZER_WORDSIZE == 64 ? kMagic64 : kMagic32;
+
+    const char *module_name = StripModuleName(r.copied_module_name);
+    if (cov_sandboxed) {
+      if (cov_fd >= 0) {
+        CovWritePacked(internal_getpid(), module_name, offsets.data(),
+                       offsets.size() * sizeof(offsets[0]));
+        VReport(1, " CovDump: %zd PCs written to packed file\n", num_offsets);
       }
-      const char *module_name = StripModuleName(module.data());
-      if (cov_sandboxed) {
-        if (cov_fd >= 0) {
-          CovWritePacked(internal_getpid(), module_name, offsets.data(),
-                         offsets.size() * sizeof(u32));
-          VReport(1, " CovDump: %zd PCs written to packed file\n", vb - old_vb);
-        }
-      } else {
-        // One file per module per process.
-        path.clear();
-        path.append("%s/%s.%zd.sancov", coverage_dir, module_name,
-                    internal_getpid());
-        int fd = CovOpenFile(false /* packed */, module_name);
-        if (fd > 0) {
-          internal_write(fd, offsets.data(), offsets.size() * sizeof(u32));
-          internal_close(fd);
-          VReport(1, " CovDump: %s: %zd PCs written\n", path.data(),
-                  vb - old_vb);
-        }
-      }
+    } else {
+      // One file per module per process.
+      int fd = CovOpenFile(&path, false /* packed */, module_name);
+      if (fd < 0) continue;
+      internal_write(fd, offsets.data(), offsets.size() * sizeof(offsets[0]));
+      internal_close(fd);
+      VReport(1, " CovDump: %s: %zd PCs written\n", path.data(), num_offsets);
     }
   }
   if (cov_fd >= 0)
     internal_close(cov_fd);
-  coverage_data.DumpCallerCalleePairs();
-#endif  // !SANITIZER_WINDOWS
+}
+
+void CoverageData::DumpAll() {
+  if (!coverage_enabled || common_flags()->coverage_direct) return;
+  if (atomic_fetch_add(&dump_once_guard, 1, memory_order_relaxed))
+    return;
+  DumpAsBitSet();
+  DumpCounters();
+  DumpTrace();
+  DumpOffsets();
+  DumpCallerCalleePairs();
 }
 
 void CovPrepareForSandboxing(__sanitizer_sandbox_arguments *args) {
@@ -623,15 +807,18 @@
   if (!cov_sandboxed) return;
   cov_fd = args->coverage_fd;
   cov_max_block_size = args->coverage_max_block_size;
-  if (cov_fd < 0)
+  if (cov_fd < 0) {
+    InternalScopedString path(kMaxPathLength);
     // Pre-open the file now. The sandbox won't allow us to do it later.
-    cov_fd = CovOpenFile(true /* packed */, 0);
+    cov_fd = CovOpenFile(&path, true /* packed */, 0);
+  }
 }
 
 int MaybeOpenCovFile(const char *name) {
   CHECK(name);
   if (!coverage_enabled) return -1;
-  return CovOpenFile(true /* packed */, name);
+  InternalScopedString path(kMaxPathLength);
+  return CovOpenFile(&path, true /* packed */, name);
 }
 
 void CovBeforeFork() {
@@ -674,7 +861,8 @@
 }
 SANITIZER_INTERFACE_ATTRIBUTE void __sanitizer_cov_with_check(u32 *guard) {
   atomic_uint32_t *atomic_guard = reinterpret_cast<atomic_uint32_t*>(guard);
-  if (__sanitizer::atomic_load(atomic_guard, memory_order_relaxed))
+  if (static_cast<s32>(
+          __sanitizer::atomic_load(atomic_guard, memory_order_relaxed)) < 0)
     __sanitizer_cov(guard);
 }
 SANITIZER_INTERFACE_ATTRIBUTE void
@@ -687,10 +875,14 @@
   coverage_dir = common_flags()->coverage_dir;
   coverage_data.Init();
 }
-SANITIZER_INTERFACE_ATTRIBUTE void __sanitizer_cov_dump() { CovDump(); }
+SANITIZER_INTERFACE_ATTRIBUTE void __sanitizer_cov_dump() {
+  coverage_data.DumpAll();
+}
 SANITIZER_INTERFACE_ATTRIBUTE void
-__sanitizer_cov_module_init(s32 *guards, uptr npcs, const char *module_name) {
-  coverage_data.InitializeGuards(guards, npcs, module_name);
+__sanitizer_cov_module_init(s32 *guards, uptr npcs, u8 *counters,
+                            const char *comp_unit_name) {
+  coverage_data.InitializeGuards(guards, npcs, comp_unit_name, GET_CALLER_PC());
+  coverage_data.InitializeCounters(counters, npcs);
   if (!common_flags()->coverage_direct) return;
   if (SANITIZER_ANDROID && coverage_enabled) {
     // dlopen/dlclose interceptors do not work on Android, so we rely on
@@ -728,4 +920,14 @@
   *data = coverage_data.data();
   return coverage_data.size();
 }
+
+SANITIZER_INTERFACE_ATTRIBUTE
+uptr __sanitizer_get_number_of_counters() {
+  return coverage_data.GetNumberOf8bitCounters();
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE
+uptr __sanitizer_update_counter_bitset_and_clear_counters(u8 *bitset) {
+  return coverage_data.Update8bitCounterBitsetAndClearCounters(bitset);
+}
 }  // extern "C"
diff --git a/lib/sanitizer_common/sanitizer_coverage_mapping_libcdep.cc b/lib/sanitizer_common/sanitizer_coverage_mapping_libcdep.cc
index 6b5e91f..d3bde4b 100644
--- a/lib/sanitizer_common/sanitizer_coverage_mapping_libcdep.cc
+++ b/lib/sanitizer_common/sanitizer_coverage_mapping_libcdep.cc
@@ -102,7 +102,7 @@
                                "%s/%zd.sancov.map.tmp", coverage_dir,
                                internal_getpid());
   CHECK_LE(res, tmp_path.size());
-  uptr map_fd = OpenFile(tmp_path.data(), true);
+  uptr map_fd = OpenFile(tmp_path.data(), WrOnly);
   if (internal_iserror(map_fd, &err)) {
     Report(" Coverage: failed to open %s for writing: %d\n", tmp_path.data(),
            err);
diff --git a/lib/sanitizer_common/sanitizer_flags.inc b/lib/sanitizer_common/sanitizer_flags.inc
index 58f7f37..884602f 100644
--- a/lib/sanitizer_common/sanitizer_flags.inc
+++ b/lib/sanitizer_common/sanitizer_flags.inc
@@ -111,13 +111,18 @@
     bool, coverage, false,
     "If set, coverage information will be dumped at program shutdown (if the "
     "coverage instrumentation was enabled at compile time).")
-// On by default, but works only if coverage == true.
 COMMON_FLAG(bool, coverage_pcs, true,
             "If set (and if 'coverage' is set too), the coverage information "
             "will be dumped as a set of PC offsets for every module.")
+COMMON_FLAG(bool, coverage_order_pcs, false,
+             "If true, the PCs will be dumped in the order they've"
+             " appeared during the execution.")
 COMMON_FLAG(bool, coverage_bitset, false,
             "If set (and if 'coverage' is set too), the coverage information "
             "will also be dumped as a bitset to a separate file.")
+COMMON_FLAG(bool, coverage_counters, false,
+            "If set (and if 'coverage' is set too), the bitmap that corresponds"
+            " to coverage counters will be dumped.")
 COMMON_FLAG(bool, coverage_direct, SANITIZER_ANDROID,
             "If set, coverage information will be dumped directly to a memory "
             "mapped file. This way data is not lost even if the process is "
diff --git a/lib/sanitizer_common/sanitizer_linux.cc b/lib/sanitizer_common/sanitizer_linux.cc
index 8029181..8d2ea48 100644
--- a/lib/sanitizer_common/sanitizer_linux.cc
+++ b/lib/sanitizer_common/sanitizer_linux.cc
@@ -57,6 +57,7 @@
 #include <sys/syscall.h>
 #include <sys/time.h>
 #include <sys/types.h>
+#include <ucontext.h>
 #include <unistd.h>
 
 #if SANITIZER_FREEBSD
@@ -147,11 +148,6 @@
 #endif
 }
 
-uptr OpenFile(const char *filename, bool write) {
-  return internal_open(filename,
-      write ? O_RDWR | O_CREAT /*| O_CLOEXEC*/ : O_RDONLY, 0660);
-}
-
 uptr internal_read(fd_t fd, void *buf, uptr count) {
   sptr res;
   HANDLE_EINTR(res, (sptr)internal_syscall(SYSCALL(read), fd, (uptr)buf,
@@ -168,7 +164,8 @@
 
 uptr internal_ftruncate(fd_t fd, uptr size) {
   sptr res;
-  HANDLE_EINTR(res, (sptr)internal_syscall(SYSCALL(ftruncate), fd, size));
+  HANDLE_EINTR(res, (sptr)internal_syscall(SYSCALL(ftruncate), fd,
+               (OFF_T)size));
   return res;
 }
 
@@ -558,6 +555,7 @@
 }
 
 #if SANITIZER_LINUX
+#define SA_RESTORER 0x04000000
 // Doesn't set sa_restorer, use with caution (see below).
 int internal_sigaction_norestorer(int signum, const void *act, void *oldact) {
   __sanitizer_kernel_sigaction_t k_act, k_oldact;
@@ -570,7 +568,8 @@
     k_act.sigaction = u_act->sigaction;
     internal_memcpy(&k_act.sa_mask, &u_act->sa_mask,
                     sizeof(__sanitizer_kernel_sigset_t));
-    k_act.sa_flags = u_act->sa_flags;
+    // Without SA_RESTORER kernel ignores the calls (probably returns EINVAL).
+    k_act.sa_flags = u_act->sa_flags | SA_RESTORER;
     // FIXME: most often sa_restorer is unset, however the kernel requires it
     // to point to a valid signal restorer that calls the rt_sigreturn syscall.
     // If sa_restorer passed to the kernel is NULL, the program may crash upon
@@ -928,6 +927,78 @@
 void internal_join_thread(void *th) {}
 #endif
 
+void GetPcSpBp(void *context, uptr *pc, uptr *sp, uptr *bp) {
+#if defined(__arm__)
+  ucontext_t *ucontext = (ucontext_t*)context;
+  *pc = ucontext->uc_mcontext.arm_pc;
+  *bp = ucontext->uc_mcontext.arm_fp;
+  *sp = ucontext->uc_mcontext.arm_sp;
+#elif defined(__aarch64__)
+  ucontext_t *ucontext = (ucontext_t*)context;
+  *pc = ucontext->uc_mcontext.pc;
+  *bp = ucontext->uc_mcontext.regs[29];
+  *sp = ucontext->uc_mcontext.sp;
+#elif defined(__hppa__)
+  ucontext_t *ucontext = (ucontext_t*)context;
+  *pc = ucontext->uc_mcontext.sc_iaoq[0];
+  /* GCC uses %r3 whenever a frame pointer is needed.  */
+  *bp = ucontext->uc_mcontext.sc_gr[3];
+  *sp = ucontext->uc_mcontext.sc_gr[30];
+#elif defined(__x86_64__)
+# if SANITIZER_FREEBSD
+  ucontext_t *ucontext = (ucontext_t*)context;
+  *pc = ucontext->uc_mcontext.mc_rip;
+  *bp = ucontext->uc_mcontext.mc_rbp;
+  *sp = ucontext->uc_mcontext.mc_rsp;
+# else
+  ucontext_t *ucontext = (ucontext_t*)context;
+  *pc = ucontext->uc_mcontext.gregs[REG_RIP];
+  *bp = ucontext->uc_mcontext.gregs[REG_RBP];
+  *sp = ucontext->uc_mcontext.gregs[REG_RSP];
+# endif
+#elif defined(__i386__)
+# if SANITIZER_FREEBSD
+  ucontext_t *ucontext = (ucontext_t*)context;
+  *pc = ucontext->uc_mcontext.mc_eip;
+  *bp = ucontext->uc_mcontext.mc_ebp;
+  *sp = ucontext->uc_mcontext.mc_esp;
+# else
+  ucontext_t *ucontext = (ucontext_t*)context;
+  *pc = ucontext->uc_mcontext.gregs[REG_EIP];
+  *bp = ucontext->uc_mcontext.gregs[REG_EBP];
+  *sp = ucontext->uc_mcontext.gregs[REG_ESP];
+# endif
+#elif defined(__powerpc__) || defined(__powerpc64__)
+  ucontext_t *ucontext = (ucontext_t*)context;
+  *pc = ucontext->uc_mcontext.regs->nip;
+  *sp = ucontext->uc_mcontext.regs->gpr[PT_R1];
+  // The powerpc{,64}-linux ABIs do not specify r31 as the frame
+  // pointer, but GCC always uses r31 when we need a frame pointer.
+  *bp = ucontext->uc_mcontext.regs->gpr[PT_R31];
+#elif defined(__sparc__)
+  ucontext_t *ucontext = (ucontext_t*)context;
+  uptr *stk_ptr;
+# if defined (__arch64__)
+  *pc = ucontext->uc_mcontext.mc_gregs[MC_PC];
+  *sp = ucontext->uc_mcontext.mc_gregs[MC_O6];
+  stk_ptr = (uptr *) (*sp + 2047);
+  *bp = stk_ptr[15];
+# else
+  *pc = ucontext->uc_mcontext.gregs[REG_PC];
+  *sp = ucontext->uc_mcontext.gregs[REG_O6];
+  stk_ptr = (uptr *) *sp;
+  *bp = stk_ptr[15];
+# endif
+#elif defined(__mips__)
+  ucontext_t *ucontext = (ucontext_t*)context;
+  *pc = ucontext->uc_mcontext.gregs[31];
+  *bp = ucontext->uc_mcontext.gregs[30];
+  *sp = ucontext->uc_mcontext.gregs[29];
+#else
+# error "Unsupported arch"
+#endif
+}
+
 }  // namespace __sanitizer
 
 #endif  // SANITIZER_FREEBSD || SANITIZER_LINUX
diff --git a/lib/sanitizer_common/sanitizer_linux.h b/lib/sanitizer_common/sanitizer_linux.h
index b2e603d..2ce2025 100644
--- a/lib/sanitizer_common/sanitizer_linux.h
+++ b/lib/sanitizer_common/sanitizer_linux.h
@@ -80,8 +80,6 @@
 // information).
 bool LibraryNameIs(const char *full_name, const char *base_name);
 
-// Read the name of the current binary from /proc/self/exe.
-uptr ReadBinaryName(/*out*/char *buf, uptr buf_len);
 // Cache the value of /proc/self/exe.
 void CacheBinaryName();
 
diff --git a/lib/sanitizer_common/sanitizer_linux_libcdep.cc b/lib/sanitizer_common/sanitizer_linux_libcdep.cc
index c71b625..1c099d8 100644
--- a/lib/sanitizer_common/sanitizer_linux_libcdep.cc
+++ b/lib/sanitizer_common/sanitizer_linux_libcdep.cc
@@ -488,7 +488,7 @@
 uptr GetRSS() {
   if (!common_flags()->can_use_proc_maps_statm)
     return GetRSSFromGetrusage();
-  uptr fd = OpenFile("/proc/self/statm", false);
+  uptr fd = OpenFile("/proc/self/statm", RdOnly);
   if ((sptr)fd < 0)
     return GetRSSFromGetrusage();
   char buf[64];
diff --git a/lib/sanitizer_common/sanitizer_mac.cc b/lib/sanitizer_common/sanitizer_mac.cc
index 39a5c7e..91a5b7d 100644
--- a/lib/sanitizer_common/sanitizer_mac.cc
+++ b/lib/sanitizer_common/sanitizer_mac.cc
@@ -31,9 +31,11 @@
 
 #include <crt_externs.h>  // for _NSGetEnviron
 #include <fcntl.h>
+#include <mach-o/dyld.h>
 #include <pthread.h>
 #include <sched.h>
 #include <signal.h>
+#include <stdlib.h>
 #include <sys/mman.h>
 #include <sys/resource.h>
 #include <sys/stat.h>
@@ -69,11 +71,6 @@
   return open(filename, flags, mode);
 }
 
-uptr OpenFile(const char *filename, bool write) {
-  return internal_open(filename,
-      write ? O_WRONLY | O_CREAT : O_RDONLY, 0660);
-}
-
 uptr internal_read(fd_t fd, void *buf, uptr count) {
   return read(fd, buf, count);
 }
@@ -204,6 +201,21 @@
   return 0;
 }
 
+uptr ReadBinaryName(/*out*/char *buf, uptr buf_len) {
+  CHECK_LE(kMaxPathLength, buf_len);
+
+  // On OS X the executable path is saved to the stack by dyld. Reading it
+  // from there is much faster than calling dladdr, especially for large
+  // binaries with symbols.
+  InternalScopedString exe_path(kMaxPathLength);
+  uint32_t size = exe_path.size();
+  if (_NSGetExecutablePath(exe_path.data(), &size) == 0 &&
+      realpath(exe_path.data(), buf) != 0) {
+    return internal_strlen(buf);
+  }
+  return 0;
+}
+
 void ReExec() {
   UNIMPLEMENTED();
 }
@@ -328,6 +340,19 @@
 void *internal_start_thread(void (*func)(void *arg), void *arg) { return 0; }
 void internal_join_thread(void *th) { }
 
+void GetPcSpBp(void *context, uptr *pc, uptr *sp, uptr *bp) {
+  ucontext_t *ucontext = (ucontext_t*)context;
+# if SANITIZER_WORDSIZE == 64
+  *pc = ucontext->uc_mcontext->__ss.__rip;
+  *bp = ucontext->uc_mcontext->__ss.__rbp;
+  *sp = ucontext->uc_mcontext->__ss.__rsp;
+# else
+  *pc = ucontext->uc_mcontext->__ss.__eip;
+  *bp = ucontext->uc_mcontext->__ss.__ebp;
+  *sp = ucontext->uc_mcontext->__ss.__esp;
+# endif  // SANITIZER_WORDSIZE
+}
+
 }  // namespace __sanitizer
 
 #endif  // SANITIZER_MAC
diff --git a/lib/sanitizer_common/sanitizer_posix.cc b/lib/sanitizer_common/sanitizer_posix.cc
index 5bc41c2..5e01212 100644
--- a/lib/sanitizer_common/sanitizer_posix.cc
+++ b/lib/sanitizer_common/sanitizer_posix.cc
@@ -20,6 +20,8 @@
 #include "sanitizer_procmaps.h"
 #include "sanitizer_stacktrace.h"
 
+#include <fcntl.h>
+#include <signal.h>
 #include <sys/mman.h>
 
 #if SANITIZER_LINUX
@@ -47,7 +49,7 @@
 #if SANITIZER_WORDSIZE == 32
 // Take care of unusable kernel area in top gigabyte.
 static uptr GetKernelAreaSize() {
-#if SANITIZER_LINUX
+#if SANITIZER_LINUX && !SANITIZER_X32
   const uptr gbyte = 1UL << 30;
 
   // Firstly check if there are writable segments
@@ -79,7 +81,7 @@
   return gbyte;
 #else
   return 0;
-#endif  // SANITIZER_LINUX
+#endif  // SANITIZER_LINUX && !SANITIZER_X32
 }
 #endif  // SANITIZER_WORDSIZE == 32
 
@@ -203,8 +205,18 @@
                                MAP_NORESERVE, -1, 0);
 }
 
+uptr OpenFile(const char *filename, FileAccessMode mode) {
+  int flags;
+  switch (mode) {
+    case RdOnly: flags = O_RDONLY; break;
+    case WrOnly: flags = O_WRONLY | O_CREAT; break;
+    case RdWr: flags = O_RDWR | O_CREAT; break;
+  }
+  return internal_open(filename, flags, 0660);
+}
+
 void *MapFileToMemory(const char *file_name, uptr *buff_size) {
-  uptr openrv = OpenFile(file_name, false);
+  uptr openrv = OpenFile(file_name, RdOnly);
   CHECK(!internal_iserror(openrv));
   fd_t fd = openrv;
   uptr fsize = internal_filesize(fd);
@@ -219,9 +231,10 @@
   uptr flags = MAP_SHARED;
   if (addr) flags |= MAP_FIXED;
   uptr p = internal_mmap(addr, size, PROT_READ | PROT_WRITE, flags, fd, offset);
-  if (internal_iserror(p)) {
-    Printf("could not map writable file (%zd, %zu, %zu): %zd\n", fd, offset,
-           size, p);
+  int mmap_errno = 0;
+  if (internal_iserror(p, &mmap_errno)) {
+    Printf("could not map writable file (%zd, %zu, %zu): %zd, errno: %d\n",
+           fd, offset, size, p, mmap_errno);
     return 0;
   }
   return (void *)p;
@@ -293,6 +306,14 @@
   return 0;
 }
 
+bool IsPathSeparator(const char c) {
+  return c == '/';
+}
+
+bool IsAbsolutePath(const char *path) {
+  return path != nullptr && IsPathSeparator(path[0]);
+}
+
 void ReportFile::Write(const char *buffer, uptr length) {
   SpinMutexLock l(mu);
   static const char *kWriteError =
@@ -319,6 +340,13 @@
   return false;
 }
 
+SignalContext SignalContext::Create(void *siginfo, void *context) {
+  uptr addr = (uptr)((siginfo_t*)siginfo)->si_addr;
+  uptr pc, sp, bp;
+  GetPcSpBp(context, &pc, &sp, &bp);
+  return SignalContext(context, addr, pc, sp, bp);
+}
+
 }  // namespace __sanitizer
 
 #endif  // SANITIZER_POSIX
diff --git a/lib/sanitizer_common/sanitizer_stoptheworld.h b/lib/sanitizer_common/sanitizer_stoptheworld.h
index a326467..aa6f5d8 100644
--- a/lib/sanitizer_common/sanitizer_stoptheworld.h
+++ b/lib/sanitizer_common/sanitizer_stoptheworld.h
@@ -59,7 +59,8 @@
 
 // Suspend all threads in the current process and run the callback on the list
 // of suspended threads. This function will resume the threads before returning.
-// The callback should not call any libc functions.
+// The callback should not call any libc functions. The callback must not call
+// exit() nor _exit() and instead return to the caller.
 // This function should NOT be called from multiple threads simultaneously.
 void StopTheWorld(StopTheWorldCallback callback, void *argument);
 
diff --git a/lib/sanitizer_common/sanitizer_stoptheworld_linux_libcdep.cc b/lib/sanitizer_common/sanitizer_stoptheworld_linux_libcdep.cc
index ad20e39..64e1c79 100644
--- a/lib/sanitizer_common/sanitizer_stoptheworld_linux_libcdep.cc
+++ b/lib/sanitizer_common/sanitizer_stoptheworld_linux_libcdep.cc
@@ -19,6 +19,7 @@
 #include "sanitizer_stoptheworld.h"
 
 #include "sanitizer_platform_limits_posix.h"
+#include "sanitizer_atomic.h"
 
 #include <errno.h>
 #include <sched.h> // for CLONE_* definitions
@@ -70,11 +71,25 @@
 COMPILER_CHECK(sizeof(SuspendedThreadID) == sizeof(pid_t));
 
 namespace __sanitizer {
+
+// Structure for passing arguments into the tracer thread.
+struct TracerThreadArgument {
+  StopTheWorldCallback callback;
+  void *callback_argument;
+  // The tracer thread waits on this mutex while the parent finishes its
+  // preparations.
+  BlockingMutex mutex;
+  // Tracer thread signals its completion by setting done.
+  atomic_uintptr_t done;
+  uptr parent_pid;
+};
+
 // This class handles thread suspending/unsuspending in the tracer thread.
 class ThreadSuspender {
  public:
-  explicit ThreadSuspender(pid_t pid)
-    : pid_(pid) {
+  explicit ThreadSuspender(pid_t pid, TracerThreadArgument *arg)
+    : arg(arg)
+    , pid_(pid) {
       CHECK_GE(pid, 0);
     }
   bool SuspendAllThreads();
@@ -83,6 +98,7 @@
   SuspendedThreadsList &suspended_threads_list() {
     return suspended_threads_list_;
   }
+  TracerThreadArgument *arg;
  private:
   SuspendedThreadsList suspended_threads_list_;
   pid_t pid_;
@@ -103,7 +119,7 @@
     VReport(1, "Could not attach to thread %d (errno %d).\n", tid, pterrno);
     return false;
   } else {
-    VReport(1, "Attached to thread %d.\n", tid);
+    VReport(2, "Attached to thread %d.\n", tid);
     // The thread is not guaranteed to stop before ptrace returns, so we must
     // wait on it. Note: if the thread receives a signal concurrently,
     // we can get notification about the signal before notification about stop.
@@ -143,7 +159,7 @@
     int pterrno;
     if (!internal_iserror(internal_ptrace(PTRACE_DETACH, tid, NULL, NULL),
                           &pterrno)) {
-      VReport(1, "Detached from thread %d.\n", tid);
+      VReport(2, "Detached from thread %d.\n", tid);
     } else {
       // Either the thread is dead, or we are already detached.
       // The latter case is possible, for instance, if this function was called
@@ -188,25 +204,23 @@
 static const int kSyncSignals[] = { SIGABRT, SIGILL, SIGFPE, SIGSEGV, SIGBUS,
                                     SIGXCPU, SIGXFSZ };
 
-// Structure for passing arguments into the tracer thread.
-struct TracerThreadArgument {
-  StopTheWorldCallback callback;
-  void *callback_argument;
-  // The tracer thread waits on this mutex while the parent finishes its
-  // preparations.
-  BlockingMutex mutex;
-  uptr parent_pid;
-};
-
 static DieCallbackType old_die_callback;
 
 // Signal handler to wake up suspended threads when the tracer thread dies.
-static void TracerThreadSignalHandler(int signum, void *siginfo, void *) {
-  if (thread_suspender_instance != NULL) {
+static void TracerThreadSignalHandler(int signum, void *siginfo, void *uctx) {
+  SignalContext ctx = SignalContext::Create(siginfo, uctx);
+  VPrintf(1, "Tracer caught signal %d: addr=0x%zx pc=0x%zx sp=0x%zx\n",
+      signum, ctx.addr, ctx.pc, ctx.sp);
+  ThreadSuspender *inst = thread_suspender_instance;
+  if (inst != NULL) {
     if (signum == SIGABRT)
-      thread_suspender_instance->KillAllThreads();
+      inst->KillAllThreads();
     else
-      thread_suspender_instance->ResumeAllThreads();
+      inst->ResumeAllThreads();
+    SetDieCallback(old_die_callback);
+    old_die_callback = NULL;
+    thread_suspender_instance = NULL;
+    atomic_store(&inst->arg->done, 1, memory_order_relaxed);
   }
   internal__exit((signum == SIGABRT) ? 1 : 2);
 }
@@ -218,10 +232,15 @@
   // point. So we correctly handle calls to Die() from within the callback, but
   // not those that happen before or after the callback. Hopefully there aren't
   // a lot of opportunities for that to happen...
-  if (thread_suspender_instance)
-    thread_suspender_instance->KillAllThreads();
+  ThreadSuspender *inst = thread_suspender_instance;
+  if (inst != NULL && stoptheworld_tracer_pid == internal_getpid()) {
+    inst->KillAllThreads();
+    thread_suspender_instance = NULL;
+  }
   if (old_die_callback)
     old_die_callback();
+  SetDieCallback(old_die_callback);
+  old_die_callback = NULL;
 }
 
 // Size of alternative stack for signal handlers in the tracer thread.
@@ -244,7 +263,7 @@
   old_die_callback = GetDieCallback();
   SetDieCallback(TracerThreadDieCallback);
 
-  ThreadSuspender thread_suspender(internal_getppid());
+  ThreadSuspender thread_suspender(internal_getppid(), tracer_thread_argument);
   // Global pointer for the signal handler.
   thread_suspender_instance = &thread_suspender;
 
@@ -276,11 +295,9 @@
     thread_suspender.ResumeAllThreads();
     exit_code = 0;
   }
-  // Note, this is a bad race. If TracerThreadDieCallback is already started
-  // in another thread and observed that thread_suspender_instance != 0,
-  // it can call KillAllThreads on the destroyed variable.
   SetDieCallback(old_die_callback);
   thread_suspender_instance = NULL;
+  atomic_store(&tracer_thread_argument->done, 1, memory_order_relaxed);
   return exit_code;
 }
 
@@ -354,6 +371,7 @@
   tracer_thread_argument.callback = callback;
   tracer_thread_argument.callback_argument = argument;
   tracer_thread_argument.parent_pid = internal_getpid();
+  atomic_store(&tracer_thread_argument.done, 0, memory_order_relaxed);
   const uptr kTracerStackSize = 2 * 1024 * 1024;
   ScopedStackSpaceWithGuard tracer_stack(kTracerStackSize);
   // Block the execution of TracerThread until after we have set ptrace
@@ -402,14 +420,27 @@
 #endif
     // Allow the tracer thread to start.
     tracer_thread_argument.mutex.Unlock();
-    // Since errno is shared between this thread and the tracer thread, we
-    // must avoid using errno while the tracer thread is running.
-    // At this point, any signal will either be blocked or kill us, so waitpid
-    // should never return (and set errno) while the tracer thread is alive.
-    uptr waitpid_status = internal_waitpid(tracer_pid, NULL, __WALL);
-    if (internal_iserror(waitpid_status, &local_errno))
+    // NOTE: errno is shared between this thread and the tracer thread.
+    // internal_waitpid() may call syscall() which can access/spoil errno,
+    // so we can't call it now. Instead we for the tracer thread to finish using
+    // the spin loop below. Man page for sched_yield() says "In the Linux
+    // implementation, sched_yield() always succeeds", so let's hope it does not
+    // spoil errno. Note that this spin loop runs only for brief periods before
+    // the tracer thread has suspended us and when it starts unblocking threads.
+    while (atomic_load(&tracer_thread_argument.done, memory_order_relaxed) == 0)
+      sched_yield();
+    // Now the tracer thread is about to exit and does not touch errno,
+    // wait for it.
+    for (;;) {
+      uptr waitpid_status = internal_waitpid(tracer_pid, NULL, __WALL);
+      if (!internal_iserror(waitpid_status, &local_errno))
+        break;
+      if (local_errno == EINTR)
+        continue;
       VReport(1, "Waiting on the tracer thread failed (errno %d).\n",
               local_errno);
+      break;
+    }
   }
 }
 
diff --git a/lib/sanitizer_common/sanitizer_suppressions.cc b/lib/sanitizer_common/sanitizer_suppressions.cc
index 2b697e9..8009b4d 100644
--- a/lib/sanitizer_common/sanitizer_suppressions.cc
+++ b/lib/sanitizer_common/sanitizer_suppressions.cc
@@ -30,18 +30,50 @@
   internal_memset(has_suppression_type_, 0, suppression_types_num_);
 }
 
+static bool GetPathAssumingFileIsRelativeToExec(const char *file_path,
+                                                /*out*/char *new_file_path,
+                                                uptr new_file_path_size) {
+  InternalScopedString exec(kMaxPathLength);
+  if (ReadBinaryName(exec.data(), exec.size())) {
+    const char *file_name_pos = StripModuleName(exec.data());
+    uptr path_to_exec_len = file_name_pos - exec.data();
+    internal_strncat(new_file_path, exec.data(),
+                     Min(path_to_exec_len, new_file_path_size - 1));
+    internal_strncat(new_file_path, file_path,
+                     new_file_path_size - internal_strlen(new_file_path) - 1);
+    return true;
+  }
+  return false;
+}
+
 void SuppressionContext::ParseFromFile(const char *filename) {
   if (filename[0] == '\0')
     return;
+
+  // If we cannot find the file, check if its location is relative to
+  // the location of the executable.
+  InternalScopedString new_file_path(kMaxPathLength);
+  if (!FileExists(filename) && !IsAbsolutePath(filename) &&
+      GetPathAssumingFileIsRelativeToExec(filename, new_file_path.data(),
+                                          new_file_path.size())) {
+    filename = new_file_path.data();
+  }
+
+  // Read the file.
   char *file_contents;
   uptr buffer_size;
-  uptr contents_size = ReadFileToBuffer(filename, &file_contents, &buffer_size,
-                                        1 << 26 /* max_len */);
+  const uptr max_len = 1 << 26;
+  uptr contents_size =
+    ReadFileToBuffer(filename, &file_contents, &buffer_size, max_len);
+  VPrintf(1, "%s: reading suppressions file at %s\n",
+          SanitizerToolName, filename);
+
   if (contents_size == 0) {
     Printf("%s: failed to read suppressions file '%s'\n", SanitizerToolName,
            filename);
     Die();
   }
+
   Parse(file_contents);
 }
 
diff --git a/lib/sanitizer_common/sanitizer_symbolizer.cc b/lib/sanitizer_common/sanitizer_symbolizer.cc
index 135720e..df7661a 100644
--- a/lib/sanitizer_common/sanitizer_symbolizer.cc
+++ b/lib/sanitizer_common/sanitizer_symbolizer.cc
@@ -16,7 +16,7 @@
 #include "sanitizer_internal_defs.h"
 #include "sanitizer_libc.h"
 #include "sanitizer_placement_new.h"
-#include "sanitizer_symbolizer.h"
+#include "sanitizer_symbolizer_internal.h"
 
 namespace __sanitizer {
 
@@ -33,9 +33,7 @@
   function_offset = kUnknown;
 }
 
-void AddressInfo::FillAddressAndModuleInfo(uptr addr, const char *mod_name,
-                                           uptr mod_offset) {
-  address = addr;
+void AddressInfo::FillModuleInfo(const char *mod_name, uptr mod_offset) {
   module = internal_strdup(mod_name);
   module_offset = mod_offset;
 }
@@ -70,13 +68,6 @@
 StaticSpinMutex Symbolizer::init_mu_;
 LowLevelAllocator Symbolizer::symbolizer_allocator_;
 
-Symbolizer *Symbolizer::Disable() {
-  CHECK_EQ(0, symbolizer_);
-  // Initialize a dummy symbolizer.
-  symbolizer_ = new(symbolizer_allocator_) Symbolizer;
-  return symbolizer_;
-}
-
 void Symbolizer::AddHooks(Symbolizer::StartSymbolizationHook start_hook,
                           Symbolizer::EndSymbolizationHook end_hook) {
   CHECK(start_hook_ == 0 && end_hook_ == 0);
@@ -84,7 +75,8 @@
   end_hook_ = end_hook;
 }
 
-Symbolizer::Symbolizer() : start_hook_(0), end_hook_(0) {}
+Symbolizer::Symbolizer(IntrusiveList<SymbolizerTool> tools)
+    : tools_(tools), start_hook_(0), end_hook_(0) {}
 
 Symbolizer::SymbolizerScope::SymbolizerScope(const Symbolizer *sym)
     : sym_(sym) {
@@ -97,4 +89,76 @@
     sym_->end_hook_();
 }
 
+SymbolizedStack *Symbolizer::SymbolizePC(uptr addr) {
+  BlockingMutexLock l(&mu_);
+  const char *module_name;
+  uptr module_offset;
+  SymbolizedStack *res = SymbolizedStack::New(addr);
+  if (!PlatformFindModuleNameAndOffsetForAddress(addr, &module_name,
+                                                 &module_offset))
+    return res;
+  // Always fill data about module name and offset.
+  res->info.FillModuleInfo(module_name, module_offset);
+  for (auto iter = Iterator(&tools_); iter.hasNext();) {
+    auto *tool = iter.next();
+    SymbolizerScope sym_scope(this);
+    if (tool->SymbolizePC(addr, res)) {
+      return res;
+    }
+  }
+  return res;
+}
+
+bool Symbolizer::SymbolizeData(uptr addr, DataInfo *info) {
+  BlockingMutexLock l(&mu_);
+  const char *module_name;
+  uptr module_offset;
+  if (!PlatformFindModuleNameAndOffsetForAddress(addr, &module_name,
+                                                 &module_offset))
+    return false;
+  info->Clear();
+  info->module = internal_strdup(module_name);
+  info->module_offset = module_offset;
+  for (auto iter = Iterator(&tools_); iter.hasNext();) {
+    auto *tool = iter.next();
+    SymbolizerScope sym_scope(this);
+    if (tool->SymbolizeData(addr, info)) {
+      return true;
+    }
+  }
+  return true;
+}
+
+bool Symbolizer::GetModuleNameAndOffsetForPC(uptr pc, const char **module_name,
+                                 uptr *module_address) {
+  BlockingMutexLock l(&mu_);
+  return PlatformFindModuleNameAndOffsetForAddress(pc, module_name,
+                                                   module_address);
+}
+
+void Symbolizer::Flush() {
+  BlockingMutexLock l(&mu_);
+  for (auto iter = Iterator(&tools_); iter.hasNext();) {
+    auto *tool = iter.next();
+    SymbolizerScope sym_scope(this);
+    tool->Flush();
+  }
+}
+
+const char *Symbolizer::Demangle(const char *name) {
+  BlockingMutexLock l(&mu_);
+  for (auto iter = Iterator(&tools_); iter.hasNext();) {
+    auto *tool = iter.next();
+    SymbolizerScope sym_scope(this);
+    if (const char *demangled = tool->Demangle(name))
+      return demangled;
+  }
+  return PlatformDemangle(name);
+}
+
+void Symbolizer::PrepareForSandboxing() {
+  BlockingMutexLock l(&mu_);
+  PlatformPrepareForSandboxing();
+}
+
 }  // namespace __sanitizer
diff --git a/lib/sanitizer_common/sanitizer_symbolizer.h b/lib/sanitizer_common/sanitizer_symbolizer.h
index 3a80774..225da70 100644
--- a/lib/sanitizer_common/sanitizer_symbolizer.h
+++ b/lib/sanitizer_common/sanitizer_symbolizer.h
@@ -43,8 +43,7 @@
   AddressInfo();
   // Deletes all strings and resets all fields.
   void Clear();
-  void FillAddressAndModuleInfo(uptr addr, const char *mod_name,
-                                uptr mod_offset);
+  void FillModuleInfo(const char *mod_name, uptr mod_offset);
 };
 
 // Linked list of symbolized frames (each frame is described by AddressInfo).
@@ -74,6 +73,8 @@
   void Clear();
 };
 
+class SymbolizerTool;
+
 class Symbolizer {
  public:
   /// Initialize and return platform-specific implementation of symbolizer
@@ -81,26 +82,22 @@
   static Symbolizer *GetOrInit();
   // Returns a list of symbolized frames for a given address (containing
   // all inlined functions, if necessary).
-  virtual SymbolizedStack *SymbolizePC(uptr address) {
-    return SymbolizedStack::New(address);
-  }
-  virtual bool SymbolizeData(uptr address, DataInfo *info) {
-    return false;
-  }
-  virtual bool GetModuleNameAndOffsetForPC(uptr pc, const char **module_name,
-                                           uptr *module_address) {
-    return false;
-  }
-  virtual bool CanReturnFileLineInfo() {
-    return false;
+  SymbolizedStack *SymbolizePC(uptr address);
+  bool SymbolizeData(uptr address, DataInfo *info);
+  bool GetModuleNameAndOffsetForPC(uptr pc, const char **module_name,
+                                   uptr *module_address);
+  const char *GetModuleNameForPc(uptr pc) {
+    const char *module_name = 0;
+    uptr unused;
+    if (GetModuleNameAndOffsetForPC(pc, &module_name, &unused))
+      return module_name;
+    return nullptr;
   }
   // Release internal caches (if any).
-  virtual void Flush() {}
+  void Flush();
   // Attempts to demangle the provided C++ mangled name.
-  virtual const char *Demangle(const char *name) {
-    return name;
-  }
-  virtual void PrepareForSandboxing() {}
+  const char *Demangle(const char *name);
+  void PrepareForSandboxing();
 
   // Allow user to install hooks that would be called before/after Symbolizer
   // does the actual file/line info fetching. Specific sanitizers may need this
@@ -115,14 +112,28 @@
  private:
   /// Platform-specific function for creating a Symbolizer object.
   static Symbolizer *PlatformInit();
-  /// Initialize the symbolizer in a disabled state.  Not thread safe.
-  static Symbolizer *Disable();
+
+  virtual bool PlatformFindModuleNameAndOffsetForAddress(
+      uptr address, const char **module_name, uptr *module_offset) {
+    UNIMPLEMENTED();
+  }
+  // Platform-specific default demangler, must not return nullptr.
+  virtual const char *PlatformDemangle(const char *name) { UNIMPLEMENTED(); }
+  virtual void PlatformPrepareForSandboxing() { UNIMPLEMENTED(); }
 
   static Symbolizer *symbolizer_;
   static StaticSpinMutex init_mu_;
 
+  // Mutex locked from public methods of |Symbolizer|, so that the internals
+  // (including individual symbolizer tools and platform-specific methods) are
+  // always synchronized.
+  BlockingMutex mu_;
+
+  typedef IntrusiveList<SymbolizerTool>::Iterator Iterator;
+  IntrusiveList<SymbolizerTool> tools_;
+
  protected:
-  Symbolizer();
+  explicit Symbolizer(IntrusiveList<SymbolizerTool> tools);
 
   static LowLevelAllocator symbolizer_allocator_;
 
@@ -137,61 +148,6 @@
   };
 };
 
-class ExternalSymbolizerInterface {
- public:
-  // Can't declare pure virtual functions in sanitizer runtimes:
-  // __cxa_pure_virtual might be unavailable.
-  virtual char *SendCommand(bool is_data, const char *module_name,
-                            uptr module_offset) {
-    UNIMPLEMENTED();
-  }
-};
-
-// SymbolizerProcess encapsulates communication between the tool and
-// external symbolizer program, running in a different subprocess.
-// SymbolizerProcess may not be used from two threads simultaneously.
-class SymbolizerProcess : public ExternalSymbolizerInterface {
- public:
-  explicit SymbolizerProcess(const char *path);
-  char *SendCommand(bool is_data, const char *module_name,
-                    uptr module_offset) override;
-
- private:
-  bool Restart();
-  char *SendCommandImpl(bool is_data, const char *module_name,
-                        uptr module_offset);
-  bool ReadFromSymbolizer(char *buffer, uptr max_length);
-  bool WriteToSymbolizer(const char *buffer, uptr length);
-  bool StartSymbolizerSubprocess();
-
-  virtual bool RenderInputCommand(char *buffer, uptr max_length, bool is_data,
-                                  const char *module_name,
-                                  uptr module_offset) const {
-    UNIMPLEMENTED();
-  }
-
-  virtual bool ReachedEndOfOutput(const char *buffer, uptr length) const {
-    UNIMPLEMENTED();
-  }
-
-  virtual void ExecuteWithDefaultArgs(const char *path_to_binary) const {
-    UNIMPLEMENTED();
-  }
-
-  const char *path_;
-  int input_fd_;
-  int output_fd_;
-
-  static const uptr kBufferSize = 16 * 1024;
-  char buffer_[kBufferSize];
-
-  static const uptr kMaxTimesRestarted = 5;
-  static const int kSymbolizerStartupTimeMillis = 10;
-  uptr times_restarted_;
-  bool failed_to_start_;
-  bool reported_invalid_path_;
-};
-
 }  // namespace __sanitizer
 
 #endif  // SANITIZER_SYMBOLIZER_H
diff --git a/lib/sanitizer_common/sanitizer_symbolizer_internal.h b/lib/sanitizer_common/sanitizer_symbolizer_internal.h
new file mode 100644
index 0000000..66ae809
--- /dev/null
+++ b/lib/sanitizer_common/sanitizer_symbolizer_internal.h
@@ -0,0 +1,109 @@
+//===-- sanitizer_symbolizer_internal.h -------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Header for internal classes and functions to be used by implementations of
+// symbolizers.
+//
+//===----------------------------------------------------------------------===//
+#ifndef SANITIZER_SYMBOLIZER_INTERNAL_H
+#define SANITIZER_SYMBOLIZER_INTERNAL_H
+
+#include "sanitizer_symbolizer.h"
+
+namespace __sanitizer {
+
+// Parsing helpers, 'str' is searched for delimiter(s) and a string or uptr
+// is extracted. When extracting a string, a newly allocated (using
+// InternalAlloc) and null-terminataed buffer is returned. They return a pointer
+// to the next characted after the found delimiter.
+const char *ExtractToken(const char *str, const char *delims, char **result);
+const char *ExtractInt(const char *str, const char *delims, int *result);
+const char *ExtractUptr(const char *str, const char *delims, uptr *result);
+const char *ExtractTokenUpToDelimiter(const char *str, const char *delimiter,
+                                      char **result);
+
+const char *DemangleCXXABI(const char *name);
+
+// SymbolizerTool is an interface that is implemented by individual "tools"
+// that can perform symbolication (external llvm-symbolizer, libbacktrace,
+// Windows DbgHelp symbolizer, etc.).
+class SymbolizerTool {
+ public:
+  // The main |Symbolizer| class implements a "fallback chain" of symbolizer
+  // tools. In a request to symbolize an address, if one tool returns false,
+  // the next tool in the chain will be tried.
+  SymbolizerTool *next;
+
+  SymbolizerTool() : next(nullptr) { }
+
+  // Can't declare pure virtual functions in sanitizer runtimes:
+  // __cxa_pure_virtual might be unavailable.
+
+  // The |stack| parameter is inout. It is pre-filled with the address,
+  // module base and module offset values and is to be used to construct
+  // other stack frames.
+  virtual bool SymbolizePC(uptr addr, SymbolizedStack *stack) {
+    UNIMPLEMENTED();
+  }
+
+  // The |info| parameter is inout. It is pre-filled with the module base
+  // and module offset values.
+  virtual bool SymbolizeData(uptr addr, DataInfo *info) {
+    UNIMPLEMENTED();
+  }
+
+  virtual void Flush() {}
+
+  // Return nullptr to fallback to the default platform-specific demangler.
+  virtual const char *Demangle(const char *name) {
+    return nullptr;
+  }
+};
+
+// SymbolizerProcess encapsulates communication between the tool and
+// external symbolizer program, running in a different subprocess.
+// SymbolizerProcess may not be used from two threads simultaneously.
+class SymbolizerProcess {
+ public:
+  explicit SymbolizerProcess(const char *path, bool use_forkpty = false);
+  const char *SendCommand(const char *command);
+
+ private:
+  bool Restart();
+  const char *SendCommandImpl(const char *command);
+  bool ReadFromSymbolizer(char *buffer, uptr max_length);
+  bool WriteToSymbolizer(const char *buffer, uptr length);
+  bool StartSymbolizerSubprocess();
+
+  virtual bool ReachedEndOfOutput(const char *buffer, uptr length) const {
+    UNIMPLEMENTED();
+  }
+
+  virtual void ExecuteWithDefaultArgs(const char *path_to_binary) const {
+    UNIMPLEMENTED();
+  }
+
+  const char *path_;
+  int input_fd_;
+  int output_fd_;
+
+  static const uptr kBufferSize = 16 * 1024;
+  char buffer_[kBufferSize];
+
+  static const uptr kMaxTimesRestarted = 5;
+  static const int kSymbolizerStartupTimeMillis = 10;
+  uptr times_restarted_;
+  bool failed_to_start_;
+  bool reported_invalid_path_;
+  bool use_forkpty_;
+};
+
+}  // namespace __sanitizer
+
+#endif  // SANITIZER_SYMBOLIZER_INTERNAL_H
diff --git a/lib/sanitizer_common/sanitizer_symbolizer_libbacktrace.cc b/lib/sanitizer_common/sanitizer_symbolizer_libbacktrace.cc
index 9317a78..5735466 100644
--- a/lib/sanitizer_common/sanitizer_symbolizer_libbacktrace.cc
+++ b/lib/sanitizer_common/sanitizer_symbolizer_libbacktrace.cc
@@ -33,6 +33,8 @@
 
 namespace __sanitizer {
 
+static char *DemangleAlloc(const char *name, bool always_alloc);
+
 #if SANITIZER_LIBBACKTRACE
 
 namespace {
@@ -86,17 +88,20 @@
 struct SymbolizeCodeCallbackArg {
   SymbolizedStack *first;
   SymbolizedStack *last;
-  const char *module_name;
-  uptr module_offset;
+  uptr frames_symbolized;
 
-  void append(SymbolizedStack *f) {
-    if (last != nullptr) {
-      last->next = f;
-      last = f;
-    } else {
-      first = f;
-      last = f;
+  AddressInfo *get_new_frame(uintptr_t addr) {
+    CHECK(last);
+    if (frames_symbolized > 0) {
+      SymbolizedStack *cur = SymbolizedStack::New(addr);
+      AddressInfo *info = &cur->info;
+      info->FillModuleInfo(first->info.module, first->info.module_offset);
+      last->next = cur;
+      last = cur;
     }
+    CHECK_EQ(addr, first->info.address);
+    CHECK_EQ(addr, last->info.address);
+    return &last->info;
   }
 };
 
@@ -106,15 +111,12 @@
                                        const char *function) {
   SymbolizeCodeCallbackArg *cdata = (SymbolizeCodeCallbackArg *)vdata;
   if (function) {
-    SymbolizedStack *cur = SymbolizedStack::New(addr);
-    cdata->append(cur);
-    AddressInfo *info = &cur->info;
-    info->FillAddressAndModuleInfo(addr, cdata->module_name,
-                                   cdata->module_offset);
-    info->function = LibbacktraceSymbolizer::Demangle(function, true);
+    AddressInfo *info = cdata->get_new_frame(addr);
+    info->function = DemangleAlloc(function, /*always_alloc*/ true);
     if (filename)
       info->file = internal_strdup(filename);
     info->line = lineno;
+    cdata->frames_symbolized++;
   }
   return 0;
 }
@@ -123,12 +125,9 @@
                                   const char *symname, uintptr_t, uintptr_t) {
   SymbolizeCodeCallbackArg *cdata = (SymbolizeCodeCallbackArg *)vdata;
   if (symname) {
-    SymbolizedStack *cur = SymbolizedStack::New(addr);
-    cdata->append(cur);
-    AddressInfo *info = &cur->info;
-    info->FillAddressAndModuleInfo(addr, cdata->module_name,
-                                   cdata->module_offset);
-    info->function = LibbacktraceSymbolizer::Demangle(symname, true);
+    AddressInfo *info = cdata->get_new_frame(addr);
+    info->function = DemangleAlloc(symname, /*always_alloc*/ true);
+    cdata->frames_symbolized++;
   }
 }
 
@@ -136,7 +135,7 @@
                                   uintptr_t symval, uintptr_t symsize) {
   DataInfo *info = (DataInfo *)vdata;
   if (symname && symval) {
-    info->name = LibbacktraceSymbolizer::Demangle(symname, true);
+    info->name = DemangleAlloc(symname, /*always_alloc*/ true);
     info->start = symval;
     info->size = symsize;
   }
@@ -156,21 +155,18 @@
   return new(*alloc) LibbacktraceSymbolizer(state);
 }
 
-SymbolizedStack *LibbacktraceSymbolizer::SymbolizeCode(uptr addr,
-                                                       const char *module_name,
-                                                       uptr module_offset) {
+bool LibbacktraceSymbolizer::SymbolizePC(uptr addr, SymbolizedStack *stack) {
   SymbolizeCodeCallbackArg data;
-  data.first = nullptr;
-  data.last = nullptr;
-  data.module_name = module_name;
-  data.module_offset = module_offset;
+  data.first = stack;
+  data.last = stack;
+  data.frames_symbolized = 0;
   backtrace_pcinfo((backtrace_state *)state_, addr, SymbolizeCodePCInfoCallback,
                    ErrorCallback, &data);
-  if (data.first)
-    return data.first;
+  if (data.frames_symbolized > 0)
+    return true;
   backtrace_syminfo((backtrace_state *)state_, addr, SymbolizeCodeCallback,
                     ErrorCallback, &data);
-  return data.first;
+  return (data.frames_symbolized > 0);
 }
 
 bool LibbacktraceSymbolizer::SymbolizeData(uptr addr, DataInfo *info) {
@@ -185,11 +181,9 @@
   return 0;
 }
 
-SymbolizedStack *LibbacktraceSymbolizer::SymbolizeCode(uptr addr,
-                                                       const char *module_name,
-                                                       uptr module_offset) {
+bool LibbacktraceSymbolizer::SymbolizePC(uptr addr, SymbolizedStack *stack) {
   (void)state_;
-  return nullptr;
+  return false;
 }
 
 bool LibbacktraceSymbolizer::SymbolizeData(uptr addr, DataInfo *info) {
@@ -198,7 +192,7 @@
 
 #endif  // SANITIZER_LIBBACKTRACE
 
-char *LibbacktraceSymbolizer::Demangle(const char *name, bool always_alloc) {
+static char *DemangleAlloc(const char *name, bool always_alloc) {
 #if SANITIZER_LIBBACKTRACE && SANITIZER_CP_DEMANGLE
   if (char *demangled = CplusV3Demangle(name))
     return demangled;
@@ -208,4 +202,8 @@
   return 0;
 }
 
+const char *LibbacktraceSymbolizer::Demangle(const char *name) {
+  return DemangleAlloc(name, /*always_alloc*/ false);
+}
+
 }  // namespace __sanitizer
diff --git a/lib/sanitizer_common/sanitizer_symbolizer_libbacktrace.h b/lib/sanitizer_common/sanitizer_symbolizer_libbacktrace.h
index 1ff0050..00b465a 100644
--- a/lib/sanitizer_common/sanitizer_symbolizer_libbacktrace.h
+++ b/lib/sanitizer_common/sanitizer_symbolizer_libbacktrace.h
@@ -16,7 +16,7 @@
 
 #include "sanitizer_platform.h"
 #include "sanitizer_common.h"
-#include "sanitizer_symbolizer.h"
+#include "sanitizer_symbolizer_internal.h"
 
 #ifndef SANITIZER_LIBBACKTRACE
 # define SANITIZER_LIBBACKTRACE 0
@@ -28,17 +28,16 @@
 
 namespace __sanitizer {
 
-class LibbacktraceSymbolizer {
+class LibbacktraceSymbolizer : public SymbolizerTool {
  public:
   static LibbacktraceSymbolizer *get(LowLevelAllocator *alloc);
 
-  SymbolizedStack *SymbolizeCode(uptr addr, const char *module_name,
-                                 uptr module_offset);
+  bool SymbolizePC(uptr addr, SymbolizedStack *stack) override;
 
-  bool SymbolizeData(uptr addr, DataInfo *info);
+  bool SymbolizeData(uptr addr, DataInfo *info) override;
 
   // May return NULL if demangling failed.
-  static char *Demangle(const char *name, bool always_alloc = false);
+  const char *Demangle(const char *name) override;
 
  private:
   explicit LibbacktraceSymbolizer(void *state) : state_(state) {}
diff --git a/lib/sanitizer_common/sanitizer_symbolizer_libcdep.cc b/lib/sanitizer_common/sanitizer_symbolizer_libcdep.cc
index 63c9356..f1e2289 100644
--- a/lib/sanitizer_common/sanitizer_symbolizer_libcdep.cc
+++ b/lib/sanitizer_common/sanitizer_symbolizer_libcdep.cc
@@ -11,18 +11,62 @@
 // run-time libraries.
 //===----------------------------------------------------------------------===//
 
+#include "sanitizer_allocator_internal.h"
 #include "sanitizer_internal_defs.h"
-#include "sanitizer_symbolizer.h"
+#include "sanitizer_symbolizer_internal.h"
 
 namespace __sanitizer {
 
+const char *ExtractToken(const char *str, const char *delims, char **result) {
+  uptr prefix_len = internal_strcspn(str, delims);
+  *result = (char*)InternalAlloc(prefix_len + 1);
+  internal_memcpy(*result, str, prefix_len);
+  (*result)[prefix_len] = '\0';
+  const char *prefix_end = str + prefix_len;
+  if (*prefix_end != '\0') prefix_end++;
+  return prefix_end;
+}
+
+const char *ExtractInt(const char *str, const char *delims, int *result) {
+  char *buff;
+  const char *ret = ExtractToken(str, delims, &buff);
+  if (buff != 0) {
+    *result = (int)internal_atoll(buff);
+  }
+  InternalFree(buff);
+  return ret;
+}
+
+const char *ExtractUptr(const char *str, const char *delims, uptr *result) {
+  char *buff;
+  const char *ret = ExtractToken(str, delims, &buff);
+  if (buff != 0) {
+    *result = (uptr)internal_atoll(buff);
+  }
+  InternalFree(buff);
+  return ret;
+}
+
+const char *ExtractTokenUpToDelimiter(const char *str, const char *delimiter,
+                                      char **result) {
+  const char *found_delimiter = internal_strstr(str, delimiter);
+  uptr prefix_len =
+      found_delimiter ? found_delimiter - str : internal_strlen(str);
+  *result = (char *)InternalAlloc(prefix_len + 1);
+  internal_memcpy(*result, str, prefix_len);
+  (*result)[prefix_len] = '\0';
+  const char *prefix_end = str + prefix_len;
+  if (*prefix_end != '\0') prefix_end += internal_strlen(delimiter);
+  return prefix_end;
+}
+
 Symbolizer *Symbolizer::GetOrInit() {
   SpinMutexLock l(&init_mu_);
   if (symbolizer_)
     return symbolizer_;
-  if ((symbolizer_ = PlatformInit()))
-    return symbolizer_;
-  return Disable();
+  symbolizer_ = PlatformInit();
+  CHECK(symbolizer_);
+  return symbolizer_;
 }
 
 }  // namespace __sanitizer
diff --git a/lib/sanitizer_common/sanitizer_symbolizer_mac.cc b/lib/sanitizer_common/sanitizer_symbolizer_mac.cc
new file mode 100644
index 0000000..c2397ef
--- /dev/null
+++ b/lib/sanitizer_common/sanitizer_symbolizer_mac.cc
@@ -0,0 +1,151 @@
+//===-- sanitizer_symbolizer_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 shared between various sanitizers' runtime libraries.
+//
+// Implementation of Mac-specific "atos" symbolizer.
+//===----------------------------------------------------------------------===//
+
+#include "sanitizer_platform.h"
+#if SANITIZER_MAC
+
+#include "sanitizer_allocator_internal.h"
+#include "sanitizer_mac.h"
+#include "sanitizer_symbolizer_mac.h"
+
+namespace __sanitizer {
+
+#include <dlfcn.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <sys/wait.h>
+#include <unistd.h>
+#include <util.h>
+
+bool DlAddrSymbolizer::SymbolizePC(uptr addr, SymbolizedStack *stack) {
+  Dl_info info;
+  int result = dladdr((const void *)addr, &info);
+  if (!result) return false;
+  const char *demangled = DemangleCXXABI(info.dli_sname);
+  stack->info.function = internal_strdup(demangled);
+  return true;
+}
+
+bool DlAddrSymbolizer::SymbolizeData(uptr addr, DataInfo *info) {
+  return false;
+}
+
+class AtosSymbolizerProcess : public SymbolizerProcess {
+ public:
+  explicit AtosSymbolizerProcess(const char *path, pid_t parent_pid)
+      : SymbolizerProcess(path, /*use_forkpty*/ true),
+        parent_pid_(parent_pid) {}
+
+ private:
+  bool ReachedEndOfOutput(const char *buffer, uptr length) const override {
+    return (length >= 1 && buffer[length - 1] == '\n');
+  }
+
+  void ExecuteWithDefaultArgs(const char *path_to_binary) const override {
+    // The `atos` binary has some issues with DYLD_ROOT_PATH on i386.
+    unsetenv("DYLD_ROOT_PATH");
+
+    char pid_str[16];
+    internal_snprintf(pid_str, sizeof(pid_str), "%d", parent_pid_);
+    if (GetMacosVersion() == MACOS_VERSION_MAVERICKS) {
+      // On Mavericks atos prints a deprecation warning which we suppress by
+      // passing -d. The warning isn't present on other OSX versions, even the
+      // newer ones.
+      execl(path_to_binary, path_to_binary, "-p", pid_str, "-d", (char *)0);
+    } else {
+      execl(path_to_binary, path_to_binary, "-p", pid_str, (char *)0);
+    }
+  }
+
+  pid_t parent_pid_;
+};
+
+static const char *kAtosErrorMessages[] = {
+  "atos cannot examine process",
+  "unable to get permission to examine process",
+  "An admin user name and password is required",
+  "could not load inserted library",
+  "architecture mismatch between analysis process",
+};
+
+static bool IsAtosErrorMessage(const char *str) {
+  for (uptr i = 0; i < ARRAY_SIZE(kAtosErrorMessages); i++) {
+    if (internal_strstr(str, kAtosErrorMessages[i])) {
+      return true;
+    }
+  }
+  return false;
+}
+
+static bool ParseCommandOutput(const char *str, SymbolizedStack *res) {
+  // Trim ending newlines.
+  char *trim;
+  ExtractTokenUpToDelimiter(str, "\n", &trim);
+
+  // The line from `atos` is in one of these formats:
+  //   myfunction (in library.dylib) (sourcefile.c:17)
+  //   myfunction (in library.dylib) + 0x1fe
+  //   0xdeadbeef (in library.dylib) + 0x1fe
+  //   0xdeadbeef (in library.dylib)
+  //   0xdeadbeef
+
+  if (IsAtosErrorMessage(trim)) {
+    Report("atos returned an error: %s\n", trim);
+    InternalFree(trim);
+    return false;
+  }
+
+  const char *rest = trim;
+  char *function_name;
+  rest = ExtractTokenUpToDelimiter(rest, " (in ", &function_name);
+  if (internal_strncmp(function_name, "0x", 2) != 0)
+    res->info.function = function_name;
+  else
+    InternalFree(function_name);
+  rest = ExtractTokenUpToDelimiter(rest, ") ", &res->info.module);
+
+  if (rest[0] == '(') {
+    rest++;
+    rest = ExtractTokenUpToDelimiter(rest, ":", &res->info.file);
+    char *extracted_line_number;
+    rest = ExtractTokenUpToDelimiter(rest, ")", &extracted_line_number);
+    res->info.line = internal_atoll(extracted_line_number);
+    InternalFree(extracted_line_number);
+  }
+
+  InternalFree(trim);
+  return true;
+}
+
+AtosSymbolizer::AtosSymbolizer(const char *path, LowLevelAllocator *allocator)
+    : process_(new(*allocator) AtosSymbolizerProcess(path, getpid())) {}
+
+bool AtosSymbolizer::SymbolizePC(uptr addr, SymbolizedStack *stack) {
+  if (!process_) return false;
+  char command[32];
+  internal_snprintf(command, sizeof(command), "0x%zx\n", addr);
+  const char *buf = process_->SendCommand(command);
+  if (!buf) return false;
+  if (!ParseCommandOutput(buf, stack)) {
+    process_ = nullptr;
+    return false;
+  }
+  return true;
+}
+
+bool AtosSymbolizer::SymbolizeData(uptr addr, DataInfo *info) { return false; }
+
+}  // namespace __sanitizer
+
+#endif  // SANITIZER_MAC
diff --git a/lib/sanitizer_common/sanitizer_symbolizer_mac.h b/lib/sanitizer_common/sanitizer_symbolizer_mac.h
new file mode 100644
index 0000000..068644d
--- /dev/null
+++ b/lib/sanitizer_common/sanitizer_symbolizer_mac.h
@@ -0,0 +1,48 @@
+//===-- sanitizer_symbolizer_mac.h ------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is shared between various sanitizers' runtime libraries.
+//
+// Header for Mac-specific "atos" symbolizer.
+//===----------------------------------------------------------------------===//
+
+#ifndef SANITIZER_SYMBOLIZER_MAC_H
+#define SANITIZER_SYMBOLIZER_MAC_H
+
+#include "sanitizer_platform.h"
+#if SANITIZER_MAC
+
+#include "sanitizer_symbolizer_internal.h"
+
+namespace __sanitizer {
+
+class DlAddrSymbolizer : public SymbolizerTool {
+ public:
+  bool SymbolizePC(uptr addr, SymbolizedStack *stack) override;
+  bool SymbolizeData(uptr addr, DataInfo *info) override;
+};
+
+class AtosSymbolizerProcess;
+
+class AtosSymbolizer : public SymbolizerTool {
+ public:
+  explicit AtosSymbolizer(const char *path, LowLevelAllocator *allocator);
+
+  bool SymbolizePC(uptr addr, SymbolizedStack *stack) override;
+  bool SymbolizeData(uptr addr, DataInfo *info) override;
+
+ private:
+  AtosSymbolizerProcess *process_;
+};
+
+} // namespace __sanitizer
+
+#endif  // SANITIZER_MAC
+
+#endif // SANITIZER_SYMBOLIZER_MAC_H
diff --git a/lib/sanitizer_common/sanitizer_symbolizer_posix_libcdep.cc b/lib/sanitizer_common/sanitizer_symbolizer_posix_libcdep.cc
index deb3429..189b0ab 100644
--- a/lib/sanitizer_common/sanitizer_symbolizer_posix_libcdep.cc
+++ b/lib/sanitizer_common/sanitizer_symbolizer_posix_libcdep.cc
@@ -21,12 +21,10 @@
 #include "sanitizer_linux.h"
 #include "sanitizer_placement_new.h"
 #include "sanitizer_procmaps.h"
-#include "sanitizer_symbolizer.h"
+#include "sanitizer_symbolizer_internal.h"
 #include "sanitizer_symbolizer_libbacktrace.h"
+#include "sanitizer_symbolizer_mac.h"
 
-#include <errno.h>
-#include <stdlib.h>
-#include <sys/wait.h>
 #include <unistd.h>
 
 // C++ demangling function, as required by Itanium C++ ABI. This is weak,
@@ -41,7 +39,7 @@
 namespace __sanitizer {
 
 // Attempts to demangle the name via __cxa_demangle from __cxxabiv1.
-static const char *DemangleCXXABI(const char *name) {
+const char *DemangleCXXABI(const char *name) {
   // FIXME: __cxa_demangle aggressively insists on allocating memory.
   // There's not much we can do about that, short of providing our
   // own demangler (libc++abi's implementation could be adapted so that
@@ -55,217 +53,6 @@
   return name;
 }
 
-// Extracts the prefix of "str" that consists of any characters not
-// present in "delims" string, and copies this prefix to "result", allocating
-// space for it.
-// Returns a pointer to "str" after skipping extracted prefix and first
-// delimiter char.
-static const char *ExtractToken(const char *str, const char *delims,
-                                char **result) {
-  uptr prefix_len = internal_strcspn(str, delims);
-  *result = (char*)InternalAlloc(prefix_len + 1);
-  internal_memcpy(*result, str, prefix_len);
-  (*result)[prefix_len] = '\0';
-  const char *prefix_end = str + prefix_len;
-  if (*prefix_end != '\0') prefix_end++;
-  return prefix_end;
-}
-
-// Same as ExtractToken, but converts extracted token to integer.
-static const char *ExtractInt(const char *str, const char *delims,
-                              int *result) {
-  char *buff;
-  const char *ret = ExtractToken(str, delims, &buff);
-  if (buff != 0) {
-    *result = (int)internal_atoll(buff);
-  }
-  InternalFree(buff);
-  return ret;
-}
-
-static const char *ExtractUptr(const char *str, const char *delims,
-                               uptr *result) {
-  char *buff;
-  const char *ret = ExtractToken(str, delims, &buff);
-  if (buff != 0) {
-    *result = (uptr)internal_atoll(buff);
-  }
-  InternalFree(buff);
-  return ret;
-}
-
-SymbolizerProcess::SymbolizerProcess(const char *path)
-    : path_(path),
-      input_fd_(kInvalidFd),
-      output_fd_(kInvalidFd),
-      times_restarted_(0),
-      failed_to_start_(false),
-      reported_invalid_path_(false) {
-  CHECK(path_);
-  CHECK_NE(path_[0], '\0');
-}
-
-char *SymbolizerProcess::SendCommand(bool is_data, const char *module_name,
-                                     uptr module_offset) {
-  for (; times_restarted_ < kMaxTimesRestarted; times_restarted_++) {
-    // Start or restart symbolizer if we failed to send command to it.
-    if (char *res = SendCommandImpl(is_data, module_name, module_offset))
-      return res;
-    Restart();
-  }
-  if (!failed_to_start_) {
-    Report("WARNING: Failed to use and restart external symbolizer!\n");
-    failed_to_start_ = true;
-  }
-  return 0;
-}
-
-bool SymbolizerProcess::Restart() {
-  if (input_fd_ != kInvalidFd)
-    internal_close(input_fd_);
-  if (output_fd_ != kInvalidFd)
-    internal_close(output_fd_);
-  return StartSymbolizerSubprocess();
-}
-
-char *SymbolizerProcess::SendCommandImpl(bool is_data, const char *module_name,
-                                         uptr module_offset) {
-  if (input_fd_ == kInvalidFd || output_fd_ == kInvalidFd)
-      return 0;
-  CHECK(module_name);
-  if (!RenderInputCommand(buffer_, kBufferSize, is_data, module_name,
-                          module_offset))
-      return 0;
-  if (!WriteToSymbolizer(buffer_, internal_strlen(buffer_)))
-      return 0;
-  if (!ReadFromSymbolizer(buffer_, kBufferSize))
-      return 0;
-  return buffer_;
-}
-
-bool SymbolizerProcess::ReadFromSymbolizer(char *buffer, uptr max_length) {
-  if (max_length == 0)
-    return true;
-  uptr read_len = 0;
-  while (true) {
-    uptr just_read = internal_read(input_fd_, buffer + read_len,
-                                   max_length - read_len - 1);
-    // We can't read 0 bytes, as we don't expect external symbolizer to close
-    // its stdout.
-    if (just_read == 0 || just_read == (uptr)-1) {
-      Report("WARNING: Can't read from symbolizer at fd %d\n", input_fd_);
-      return false;
-    }
-    read_len += just_read;
-    if (ReachedEndOfOutput(buffer, read_len))
-      break;
-  }
-  buffer[read_len] = '\0';
-  return true;
-}
-
-bool SymbolizerProcess::WriteToSymbolizer(const char *buffer, uptr length) {
-  if (length == 0)
-    return true;
-  uptr write_len = internal_write(output_fd_, buffer, length);
-  if (write_len == 0 || write_len == (uptr)-1) {
-    Report("WARNING: Can't write to symbolizer at fd %d\n", output_fd_);
-    return false;
-  }
-  return true;
-}
-
-bool SymbolizerProcess::StartSymbolizerSubprocess() {
-  if (!FileExists(path_)) {
-    if (!reported_invalid_path_) {
-      Report("WARNING: invalid path to external symbolizer!\n");
-      reported_invalid_path_ = true;
-    }
-    return false;
-  }
-
-  int *infd = NULL;
-  int *outfd = NULL;
-  // The client program may close its stdin and/or stdout and/or stderr
-  // thus allowing socketpair to reuse file descriptors 0, 1 or 2.
-  // In this case the communication between the forked processes may be
-  // broken if either the parent or the child tries to close or duplicate
-  // these descriptors. The loop below produces two pairs of file
-  // descriptors, each greater than 2 (stderr).
-  int sock_pair[5][2];
-  for (int i = 0; i < 5; i++) {
-    if (pipe(sock_pair[i]) == -1) {
-      for (int j = 0; j < i; j++) {
-        internal_close(sock_pair[j][0]);
-        internal_close(sock_pair[j][1]);
-      }
-      Report("WARNING: Can't create a socket pair to start "
-             "external symbolizer (errno: %d)\n", errno);
-      return false;
-    } else if (sock_pair[i][0] > 2 && sock_pair[i][1] > 2) {
-      if (infd == NULL) {
-        infd = sock_pair[i];
-      } else {
-        outfd = sock_pair[i];
-        for (int j = 0; j < i; j++) {
-          if (sock_pair[j] == infd) continue;
-          internal_close(sock_pair[j][0]);
-          internal_close(sock_pair[j][1]);
-        }
-        break;
-      }
-    }
-  }
-  CHECK(infd);
-  CHECK(outfd);
-
-  // Real fork() may call user callbacks registered with pthread_atfork().
-  int pid = internal_fork();
-  if (pid == -1) {
-    // Fork() failed.
-    internal_close(infd[0]);
-    internal_close(infd[1]);
-    internal_close(outfd[0]);
-    internal_close(outfd[1]);
-    Report("WARNING: failed to fork external symbolizer "
-           " (errno: %d)\n", errno);
-    return false;
-  } else if (pid == 0) {
-    // Child subprocess.
-    internal_close(STDOUT_FILENO);
-    internal_close(STDIN_FILENO);
-    internal_dup2(outfd[0], STDIN_FILENO);
-    internal_dup2(infd[1], STDOUT_FILENO);
-    internal_close(outfd[0]);
-    internal_close(outfd[1]);
-    internal_close(infd[0]);
-    internal_close(infd[1]);
-    for (int fd = sysconf(_SC_OPEN_MAX); fd > 2; fd--)
-      internal_close(fd);
-    ExecuteWithDefaultArgs(path_);
-    internal__exit(1);
-  }
-
-  // Continue execution in parent process.
-  internal_close(outfd[0]);
-  internal_close(infd[1]);
-  input_fd_ = infd[0];
-  output_fd_ = outfd[1];
-
-  // Check that symbolizer subprocess started successfully.
-  int pid_status;
-  SleepForMillis(kSymbolizerStartupTimeMillis);
-  int exited_pid = waitpid(pid, &pid_status, WNOHANG);
-  if (exited_pid != 0) {
-    // Either waitpid failed, or child has already exited.
-    Report("WARNING: external symbolizer didn't start up correctly!\n");
-    return false;
-  }
-
-  return true;
-}
-
-
 // Parses one or more two-line strings in the following format:
 //   <function_name>
 //   <file_name>:<line_number>[:<column_number>]
@@ -288,8 +75,7 @@
       top_frame = false;
     } else {
       cur = SymbolizedStack::New(res->info.address);
-      cur->info.FillAddressAndModuleInfo(res->info.address, res->info.module,
-                                         res->info.module_offset);
+      cur->info.FillModuleInfo(res->info.module, res->info.module_offset);
       last->next = cur;
       last = cur;
     }
@@ -343,13 +129,6 @@
   explicit LLVMSymbolizerProcess(const char *path) : SymbolizerProcess(path) {}
 
  private:
-  bool RenderInputCommand(char *buffer, uptr max_length, bool is_data,
-                          const char *module_name, uptr module_offset) const {
-    internal_snprintf(buffer, max_length, "%s\"%s\" 0x%zx\n",
-                      is_data ? "DATA " : "", module_name, module_offset);
-    return true;
-  }
-
   bool ReachedEndOfOutput(const char *buffer, uptr length) const {
     // Empty line marks the end of llvm-symbolizer output.
     return length >= 2 && buffer[length - 1] == '\n' &&
@@ -377,6 +156,44 @@
   }
 };
 
+class LLVMSymbolizer : public SymbolizerTool {
+ public:
+  explicit LLVMSymbolizer(const char *path, LowLevelAllocator *allocator)
+      : symbolizer_process_(new(*allocator) LLVMSymbolizerProcess(path)) {}
+
+  bool SymbolizePC(uptr addr, SymbolizedStack *stack) override {
+    if (const char *buf = SendCommand(/*is_data*/ false, stack->info.module,
+                                      stack->info.module_offset)) {
+      ParseSymbolizePCOutput(buf, stack);
+      return true;
+    }
+    return false;
+  }
+
+  bool SymbolizeData(uptr addr, DataInfo *info) override {
+    if (const char *buf =
+            SendCommand(/*is_data*/ true, info->module, info->module_offset)) {
+      ParseSymbolizeDataOutput(buf, info);
+      info->start += (addr - info->module_offset);  // Add the base address.
+      return true;
+    }
+    return false;
+  }
+
+ private:
+  const char *SendCommand(bool is_data, const char *module_name,
+                          uptr module_offset) {
+    CHECK(module_name);
+    internal_snprintf(buffer_, kBufferSize, "%s\"%s\" 0x%zx\n",
+                      is_data ? "DATA " : "", module_name, module_offset);
+    return symbolizer_process_->SendCommand(buffer_);
+  }
+
+  LLVMSymbolizerProcess *symbolizer_process_;
+  static const uptr kBufferSize = 16 * 1024;
+  char buffer_[kBufferSize];
+};
+
 class Addr2LineProcess : public SymbolizerProcess {
  public:
   Addr2LineProcess(const char *path, const char *module_name)
@@ -385,15 +202,6 @@
   const char *module_name() const { return module_name_; }
 
  private:
-  bool RenderInputCommand(char *buffer, uptr max_length, bool is_data,
-                          const char *module_name, uptr module_offset) const {
-    if (is_data)
-      return false;
-    CHECK_EQ(0, internal_strcmp(module_name, module_name_));
-    internal_snprintf(buffer, max_length, "0x%zx\n", module_offset);
-    return true;
-  }
-
   bool ReachedEndOfOutput(const char *buffer, uptr length) const {
     // Output should consist of two lines.
     int num_lines = 0;
@@ -413,16 +221,28 @@
   const char *module_name_;  // Owned, leaked.
 };
 
-class Addr2LinePool : public ExternalSymbolizerInterface {
+class Addr2LinePool : public SymbolizerTool {
  public:
   explicit Addr2LinePool(const char *addr2line_path,
                          LowLevelAllocator *allocator)
       : addr2line_path_(addr2line_path), allocator_(allocator),
         addr2line_pool_(16) {}
 
-  char *SendCommand(bool is_data, const char *module_name, uptr module_offset) {
-    if (is_data)
-      return 0;
+  bool SymbolizePC(uptr addr, SymbolizedStack *stack) override {
+    if (const char *buf =
+            SendCommand(stack->info.module, stack->info.module_offset)) {
+      ParseSymbolizePCOutput(buf, stack);
+      return true;
+    }
+    return false;
+  }
+
+  bool SymbolizeData(uptr addr, DataInfo *info) override {
+    return false;
+  }
+
+ private:
+  const char *SendCommand(const char *module_name, uptr module_offset) {
     Addr2LineProcess *addr2line = 0;
     for (uptr i = 0; i < addr2line_pool_.size(); ++i) {
       if (0 ==
@@ -436,10 +256,13 @@
           new(*allocator_) Addr2LineProcess(addr2line_path_, module_name);
       addr2line_pool_.push_back(addr2line);
     }
-    return addr2line->SendCommand(is_data, module_name, module_offset);
+    CHECK_EQ(0, internal_strcmp(module_name, addr2line->module_name()));
+    char buffer_[kBufferSize];
+    internal_snprintf(buffer_, kBufferSize, "0x%zx\n", module_offset);
+    return addr2line->SendCommand(buffer_);
   }
 
- private:
+  static const uptr kBufferSize = 32;
   const char *addr2line_path_;
   LowLevelAllocator *allocator_;
   InternalMmapVector<Addr2LineProcess*> addr2line_pool_;
@@ -460,10 +283,8 @@
                                    int MaxLength);
 }  // extern "C"
 
-class InternalSymbolizer {
+class InternalSymbolizer : public SymbolizerTool {
  public:
-  typedef bool (*SanitizerSymbolizeFn)(const char*, u64, char*, int);
-
   static InternalSymbolizer *get(LowLevelAllocator *alloc) {
     if (__sanitizer_symbolize_code != 0 &&
         __sanitizer_symbolize_data != 0) {
@@ -472,20 +293,29 @@
     return 0;
   }
 
-  char *SendCommand(bool is_data, const char *module_name, uptr module_offset) {
-    SanitizerSymbolizeFn symbolize_fn = is_data ? __sanitizer_symbolize_data
-                                                : __sanitizer_symbolize_code;
-    if (symbolize_fn(module_name, module_offset, buffer_, kBufferSize))
-      return buffer_;
-    return 0;
+  bool SymbolizePC(uptr addr, SymbolizedStack *stack) override {
+    bool result = __sanitizer_symbolize_code(
+        stack->info.module, stack->info.module_offset, buffer_, kBufferSize);
+    if (result) ParseSymbolizePCOutput(buffer_, stack);
+    return result;
   }
 
-  void Flush() {
+  bool SymbolizeData(uptr addr, DataInfo *info) override {
+    bool result = __sanitizer_symbolize_data(info->module, info->module_offset,
+                                             buffer_, kBufferSize);
+    if (result) {
+      ParseSymbolizeDataOutput(buffer_, info);
+      info->start += (addr - info->module_offset);  // Add the base address.
+    }
+    return result;
+  }
+
+  void Flush() override {
     if (__sanitizer_symbolize_flush)
       __sanitizer_symbolize_flush();
   }
 
-  const char *Demangle(const char *name) {
+  const char *Demangle(const char *name) override {
     if (__sanitizer_symbolize_demangle) {
       for (uptr res_length = 1024;
            res_length <= InternalSizeClassMap::kMaxSize;) {
@@ -512,146 +342,35 @@
 };
 #else  // SANITIZER_SUPPORTS_WEAK_HOOKS
 
-class InternalSymbolizer {
+class InternalSymbolizer : public SymbolizerTool {
  public:
   static InternalSymbolizer *get(LowLevelAllocator *alloc) { return 0; }
-  char *SendCommand(bool is_data, const char *module_name, uptr module_offset) {
-    return 0;
-  }
-  void Flush() { }
-  const char *Demangle(const char *name) { return name; }
 };
 
 #endif  // SANITIZER_SUPPORTS_WEAK_HOOKS
 
 class POSIXSymbolizer : public Symbolizer {
  public:
-  POSIXSymbolizer(ExternalSymbolizerInterface *external_symbolizer,
-                  InternalSymbolizer *internal_symbolizer,
-                  LibbacktraceSymbolizer *libbacktrace_symbolizer)
-      : Symbolizer(),
-        external_symbolizer_(external_symbolizer),
-        internal_symbolizer_(internal_symbolizer),
-        libbacktrace_symbolizer_(libbacktrace_symbolizer) {}
+  explicit POSIXSymbolizer(IntrusiveList<SymbolizerTool> tools)
+      : Symbolizer(tools), n_modules_(0), modules_fresh_(false) {}
 
-  SymbolizedStack *SymbolizePC(uptr addr) override {
-    BlockingMutexLock l(&mu_);
-    const char *module_name;
-    uptr module_offset;
-    if (!FindModuleNameAndOffsetForAddress(addr, &module_name, &module_offset))
-      return SymbolizedStack::New(addr);
-    // First, try to use libbacktrace symbolizer (if it's available).
-    if (libbacktrace_symbolizer_ != 0) {
-      mu_.CheckLocked();
-      if (SymbolizedStack *res = libbacktrace_symbolizer_->SymbolizeCode(
-              addr, module_name, module_offset))
-        return res;
-    }
-    // Always fill data about module name and offset.
-    SymbolizedStack *res = SymbolizedStack::New(addr);
-    res->info.FillAddressAndModuleInfo(addr, module_name, module_offset);
-
-    const char *str = SendCommand(false, module_name, module_offset);
-    if (str == 0) {
-      // Symbolizer was not initialized or failed.
-      return res;
-    }
-
-    ParseSymbolizePCOutput(str, res);
-    return res;
-  }
-
-  bool SymbolizeData(uptr addr, DataInfo *info) override {
-    BlockingMutexLock l(&mu_);
-    LoadedModule *module = FindModuleForAddress(addr);
-    if (module == 0)
-      return false;
-    const char *module_name = module->full_name();
-    uptr module_offset = addr - module->base_address();
-    info->Clear();
-    info->module = internal_strdup(module_name);
-    info->module_offset = module_offset;
-    // First, try to use libbacktrace symbolizer (if it's available).
-    if (libbacktrace_symbolizer_ != 0) {
-      mu_.CheckLocked();
-      if (libbacktrace_symbolizer_->SymbolizeData(addr, info))
-        return true;
-    }
-    const char *str = SendCommand(true, module_name, module_offset);
-    if (str == 0)
-      return true;
-    ParseSymbolizeDataOutput(str, info);
-    info->start += module->base_address();
-    return true;
-  }
-
-  bool GetModuleNameAndOffsetForPC(uptr pc, const char **module_name,
-                                   uptr *module_address) override {
-    BlockingMutexLock l(&mu_);
-    return FindModuleNameAndOffsetForAddress(pc, module_name, module_address);
-  }
-
-  bool CanReturnFileLineInfo() override {
-    return internal_symbolizer_ != 0 || external_symbolizer_ != 0 ||
-           libbacktrace_symbolizer_ != 0;
-  }
-
-  void Flush() override {
-    BlockingMutexLock l(&mu_);
-    if (internal_symbolizer_ != 0) {
-      SymbolizerScope sym_scope(this);
-      internal_symbolizer_->Flush();
-    }
-  }
-
-  const char *Demangle(const char *name) override {
-    BlockingMutexLock l(&mu_);
-    // Run hooks even if we don't use internal symbolizer, as cxxabi
-    // demangle may call system functions.
-    SymbolizerScope sym_scope(this);
-    // Try to use libbacktrace demangler (if available).
-    if (libbacktrace_symbolizer_ != 0) {
-      if (const char *demangled = libbacktrace_symbolizer_->Demangle(name))
-        return demangled;
-    }
-    if (internal_symbolizer_ != 0)
-      return internal_symbolizer_->Demangle(name);
+ private:
+  const char *PlatformDemangle(const char *name) override {
     return DemangleCXXABI(name);
   }
 
-  void PrepareForSandboxing() override {
+  void PlatformPrepareForSandboxing() override {
 #if SANITIZER_LINUX && !SANITIZER_ANDROID
-    BlockingMutexLock l(&mu_);
     // Cache /proc/self/exe on Linux.
     CacheBinaryName();
 #endif
   }
 
- private:
-  char *SendCommand(bool is_data, const char *module_name, uptr module_offset) {
-    mu_.CheckLocked();
-    // First, try to use internal symbolizer.
-    if (internal_symbolizer_) {
-      SymbolizerScope sym_scope(this);
-      return internal_symbolizer_->SendCommand(is_data, module_name,
-                                               module_offset);
-    }
-    // Otherwise, fall back to external symbolizer.
-    if (external_symbolizer_) {
-      SymbolizerScope sym_scope(this);
-      return external_symbolizer_->SendCommand(is_data, module_name,
-                                               module_offset);
-    }
-    return 0;
-  }
-
   LoadedModule *FindModuleForAddress(uptr address) {
-    mu_.CheckLocked();
     bool modules_were_reloaded = false;
-    if (modules_ == 0 || !modules_fresh_) {
-      modules_ = (LoadedModule*)(symbolizer_allocator_.Allocate(
-          kMaxNumberOfModuleContexts * sizeof(LoadedModule)));
-      CHECK(modules_);
+    if (!modules_fresh_) {
+      for (uptr i = 0; i < n_modules_; i++)
+        modules_[i].clear();
       n_modules_ = GetListOfModules(modules_, kMaxNumberOfModuleContexts,
                                     /* filter */ 0);
       CHECK_GT(n_modules_, 0);
@@ -675,9 +394,9 @@
     return 0;
   }
 
-  bool FindModuleNameAndOffsetForAddress(uptr address, const char **module_name,
-                                         uptr *module_offset) {
-    mu_.CheckLocked();
+  bool PlatformFindModuleNameAndOffsetForAddress(uptr address,
+                                                 const char **module_name,
+                                                 uptr *module_offset) override {
     LoadedModule *module = FindModuleForAddress(address);
     if (module == 0)
       return false;
@@ -688,53 +407,94 @@
 
   // 16K loaded modules should be enough for everyone.
   static const uptr kMaxNumberOfModuleContexts = 1 << 14;
-  LoadedModule *modules_;  // Array of module descriptions is leaked.
+  LoadedModule modules_[kMaxNumberOfModuleContexts];
   uptr n_modules_;
   // If stale, need to reload the modules before looking up addresses.
   bool modules_fresh_;
-  BlockingMutex mu_;
-
-  ExternalSymbolizerInterface *external_symbolizer_;  // Leaked.
-  InternalSymbolizer *const internal_symbolizer_;     // Leaked.
-  LibbacktraceSymbolizer *libbacktrace_symbolizer_;   // Leaked.
 };
 
-Symbolizer *Symbolizer::PlatformInit() {
-  if (!common_flags()->symbolize) {
-    return new(symbolizer_allocator_) POSIXSymbolizer(0, 0, 0);
+static SymbolizerTool *ChooseExternalSymbolizer(LowLevelAllocator *allocator) {
+  const char *path = common_flags()->external_symbolizer_path;
+  const char *binary_name = path ? StripModuleName(path) : "";
+  if (path && path[0] == '\0') {
+    VReport(2, "External symbolizer is explicitly disabled.\n");
+    return nullptr;
+  } else if (!internal_strcmp(binary_name, "llvm-symbolizer")) {
+    VReport(2, "Using llvm-symbolizer at user-specified path: %s\n", path);
+    return new(*allocator) LLVMSymbolizer(path, allocator);
+  } else if (!internal_strcmp(binary_name, "atos")) {
+#if SANITIZER_MAC
+    VReport(2, "Using atos at user-specified path: %s\n", path);
+    return new(*allocator) AtosSymbolizer(path, allocator);
+#else  // SANITIZER_MAC
+    Report("ERROR: Using `atos` is only supported on Darwin.\n");
+    Die();
+#endif  // SANITIZER_MAC
+  } else if (!internal_strcmp(binary_name, "addr2line")) {
+    VReport(2, "Using addr2line at user-specified path: %s\n", path);
+    return new(*allocator) Addr2LinePool(path, allocator);
+  } else if (path) {
+    Report("ERROR: External symbolizer path is set to '%s' which isn't "
+           "a known symbolizer. Please set the path to the llvm-symbolizer "
+           "binary or other known tool.\n", path);
+    Die();
   }
-  InternalSymbolizer* internal_symbolizer =
-      InternalSymbolizer::get(&symbolizer_allocator_);
-  ExternalSymbolizerInterface *external_symbolizer = 0;
-  LibbacktraceSymbolizer *libbacktrace_symbolizer = 0;
 
-  if (!internal_symbolizer) {
-    libbacktrace_symbolizer =
-        LibbacktraceSymbolizer::get(&symbolizer_allocator_);
-    if (!libbacktrace_symbolizer) {
-      const char *path_to_external = common_flags()->external_symbolizer_path;
-      if (path_to_external && path_to_external[0] == '\0') {
-        // External symbolizer is explicitly disabled. Do nothing.
-      } else {
-        // Find path to llvm-symbolizer if it's not provided.
-        if (!path_to_external)
-          path_to_external = FindPathToBinary("llvm-symbolizer");
-        if (path_to_external) {
-          external_symbolizer = new(symbolizer_allocator_)
-              LLVMSymbolizerProcess(path_to_external);
-        } else if (common_flags()->allow_addr2line) {
-          // If llvm-symbolizer is not found, try to use addr2line.
-          if (const char *addr2line_path = FindPathToBinary("addr2line")) {
-            external_symbolizer = new(symbolizer_allocator_)
-                Addr2LinePool(addr2line_path, &symbolizer_allocator_);
-          }
-        }
-      }
+  // Otherwise symbolizer program is unknown, let's search $PATH
+  CHECK(path == nullptr);
+  if (const char *found_path = FindPathToBinary("llvm-symbolizer")) {
+    VReport(2, "Using llvm-symbolizer found at: %s\n", found_path);
+    return new(*allocator) LLVMSymbolizer(found_path, allocator);
+  }
+#if SANITIZER_MAC
+  if (const char *found_path = FindPathToBinary("atos")) {
+    VReport(2, "Using atos found at: %s\n", found_path);
+    return new(*allocator) AtosSymbolizer(found_path, allocator);
+  }
+#endif  // SANITIZER_MAC
+  if (common_flags()->allow_addr2line) {
+    if (const char *found_path = FindPathToBinary("addr2line")) {
+      VReport(2, "Using addr2line found at: %s\n", found_path);
+      return new(*allocator) Addr2LinePool(found_path, allocator);
     }
   }
+  return nullptr;
+}
 
-  return new(symbolizer_allocator_) POSIXSymbolizer(
-      external_symbolizer, internal_symbolizer, libbacktrace_symbolizer);
+static void ChooseSymbolizerTools(IntrusiveList<SymbolizerTool> *list,
+                                  LowLevelAllocator *allocator) {
+  if (!common_flags()->symbolize) {
+    VReport(2, "Symbolizer is disabled.\n");
+    return;
+  }
+  if (SymbolizerTool *tool = InternalSymbolizer::get(allocator)) {
+    VReport(2, "Using internal symbolizer.\n");
+    list->push_back(tool);
+    return;
+  }
+  if (SymbolizerTool *tool = LibbacktraceSymbolizer::get(allocator)) {
+    VReport(2, "Using libbacktrace symbolizer.\n");
+    list->push_back(tool);
+    return;
+  }
+
+  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
+}
+
+Symbolizer *Symbolizer::PlatformInit() {
+  IntrusiveList<SymbolizerTool> list;
+  list.clear();
+  ChooseSymbolizerTools(&list, &symbolizer_allocator_);
+  return new(symbolizer_allocator_) POSIXSymbolizer(list);
 }
 
 }  // namespace __sanitizer
diff --git a/lib/sanitizer_common/sanitizer_symbolizer_process_libcdep.cc b/lib/sanitizer_common/sanitizer_symbolizer_process_libcdep.cc
new file mode 100644
index 0000000..98d16e0
--- /dev/null
+++ b/lib/sanitizer_common/sanitizer_symbolizer_process_libcdep.cc
@@ -0,0 +1,228 @@
+//===-- sanitizer_symbolizer_process_libcdep.cc ---------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Implementation of SymbolizerProcess used by external symbolizers.
+//
+//===----------------------------------------------------------------------===//
+
+#include "sanitizer_platform.h"
+#if SANITIZER_POSIX
+#include "sanitizer_symbolizer_internal.h"
+
+#include <errno.h>
+#include <stdlib.h>
+#include <sys/wait.h>
+#include <unistd.h>
+
+#if SANITIZER_MAC
+#include <util.h>  // for forkpty()
+#endif  // SANITIZER_MAC
+
+namespace __sanitizer {
+
+SymbolizerProcess::SymbolizerProcess(const char *path, bool use_forkpty)
+    : path_(path),
+      input_fd_(kInvalidFd),
+      output_fd_(kInvalidFd),
+      times_restarted_(0),
+      failed_to_start_(false),
+      reported_invalid_path_(false),
+      use_forkpty_(use_forkpty) {
+  CHECK(path_);
+  CHECK_NE(path_[0], '\0');
+}
+
+const char *SymbolizerProcess::SendCommand(const char *command) {
+  for (; times_restarted_ < kMaxTimesRestarted; times_restarted_++) {
+    // Start or restart symbolizer if we failed to send command to it.
+    if (const char *res = SendCommandImpl(command))
+      return res;
+    Restart();
+  }
+  if (!failed_to_start_) {
+    Report("WARNING: Failed to use and restart external symbolizer!\n");
+    failed_to_start_ = true;
+  }
+  return 0;
+}
+
+bool SymbolizerProcess::Restart() {
+  if (input_fd_ != kInvalidFd)
+    internal_close(input_fd_);
+  if (output_fd_ != kInvalidFd)
+    internal_close(output_fd_);
+  return StartSymbolizerSubprocess();
+}
+
+const char *SymbolizerProcess::SendCommandImpl(const char *command) {
+  if (input_fd_ == kInvalidFd || output_fd_ == kInvalidFd)
+      return 0;
+  if (!WriteToSymbolizer(command, internal_strlen(command)))
+      return 0;
+  if (!ReadFromSymbolizer(buffer_, kBufferSize))
+      return 0;
+  return buffer_;
+}
+
+bool SymbolizerProcess::ReadFromSymbolizer(char *buffer, uptr max_length) {
+  if (max_length == 0)
+    return true;
+  uptr read_len = 0;
+  while (true) {
+    uptr just_read = internal_read(input_fd_, buffer + read_len,
+                                   max_length - read_len - 1);
+    // We can't read 0 bytes, as we don't expect external symbolizer to close
+    // its stdout.
+    if (just_read == 0 || just_read == (uptr)-1) {
+      Report("WARNING: Can't read from symbolizer at fd %d\n", input_fd_);
+      return false;
+    }
+    read_len += just_read;
+    if (ReachedEndOfOutput(buffer, read_len))
+      break;
+  }
+  buffer[read_len] = '\0';
+  return true;
+}
+
+bool SymbolizerProcess::WriteToSymbolizer(const char *buffer, uptr length) {
+  if (length == 0)
+    return true;
+  uptr write_len = internal_write(output_fd_, buffer, length);
+  if (write_len == 0 || write_len == (uptr)-1) {
+    Report("WARNING: Can't write to symbolizer at fd %d\n", output_fd_);
+    return false;
+  }
+  return true;
+}
+
+bool SymbolizerProcess::StartSymbolizerSubprocess() {
+  if (!FileExists(path_)) {
+    if (!reported_invalid_path_) {
+      Report("WARNING: invalid path to external symbolizer!\n");
+      reported_invalid_path_ = true;
+    }
+    return false;
+  }
+
+  int pid;
+  if (use_forkpty_) {
+#if SANITIZER_MAC
+    fd_t fd = kInvalidFd;
+    // Use forkpty to disable buffering in the new terminal.
+    pid = forkpty(&fd, 0, 0, 0);
+    if (pid == -1) {
+      // forkpty() failed.
+      Report("WARNING: failed to fork external symbolizer (errno: %d)\n",
+             errno);
+      return false;
+    } else if (pid == 0) {
+      // Child subprocess.
+      ExecuteWithDefaultArgs(path_);
+      internal__exit(1);
+    }
+
+    // Continue execution in parent process.
+    input_fd_ = output_fd_ = fd;
+
+    // Disable echo in the new terminal, disable CR.
+    struct termios termflags;
+    tcgetattr(fd, &termflags);
+    termflags.c_oflag &= ~ONLCR;
+    termflags.c_lflag &= ~ECHO;
+    tcsetattr(fd, TCSANOW, &termflags);
+#else  // SANITIZER_MAC
+    UNIMPLEMENTED();
+#endif  // SANITIZER_MAC
+  } else {
+    int *infd = NULL;
+    int *outfd = NULL;
+    // The client program may close its stdin and/or stdout and/or stderr
+    // thus allowing socketpair to reuse file descriptors 0, 1 or 2.
+    // In this case the communication between the forked processes may be
+    // broken if either the parent or the child tries to close or duplicate
+    // these descriptors. The loop below produces two pairs of file
+    // descriptors, each greater than 2 (stderr).
+    int sock_pair[5][2];
+    for (int i = 0; i < 5; i++) {
+      if (pipe(sock_pair[i]) == -1) {
+        for (int j = 0; j < i; j++) {
+          internal_close(sock_pair[j][0]);
+          internal_close(sock_pair[j][1]);
+        }
+        Report("WARNING: Can't create a socket pair to start "
+               "external symbolizer (errno: %d)\n", errno);
+        return false;
+      } else if (sock_pair[i][0] > 2 && sock_pair[i][1] > 2) {
+        if (infd == NULL) {
+          infd = sock_pair[i];
+        } else {
+          outfd = sock_pair[i];
+          for (int j = 0; j < i; j++) {
+            if (sock_pair[j] == infd) continue;
+            internal_close(sock_pair[j][0]);
+            internal_close(sock_pair[j][1]);
+          }
+          break;
+        }
+      }
+    }
+    CHECK(infd);
+    CHECK(outfd);
+
+    // Real fork() may call user callbacks registered with pthread_atfork().
+    pid = internal_fork();
+    if (pid == -1) {
+      // Fork() failed.
+      internal_close(infd[0]);
+      internal_close(infd[1]);
+      internal_close(outfd[0]);
+      internal_close(outfd[1]);
+      Report("WARNING: failed to fork external symbolizer "
+             " (errno: %d)\n", errno);
+      return false;
+    } else if (pid == 0) {
+      // Child subprocess.
+      internal_close(STDOUT_FILENO);
+      internal_close(STDIN_FILENO);
+      internal_dup2(outfd[0], STDIN_FILENO);
+      internal_dup2(infd[1], STDOUT_FILENO);
+      internal_close(outfd[0]);
+      internal_close(outfd[1]);
+      internal_close(infd[0]);
+      internal_close(infd[1]);
+      for (int fd = sysconf(_SC_OPEN_MAX); fd > 2; fd--)
+        internal_close(fd);
+      ExecuteWithDefaultArgs(path_);
+      internal__exit(1);
+    }
+
+    // Continue execution in parent process.
+    internal_close(outfd[0]);
+    internal_close(infd[1]);
+    input_fd_ = infd[0];
+    output_fd_ = outfd[1];
+  }
+
+  // Check that symbolizer subprocess started successfully.
+  int pid_status;
+  SleepForMillis(kSymbolizerStartupTimeMillis);
+  int exited_pid = waitpid(pid, &pid_status, WNOHANG);
+  if (exited_pid != 0) {
+    // Either waitpid failed, or child has already exited.
+    Report("WARNING: external symbolizer didn't start up correctly!\n");
+    return false;
+  }
+
+  return true;
+}
+
+}  // namespace __sanitizer
+
+#endif  // SANITIZER_POSIX
diff --git a/lib/sanitizer_common/sanitizer_symbolizer_win.cc b/lib/sanitizer_common/sanitizer_symbolizer_win.cc
index ed96a3a..67ed4b3 100644
--- a/lib/sanitizer_common/sanitizer_symbolizer_win.cc
+++ b/lib/sanitizer_common/sanitizer_symbolizer_win.cc
@@ -18,139 +18,153 @@
 #include <dbghelp.h>
 #pragma comment(lib, "dbghelp.lib")
 
-#include "sanitizer_symbolizer.h"
+#include "sanitizer_symbolizer_win.h"
+#include "sanitizer_symbolizer_internal.h"
 
 namespace __sanitizer {
 
-class WinSymbolizer : public Symbolizer {
- public:
-  WinSymbolizer() : initialized_(false) {}
+namespace {
 
-  SymbolizedStack *SymbolizePC(uptr addr) override {
-    SymbolizedStack *frame = SymbolizedStack::New(addr);
+bool is_dbghelp_initialized = false;
 
-    BlockingMutexLock l(&dbghelp_mu_);
-    InitializeIfNeeded();
+bool TrySymInitialize() {
+  SymSetOptions(SYMOPT_DEFERRED_LOADS | SYMOPT_UNDNAME | SYMOPT_LOAD_LINES);
+  return SymInitialize(GetCurrentProcess(), 0, TRUE);
+  // FIXME: We don't call SymCleanup() on exit yet - should we?
+}
 
-    // See http://msdn.microsoft.com/en-us/library/ms680578(VS.85).aspx
-    char buffer[sizeof(SYMBOL_INFO) + MAX_SYM_NAME * sizeof(CHAR)];
-    PSYMBOL_INFO symbol = (PSYMBOL_INFO)buffer;
-    symbol->SizeOfStruct = sizeof(SYMBOL_INFO);
-    symbol->MaxNameLen = MAX_SYM_NAME;
-    DWORD64 offset = 0;
-    BOOL got_objname = SymFromAddr(GetCurrentProcess(),
-                                   (DWORD64)addr, &offset, symbol);
-    if (!got_objname)
-      return frame;
-
-    DWORD unused;
-    IMAGEHLP_LINE64 line_info;
-    line_info.SizeOfStruct = sizeof(IMAGEHLP_LINE64);
-    BOOL got_fileline = SymGetLineFromAddr64(GetCurrentProcess(), (DWORD64)addr,
-                                             &unused, &line_info);
-    frame->info.function = internal_strdup(symbol->Name);
-    frame->info.function_offset = (uptr)offset;
-    if (got_fileline) {
-      frame->info.file = internal_strdup(line_info.FileName);
-      frame->info.line = line_info.LineNumber;
-    }
-
-    IMAGEHLP_MODULE64 mod_info;
-    internal_memset(&mod_info, 0, sizeof(mod_info));
-    mod_info.SizeOfStruct = sizeof(mod_info);
-    if (SymGetModuleInfo64(GetCurrentProcess(), addr, &mod_info))
-      frame->info.FillAddressAndModuleInfo(addr, mod_info.ImageName,
-                                           addr - (uptr)mod_info.BaseOfImage);
-    return frame;
+// Initializes DbgHelp library, if it's not yet initialized. Calls to this
+// function should be synchronized with respect to other calls to DbgHelp API
+// (e.g. from WinSymbolizerTool).
+void InitializeDbgHelpIfNeeded() {
+  if (is_dbghelp_initialized)
+    return;
+  if (!TrySymInitialize()) {
+    // OK, maybe the client app has called SymInitialize already.
+    // That's a bit unfortunate for us as all the DbgHelp functions are
+    // single-threaded and we can't coordinate with the app.
+    // FIXME: Can we stop the other threads at this point?
+    // Anyways, we have to reconfigure stuff to make sure that SymInitialize
+    // has all the appropriate options set.
+    // Cross our fingers and reinitialize DbgHelp.
+    Report("*** WARNING: Failed to initialize DbgHelp!              ***\n");
+    Report("*** Most likely this means that the app is already      ***\n");
+    Report("*** using DbgHelp, possibly with incompatible flags.    ***\n");
+    Report("*** Due to technical reasons, symbolization might crash ***\n");
+    Report("*** or produce wrong results.                           ***\n");
+    SymCleanup(GetCurrentProcess());
+    TrySymInitialize();
   }
+  is_dbghelp_initialized = true;
 
-  bool CanReturnFileLineInfo() override {
+  // When an executable is run from a location different from the one where it
+  // was originally built, we may not see the nearby PDB files.
+  // To work around this, let's append the directory of the main module
+  // to the symbol search path.  All the failures below are not fatal.
+  const size_t kSymPathSize = 2048;
+  static wchar_t path_buffer[kSymPathSize + 1 + MAX_PATH];
+  if (!SymGetSearchPathW(GetCurrentProcess(), path_buffer, kSymPathSize)) {
+    Report("*** WARNING: Failed to SymGetSearchPathW ***\n");
+    return;
+  }
+  size_t sz = wcslen(path_buffer);
+  if (sz) {
+    CHECK_EQ(0, wcscat_s(path_buffer, L";"));
+    sz++;
+  }
+  DWORD res = GetModuleFileNameW(NULL, path_buffer + sz, MAX_PATH);
+  if (res == 0 || res == MAX_PATH) {
+    Report("*** WARNING: Failed to getting the EXE directory ***\n");
+    return;
+  }
+  // Write the zero character in place of the last backslash to get the
+  // directory of the main module at the end of path_buffer.
+  wchar_t *last_bslash = wcsrchr(path_buffer + sz, L'\\');
+  CHECK_NE(last_bslash, 0);
+  *last_bslash = L'\0';
+  if (!SymSetSearchPathW(GetCurrentProcess(), path_buffer)) {
+    Report("*** WARNING: Failed to SymSetSearchPathW\n");
+    return;
+  }
+}
+
+}  // namespace
+
+bool WinSymbolizerTool::SymbolizePC(uptr addr, SymbolizedStack *frame) {
+  InitializeDbgHelpIfNeeded();
+
+  // See http://msdn.microsoft.com/en-us/library/ms680578(VS.85).aspx
+  char buffer[sizeof(SYMBOL_INFO) + MAX_SYM_NAME * sizeof(CHAR)];
+  PSYMBOL_INFO symbol = (PSYMBOL_INFO)buffer;
+  symbol->SizeOfStruct = sizeof(SYMBOL_INFO);
+  symbol->MaxNameLen = MAX_SYM_NAME;
+  DWORD64 offset = 0;
+  BOOL got_objname = SymFromAddr(GetCurrentProcess(),
+                                 (DWORD64)addr, &offset, symbol);
+  if (!got_objname)
+    return false;
+
+  DWORD unused;
+  IMAGEHLP_LINE64 line_info;
+  line_info.SizeOfStruct = sizeof(IMAGEHLP_LINE64);
+  BOOL got_fileline = SymGetLineFromAddr64(GetCurrentProcess(), (DWORD64)addr,
+                                           &unused, &line_info);
+  frame->info.function = internal_strdup(symbol->Name);
+  frame->info.function_offset = (uptr)offset;
+  if (got_fileline) {
+    frame->info.file = internal_strdup(line_info.FileName);
+    frame->info.line = line_info.LineNumber;
+  }
+  return true;
+}
+
+const char *WinSymbolizerTool::Demangle(const char *name) {
+  CHECK(is_dbghelp_initialized);
+  static char demangle_buffer[1000];
+  if (name[0] == '\01' &&
+      UnDecorateSymbolName(name + 1, demangle_buffer, sizeof(demangle_buffer),
+                           UNDNAME_NAME_ONLY))
+    return demangle_buffer;
+  else
+    return name;
+}
+
+bool FindModuleNameAndOffsetForAddress(uptr addr, const char **module_name,
+                                       uptr *module_offset) {
+  InitializeDbgHelpIfNeeded();
+
+  IMAGEHLP_MODULE64 mod_info;
+  internal_memset(&mod_info, 0, sizeof(mod_info));
+  mod_info.SizeOfStruct = sizeof(mod_info);
+  if (SymGetModuleInfo64(GetCurrentProcess(), addr, &mod_info)) {
+    *module_name = mod_info.ImageName;
+    *module_offset = addr - (uptr)mod_info.BaseOfImage;
     return true;
   }
+  return false;
+}
 
-  const char *Demangle(const char *name) override {
-    CHECK(initialized_);
-    static char demangle_buffer[1000];
-    if (name[0] == '\01' &&
-        UnDecorateSymbolName(name + 1, demangle_buffer, sizeof(demangle_buffer),
-                             UNDNAME_NAME_ONLY))
-      return demangle_buffer;
-    else
-      return name;
-  }
-
-  // FIXME: Implement GetModuleNameAndOffsetForPC().
+// TODO(kuba.brecka): To be merged with POSIXSymbolizer.
+class WinSymbolizer : public Symbolizer {
+ public:
+  explicit WinSymbolizer(IntrusiveList<SymbolizerTool> tools)
+      : Symbolizer(tools) {}
 
  private:
-  void InitializeIfNeeded() {
-    if (initialized_)
-      return;
-    if (!TrySymInitialize()) {
-      // OK, maybe the client app has called SymInitialize already.
-      // That's a bit unfortunate for us as all the DbgHelp functions are
-      // single-threaded and we can't coordinate with the app.
-      // FIXME: Can we stop the other threads at this point?
-      // Anyways, we have to reconfigure stuff to make sure that SymInitialize
-      // has all the appropriate options set.
-      // Cross our fingers and reinitialize DbgHelp.
-      Report("*** WARNING: Failed to initialize DbgHelp!              ***\n");
-      Report("*** Most likely this means that the app is already      ***\n");
-      Report("*** using DbgHelp, possibly with incompatible flags.    ***\n");
-      Report("*** Due to technical reasons, symbolization might crash ***\n");
-      Report("*** or produce wrong results.                           ***\n");
-      SymCleanup(GetCurrentProcess());
-      TrySymInitialize();
-    }
-    initialized_ = true;
-
-    // When an executable is run from a location different from the one where it
-    // was originally built, we may not see the nearby PDB files.
-    // To work around this, let's append the directory of the main module
-    // to the symbol search path.  All the failures below are not fatal.
-    const size_t kSymPathSize = 2048;
-    static wchar_t path_buffer[kSymPathSize + 1 + MAX_PATH];
-    if (!SymGetSearchPathW(GetCurrentProcess(), path_buffer, kSymPathSize)) {
-      Report("*** WARNING: Failed to SymGetSearchPathW ***\n");
-      return;
-    }
-    size_t sz = wcslen(path_buffer);
-    if (sz) {
-      CHECK_EQ(0, wcscat_s(path_buffer, L";"));
-      sz++;
-    }
-    DWORD res = GetModuleFileNameW(NULL, path_buffer + sz, MAX_PATH);
-    if (res == 0 || res == MAX_PATH) {
-      Report("*** WARNING: Failed to getting the EXE directory ***\n");
-      return;
-    }
-    // Write the zero character in place of the last backslash to get the
-    // directory of the main module at the end of path_buffer.
-    wchar_t *last_bslash = wcsrchr(path_buffer + sz, L'\\');
-    CHECK_NE(last_bslash, 0);
-    *last_bslash = L'\0';
-    if (!SymSetSearchPathW(GetCurrentProcess(), path_buffer)) {
-      Report("*** WARNING: Failed to SymSetSearchPathW\n");
-      return;
-    }
+  bool PlatformFindModuleNameAndOffsetForAddress(
+      uptr addr, const char **module_name, uptr *module_offset) override {
+    return ::FindModuleNameAndOffsetForAddress(addr, module_name,
+                                               module_offset);
   }
-
-  bool TrySymInitialize() {
-    SymSetOptions(SYMOPT_DEFERRED_LOADS | SYMOPT_UNDNAME | SYMOPT_LOAD_LINES);
-    return SymInitialize(GetCurrentProcess(), 0, TRUE);
-    // FIXME: We don't call SymCleanup() on exit yet - should we?
-  }
-
-  // All DbgHelp functions are single threaded, so we should use a mutex to
-  // serialize accesses.
-  BlockingMutex dbghelp_mu_;
-  bool initialized_;
+  const char *PlatformDemangle(const char *name) override { return name; }
+  void PlatformPrepareForSandboxing() override { }
 };
 
 Symbolizer *Symbolizer::PlatformInit() {
-  static bool called_once = false;
-  CHECK(!called_once && "Shouldn't create more than one symbolizer");
-  called_once = true;
-  return new(symbolizer_allocator_) WinSymbolizer();
+  IntrusiveList<SymbolizerTool> list;
+  list.clear();
+  list.push_back(new(symbolizer_allocator_) WinSymbolizerTool());
+  return new(symbolizer_allocator_) WinSymbolizer(list);
 }
 
 }  // namespace __sanitizer
diff --git a/lib/sanitizer_common/sanitizer_symbolizer_win.h b/lib/sanitizer_common/sanitizer_symbolizer_win.h
new file mode 100644
index 0000000..72ac5e5
--- /dev/null
+++ b/lib/sanitizer_common/sanitizer_symbolizer_win.h
@@ -0,0 +1,31 @@
+//===-- sanitizer_symbolizer_win.h ------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Header file for the Windows symbolizer tool.
+//
+//===----------------------------------------------------------------------===//
+#ifndef SANITIZER_SYMBOLIZER_WIN_H
+#define SANITIZER_SYMBOLIZER_WIN_H
+
+#include "sanitizer_symbolizer_internal.h"
+
+namespace __sanitizer {
+
+class WinSymbolizerTool : public SymbolizerTool {
+ public:
+  bool SymbolizePC(uptr addr, SymbolizedStack *stack) override;
+  bool SymbolizeData(uptr addr, DataInfo *info) override {
+    return false;
+  }
+  const char *Demangle(const char *name) override;
+};
+
+}  // namespace __sanitizer
+
+#endif  // SANITIZER_SYMBOLIZER_WIN_H
diff --git a/lib/sanitizer_common/sanitizer_win.cc b/lib/sanitizer_common/sanitizer_win.cc
index 335ceca..3ec9084 100644
--- a/lib/sanitizer_common/sanitizer_win.cc
+++ b/lib/sanitizer_common/sanitizer_win.cc
@@ -313,6 +313,19 @@
   return 0;
 }
 
+uptr ReadBinaryName(/*out*/char *buf, uptr buf_len) {
+  // Nothing here for now.
+  return 0;
+}
+
+bool IsPathSeparator(const char c) {
+  return c == '\\' || c == '/';
+}
+
+bool IsAbsolutePath(const char *path) {
+  UNIMPLEMENTED();
+}
+
 void SleepForSeconds(int seconds) {
   Sleep(seconds * 1000);
 }
@@ -368,7 +381,7 @@
   UNIMPLEMENTED();
 }
 
-uptr OpenFile(const char *filename, bool write) {
+uptr OpenFile(const char *filename, FileAccessMode mode) {
   UNIMPLEMENTED();
 }
 
@@ -618,6 +631,23 @@
   return true;
 }
 
+SignalContext SignalContext::Create(void *siginfo, void *context) {
+  EXCEPTION_RECORD *exception_record = (EXCEPTION_RECORD*)siginfo;
+  CONTEXT *context_record = (CONTEXT*)context;
+
+  uptr pc = (uptr)exception_record->ExceptionAddress;
+#ifdef _WIN64
+  uptr bp = (uptr)context_record->Rbp;
+  uptr sp = (uptr)context_record->Rsp;
+#else
+  uptr bp = (uptr)context_record->Ebp;
+  uptr sp = (uptr)context_record->Esp;
+#endif
+  uptr access_addr = exception_record->ExceptionInformation[1];
+
+  return SignalContext(context, access_addr, pc, sp, bp);
+}
+
 }  // namespace __sanitizer
 
 #endif  // _WIN32
diff --git a/lib/sanitizer_common/scripts/check_lint.sh b/lib/sanitizer_common/scripts/check_lint.sh
index 7ed05d7..9108a81 100755
--- a/lib/sanitizer_common/scripts/check_lint.sh
+++ b/lib/sanitizer_common/scripts/check_lint.sh
@@ -17,7 +17,6 @@
 
 # Filters
 # TODO: remove some of these filters
-LLVM_LINT_FILTER=-,+whitespace
 COMMON_LINT_FILTER=-build/include,-build/header_guard,-legal/copyright,-whitespace/comments,-readability/casting,\
 -build/namespaces
 ASAN_RTL_LINT_FILTER=${COMMON_LINT_FILTER},-runtime/int
@@ -60,9 +59,6 @@
   ${LITLINT} "$@" 2>>$ERROR_LOG
 }
 
-run_lint ${LLVM_LINT_FILTER} --filter=${LLVM_LINT_FILTER} \
-  lib/Transforms/Instrumentation/*Sanitizer.cpp &
-
 if [ "${COMPILER_RT}" = "" ]; then
   COMPILER_RT=projects/compiler-rt
 fi
diff --git a/lib/sanitizer_common/scripts/sancov.py b/lib/sanitizer_common/scripts/sancov.py
index 566116e..53180d0 100755
--- a/lib/sanitizer_common/scripts/sancov.py
+++ b/lib/sanitizer_common/scripts/sancov.py
@@ -9,35 +9,77 @@
 import bisect
 import os.path
 
-prog_name = "";
+prog_name = ""
 
 def Usage():
   print >> sys.stderr, "Usage: \n" + \
-      " " + prog_name + " merge file1 [file2 ...]  > output\n" \
-      " " + prog_name + " print file1 [file2 ...]\n" \
-      " " + prog_name + " unpack file1 [file2 ...]\n" \
-      " " + prog_name + " rawunpack file1 [file2 ...]\n"
+      " " + prog_name + " [32|64] merge file1 [file2 ...]  > output\n" \
+      " " + prog_name + " [32|64] print file1 [file2 ...]\n" \
+      " " + prog_name + " [32|64] unpack file1 [file2 ...]\n" \
+      " " + prog_name + " [32|64] rawunpack file1 [file2 ...]\n"
   exit(1)
 
+def CheckBits(bits):
+  if bits != 32 and bits != 64:
+    raise Exception("Wrong bitness: %d" % bits)
+
+def TypeCodeForBits(bits):
+  CheckBits(bits)
+  return 'L' if bits == 64 else 'I'
+
+kMagic32SecondHalf = 0xFFFFFF32;
+kMagic64SecondHalf = 0xFFFFFF64;
+kMagicFirstHalf    = 0xC0BFFFFF;
+
+def MagicForBits(bits):
+  CheckBits(bits)
+  if sys.byteorder == 'little':
+    return [kMagic64SecondHalf if bits == 64 else kMagic32SecondHalf, kMagicFirstHalf]
+  else:
+    return [kMagicFirstHalf, kMagic64SecondHalf if bits == 64 else kMagic32SecondHalf]
+
+def ReadMagicAndReturnBitness(f, path):
+  magic_bytes = f.read(8)
+  magic_words = struct.unpack('II', magic_bytes);
+  bits = 0
+  idx = 1 if sys.byteorder == 'little' else 0
+  if magic_words[idx] == kMagicFirstHalf:
+    if magic_words[1-idx] == kMagic64SecondHalf:
+      bits = 64
+    elif magic_words[1-idx] == kMagic32SecondHalf:
+      bits = 32
+  if bits == 0:
+    raise Exception('Bad magic word in %s' % path)
+  return bits
+
 def ReadOneFile(path):
   with open(path, mode="rb") as f:
     f.seek(0, 2)
     size = f.tell()
     f.seek(0, 0)
-    s = set(array.array('I', f.read(size)))
-  print >>sys.stderr, "%s: read %d PCs from %s" % (prog_name, size / 4, path)
+    if size < 8:
+      raise Exception('File %s is short (< 8 bytes)' % path)
+    bits = ReadMagicAndReturnBitness(f, path)
+    size -= 8
+    s = array.array(TypeCodeForBits(bits), f.read(size))
+  print >>sys.stderr, "%s: read %d %d-bit PCs from %s" % (prog_name, size * 8 / bits, bits, path)
   return s
 
 def Merge(files):
   s = set()
   for f in files:
-    s = s.union(ReadOneFile(f))
+    s = s.union(set(ReadOneFile(f)))
   print >> sys.stderr, "%s: %d files merged; %d PCs total" % \
     (prog_name, len(files), len(s))
   return sorted(s)
 
 def PrintFiles(files):
-  s = Merge(files)
+  if len(files) > 1:
+    s = Merge(files)
+  else:  # If there is just on file, print the PCs in order.
+    s = ReadOneFile(files[0])
+    print >> sys.stderr, "%s: 1 file merged; %d PCs total" % \
+      (prog_name, len(s))
   for i in s:
     print "0x%x" % i
 
@@ -45,7 +87,11 @@
   if sys.stdout.isatty():
     Usage()
   s = Merge(files)
-  a = array.array('I', s)
+  bits = 32
+  if max(s) > 0xFFFFFFFF:
+    bits = 64
+  array.array('I', MagicForBits(bits)).tofile(sys.stdout)
+  a = array.array(TypeCodeForBits(bits), s)
   a.tofile(sys.stdout)
 
 
@@ -82,6 +128,8 @@
   with open(map_path, mode="rt") as f_map:
     print >> sys.stderr, "%s: reading map %s" % (prog_name, map_path)
     bits = int(f_map.readline())
+    if bits != 32 and bits != 64:
+      raise Exception('Wrong bits size in the map')
     for line in f_map:
       parts = line.rstrip().split()
       mem_map.append((int(parts[0], 16),
@@ -97,11 +145,7 @@
     f.seek(0, 2)
     size = f.tell()
     f.seek(0, 0)
-    if bits == 64:
-      typecode = 'L'
-    else:
-      typecode = 'I'
-    pcs = array.array(typecode, f.read(size))
+    pcs = array.array(TypeCodeForBits(bits), f.read(size))
     mem_map_pcs = [[] for i in range(0, len(mem_map))]
 
     for pc in pcs:
@@ -119,9 +163,10 @@
       assert path.endswith('.sancov.raw')
       dst_path = module_path + '.' + os.path.basename(path)[:-4]
       print >> sys.stderr, "%s: writing %d PCs to %s" % (prog_name, len(pc_list), dst_path)
-      arr = array.array('I')
+      arr = array.array(TypeCodeForBits(bits))
       arr.fromlist(sorted(pc_list))
       with open(dst_path, 'ab') as f2:
+        array.array('I', MagicForBits(bits)).tofile(f2)
         arr.tofile(f2)
 
 def RawUnpack(files):
@@ -135,6 +180,7 @@
   prog_name = sys.argv[0]
   if len(sys.argv) <= 2:
     Usage();
+
   if sys.argv[1] == "print":
     PrintFiles(sys.argv[2:])
   elif sys.argv[1] == "merge":
diff --git a/lib/sanitizer_common/tests/CMakeLists.txt b/lib/sanitizer_common/tests/CMakeLists.txt
index 75008db..b062c5a 100644
--- a/lib/sanitizer_common/tests/CMakeLists.txt
+++ b/lib/sanitizer_common/tests/CMakeLists.txt
@@ -28,6 +28,7 @@
   sanitizer_stacktrace_test.cc
   sanitizer_stoptheworld_test.cc
   sanitizer_suppressions_test.cc
+  sanitizer_symbolizer_test.cc
   sanitizer_test_main.cc
   sanitizer_thread_registry_test.cc)
 
diff --git a/lib/sanitizer_common/tests/sanitizer_libc_test.cc b/lib/sanitizer_common/tests/sanitizer_libc_test.cc
index 8712d2c..279f6fe 100644
--- a/lib/sanitizer_common/tests/sanitizer_libc_test.cc
+++ b/lib/sanitizer_common/tests/sanitizer_libc_test.cc
@@ -78,14 +78,14 @@
 
   char tmpfile[128];
   temp_file_name(tmpfile, sizeof(tmpfile), "sanitizer_common.fileops.tmp.");
-  uptr openrv = OpenFile(tmpfile, true);
+  uptr openrv = OpenFile(tmpfile, WrOnly);
   EXPECT_FALSE(internal_iserror(openrv));
   fd_t fd = openrv;
   EXPECT_EQ(len1, internal_write(fd, str1, len1));
   EXPECT_EQ(len2, internal_write(fd, str2, len2));
   internal_close(fd);
 
-  openrv = OpenFile(tmpfile, false);
+  openrv = OpenFile(tmpfile, RdOnly);
   EXPECT_FALSE(internal_iserror(openrv));
   fd = openrv;
   uptr fsize = internal_filesize(fd);
@@ -134,7 +134,7 @@
   char tmpfile[128];
   temp_file_name(tmpfile, sizeof(tmpfile),
                  "sanitizer_common.internalmmapwithoffset.tmp.");
-  uptr res = OpenFile(tmpfile, true);
+  uptr res = OpenFile(tmpfile, RdWr);
   ASSERT_FALSE(internal_iserror(res));
   fd_t fd = res;
 
diff --git a/lib/sanitizer_common/tests/sanitizer_stacktrace_test.cc b/lib/sanitizer_common/tests/sanitizer_stacktrace_test.cc
index ac820c2..a8bd726 100644
--- a/lib/sanitizer_common/tests/sanitizer_stacktrace_test.cc
+++ b/lib/sanitizer_common/tests/sanitizer_stacktrace_test.cc
@@ -30,11 +30,11 @@
   }
 
   void *mapping;
-  uptr *fake_stack;
+  uhwptr *fake_stack;
   const uptr fake_stack_size = 10;
-  uptr start_pc;
-  uptr fake_top;
-  uptr fake_bottom;
+  uhwptr start_pc;
+  uhwptr fake_top;
+  uhwptr fake_bottom;
   BufferedStackTrace trace;
 };
 
@@ -48,7 +48,7 @@
   Mprotect((uptr)mapping, ps);
 
   // Unwinder may peek 1 word down from the starting FP.
-  fake_stack = (uptr *)((uptr)mapping + ps + sizeof(uptr));
+  fake_stack = (uhwptr *)((uptr)mapping + ps + sizeof(uhwptr));
 
   // Fill an array of pointers with fake fp+retaddr pairs.  Frame pointers have
   // even indices.
@@ -57,12 +57,12 @@
     fake_stack[i+1] = PC(i + 1); // retaddr
   }
   // Mark the last fp point back up to terminate the stack trace.
-  fake_stack[RoundDownTo(fake_stack_size - 1, 2)] = (uptr)&fake_stack[0];
+  fake_stack[RoundDownTo(fake_stack_size - 1, 2)] = (uhwptr)&fake_stack[0];
 
   // Top is two slots past the end because FastUnwindStack subtracts two.
-  fake_top = (uptr)&fake_stack[fake_stack_size + 2];
+  fake_top = (uhwptr)&fake_stack[fake_stack_size + 2];
   // Bottom is one slot before the start because FastUnwindStack uses >.
-  fake_bottom = (uptr)mapping;
+  fake_bottom = (uhwptr)mapping;
   start_pc = PC(0);
 }
 
@@ -85,7 +85,7 @@
 // From: http://code.google.com/p/address-sanitizer/issues/detail?id=162
 TEST_F(FastUnwindTest, FramePointerLoop) {
   // Make one fp point to itself.
-  fake_stack[4] = (uptr)&fake_stack[4];
+  fake_stack[4] = (uhwptr)&fake_stack[4];
   if (!TryFastUnwind(kStackTraceMax))
     return;
   // Should get all on-stack retaddrs up to the 4th slot and start_pc.
@@ -114,7 +114,7 @@
     return;
   EXPECT_EQ(1U, trace.size);
   EXPECT_EQ(start_pc, trace.trace[0]);
-  EXPECT_EQ((uptr)&fake_stack[0], trace.top_frame_bp);
+  EXPECT_EQ((uhwptr)&fake_stack[0], trace.top_frame_bp);
 }
 
 TEST_F(FastUnwindTest, ZeroFramesStackTrace) {
@@ -127,7 +127,7 @@
 TEST_F(FastUnwindTest, FPBelowPrevFP) {
   // The next FP points to unreadable memory inside the stack limits, but below
   // current FP.
-  fake_stack[0] = (uptr)&fake_stack[-50];
+  fake_stack[0] = (uhwptr)&fake_stack[-50];
   fake_stack[1] = PC(1);
   if (!TryFastUnwind(3))
     return;
diff --git a/lib/sanitizer_common/tests/sanitizer_stoptheworld_test.cc b/lib/sanitizer_common/tests/sanitizer_stoptheworld_test.cc
index b6786ba..802af39 100644
--- a/lib/sanitizer_common/tests/sanitizer_stoptheworld_test.cc
+++ b/lib/sanitizer_common/tests/sanitizer_stoptheworld_test.cc
@@ -189,6 +189,16 @@
   pthread_mutex_destroy(&advanced_incrementer_thread_exit_mutex);
 }
 
+static void SegvCallback(const SuspendedThreadsList &suspended_threads_list,
+                         void *argument) {
+  *(volatile int*)0x1234 = 0;
+}
+
+TEST(StopTheWorld, SegvInCallback) {
+  // Test that tracer thread catches SIGSEGV.
+  StopTheWorld(&SegvCallback, NULL);
+}
+
 }  // namespace __sanitizer
 
 #endif  // SANITIZER_LINUX && defined(__x86_64__)
diff --git a/lib/sanitizer_common/tests/sanitizer_symbolizer_test.cc b/lib/sanitizer_common/tests/sanitizer_symbolizer_test.cc
new file mode 100644
index 0000000..429ac59
--- /dev/null
+++ b/lib/sanitizer_common/tests/sanitizer_symbolizer_test.cc
@@ -0,0 +1,58 @@
+//===-- sanitizer_symbolizer_test.cc --------------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Tests for sanitizer_symbolizer.h and sanitizer_symbolizer_internal.h
+//
+//===----------------------------------------------------------------------===//
+
+#include "sanitizer_common/sanitizer_allocator_internal.h"
+#include "sanitizer_common/sanitizer_symbolizer_internal.h"
+#include "gtest/gtest.h"
+
+namespace __sanitizer {
+
+TEST(Symbolizer, ExtractToken) {
+  char *token;
+  const char *rest;
+
+  rest = ExtractToken("a;b;c", ";", &token);
+  EXPECT_STREQ("a", token);
+  EXPECT_STREQ("b;c", rest);
+  InternalFree(token);
+
+  rest = ExtractToken("aaa-bbb.ccc", ";.-*", &token);
+  EXPECT_STREQ("aaa", token);
+  EXPECT_STREQ("bbb.ccc", rest);
+  InternalFree(token);
+}
+
+TEST(Symbolizer, ExtractInt) {
+  int token;
+  const char *rest = ExtractInt("123,456;789", ";,", &token);
+  EXPECT_EQ(123, token);
+  EXPECT_STREQ("456;789", rest);
+}
+
+TEST(Symbolizer, ExtractUptr) {
+  uptr token;
+  const char *rest = ExtractUptr("123,456;789", ";,", &token);
+  EXPECT_EQ(123U, token);
+  EXPECT_STREQ("456;789", rest);
+}
+
+TEST(Symbolizer, ExtractTokenUpToDelimiter) {
+  char *token;
+  const char *rest =
+      ExtractTokenUpToDelimiter("aaa-+-bbb-+-ccc", "-+-", &token);
+  EXPECT_STREQ("aaa", token);
+  EXPECT_STREQ("bbb-+-ccc", rest);
+  InternalFree(token);
+}
+
+}  // namespace __sanitizer
diff --git a/lib/tsan/Makefile.old b/lib/tsan/Makefile.old
index 9e0693f..fbdb9dd 100644
--- a/lib/tsan/Makefile.old
+++ b/lib/tsan/Makefile.old
@@ -11,7 +11,9 @@
 	CXXFLAGS += -O3
 endif
 ifeq ($(CXX), $(CLANG)++)
-  CXXFLAGS+= -Wno-unused-private-field -Wno-static-in-inline -Wgnu
+  CXXFLAGS += -Wno-unused-private-field -Wno-static-in-inline -Wgnu
+else
+  CXXFLAGS += -Wno-maybe-uninitialized
 endif
 
 LIBTSAN=rtl/libtsan.a
diff --git a/lib/tsan/rtl/Makefile.old b/lib/tsan/rtl/Makefile.old
index 150b376..627e03b 100644
--- a/lib/tsan/rtl/Makefile.old
+++ b/lib/tsan/rtl/Makefile.old
@@ -15,6 +15,7 @@
 ifeq ($(DEBUG), 0)
   CXXFLAGS+=-fomit-frame-pointer
 ifeq ($(CXX), g++)
+  CXXFLAGS+=-Wno-maybe-uninitialized
   CXXFLAGS+=-Wframe-larger-than=512
 endif  # CXX=g++
 endif  # DEBUG=0
diff --git a/lib/tsan/rtl/tsan_interceptors.cc b/lib/tsan/rtl/tsan_interceptors.cc
index 31ff7d5..c45bcdc 100644
--- a/lib/tsan/rtl/tsan_interceptors.cc
+++ b/lib/tsan/rtl/tsan_interceptors.cc
@@ -145,7 +145,10 @@
 const sighandler_t SIG_DFL = (sighandler_t)0;
 const sighandler_t SIG_IGN = (sighandler_t)1;
 const sighandler_t SIG_ERR = (sighandler_t)-1;
-#ifdef __mips__
+#if SANITIZER_FREEBSD
+const int SA_SIGINFO = 0x40;
+const int SIG_SETMASK = 3;
+#elif defined(__mips__)
 const int SA_SIGINFO = 8;
 const int SIG_SETMASK = 3;
 #else
@@ -167,7 +170,7 @@
   ucontext_t ctx;
 };
 
-struct SignalContext {
+struct ThreadSignalContext {
   int int_signal_send;
   atomic_uintptr_t in_blocking_func;
   atomic_uintptr_t have_pending_signals;
@@ -194,10 +197,10 @@
 
 }  // namespace __tsan
 
-static SignalContext *SigCtx(ThreadState *thr) {
-  SignalContext *ctx = (SignalContext*)thr->signal_ctx;
+static ThreadSignalContext *SigCtx(ThreadState *thr) {
+  ThreadSignalContext *ctx = (ThreadSignalContext*)thr->signal_ctx;
   if (ctx == 0 && !thr->is_dead) {
-    ctx = (SignalContext*)MmapOrDie(sizeof(*ctx), "SignalContext");
+    ctx = (ThreadSignalContext*)MmapOrDie(sizeof(*ctx), "ThreadSignalContext");
     MemoryResetRange(thr, (uptr)&SigCtx, (uptr)ctx, sizeof(*ctx));
     thr->signal_ctx = ctx;
   }
@@ -298,7 +301,7 @@
   }
 
   ThreadState *thr;
-  SignalContext *ctx;
+  ThreadSignalContext *ctx;
 };
 
 TSAN_INTERCEPTOR(unsigned, sleep, unsigned sec) {
@@ -410,7 +413,7 @@
 }
 
 static void SetJmp(ThreadState *thr, uptr sp, uptr mangled_sp) {
-  if (thr->shadow_stack_pos == 0)  // called from libc guts during bootstrap
+  if (!thr->is_inited)  // called from libc guts during bootstrap
     return;
   // Cleanup old bufs.
   JmpBufGarbageCollect(thr, sp);
@@ -419,7 +422,7 @@
   buf->sp = sp;
   buf->mangled_sp = mangled_sp;
   buf->shadow_stack_pos = thr->shadow_stack_pos;
-  SignalContext *sctx = SigCtx(thr);
+  ThreadSignalContext *sctx = SigCtx(thr);
   buf->int_signal_send = sctx ? sctx->int_signal_send : 0;
   buf->in_blocking_func = sctx ?
       atomic_load(&sctx->in_blocking_func, memory_order_relaxed) :
@@ -442,7 +445,7 @@
       // Unwind the stack.
       while (thr->shadow_stack_pos > buf->shadow_stack_pos)
         FuncExit(thr);
-      SignalContext *sctx = SigCtx(thr);
+      ThreadSignalContext *sctx = SigCtx(thr);
       if (sctx) {
         sctx->int_signal_send = buf->int_signal_send;
         atomic_store(&sctx->in_blocking_func, buf->in_blocking_func,
@@ -666,9 +669,12 @@
 }
 
 TSAN_INTERCEPTOR(void*, memcpy, void *dst, const void *src, uptr size) {
-  SCOPED_TSAN_INTERCEPTOR(memcpy, dst, src, size);
-  MemoryAccessRange(thr, pc, (uptr)dst, size, true);
-  MemoryAccessRange(thr, pc, (uptr)src, size, false);
+  // On FreeBSD we get here from libthr internals on thread initialization.
+  if (cur_thread()->is_inited) {
+    SCOPED_TSAN_INTERCEPTOR(memcpy, dst, src, size);
+    MemoryAccessRange(thr, pc, (uptr)dst, size, true);
+    MemoryAccessRange(thr, pc, (uptr)src, size, false);
+  }
   return internal_memcpy(dst, src, size);
 }
 
@@ -797,6 +803,7 @@
 TSAN_INTERCEPTOR(int, munmap, void *addr, long_t sz) {
   SCOPED_TSAN_INTERCEPTOR(munmap, addr, sz);
   DontNeedShadowFor((uptr)addr, sz);
+  ctx->metamap.ResetRange(thr, pc, (uptr)addr, (uptr)sz);
   int res = REAL(munmap)(addr, sz);
   return res;
 }
@@ -878,7 +885,7 @@
   {
     ThreadState *thr = cur_thread();
     ThreadFinish(thr);
-    SignalContext *sctx = thr->signal_ctx;
+    ThreadSignalContext *sctx = thr->signal_ctx;
     if (sctx) {
       thr->signal_ctx = 0;
       UnmapOrDie(sctx, sizeof(*sctx));
@@ -1940,7 +1947,7 @@
 }
 
 void ProcessPendingSignals(ThreadState *thr) {
-  SignalContext *sctx = SigCtx(thr);
+  ThreadSignalContext *sctx = SigCtx(thr);
   if (sctx == 0 ||
       atomic_load(&sctx->have_pending_signals, memory_order_relaxed) == 0)
     return;
@@ -1948,8 +1955,8 @@
   atomic_fetch_add(&thr->in_signal_handler, 1, memory_order_relaxed);
   // These are too big for stack.
   static THREADLOCAL __sanitizer_sigset_t emptyset, oldset;
-  REAL(sigfillset)(&emptyset);
-  pthread_sigmask(SIG_SETMASK, &emptyset, &oldset);
+  CHECK_EQ(0, REAL(sigfillset)(&emptyset));
+  CHECK_EQ(0, pthread_sigmask(SIG_SETMASK, &emptyset, &oldset));
   for (int sig = 0; sig < kSigCount; sig++) {
     SignalDesc *signal = &sctx->pending_signals[sig];
     if (signal->armed) {
@@ -1958,13 +1965,13 @@
           &signal->siginfo, &signal->ctx);
     }
   }
-  pthread_sigmask(SIG_SETMASK, &oldset, 0);
+  CHECK_EQ(0, pthread_sigmask(SIG_SETMASK, &oldset, 0));
   atomic_fetch_add(&thr->in_signal_handler, -1, memory_order_relaxed);
 }
 
 }  // namespace __tsan
 
-static bool is_sync_signal(SignalContext *sctx, int sig) {
+static bool is_sync_signal(ThreadSignalContext *sctx, int sig) {
   return sig == SIGSEGV || sig == SIGBUS || sig == SIGILL ||
       sig == SIGABRT || sig == SIGFPE || sig == SIGPIPE || sig == SIGSYS ||
       // If we are sending signal to ourselves, we must process it now.
@@ -1974,7 +1981,7 @@
 void ALWAYS_INLINE rtl_generic_sighandler(bool sigact, int sig,
     my_siginfo_t *info, void *ctx) {
   ThreadState *thr = cur_thread();
-  SignalContext *sctx = SigCtx(thr);
+  ThreadSignalContext *sctx = SigCtx(thr);
   if (sig < 0 || sig >= kSigCount) {
     VPrintf(1, "ThreadSanitizer: ignoring signal %d\n", sig);
     return;
@@ -2083,7 +2090,7 @@
 
 TSAN_INTERCEPTOR(int, raise, int sig) {
   SCOPED_TSAN_INTERCEPTOR(raise, sig);
-  SignalContext *sctx = SigCtx(thr);
+  ThreadSignalContext *sctx = SigCtx(thr);
   CHECK_NE(sctx, 0);
   int prev = sctx->int_signal_send;
   sctx->int_signal_send = sig;
@@ -2095,7 +2102,7 @@
 
 TSAN_INTERCEPTOR(int, kill, int pid, int sig) {
   SCOPED_TSAN_INTERCEPTOR(kill, pid, sig);
-  SignalContext *sctx = SigCtx(thr);
+  ThreadSignalContext *sctx = SigCtx(thr);
   CHECK_NE(sctx, 0);
   int prev = sctx->int_signal_send;
   if (pid == (int)internal_getpid()) {
@@ -2111,7 +2118,7 @@
 
 TSAN_INTERCEPTOR(int, pthread_kill, void *tid, int sig) {
   SCOPED_TSAN_INTERCEPTOR(pthread_kill, tid, sig);
-  SignalContext *sctx = SigCtx(thr);
+  ThreadSignalContext *sctx = SigCtx(thr);
   CHECK_NE(sctx, 0);
   int prev = sctx->int_signal_send;
   if (tid == pthread_self()) {
diff --git a/lib/tsan/rtl/tsan_report.cc b/lib/tsan/rtl/tsan_report.cc
index 7e69cb4..18bad14 100644
--- a/lib/tsan/rtl/tsan_report.cc
+++ b/lib/tsan/rtl/tsan_report.cc
@@ -335,10 +335,8 @@
     Printf("  And %d more similar thread leaks.\n\n", rep->count - 1);
 
   if (ReportStack *stack = ChooseSummaryStack(rep)) {
-    if (SymbolizedStack *frame = SkipTsanInternalFrames(stack->frames)) {
-      const AddressInfo &info = frame->info;
-      ReportErrorSummary(rep_typ_str, info.file, info.line, info.function);
-    }
+    if (SymbolizedStack *frame = SkipTsanInternalFrames(stack->frames))
+      ReportErrorSummary(rep_typ_str, frame->info);
   }
 
   Printf("==================\n");
diff --git a/lib/tsan/rtl/tsan_rtl.cc b/lib/tsan/rtl/tsan_rtl.cc
index b76f3e0..1c64caf 100644
--- a/lib/tsan/rtl/tsan_rtl.cc
+++ b/lib/tsan/rtl/tsan_rtl.cc
@@ -153,7 +153,7 @@
     } else {
       InternalScopedString filename(kMaxPathLength);
       filename.append("%s.%d", flags()->profile_memory, (int)internal_getpid());
-      uptr openrv = OpenFile(filename.data(), true);
+      uptr openrv = OpenFile(filename.data(), WrOnly);
       if (internal_iserror(openrv)) {
         Printf("ThreadSanitizer: failed to open memory profile file '%s'\n",
             &filename[0]);
@@ -461,7 +461,7 @@
 #endif
 
 u32 CurrentStackId(ThreadState *thr, uptr pc) {
-  if (thr->shadow_stack_pos == 0)  // May happen during bootstrap.
+  if (!thr->is_inited)  // May happen during bootstrap.
     return 0;
   if (pc != 0) {
 #ifndef SANITIZER_GO
diff --git a/lib/tsan/rtl/tsan_rtl.h b/lib/tsan/rtl/tsan_rtl.h
index 7a60e5c..d32688e 100644
--- a/lib/tsan/rtl/tsan_rtl.h
+++ b/lib/tsan/rtl/tsan_rtl.h
@@ -313,7 +313,7 @@
   }
 };
 
-struct SignalContext;
+struct ThreadSignalContext;
 
 struct JmpBuf {
   uptr sp;
@@ -371,6 +371,7 @@
   const int unique_id;
   bool in_symbolizer;
   bool in_ignored_lib;
+  bool is_inited;
   bool is_dead;
   bool is_freeing;
   bool is_vptr_access;
@@ -387,7 +388,7 @@
   DDLogicalThread *dd_lt;
 
   atomic_uintptr_t in_signal_handler;
-  SignalContext *signal_ctx;
+  ThreadSignalContext *signal_ctx;
 
   DenseSlabAllocCache block_cache;
   DenseSlabAllocCache sync_cache;
diff --git a/lib/tsan/rtl/tsan_rtl_thread.cc b/lib/tsan/rtl/tsan_rtl_thread.cc
index 8ed1fbf..66c78cf 100644
--- a/lib/tsan/rtl/tsan_rtl_thread.cc
+++ b/lib/tsan/rtl/tsan_rtl_thread.cc
@@ -120,6 +120,7 @@
   AcquireImpl(thr, 0, &sync);
   StatInc(thr, StatSyncAcquire);
   sync.Reset(&thr->clock_cache);
+  thr->is_inited = true;
   DPrintf("#%d: ThreadStart epoch=%zu stk_addr=%zx stk_size=%zx "
           "tls_addr=%zx tls_size=%zx\n",
           tid, (uptr)epoch0, args->stk_addr, args->stk_size,
diff --git a/lib/tsan/rtl/tsan_suppressions.cc b/lib/tsan/rtl/tsan_suppressions.cc
index 5413f04..7315729 100644
--- a/lib/tsan/rtl/tsan_suppressions.cc
+++ b/lib/tsan/rtl/tsan_suppressions.cc
@@ -21,6 +21,7 @@
 #include "tsan_mman.h"
 #include "tsan_platform.h"
 
+#ifndef SANITIZER_GO
 // Suppressions for true/false positives in standard libraries.
 static const char *const std_suppressions =
 // Libstdc++ 4.4 has data races in std::string.
@@ -33,7 +34,6 @@
 "race:std::_Sp_counted_ptr_inplace<std::thread::_Impl\n";
 
 // Can be overriden in frontend.
-#ifndef SANITIZER_GO
 extern "C" const char *WEAK __tsan_default_suppressions() {
   return 0;
 }
diff --git a/lib/tsan/rtl/tsan_sync.cc b/lib/tsan/rtl/tsan_sync.cc
index 1041073..49c4d15 100644
--- a/lib/tsan/rtl/tsan_sync.cc
+++ b/lib/tsan/rtl/tsan_sync.cc
@@ -80,7 +80,8 @@
   return sz;
 }
 
-void MetaMap::FreeRange(ThreadState *thr, uptr pc, uptr p, uptr sz) {
+bool MetaMap::FreeRange(ThreadState *thr, uptr pc, uptr p, uptr sz) {
+  bool has_something = false;
   u32 *meta = MemToMeta(p);
   u32 *end = MemToMeta(p + sz);
   if (end == meta)
@@ -91,6 +92,7 @@
     for (;;) {
       if (idx == 0)
         break;
+      has_something = true;
       if (idx & kFlagBlock) {
         block_alloc_.Free(&thr->block_cache, idx & ~kFlagMask);
         break;
@@ -106,6 +108,64 @@
       }
     }
   }
+  return has_something;
+}
+
+// ResetRange removes all meta objects from the range.
+// It is called for large mmap-ed regions. The function is best-effort wrt
+// freeing of meta objects, because we don't want to page in the whole range
+// which can be huge. The function probes pages one-by-one until it finds a page
+// without meta objects, at this point it stops freeing meta objects. Because
+// thread stacks grow top-down, we do the same starting from end as well.
+void MetaMap::ResetRange(ThreadState *thr, uptr pc, uptr p, uptr sz) {
+  const uptr kMetaRatio = kMetaShadowCell / kMetaShadowSize;
+  const uptr kPageSize = GetPageSizeCached() * kMetaRatio;
+  if (sz <= 4 * kPageSize) {
+    // If the range is small, just do the normal free procedure.
+    FreeRange(thr, pc, p, sz);
+    return;
+  }
+  // First, round both ends of the range to page size.
+  uptr diff = RoundUp(p, kPageSize) - p;
+  if (diff != 0) {
+    FreeRange(thr, pc, p, diff);
+    p += diff;
+    sz -= diff;
+  }
+  diff = p + sz - RoundDown(p + sz, kPageSize);
+  if (diff != 0) {
+    FreeRange(thr, pc, p + sz - diff, diff);
+    sz -= diff;
+  }
+  // Now we must have a non-empty page-aligned range.
+  CHECK_GT(sz, 0);
+  CHECK_EQ(p, RoundUp(p, kPageSize));
+  CHECK_EQ(sz, RoundUp(sz, kPageSize));
+  const uptr p0 = p;
+  const uptr sz0 = sz;
+  // Probe start of the range.
+  while (sz > 0) {
+    bool has_something = FreeRange(thr, pc, p, kPageSize);
+    p += kPageSize;
+    sz -= kPageSize;
+    if (!has_something)
+      break;
+  }
+  // Probe end of the range.
+  while (sz > 0) {
+    bool has_something = FreeRange(thr, pc, p - kPageSize, kPageSize);
+    sz -= kPageSize;
+    if (!has_something)
+      break;
+  }
+  // Finally, page out the whole range (including the parts that we've just
+  // freed). Note: we can't simply madvise, because we need to leave a zeroed
+  // range (otherwise __tsan_java_move can crash if it encounters a left-over
+  // meta objects in java heap).
+  uptr metap = (uptr)MemToMeta(p0);
+  uptr metasz = sz0 / kMetaRatio;
+  UnmapOrDie((void*)metap, metasz);
+  MmapFixedNoReserve(metap, metasz);
 }
 
 MBlock* MetaMap::GetBlock(uptr p) {
diff --git a/lib/tsan/rtl/tsan_sync.h b/lib/tsan/rtl/tsan_sync.h
index 574810d..2d12cdf 100644
--- a/lib/tsan/rtl/tsan_sync.h
+++ b/lib/tsan/rtl/tsan_sync.h
@@ -73,7 +73,8 @@
 
   void AllocBlock(ThreadState *thr, uptr pc, uptr p, uptr sz);
   uptr FreeBlock(ThreadState *thr, uptr pc, uptr p);
-  void FreeRange(ThreadState *thr, uptr pc, uptr p, uptr sz);
+  bool FreeRange(ThreadState *thr, uptr pc, uptr p, uptr sz);
+  void ResetRange(ThreadState *thr, uptr pc, uptr p, uptr sz);
   MBlock* GetBlock(uptr p);
 
   SyncVar* GetOrCreateAndLock(ThreadState *thr, uptr pc,
diff --git a/lib/ubsan/CMakeLists.txt b/lib/ubsan/CMakeLists.txt
index 6683272..a8b3f61 100644
--- a/lib/ubsan/CMakeLists.txt
+++ b/lib/ubsan/CMakeLists.txt
@@ -22,34 +22,61 @@
 add_custom_target(ubsan)
 
 if(APPLE)
-  # Build universal binary on APPLE.
-  add_compiler_rt_osx_static_runtime(clang_rt.ubsan_osx
-    ARCH ${UBSAN_SUPPORTED_ARCH}
-    SOURCES ${UBSAN_SOURCES} ${UBSAN_CXX_SOURCES}
-            $<TARGET_OBJECTS:RTSanitizerCommon.osx>
-    CFLAGS ${UBSAN_CXXFLAGS})
-  add_dependencies(ubsan clang_rt.ubsan_osx)
+  foreach(os ${SANITIZER_COMMON_SUPPORTED_DARWIN_OS})
+    add_compiler_rt_darwin_object_library(RTUbsan ${os}
+      ARCH ${UBSAN_SUPPORTED_ARCH}
+      SOURCES ${UBSAN_SOURCES} ${UBSAN_CXX_SOURCES}
+      CFLAGS ${UBSAN_CXXFLAGS})
+
+    add_compiler_rt_darwin_dynamic_runtime(clang_rt.ubsan_${os}_dynamic ${os}
+      ARCH ${UBSAN_SUPPORTED_ARCH}
+      SOURCES $<TARGET_OBJECTS:RTUbsan.${os}>
+              $<TARGET_OBJECTS:RTSanitizerCommon.${os}>
+      LINKFLAGS -lc++abi)
+
+    add_dependencies(ubsan clang_rt.ubsan_${os}_dynamic)
+  endforeach()
 else()
   # Build separate libraries for each target.
   foreach(arch ${UBSAN_SUPPORTED_ARCH})
-    # Main UBSan runtime.
-    add_compiler_rt_runtime(clang_rt.ubsan-${arch} ${arch} STATIC
-      SOURCES ${UBSAN_SOURCES}
-      CFLAGS ${UBSAN_CFLAGS})
+    add_compiler_rt_object_library(RTUbsan ${arch}
+      SOURCES ${UBSAN_SOURCES} CFLAGS ${UBSAN_CFLAGS})
     # C++-specific parts of UBSan runtime. Requires a C++ ABI library.
-    add_compiler_rt_runtime(clang_rt.ubsan_cxx-${arch} ${arch} STATIC
-      SOURCES ${UBSAN_CXX_SOURCES}
+    add_compiler_rt_object_library(RTUbsan_cxx ${arch}
+      SOURCES ${UBSAN_CXX_SOURCES} CFLAGS ${UBSAN_CXXFLAGS})
+
+    # Standalone UBSan runtimes.
+    add_compiler_rt_runtime(clang_rt.ubsan_standalone-${arch} ${arch} STATIC
+      SOURCES $<TARGET_OBJECTS:RTSanitizerCommon.${arch}>
+              $<TARGET_OBJECTS:RTSanitizerCommonLibc.${arch}>
+              $<TARGET_OBJECTS:RTUbsan.${arch}>
+      CFLAGS ${UBSAN_CFLAGS})
+    add_compiler_rt_runtime(clang_rt.ubsan_standalone_cxx-${arch} ${arch} STATIC
+      SOURCES $<TARGET_OBJECTS:RTUbsan_cxx.${arch}>
       CFLAGS ${UBSAN_CXXFLAGS})
+    # UBSan runtimes used when another sanitizer is available.
+    add_compiler_rt_runtime(clang_rt.ubsan-${arch} ${arch} STATIC
+      SOURCES $<TARGET_OBJECTS:RTUbsan.${arch}>
+      CFLAGS ${UBSAN_CFLAGS})
+    add_compiler_rt_runtime(clang_rt.ubsan_cxx-${arch} ${arch} STATIC
+      SOURCES $<TARGET_OBJECTS:RTUbsan_cxx.${arch}>
+      CFLAGS ${UBSAN_CXXFLAGS})
+
     add_dependencies(ubsan
-      clang_rt.san-${arch}
       clang_rt.ubsan-${arch}
-      clang_rt.ubsan_cxx-${arch})
+      clang_rt.ubsan_cxx-${arch}
+      clang_rt.ubsan_standalone-${arch}
+      clang_rt.ubsan_standalone_cxx-${arch})
     if (UNIX AND NOT ${arch} MATCHES "i386|i686")
       add_sanitizer_rt_symbols(clang_rt.ubsan-${arch} ubsan.syms.extra)
       add_sanitizer_rt_symbols(clang_rt.ubsan_cxx-${arch} ubsan.syms.extra)
+      add_sanitizer_rt_symbols(clang_rt.ubsan_standalone-${arch} ubsan.syms.extra)
+      add_sanitizer_rt_symbols(clang_rt.ubsan_standalone_cxx-${arch} ubsan.syms.extra)
       add_dependencies(ubsan
         clang_rt.ubsan-${arch}-symbols
-        clang_rt.ubsan_cxx-${arch}-symbols)
+        clang_rt.ubsan_cxx-${arch}-symbols
+        clang_rt.ubsan_standalone-${arch}-symbols
+        clang_rt.ubsan_standalone_cxx-${arch}-symbols)
     endif()
   endforeach()
 endif()
diff --git a/lib/ubsan/ubsan_diag.cc b/lib/ubsan/ubsan_diag.cc
index 4f2a2a9..2314fb6 100644
--- a/lib/ubsan/ubsan_diag.cc
+++ b/lib/ubsan/ubsan_diag.cc
@@ -11,6 +11,8 @@
 //
 //===----------------------------------------------------------------------===//
 
+#include "ubsan_platform.h"
+#if CAN_SANITIZE_UB
 #include "ubsan_diag.h"
 #include "ubsan_init.h"
 #include "ubsan_flags.h"
@@ -49,8 +51,13 @@
   if (Loc.isSourceLocation()) {
     SourceLocation SLoc = Loc.getSourceLocation();
     if (!SLoc.isInvalid()) {
-      ReportErrorSummary("undefined-behavior", SLoc.getFilename(),
-                         SLoc.getLine(), "");
+      AddressInfo AI;
+      AI.file = internal_strdup(SLoc.getFilename());
+      AI.line = SLoc.getLine();
+      AI.column = SLoc.getColumn();
+      AI.function = internal_strdup("");  // Avoid printing ?? as function name.
+      ReportErrorSummary("undefined-behavior", AI);
+      AI.Clear();
       return;
     }
   }
@@ -356,3 +363,5 @@
   Suppression *s;
   return suppression_ctx->Match(TypeName, kVptrCheck, &s);
 }
+
+#endif  // CAN_SANITIZE_UB
diff --git a/lib/ubsan/ubsan_flags.cc b/lib/ubsan/ubsan_flags.cc
index 0dbffc9..49ada8a 100644
--- a/lib/ubsan/ubsan_flags.cc
+++ b/lib/ubsan/ubsan_flags.cc
@@ -11,6 +11,8 @@
 //
 //===----------------------------------------------------------------------===//
 
+#include "ubsan_platform.h"
+#if CAN_SANITIZE_UB
 #include "ubsan_flags.h"
 #include "sanitizer_common/sanitizer_common.h"
 #include "sanitizer_common/sanitizer_flags.h"
@@ -77,3 +79,5 @@
 const char *__ubsan_default_options() { return ""; }
 }  // extern "C"
 #endif
+
+#endif  // CAN_SANITIZE_UB
diff --git a/lib/ubsan/ubsan_handlers.cc b/lib/ubsan/ubsan_handlers.cc
index 78e7508..a65b2f5 100644
--- a/lib/ubsan/ubsan_handlers.cc
+++ b/lib/ubsan/ubsan_handlers.cc
@@ -11,6 +11,8 @@
 //
 //===----------------------------------------------------------------------===//
 
+#include "ubsan_platform.h"
+#if CAN_SANITIZE_UB
 #include "ubsan_handlers.h"
 #include "ubsan_diag.h"
 
@@ -419,3 +421,5 @@
   handleNonNullArg(Data, Opts);
   Die();
 }
+
+#endif  // CAN_SANITIZE_UB
diff --git a/lib/ubsan/ubsan_handlers_cxx.cc b/lib/ubsan/ubsan_handlers_cxx.cc
index 4718e6e..b3cda32 100644
--- a/lib/ubsan/ubsan_handlers_cxx.cc
+++ b/lib/ubsan/ubsan_handlers_cxx.cc
@@ -13,6 +13,8 @@
 //
 //===----------------------------------------------------------------------===//
 
+#include "ubsan_platform.h"
+#if CAN_SANITIZE_UB
 #include "ubsan_handlers_cxx.h"
 #include "ubsan_diag.h"
 #include "ubsan_type_hash.h"
@@ -79,3 +81,5 @@
   GET_REPORT_OPTIONS(true);
   HandleDynamicTypeCacheMiss(Data, Pointer, Hash, Opts);
 }
+
+#endif  // CAN_SANITIZE_UB
diff --git a/lib/ubsan/ubsan_init.cc b/lib/ubsan/ubsan_init.cc
index 219273d..9527269 100644
--- a/lib/ubsan/ubsan_init.cc
+++ b/lib/ubsan/ubsan_init.cc
@@ -11,6 +11,8 @@
 //
 //===----------------------------------------------------------------------===//
 
+#include "ubsan_platform.h"
+#if CAN_SANITIZE_UB
 #include "ubsan_diag.h"
 #include "ubsan_init.h"
 #include "ubsan_flags.h"
@@ -61,3 +63,5 @@
 };
 static UbsanInitializer ubsan_initializer;
 #endif  // SANITIZER_CAN_USE_PREINIT_ARRAY
+
+#endif  // CAN_SANITIZE_UB
diff --git a/lib/ubsan/ubsan_platform.h b/lib/ubsan/ubsan_platform.h
new file mode 100644
index 0000000..efb7974
--- /dev/null
+++ b/lib/ubsan/ubsan_platform.h
@@ -0,0 +1,26 @@
+//===-- ubsan_platform.h ----------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Defines the platforms which UBSan is supported at.
+//
+//===----------------------------------------------------------------------===//
+#ifndef UBSAN_PLATFORM_H
+#define UBSAN_PLATFORM_H
+
+// Other platforms should be easy to add, and probably work as-is.
+#if (defined(__linux__) || defined(__FreeBSD__) || defined(__APPLE__)) && \
+    (defined(__x86_64__) || defined(__i386__) || defined(__arm__) || \
+     defined(__aarch64__) || defined(__mips__))
+# define CAN_SANITIZE_UB 1
+#else
+# define CAN_SANITIZE_UB 0
+# error "UBSan not supported for this platform!"
+#endif
+
+#endif
diff --git a/lib/ubsan/ubsan_type_hash.cc b/lib/ubsan/ubsan_type_hash.cc
index a388bcc..c85d68d 100644
--- a/lib/ubsan/ubsan_type_hash.cc
+++ b/lib/ubsan/ubsan_type_hash.cc
@@ -13,6 +13,8 @@
 //
 //===----------------------------------------------------------------------===//
 
+#include "ubsan_platform.h"
+#if CAN_SANITIZE_UB
 #include "ubsan_type_hash.h"
 
 #include "sanitizer_common/sanitizer_common.h"
@@ -248,3 +250,5 @@
   return DynamicTypeInfo(Vtable->TypeInfo->__type_name, -Vtable->Offset,
                          ObjectType ? ObjectType->__type_name : "<unknown>");
 }
+
+#endif  // CAN_SANITIZE_UB
diff --git a/lib/ubsan/ubsan_value.cc b/lib/ubsan/ubsan_value.cc
index ab74720..ea91d63 100644
--- a/lib/ubsan/ubsan_value.cc
+++ b/lib/ubsan/ubsan_value.cc
@@ -12,6 +12,8 @@
 //
 //===----------------------------------------------------------------------===//
 
+#include "ubsan_platform.h"
+#if CAN_SANITIZE_UB
 #include "ubsan_value.h"
 #include "sanitizer_common/sanitizer_common.h"
 #include "sanitizer_common/sanitizer_libc.h"
@@ -100,3 +102,5 @@
   }
   UNREACHABLE("unexpected floating point bit width");
 }
+
+#endif  // CAN_SANITIZE_UB
diff --git a/lib/ubsan/ubsan_value.h b/lib/ubsan/ubsan_value.h
index a681084..72eee15 100644
--- a/lib/ubsan/ubsan_value.h
+++ b/lib/ubsan/ubsan_value.h
@@ -14,12 +14,6 @@
 #ifndef UBSAN_VALUE_H
 #define UBSAN_VALUE_H
 
-// For now, only support Linux, FreeBSD and Darwin. Other platforms should
-// be easy to add, and probably work as-is.
-#if !defined(__linux__) && !defined(__FreeBSD__) && !defined(__APPLE__)
-#error "UBSan not supported for this platform!"
-#endif
-
 #include "sanitizer_common/sanitizer_atomic.h"
 #include "sanitizer_common/sanitizer_common.h"
 
@@ -32,7 +26,6 @@
 #define HAVE_INT128_T 0
 #endif
 
-
 namespace __ubsan {
 
 /// \brief Largest integer types we support.
diff --git a/make/platform/clang_darwin.mk b/make/platform/clang_darwin.mk
index 4f71c0b..b0e8802 100644
--- a/make/platform/clang_darwin.mk
+++ b/make/platform/clang_darwin.mk
@@ -119,8 +119,11 @@
 Configs += asan_iossim_dynamic
 UniversalArchs.asan_iossim_dynamic := $(call CheckArches,i386 x86_64,asan_iossim_dynamic,$(IOSSIM_SDK))
 
-Configs += ubsan_osx
-UniversalArchs.ubsan_osx := $(call CheckArches,i386 x86_64 x86_64h,ubsan_osx,$(OSX_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
@@ -172,26 +175,31 @@
 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) -mmacosx-version-min=10.7 \
-	-stdlib=libc++ \
-	-isysroot $(OSX_SDK) \
-	-fno-builtin \
-	-gline-tables-only \
+	$(CFLAGS) $(SANITIZER_MACOSX_DEPLOYMENT_ARGS) \
+	$(SANITIZER_CFLAGS) \
 	-DMAC_INTERPOSE_FUNCTIONS=1 \
 	-DASAN_DYNAMIC=1
 
 CFLAGS.asan_iossim_dynamic := \
-	$(CFLAGS) -mios-simulator-version-min=7.0 \
-        -isysroot $(IOSSIM_SDK) \
-        -fno-builtin \
-	-gline-tables-only \
+	$(CFLAGS) $(SANITIZER_IOSSIM_DEPLOYMENT_ARGS) \
+	$(SANITIZER_CFLAGS) \
 	-DMAC_INTERPOSE_FUNCTIONS=1 \
 	-DASAN_DYNAMIC=1
 
-CFLAGS.ubsan_osx := $(CFLAGS) -mmacosx-version-min=10.6 \
-	-isysroot $(OSX_SDK) \
-	-fno-builtin
+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)
@@ -222,19 +230,30 @@
 CFLAGS.profile_ios.armv7s := $(CFLAGS) $(IOS_DEPLOYMENT_ARGS)
 CFLAGS.profile_ios.arm64  := $(CFLAGS) $(IOS6_DEPLOYMENT_ARGS)
 
-# Configure the asan_osx_dynamic library to be built shared.
-SHARED_LIBRARY.asan_osx_dynamic := 1
-LDFLAGS.asan_osx_dynamic := -lc++ -undefined dynamic_lookup -install_name @rpath/libclang_rt.asan_osx_dynamic.dylib \
-  -mmacosx-version-min=10.7 \
-  -isysroot $(OSX_SDK)
+SANITIZER_LDFLAGS := -stdlib=libc++ -lc++
 
-# Configure the asan_iossim_dynamic library to be built shared.
+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
-# configure+make uses Clang, so we're using isysroot instead of --sysroot
-# or -Wl,-syslibroot.
-LDFLAGS.asan_iossim_dynamic := -undefined dynamic_lookup -install_name @rpath/libclang_rt.asan_iossim_dynamic.dylib \
-  -Wl,-ios_simulator_version_min,7.0.0 \
-  -mios-simulator-version-min=7.0 -isysroot $(IOSSIM_SDK)
+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) -lc++abi -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) -lc++abi -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
 
 FUNCTIONS.eprintf := eprintf
 FUNCTIONS.10.4 := eprintf floatundidf floatundisf floatundixf
@@ -256,15 +275,18 @@
 FUNCTIONS.asan_osx_dynamic := $(AsanFunctions) $(AsanCXXFunctions) \
                               $(InterceptionFunctions) \
                               $(SanitizerCommonFunctions) \
-	                      $(AsanDynamicFunctions)
+                              $(AsanDynamicFunctions)
 
 FUNCTIONS.asan_iossim_dynamic := $(AsanFunctions) $(AsanCXXFunctions) \
                                  $(InterceptionFunctions) \
                                  $(SanitizerCommonFunctions) \
-	                         $(AsanDynamicFunctions)
+                                 $(AsanDynamicFunctions)
 
-FUNCTIONS.ubsan_osx := $(UbsanFunctions) $(UbsanCXXFunctions) \
-                       $(SanitizerCommonFunctions)
+FUNCTIONS.ubsan_osx_dynamic := $(UbsanFunctions) $(UbsanCXXFunctions) \
+                               $(SanitizerCommonFunctions)
+
+FUNCTIONS.ubsan_iossim_dynamic := $(UbsanFunctions) $(UbsanCXXFunctions) \
+                                  $(SanitizerCommonFunctions)
 
 CCKEXT_PROFILE_FUNCTIONS := \
 	InstrProfiling \
diff --git a/make/platform/clang_linux.mk b/make/platform/clang_linux.mk
index cb023f3..4585cd9 100644
--- a/make/platform/clang_linux.mk
+++ b/make/platform/clang_linux.mk
@@ -74,12 +74,6 @@
 CFLAGS.profile-i386 := $(CFLAGS) -m32
 CFLAGS.profile-x86_64 := $(CFLAGS) -m64
 
-# Use our stub SDK as the sysroot to support more portable building. For now we
-# just do this for the core module, because the stub SDK doesn't have
-# enough support to build the profile runtime.
-CFLAGS.builtins-i386 += --sysroot=$(ProjSrcRoot)/SDKs/linux
-CFLAGS.builtins-x86_64 += --sysroot=$(ProjSrcRoot)/SDKs/linux
-
 FUNCTIONS.builtins-i386 := $(CommonFunctions) $(ArchFunctions.i386)
 FUNCTIONS.builtins-x86_64 := $(CommonFunctions) $(ArchFunctions.x86_64)
 FUNCTIONS.profile-i386 := GCDAProfiling InstrProfiling InstrProfilingBuffer \
diff --git a/test/asan/CMakeLists.txt b/test/asan/CMakeLists.txt
index e1b8126..08c1689 100644
--- a/test/asan/CMakeLists.txt
+++ b/test/asan/CMakeLists.txt
@@ -5,9 +5,9 @@
 
 macro(get_bits_for_arch arch bits)
   if (${arch} MATCHES "i386|i686|arm|mips|mipsel")
-    set(bits 32)
+    set(${bits} 32)
   elseif (${arch} MATCHES "x86_64|powerpc64|powerpc64le|aarch64|mips64|mips64el")
-    set(bits 64)
+    set(${bits} 64)
   else()
     message(FATAL_ERROR "Unknown target architecture: ${arch}")
   endif()
diff --git a/test/asan/TestCases/Darwin/atos-symbolizer.cc b/test/asan/TestCases/Darwin/atos-symbolizer.cc
new file mode 100644
index 0000000..a4df3a2
--- /dev/null
+++ b/test/asan/TestCases/Darwin/atos-symbolizer.cc
@@ -0,0 +1,28 @@
+// Check that the `atos` symbolizer works.
+
+// RUN: %clangxx_asan -O0 %s -o %t 
+// RUN: ASAN_OPTIONS=verbosity=2 ASAN_SYMBOLIZER_PATH=$(which atos) not %run %t 2>&1 | FileCheck %s
+
+// Check that when having a DYLD_ROOT_PATH set, the symbolizer still works.
+// RUN: DYLD_ROOT_PATH="/" ASAN_OPTIONS=verbosity=2 ASAN_SYMBOLIZER_PATH=$(which atos) \
+// RUN:   not %run %t 2>&1 | FileCheck %s
+
+#include <stdlib.h>
+#include <string.h>
+int main(int argc, char **argv) {
+  char *x = (char*)malloc(10 * sizeof(char));
+  memset(x, 0, 10);
+  int res = x[argc];
+  free(x);
+  free(x + argc - 1);  // BOOM
+  // CHECK: AddressSanitizer: attempting double-free{{.*}}in thread T0
+  // CHECK: Using atos at user-specified path:
+  // CHECK: #0 0x{{.*}} in {{.*}}free
+  // CHECK: #1 0x{{.*}} in main {{.*}}atos-symbolizer.cc:[[@LINE-4]]
+  // CHECK: freed by thread T0 here:
+  // CHECK: #0 0x{{.*}} in {{.*}}free
+  // CHECK: #1 0x{{.*}} in main {{.*}}atos-symbolizer.cc:[[@LINE-8]]
+  // CHECK: allocated by thread T0 here:
+  // CHECK: atos-symbolizer.cc:[[@LINE-13]]
+  return res;
+}
diff --git a/test/asan/TestCases/Darwin/dladdr-demangling.cc b/test/asan/TestCases/Darwin/dladdr-demangling.cc
new file mode 100644
index 0000000..494007f
--- /dev/null
+++ b/test/asan/TestCases/Darwin/dladdr-demangling.cc
@@ -0,0 +1,33 @@
+// In a non-forking sandbox, we fallback to dladdr(). Test that we provide
+// properly demangled C++ names in that case.
+
+// RUN: %clangxx_asan -O0 %s -o %t 
+// RUN: not %run %t 2>&1 | FileCheck %s
+// RUN: ASAN_OPTIONS=verbosity=2 not %run sandbox-exec -p '(version 1)(allow default)(deny process-fork)' %t 2>&1 | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-DLADDR
+
+#include <stdlib.h>
+
+class MyClass {
+ public:
+  int my_function(int n) {
+    char *x = (char*)malloc(n * sizeof(char));
+    free(x);
+    return x[5];
+    // CHECK: {{.*ERROR: AddressSanitizer: heap-use-after-free on address}}
+    // CHECK: {{READ of size 1 at 0x.* thread T0}}
+    // CHECK-DLADDR: Using dladdr symbolizer
+    // CHECK-DLADDR: failed to fork external symbolizer
+    // CHECK: {{    #0 0x.* in MyClass::my_function\(int\)}}
+    // CHECK: {{freed by thread T0 here:}}
+    // CHECK: {{    #0 0x.* in wrap_free}}
+    // CHECK: {{    #1 0x.* in MyClass::my_function\(int\)}}
+    // CHECK: {{previously allocated by thread T0 here:}}
+    // CHECK: {{    #0 0x.* in wrap_malloc}}
+    // CHECK: {{    #1 0x.* in MyClass::my_function\(int\)}}
+  }
+};
+
+int main() {
+  MyClass o;
+  return o.my_function(10);
+}
diff --git a/test/asan/TestCases/Darwin/interface_symbols_darwin.c b/test/asan/TestCases/Darwin/interface_symbols_darwin.c
index a75044d..bd9bbee 100644
--- a/test/asan/TestCases/Darwin/interface_symbols_darwin.c
+++ b/test/asan/TestCases/Darwin/interface_symbols_darwin.c
@@ -29,6 +29,18 @@
 // RUN: echo __asan_report_store16 >> %t.interface
 // RUN: echo __asan_report_load_n >> %t.interface
 // RUN: echo __asan_report_store_n >> %t.interface
+// RUN: echo __asan_report_exp_load1 >> %t.interface
+// RUN: echo __asan_report_exp_load2 >> %t.interface
+// RUN: echo __asan_report_exp_load4 >> %t.interface
+// RUN: echo __asan_report_exp_load8 >> %t.interface
+// RUN: echo __asan_report_exp_load16 >> %t.interface
+// RUN: echo __asan_report_exp_store1 >> %t.interface
+// RUN: echo __asan_report_exp_store2 >> %t.interface
+// RUN: echo __asan_report_exp_store4 >> %t.interface
+// RUN: echo __asan_report_exp_store8 >> %t.interface
+// RUN: echo __asan_report_exp_store16 >> %t.interface
+// RUN: echo __asan_report_exp_load_n >> %t.interface
+// 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
diff --git a/test/asan/TestCases/Darwin/sandbox-symbolizer.cc b/test/asan/TestCases/Darwin/sandbox-symbolizer.cc
new file mode 100644
index 0000000..4313371
--- /dev/null
+++ b/test/asan/TestCases/Darwin/sandbox-symbolizer.cc
@@ -0,0 +1,29 @@
+// In a non-forking sandbox, we can't spawn an external symbolizer, but dladdr()
+// should still work and provide function names. No line numbers though.
+// Second, `atos` symbolizer can't inspect a process that has an inaccessible
+// task port, in which case we should again fallback to dladdr gracefully.
+
+// RUN: %clangxx_asan -O0 %s -o %t 
+// RUN: not %run sandbox-exec -p '(version 1)(allow default)(deny process-fork)' %t 2>&1 | FileCheck %s
+// RUN: not %run sandbox-exec -p '(version 1)(allow default)(deny mach-priv-task-port)' %t 2>&1 | FileCheck %s
+// RUN: ASAN_SYMBOLIZER_PATH="" not %run sandbox-exec -p '(version 1)(allow default)(deny mach-priv-task-port)' %t 2>&1 | FileCheck %s
+// RUN: %clangxx_asan -O3 %s -o %t 
+// RUN: not %run sandbox-exec -p '(version 1)(allow default)(deny process-fork)' %t 2>&1 | FileCheck %s
+// RUN: not %run sandbox-exec -p '(version 1)(allow default)(deny mach-priv-task-port)' %t 2>&1 | FileCheck %s
+// RUN: ASAN_SYMBOLIZER_PATH="" not %run sandbox-exec -p '(version 1)(allow default)(deny mach-priv-task-port)' %t 2>&1 | FileCheck %s
+
+#include <stdlib.h>
+int main() {
+  char *x = (char*)malloc(10 * sizeof(char));
+  free(x);
+  return x[5];
+  // CHECK: {{.*ERROR: AddressSanitizer: heap-use-after-free on address}}
+  // CHECK: {{READ of size 1 at 0x.* thread T0}}
+  // CHECK: {{    #0 0x.* in main}}
+  // CHECK: {{freed by thread T0 here:}}
+  // CHECK: {{    #0 0x.* in wrap_free}}
+  // CHECK: {{    #1 0x.* in main}}
+  // CHECK: {{previously allocated by thread T0 here:}}
+  // CHECK: {{    #0 0x.* in wrap_malloc}}
+  // CHECK: {{    #1 0x.* in main}}
+}
diff --git a/test/asan/TestCases/Darwin/suppressions-sandbox.cc b/test/asan/TestCases/Darwin/suppressions-sandbox.cc
new file mode 100644
index 0000000..59fe475
--- /dev/null
+++ b/test/asan/TestCases/Darwin/suppressions-sandbox.cc
@@ -0,0 +1,26 @@
+// Check that without suppressions, we catch the issue.
+// RUN: %clangxx_asan -O0 %s -o %t -framework Foundation
+// RUN: not %run %t 2>&1 | FileCheck --check-prefix=CHECK-CRASH %s
+
+// Check that suppressing a function name works within a no-fork sandbox
+// RUN: echo "interceptor_via_fun:CFStringCreateWithBytes" > %t.supp
+// RUN: ASAN_OPTIONS=suppressions=%t.supp \
+// RUN:   sandbox-exec -p '(version 1)(allow default)(deny process-fork)' \
+// RUN:   %run %t 2>&1 | FileCheck --check-prefix=CHECK-IGNORE %s
+
+#include <CoreFoundation/CoreFoundation.h>
+
+int main() {
+  char *a = (char *)malloc(6);
+  strcpy(a, "hello");
+  CFStringRef str =
+      CFStringCreateWithBytes(kCFAllocatorDefault, (unsigned char *)a, 10,
+                              kCFStringEncodingUTF8, FALSE);  // BOOM
+  fprintf(stderr, "Ignored.\n");
+  free(a);
+}
+
+// CHECK-CRASH: AddressSanitizer: heap-buffer-overflow
+// CHECK-CRASH-NOT: Ignored.
+// CHECK-IGNORE-NOT: AddressSanitizer: heap-buffer-overflow
+// CHECK-IGNORE: Ignored.
diff --git a/test/asan/TestCases/Linux/coverage-module-unloaded.cc b/test/asan/TestCases/Linux/coverage-module-unloaded.cc
index f8d9c57..573fc46 100644
--- a/test/asan/TestCases/Linux/coverage-module-unloaded.cc
+++ b/test/asan/TestCases/Linux/coverage-module-unloaded.cc
@@ -50,7 +50,7 @@
 
 // CHECK: PID: [[PID:[0-9]+]]
 // CHECK: [[PID]].sancov: 1 PCs written
-// CHECK: .so.[[PID]]
-// If we get coverage for both DSOs, it means the module wasn't unloaded and
-// this test is useless.
-// CHECK-NOT: .so.[[PID]]
+// CHECK: test_1.so.[[PID]]
+// CHECK: test_2.so.[[PID]]
+// Even though we've unloaded one of the libs we still dump the coverage file
+// for that lib (although the data will be inaccurate, it at all useful)
diff --git a/test/asan/TestCases/Linux/coverage-sandboxing.cc b/test/asan/TestCases/Linux/coverage-sandboxing.cc
index 1a72c6b..15bada8 100644
--- a/test/asan/TestCases/Linux/coverage-sandboxing.cc
+++ b/test/asan/TestCases/Linux/coverage-sandboxing.cc
@@ -78,8 +78,8 @@
 #endif
 
 // CHECK-vanilla: PID: [[PID:[0-9]+]]
-// CHECK-vanilla: [[PID]].sancov: 1 PCs written
 // CHECK-vanilla: .so.[[PID]].sancov: 258 PCs written
+// CHECK-vanilla: [[PID]].sancov: 1 PCs written
 
 // CHECK-sandbox: PID: [[PID:[0-9]+]]
 // CHECK-sandbox: 258 PCs written to packed file
diff --git a/test/asan/TestCases/Linux/coverage.cc b/test/asan/TestCases/Linux/coverage.cc
index 06fe1a2..1ad19e6 100644
--- a/test/asan/TestCases/Linux/coverage.cc
+++ b/test/asan/TestCases/Linux/coverage.cc
@@ -1,11 +1,18 @@
 // RUN: %clangxx_asan -fsanitize-coverage=1 -DSHARED %s -shared -o %T/libcoverage_test.so -fPIC
 // RUN: %clangxx_asan -fsanitize-coverage=1 %s   -o %t -Wl,-R,\$ORIGIN -L%T -lcoverage_test
 // RUN: export ASAN_OPTIONS=coverage=1:verbosity=1
-// RUN: mkdir -p %T/coverage && cd %T/coverage
+// RUN: rm -rf %T/coverage && mkdir -p %T/coverage && cd %T/coverage
 // RUN: %run %t 2>&1         | FileCheck %s --check-prefix=CHECK-main
+// RUN: %sancov print coverage.*sancov 2>&1 | FileCheck %s --check-prefix=CHECK-SANCOV1
 // RUN: %run %t foo 2>&1     | FileCheck %s --check-prefix=CHECK-foo
+// RUN: %sancov print coverage.*sancov 2>&1 | FileCheck %s --check-prefix=CHECK-SANCOV2
 // RUN: %run %t bar 2>&1     | FileCheck %s --check-prefix=CHECK-bar
+// RUN: %sancov print coverage.*sancov 2>&1 | FileCheck %s --check-prefix=CHECK-SANCOV2
 // RUN: %run %t foo bar 2>&1 | FileCheck %s --check-prefix=CHECK-foo-bar
+// RUN: %sancov print coverage.*sancov 2>&1 | FileCheck %s --check-prefix=CHECK-SANCOV2
+// RUN: %sancov print libcoverage_test.*sancov 2>&1 | FileCheck %s --check-prefix=CHECK-SANCOV1
+// RUN: %sancov merge coverage.*sancov > merged-cov
+// RUN: %sancov print merged-cov 2>&1 | FileCheck %s --check-prefix=CHECK-SANCOV2
 // RUN: not %run %t foo bar 4    2>&1 | FileCheck %s --check-prefix=CHECK-report
 // RUN: not %run %t foo bar 4 5  2>&1 | FileCheck %s --check-prefix=CHECK-segv
 // RUN: cd .. && rm coverage -r
@@ -57,15 +64,18 @@
 // CHECK-foo-NOT: .so.[[PID]]
 //
 // CHECK-bar: PID: [[PID:[0-9]+]]
-// CHECK-bar: [[PID]].sancov: 1 PCs written
 // CHECK-bar: .so.[[PID]].sancov: 1 PCs written
+// CHECK-bar: [[PID]].sancov: 1 PCs written
 //
 // CHECK-foo-bar: PID: [[PID:[0-9]+]]
-// CHECK-foo-bar: [[PID]].sancov: 2 PCs written
 // CHECK-foo-bar: so.[[PID]].sancov: 1 PCs written
+// CHECK-foo-bar: [[PID]].sancov: 2 PCs written
 //
 // CHECK-report: AddressSanitizer: global-buffer-overflow
 // CHECK-report: PCs written
 //
 // CHECK-segv: AddressSanitizer: SEGV
 // CHECK-segv: PCs written
+//
+// CHECK-SANCOV1: 1 PCs total
+// CHECK-SANCOV2: 2 PCs total
diff --git a/test/asan/TestCases/Linux/interface_symbols_linux.c b/test/asan/TestCases/Linux/interface_symbols_linux.c
index a616732..bec501b 100644
--- a/test/asan/TestCases/Linux/interface_symbols_linux.c
+++ b/test/asan/TestCases/Linux/interface_symbols_linux.c
@@ -24,6 +24,18 @@
 // RUN: echo __asan_report_store16 >> %t.interface
 // RUN: echo __asan_report_load_n >> %t.interface
 // RUN: echo __asan_report_store_n >> %t.interface
+// RUN: echo __asan_report_exp_load1 >> %t.interface
+// RUN: echo __asan_report_exp_load2 >> %t.interface
+// RUN: echo __asan_report_exp_load4 >> %t.interface
+// RUN: echo __asan_report_exp_load8 >> %t.interface
+// RUN: echo __asan_report_exp_load16 >> %t.interface
+// RUN: echo __asan_report_exp_store1 >> %t.interface
+// RUN: echo __asan_report_exp_store2 >> %t.interface
+// RUN: echo __asan_report_exp_store4 >> %t.interface
+// RUN: echo __asan_report_exp_store8 >> %t.interface
+// RUN: echo __asan_report_exp_store16 >> %t.interface
+// RUN: echo __asan_report_exp_load_n >> %t.interface
+// 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: cat %t.interface | sort -u | diff %t.symbols -
diff --git a/test/asan/TestCases/Linux/leak_check_segv.cc b/test/asan/TestCases/Linux/leak_check_segv.cc
new file mode 100644
index 0000000..8160d5f
--- /dev/null
+++ b/test/asan/TestCases/Linux/leak_check_segv.cc
@@ -0,0 +1,23 @@
+// Test that SIGSEGV during leak checking does not crash the process.
+// RUN: %clangxx_asan -O1 %s -o %t && LSAN_OPTIONS="verbosity=1" not %run %t 2>&1
+// REQUIRES: leak-detection
+#include <stdlib.h>
+#include <stdio.h>
+#include <sys/mman.h>
+#include <sanitizer/lsan_interface.h>
+
+char data[10 * 1024 * 1024];
+
+int main() {
+  void *p = malloc(10 * 1024 * 1024);
+  // surprise-surprise!
+  mprotect((void*)(((unsigned long)p + 4095) & ~4095), 16 * 1024, PROT_NONE); 
+  mprotect((void*)(((unsigned long)data + 4095) & ~4095), 16 * 1024, PROT_NONE);
+  __lsan_do_leak_check();
+  fprintf(stderr, "DONE\n");
+}
+
+// CHECK: Tracer caught signal 11
+// CHECK: LeakSanitizer has encountered a fatal error
+// CHECK-NOT: DONE
+
diff --git a/test/asan/TestCases/Linux/nohugepage_test.cc b/test/asan/TestCases/Linux/nohugepage_test.cc
index b549f3b..337b95d 100644
--- a/test/asan/TestCases/Linux/nohugepage_test.cc
+++ b/test/asan/TestCases/Linux/nohugepage_test.cc
@@ -22,15 +22,31 @@
 #include <sys/stat.h>
 #include <fcntl.h>
 #include <unistd.h>
+#include <errno.h>
 #include <sanitizer/asan_interface.h>
 
-char FileContents[1 << 14];
+char FileContents[1 << 16];
 
 void FileToString(const char *path) {
   FileContents[0] = 0;
   int fd = open(path, 0);
   if (fd < 0) return;
-  ssize_t res = read(fd, FileContents, sizeof(FileContents) - 1);
+  char *p = FileContents;
+  ssize_t size = sizeof(FileContents) - 1;
+  ssize_t res = 0;
+  do {
+    ssize_t got = read (fd, p, size);
+    if (got == 0)
+      break;
+    else if (got > 0)
+      {
+        p += got;
+        res += got;
+        size -= got;
+      }
+    else if (errno != EINTR)
+      break;
+  } while (size > 0 && res < sizeof(FileContents));
   if (res >= 0)
     FileContents[res] = 0;
 }
diff --git a/test/asan/TestCases/Linux/ptrace.cc b/test/asan/TestCases/Linux/ptrace.cc
index 7e5acb6..6840ebe 100644
--- a/test/asan/TestCases/Linux/ptrace.cc
+++ b/test/asan/TestCases/Linux/ptrace.cc
@@ -31,8 +31,8 @@
     // CHECK: AddressSanitizer: stack-buffer-overflow
     // CHECK: {{.*ptrace.cc:}}[[@LINE-2]]
     assert(!res);
-#if __WORDSIZE == 64
-    printf("%zx\n", regs.rip);
+#ifdef __x86_64__
+    printf("%lx\n", (unsigned long)regs.rip);
 #else
     printf("%lx\n", regs.eip);
 #endif
@@ -42,7 +42,7 @@
     assert(!res);
     printf("%lx\n", (unsigned long)fpregs.cwd);
 
-#if __WORDSIZE == 32
+#ifndef __x86_64__
     user_fpxregs_struct fpxregs;
     res = ptrace(PTRACE_GETFPXREGS, pid, NULL, &fpxregs);
     assert(!res);
diff --git a/test/asan/TestCases/Linux/signal_during_stop_the_world.cc b/test/asan/TestCases/Linux/signal_during_stop_the_world.cc
new file mode 100644
index 0000000..b1a41fe
--- /dev/null
+++ b/test/asan/TestCases/Linux/signal_during_stop_the_world.cc
@@ -0,0 +1,60 @@
+// Test StopTheWorld behavior during signal storm.
+// Historically StopTheWorld crashed because did not handle EINTR properly.
+// The test is somewhat convoluted, but that's what caused crashes previously.
+
+// RUN: %clangxx_asan -O1 %s -o %t && %run %t 2>&1 | FileCheck %s
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <signal.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/prctl.h>
+#include <sys/wait.h>
+#include <time.h>
+#include <pthread.h>
+#include <sanitizer/lsan_interface.h>
+
+static void handler(int signo);
+static void *thr(void *arg);
+
+int main() {
+  struct sigaction act = {};
+  act.sa_handler = handler;
+  sigaction(SIGPROF, &act, 0);
+
+  pid_t pid = fork();
+  if (pid < 0) {
+    fprintf(stderr, "failed to fork\n");
+    exit(1);
+  }
+  if (pid == 0) {
+    // Child constantly sends signals to parent to cause spurious return from
+    // waitpid in StopTheWorld.
+    prctl(PR_SET_PDEATHSIG, SIGTERM, 0, 0, 0);
+    pid_t parent = getppid();
+    for (;;) {
+      // There is no strong reason for these two particular signals,
+      // but at least one of them ought to unblock waitpid.
+      kill(parent, SIGCHLD);
+      kill(parent, SIGPROF);
+    }
+  }
+  usleep(10000);  // Let the child start.
+  __lsan_do_leak_check();
+  // Kill and join the child.
+  kill(pid, SIGTERM);
+  waitpid(pid, 0, 0);
+  sleep(1);  // If the tracer thread still runs, give it time to crash.
+  fprintf(stderr, "DONE\n");
+// CHECK: DONE
+}
+
+static void handler(int signo) {
+}
+
+static void *thr(void *arg) {
+  for (;;)
+    sleep(1);
+  return 0;
+}
diff --git a/test/asan/TestCases/Linux/sized_delete_test.cc b/test/asan/TestCases/Linux/sized_delete_test.cc
index 1ce610f..1401644 100644
--- a/test/asan/TestCases/Linux/sized_delete_test.cc
+++ b/test/asan/TestCases/Linux/sized_delete_test.cc
@@ -1,4 +1,4 @@
-// RUN: %clangxx_asan -Xclang -fdefine-sized-deallocation -Xclang -fsized-deallocation -O0 %s -o %t
+// RUN: %clangxx_asan -fsized-deallocation -O0 %s -o %t
 // RUN:                                         not %run %t scalar 2>&1 | FileCheck %s -check-prefix=SCALAR
 // RUN: ASAN_OPTIONS=new_delete_type_mismatch=1 not %run %t scalar 2>&1 | FileCheck %s -check-prefix=SCALAR
 // RUN:                                         not %run %t array  2>&1 | FileCheck %s -check-prefix=ARRAY
@@ -6,9 +6,10 @@
 // RUN: ASAN_OPTIONS=new_delete_type_mismatch=0     %run %t scalar
 // RUN: ASAN_OPTIONS=new_delete_type_mismatch=0     %run %t array
 
+// FIXME: the following two lines are not true after r232788.
 // Sized-delete is implemented with a weak delete() definition.
 // Weak symbols are kind of broken on Android.
-// XFAIL: android, asan-dynamic-runtime
+// XFAIL: android
 
 #include <new>
 #include <stdio.h>
diff --git a/test/asan/TestCases/Linux/coverage-direct.cc b/test/asan/TestCases/Posix/coverage-direct.cc
similarity index 100%
rename from test/asan/TestCases/Linux/coverage-direct.cc
rename to test/asan/TestCases/Posix/coverage-direct.cc
diff --git a/test/asan/TestCases/Linux/coverage-fork.cc b/test/asan/TestCases/Posix/coverage-fork.cc
similarity index 100%
rename from test/asan/TestCases/Linux/coverage-fork.cc
rename to test/asan/TestCases/Posix/coverage-fork.cc
diff --git a/test/asan/TestCases/log_path_fork_test.cc.disabled b/test/asan/TestCases/Posix/log_path_fork_test.cc.disabled
similarity index 100%
rename from test/asan/TestCases/log_path_fork_test.cc.disabled
rename to test/asan/TestCases/Posix/log_path_fork_test.cc.disabled
diff --git a/test/asan/TestCases/Posix/start-deactivated.cc b/test/asan/TestCases/Posix/start-deactivated.cc
index d7e0dfc..2eb02df 100644
--- a/test/asan/TestCases/Posix/start-deactivated.cc
+++ b/test/asan/TestCases/Posix/start-deactivated.cc
@@ -19,7 +19,6 @@
 // RUN:   ASAN_ACTIVATION_OPTIONS=help=1,handle_segv=0,verbosity=1 not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-UNSUPPORTED
 
 // XFAIL: arm-linux-gnueabi
-// XFAIL: armv7l-unknown-linux-gnueabihf
 
 #if !defined(SHARED_LIB)
 #include <assert.h>
diff --git a/test/asan/TestCases/Windows/bind_io_completion_callback.cc b/test/asan/TestCases/Windows/bind_io_completion_callback.cc
new file mode 100644
index 0000000..c062a79
--- /dev/null
+++ b/test/asan/TestCases/Windows/bind_io_completion_callback.cc
@@ -0,0 +1,70 @@
+// Make sure we can throw exceptions from work items executed via
+// BindIoCompletionCallback.
+//
+// Clang doesn't support exceptions on Windows yet, so for the time being we
+// build this program in two parts: the code with exceptions is built with CL,
+// the rest is built with Clang.  This represents the typical scenario when we
+// build a large project using "clang-cl -fallback -fsanitize=address".
+//
+// RUN: cl -c %s -Fo%t.obj
+// RUN: %clangxx_asan -o %t.exe %s %t.obj
+// RUN: %run %t.exe 2>&1 | FileCheck %s
+
+#include <windows.h>
+#include <stdio.h>
+
+void ThrowAndCatch();
+
+#if !defined(__clang__)
+__declspec(noinline)
+void Throw() {
+  fprintf(stderr, "Throw\n");
+// CHECK: Throw
+  throw 1;
+}
+
+void ThrowAndCatch() {
+  int local;
+  try {
+    Throw();
+  } catch(...) {
+    fprintf(stderr, "Catch\n");
+// CHECK: Catch
+  }
+}
+#else
+
+char buffer[65536];
+HANDLE done;
+OVERLAPPED ov;
+
+void CALLBACK completion_callback(DWORD error, DWORD bytesRead,
+                                  LPOVERLAPPED pov) {
+  ThrowAndCatch();
+  SetEvent(done);
+}
+
+int main(int argc, char **argv) {
+  done = CreateEvent(0, false, false, "job is done");
+  if (!done)
+    return 1;
+  HANDLE file = CreateFile(
+      argv[0], GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
+      OPEN_EXISTING,
+      FILE_ATTRIBUTE_NORMAL | FILE_FLAG_NO_BUFFERING | FILE_FLAG_OVERLAPPED,
+      NULL);
+  if (!file)
+    return 2;
+  if (!BindIoCompletionCallback(file, completion_callback, 0))
+    return 3;
+
+  if (!ReadFile(file, buffer, sizeof(buffer), NULL, &ov) &&
+      GetLastError() != ERROR_IO_PENDING)
+    return 4;
+
+  if (WAIT_OBJECT_0 != WaitForSingleObject(done, INFINITE))
+    return 5;
+  fprintf(stderr, "Done!\n");
+// CHECK: Done!
+}
+#endif
diff --git a/test/asan/TestCases/Windows/dll_noreturn.cc b/test/asan/TestCases/Windows/dll_noreturn.cc
index 6ec9072..79f923e 100644
--- a/test/asan/TestCases/Windows/dll_noreturn.cc
+++ b/test/asan/TestCases/Windows/dll_noreturn.cc
@@ -9,7 +9,7 @@
   char buffer[42];
   buffer[subscript] = 42;
   _exit(1);
-// CHECK: AddressSanitizer: stack-buffer-overflow on address [[ADDR:0x[0-9a-f]+]]
+// CHECK: AddressSanitizer: stack-buffer-underflow on address [[ADDR:0x[0-9a-f]+]]
 // CHECK: WRITE of size 1 at [[ADDR]] thread T0
 // CHECK-NEXT:  noreturn_f {{.*}}dll_noreturn.cc:[[@LINE-4]]
 // CHECK-NEXT:  test_function {{.*}}dll_noreturn.cc
diff --git a/test/asan/TestCases/Windows/dll_report_globals_symbolization_at_startup.cc b/test/asan/TestCases/Windows/dll_report_globals_symbolization_at_startup.cc
new file mode 100644
index 0000000..fbdb1c1
--- /dev/null
+++ b/test/asan/TestCases/Windows/dll_report_globals_symbolization_at_startup.cc
@@ -0,0 +1,40 @@
+// RUN: %clang_cl_asan -LD -O0 -DDLL %s -Fe%t.dll
+// RUN: %clang_cl_asan -O0 -DEXE %s %t.lib -Fe%te.exe
+// RUN: env ASAN_OPTIONS=report_globals=2 %run %te.exe 2>&1 | FileCheck %s
+
+// FIXME: Currently, the MT runtime build crashes on startup due to dbghelp.dll
+// initialization failure.
+// REQUIRES: asan-dynamic-runtime
+
+#include <windows.h>
+#include <stdio.h>
+
+extern "C" {
+#if defined(EXE)
+__declspec(dllimport) int foo_from_dll();
+
+// CHECK: in DLL(reason=1)
+int main(int argc, char **argv) {
+  foo_from_dll();
+// CHECK: hello!
+  printf("hello!\n");
+  fflush(0);
+// CHECK: in DLL(reason=0)
+}
+#elif defined(DLL)
+// This global is registered at startup.
+int x[42];
+
+__declspec(dllexport) int foo_from_dll() {
+  return x[2];
+}
+
+BOOL WINAPI DllMain(HMODULE, DWORD reason, LPVOID) {
+  printf("in DLL(reason=%d)\n", (int)reason);
+  fflush(0);
+  return TRUE;
+}
+#else
+# error oops!
+#endif
+}
diff --git a/test/asan/TestCases/Windows/dll_thread_stack_array_left_oob.cc b/test/asan/TestCases/Windows/dll_thread_stack_array_left_oob.cc
index 8f53623..04d3e2e 100644
--- a/test/asan/TestCases/Windows/dll_thread_stack_array_left_oob.cc
+++ b/test/asan/TestCases/Windows/dll_thread_stack_array_left_oob.cc
@@ -9,7 +9,7 @@
   int subscript = -1;
   char stack_buffer[42];
   stack_buffer[subscript] = 42;
-// CHECK: AddressSanitizer: stack-buffer-overflow on address [[ADDR:0x[0-9a-f]+]]
+// CHECK: AddressSanitizer: stack-buffer-underflow on address [[ADDR:0x[0-9a-f]+]]
 // CHECK: WRITE of size 1 at [[ADDR]] thread T1
 // CHECK-NEXT:  thread_proc {{.*}}dll_thread_stack_array_left_oob.cc:[[@LINE-3]]
 //
diff --git a/test/asan/TestCases/Windows/queue_user_work_item.cc b/test/asan/TestCases/Windows/queue_user_work_item.cc
new file mode 100644
index 0000000..d99ea6f
--- /dev/null
+++ b/test/asan/TestCases/Windows/queue_user_work_item.cc
@@ -0,0 +1,55 @@
+// Make sure we can throw exceptions from work items executed via
+// QueueUserWorkItem.
+//
+// Clang doesn't support exceptions on Windows yet, so for the time being we
+// build this program in two parts: the code with exceptions is built with CL,
+// the rest is built with Clang.  This represents the typical scenario when we
+// build a large project using "clang-cl -fallback -fsanitize=address".
+//
+// RUN: cl -c %s -Fo%t.obj
+// RUN: %clangxx_asan -o %t.exe %s %t.obj
+// RUN: %run %t.exe 2>&1 | FileCheck %s
+
+#include <windows.h>
+#include <stdio.h>
+
+void ThrowAndCatch();
+
+#if !defined(__clang__)
+__declspec(noinline)
+void Throw() {
+  fprintf(stderr, "Throw\n");
+// CHECK: Throw
+  throw 1;
+}
+
+void ThrowAndCatch() {
+  int local;
+  try {
+    Throw();
+  } catch(...) {
+    fprintf(stderr, "Catch\n");
+// CHECK: Catch
+  }
+}
+#else
+
+HANDLE done;
+
+DWORD CALLBACK work_item(LPVOID) {
+  ThrowAndCatch();
+  SetEvent(done);
+  return 0;
+}
+
+int main(int argc, char **argv) {
+  done = CreateEvent(0, false, false, "job is done");
+  if (!done)
+    return 1;
+  QueueUserWorkItem(&work_item, nullptr, 0);
+  if (WAIT_OBJECT_0 != WaitForSingleObject(done, INFINITE))
+    return 2;
+  fprintf(stderr, "Done!\n");
+// CHECK: Done!
+}
+#endif
diff --git a/test/asan/TestCases/Windows/queue_user_work_item_report.cc b/test/asan/TestCases/Windows/queue_user_work_item_report.cc
new file mode 100644
index 0000000..a57e1e7
--- /dev/null
+++ b/test/asan/TestCases/Windows/queue_user_work_item_report.cc
@@ -0,0 +1,29 @@
+// RUN: %clang_cl_asan -O0 %s -Fe%t
+// RUN: not %run %t 2>&1 | FileCheck %s
+
+#include <windows.h>
+
+HANDLE done;
+
+DWORD CALLBACK work_item(LPVOID) {
+  int subscript = -1;
+  volatile char stack_buffer[42];
+  stack_buffer[subscript] = 42;
+// CHECK: AddressSanitizer: stack-buffer-underflow on address [[ADDR:0x[0-9a-f]+]]
+// CHECK: WRITE of size 1 at [[ADDR]] thread T1
+// CHECK:   {{#0 .* work_item .*queue_user_work_item_report.cc}}:[[@LINE-3]]
+// CHECK: Address [[ADDR]] is located in stack of thread T1 at offset {{.*}} in frame
+// CHECK:   work_item
+  SetEvent(done);
+  return 0;
+}
+
+int main(int argc, char **argv) {
+  done = CreateEvent(0, false, false, "job is done");
+  if (!done)
+    return 1;
+// CHECK-NOT: Thread T1 created
+  QueueUserWorkItem(&work_item, nullptr, 0);
+  if (WAIT_OBJECT_0 != WaitForSingleObject(done, INFINITE))
+    return 2;
+}
diff --git a/test/asan/TestCases/Windows/report_globals_reload_dll.cc b/test/asan/TestCases/Windows/report_globals_reload_dll.cc
new file mode 100644
index 0000000..8b05097
--- /dev/null
+++ b/test/asan/TestCases/Windows/report_globals_reload_dll.cc
@@ -0,0 +1,51 @@
+// Make sure we can handle reloading the same DLL multiple times.
+// RUN: %clang_cl_asan -LD -O0 -DDLL %s -Fe%t.dll
+// RUN: %clang_cl_asan -O0 -DEXE %s -Fe%te.exe
+// RUN: env ASAN_OPTIONS=report_globals=1 %run %te.exe %t.dll 2>&1 | FileCheck %s
+
+#include <windows.h>
+#include <stdio.h>
+#include <string.h>
+
+extern "C" {
+#if defined(EXE)
+int main(int argc, char **argv) {
+  if (argc != 2) {
+    printf("Usage: %s [client].dll\n", argv[0]);
+    return 101;
+  }
+  const char *dll_name = argv[1];
+
+// CHECK: time to load DLL
+  printf("time to load DLL\n");
+  fflush(0);
+
+// CHECK: in DLL(reason=1)
+// CHECK: in DLL(reason=0)
+// CHECK: in DLL(reason=1)
+// CHECK: in DLL(reason=0)
+// CHECK: in DLL(reason=1)
+// CHECK: in DLL(reason=0)
+  for (int i = 0; i < 30; ++i) {
+    HMODULE dll = LoadLibrary(dll_name);
+    if (dll == NULL)
+      return 3;
+
+    if (!FreeLibrary(dll))
+      return 4;
+  }
+
+// CHECK: All OK!
+  printf("All OK!\n");
+  fflush(0);
+}
+#elif defined(DLL)
+BOOL WINAPI DllMain(HMODULE, DWORD reason, LPVOID) {
+  printf("in DLL(reason=%d)\n", (int)reason);
+  fflush(0);
+  return TRUE;
+}
+#else
+# error oops!
+#endif
+}
diff --git a/test/asan/TestCases/Windows/globals_multiple_dlls.cc b/test/asan/TestCases/Windows/report_globals_vs_freelibrary.cc
similarity index 85%
rename from test/asan/TestCases/Windows/globals_multiple_dlls.cc
rename to test/asan/TestCases/Windows/report_globals_vs_freelibrary.cc
index 634e578..72bf36a 100644
--- a/test/asan/TestCases/Windows/globals_multiple_dlls.cc
+++ b/test/asan/TestCases/Windows/report_globals_vs_freelibrary.cc
@@ -1,7 +1,3 @@
-// Make sure everything works even if the main module doesn't have any stack
-// variables, thus doesn't explicitly reference any symbol exported by the
-// runtime thunk.
-//
 // RUN: %clang_cl_asan -LD -O0 -DDLL %s -Fe%t.dll
 // RUN: %clang_cl_asan -O0 -DEXE %s -Fe%te.exe
 // RUN: env ASAN_OPTIONS=report_globals=2 %run %te.exe %t.dll 2>&1 | FileCheck %s
diff --git a/test/asan/TestCases/Windows/stack_array_left_oob.cc b/test/asan/TestCases/Windows/stack_array_left_oob.cc
index 040d855..845a1f3 100644
--- a/test/asan/TestCases/Windows/stack_array_left_oob.cc
+++ b/test/asan/TestCases/Windows/stack_array_left_oob.cc
@@ -7,7 +7,7 @@
   int subscript = -1;
   char buffer[42];
   buffer[subscript] = 42;
-// CHECK: AddressSanitizer: stack-buffer-overflow on address [[ADDR:0x[0-9a-f]+]]
+// CHECK: AddressSanitizer: stack-buffer-underflow on address [[ADDR:0x[0-9a-f]+]]
 // CHECK: WRITE of size 1 at [[ADDR]] thread T0
 // CHECK-NEXT: {{#0 .* main .*stack_array_left_oob.cc}}:[[@LINE-3]]
 // CHECK: Address [[ADDR]] is located in stack of thread T0 at offset [[OFFSET:.*]] in frame
diff --git a/test/asan/TestCases/Windows/thread_stack_array_left_oob.cc b/test/asan/TestCases/Windows/thread_stack_array_left_oob.cc
index 17b9b1b..63cb8ae 100644
--- a/test/asan/TestCases/Windows/thread_stack_array_left_oob.cc
+++ b/test/asan/TestCases/Windows/thread_stack_array_left_oob.cc
@@ -7,7 +7,7 @@
   int subscript = -1;
   volatile char stack_buffer[42];
   stack_buffer[subscript] = 42;
-// CHECK: AddressSanitizer: stack-buffer-overflow on address [[ADDR:0x[0-9a-f]+]]
+// CHECK: AddressSanitizer: stack-buffer-underflow on address [[ADDR:0x[0-9a-f]+]]
 // CHECK: WRITE of size 1 at [[ADDR]] thread T1
 // CHECK:   {{#0 .* thread_proc .*thread_stack_array_left_oob.cc}}:[[@LINE-3]]
 // CHECK: Address [[ADDR]] is located in stack of thread T1 at offset {{.*}} in frame
diff --git a/test/asan/TestCases/closed-fds.cc b/test/asan/TestCases/closed-fds.cc
new file mode 100644
index 0000000..604bf8b
--- /dev/null
+++ b/test/asan/TestCases/closed-fds.cc
@@ -0,0 +1,30 @@
+// Check that when the program closed its std(in|out|err), running the external
+// symbolizer still works.
+
+// RUN: rm -f %t.log.*
+// RUN: %clangxx_asan -O0 %s -o %t 2>&1 && ASAN_OPTIONS=log_path=%t.log:verbosity=2 not %run %t 2>&1
+// RUN: FileCheck %s --check-prefix=CHECK-FILE < %t.log.*
+
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+int main(int argc, char **argv) {
+  int result = fprintf(stderr, "Closing streams.\n");
+  assert(result > 0);
+  close(STDIN_FILENO);
+  close(STDOUT_FILENO);
+  close(STDERR_FILENO);
+  result = fprintf(stderr, "Can you hear me now?\n");
+  assert(result < 0);
+  char *x = (char *)malloc(10 * sizeof(char));
+  free(x);
+  x[argc] = 'X';  // BOOM
+  // CHECK-FILE: {{.*ERROR: AddressSanitizer: heap-use-after-free on address}}
+  // CHECK-FILE:   {{0x.* at pc 0x.* bp 0x.* sp 0x.*}}
+  // CHECK-FILE: {{WRITE of size 1 at 0x.* thread T0}}
+  // CHECK-FILE: {{    #0 0x.* in main .*closed-fds.cc:}}[[@LINE-4]]
+  return 0;
+}
diff --git a/test/asan/TestCases/Linux/coverage-and-lsan.cc b/test/asan/TestCases/coverage-and-lsan.cc
similarity index 100%
rename from test/asan/TestCases/Linux/coverage-and-lsan.cc
rename to test/asan/TestCases/coverage-and-lsan.cc
diff --git a/test/asan/TestCases/Linux/coverage-caller-callee-total-count.cc b/test/asan/TestCases/coverage-caller-callee-total-count.cc
similarity index 100%
rename from test/asan/TestCases/Linux/coverage-caller-callee-total-count.cc
rename to test/asan/TestCases/coverage-caller-callee-total-count.cc
diff --git a/test/asan/TestCases/Linux/coverage-caller-callee.cc b/test/asan/TestCases/coverage-caller-callee.cc
similarity index 100%
rename from test/asan/TestCases/Linux/coverage-caller-callee.cc
rename to test/asan/TestCases/coverage-caller-callee.cc
diff --git a/test/asan/TestCases/Linux/coverage-disabled.cc b/test/asan/TestCases/coverage-disabled.cc
similarity index 100%
rename from test/asan/TestCases/Linux/coverage-disabled.cc
rename to test/asan/TestCases/coverage-disabled.cc
diff --git a/test/asan/TestCases/Linux/coverage-levels.cc b/test/asan/TestCases/coverage-levels.cc
similarity index 61%
rename from test/asan/TestCases/Linux/coverage-levels.cc
rename to test/asan/TestCases/coverage-levels.cc
index cc196c5..63bed65 100644
--- a/test/asan/TestCases/Linux/coverage-levels.cc
+++ b/test/asan/TestCases/coverage-levels.cc
@@ -6,6 +6,10 @@
 // RUN: ASAN_OPTIONS=coverage=1:coverage_bitset=1:verbosity=1 %run %t 2>&1 | FileCheck %s --check-prefix=CHECK2
 // RUN: %clangxx_asan -O1 -fsanitize-coverage=3  %s -o %t
 // RUN: ASAN_OPTIONS=coverage=1:coverage_bitset=1:verbosity=1 %run %t 2>&1 | FileCheck %s --check-prefix=CHECK3
+// RUN: %clangxx_asan -O1 -fsanitize-coverage=3 -mllvm -sanitizer-coverage-block-threshold=0 %s -o %t
+// RUN: ASAN_OPTIONS=coverage=1:coverage_bitset=1:verbosity=1 %run %t 2>&1 | FileCheck %s --check-prefix=CHECK3
+// RUN: %clangxx_asan -O1 -fsanitize-coverage=3 -mllvm -sanitizer-coverage-8bit-counters=1 %s -o %t
+// RUN: ASAN_OPTIONS=coverage=1:coverage_counters=1:verbosity=1 %run %t 2>&1 | FileCheck %s --check-prefix=CHECK_COUNTERS
 
 // RUN: ASAN_OPTIONS=coverage=1:coverage_bitset=0:verbosity=1 %run %t 2>&1 | FileCheck %s --check-prefix=CHECK3_NOBITSET
 // RUN: ASAN_OPTIONS=coverage=1:verbosity=1 %run %t 2>&1 | FileCheck %s --check-prefix=CHECK3_NOBITSET
@@ -19,11 +23,12 @@
     sink = 0;
 }
 
-// CHECK1: CovDump: bitset of 1 bits written, 1 bits are set
+// CHECK1: CovDump: bitset of 1 bits written for '{{.*}}', 1 bits are set
 // CHECK1:  1 PCs written
-// CHECK2: CovDump: bitset of 3 bits written, 2 bits are set
+// CHECK2: CovDump: bitset of 3 bits written for '{{.*}}', 2 bits are set
 // CHECK2:  2 PCs written
-// CHECK3: CovDump: bitset of 4 bits written, 3 bits are set
+// CHECK3: CovDump: bitset of 4 bits written for '{{.*}}', 3 bits are set
 // CHECK3:  3 PCs written
 // CHECK3_NOBITSET-NOT: bitset of
 // CHECK3_NOPCS-NOT: PCs written
+// CHECK_COUNTERS: CovDump: 4 counters written for
diff --git a/test/asan/TestCases/Linux/coverage-maybe-open-file.cc b/test/asan/TestCases/coverage-maybe-open-file.cc
similarity index 94%
rename from test/asan/TestCases/Linux/coverage-maybe-open-file.cc
rename to test/asan/TestCases/coverage-maybe-open-file.cc
index 4580de4..ca3f92e 100644
--- a/test/asan/TestCases/Linux/coverage-maybe-open-file.cc
+++ b/test/asan/TestCases/coverage-maybe-open-file.cc
@@ -15,6 +15,7 @@
 
 #include <sanitizer/coverage_interface.h>
 
+// FIXME: the code below might not work on Windows.
 int main(int argc, char **argv) {
   int fd = __sanitizer_maybe_open_cov_file("test");
   if (fd > 0) {
diff --git a/test/asan/TestCases/coverage-order-pcs.cc b/test/asan/TestCases/coverage-order-pcs.cc
new file mode 100644
index 0000000..076fe1b
--- /dev/null
+++ b/test/asan/TestCases/coverage-order-pcs.cc
@@ -0,0 +1,56 @@
+// Test coverage_order_pcs=1 flag which orders the PCs by their appearance.
+// RUN: DIR=%T/coverage-order-pcs
+// RUN: rm -rf $DIR
+// RUN: mkdir $DIR
+// RUN: %clangxx_asan -fsanitize-coverage=1 %s -o %t
+// RUN: ASAN_OPTIONS=coverage_dir=$DIR:coverage=1:coverage_order_pcs=0 %run %t
+// RUN: mv $DIR/*sancov $DIR/A
+
+// RUN: ASAN_OPTIONS=coverage_dir=$DIR:coverage=1:coverage_order_pcs=0 %run %t 1
+// RUN: mv $DIR/*sancov $DIR/B
+
+// RUN: ASAN_OPTIONS=coverage_dir=$DIR:coverage=1:coverage_order_pcs=1 %run %t
+// RUN: mv $DIR/*sancov $DIR/C
+
+// RUN: ASAN_OPTIONS=coverage_dir=$DIR:coverage=1:coverage_order_pcs=1 %run %t 1
+// RUN: mv $DIR/*sancov $DIR/D
+//
+// RUN: (%sancov print $DIR/A; %sancov print $DIR/B; %sancov print $DIR/C; %sancov print $DIR/D) | FileCheck %s
+//
+// RUN: rm -rf $DIR
+// Ordering works only in 64-bit mode for now.
+// REQUIRES: asan-64-bits
+#include <stdio.h>
+
+void foo() { fprintf(stderr, "FOO\n"); }
+void bar() { fprintf(stderr, "BAR\n"); }
+
+int main(int argc, char **argv) {
+  if (argc == 2) {
+    foo();
+    bar();
+  } else {
+    bar();
+    foo();
+  }
+}
+
+// Run A: no ordering
+// CHECK: [[FOO:0x[0-9a-f]*]]
+// CHECK-NEXT: [[BAR:0x[0-9a-f]*]]
+// CHECK-NEXT: [[MAIN:0x[0-9a-f]*]]
+//
+// Run B: still no ordering
+// CHECK-NEXT: [[FOO]]
+// CHECK-NEXT: [[BAR]]
+// CHECK-NEXT: [[MAIN]]
+//
+// Run C: MAIN, BAR, FOO
+// CHECK-NEXT: [[MAIN]]
+// CHECK-NEXT: [[BAR]]
+// CHECK-NEXT: [[FOO]]
+//
+// Run D: MAIN, FOO, BAR
+// CHECK-NEXT: [[MAIN]]
+// CHECK-NEXT: [[FOO]]
+// CHECK-NEXT: [[BAR]]
diff --git a/test/asan/TestCases/Linux/coverage-reset.cc b/test/asan/TestCases/coverage-reset.cc
similarity index 100%
rename from test/asan/TestCases/Linux/coverage-reset.cc
rename to test/asan/TestCases/coverage-reset.cc
diff --git a/test/asan/TestCases/Linux/coverage-tracing.cc b/test/asan/TestCases/coverage-tracing.cc
similarity index 100%
rename from test/asan/TestCases/Linux/coverage-tracing.cc
rename to test/asan/TestCases/coverage-tracing.cc
diff --git a/test/asan/TestCases/debug_stacks.cc b/test/asan/TestCases/debug_stacks.cc
index 57bb546..15af76d 100644
--- a/test/asan/TestCases/debug_stacks.cc
+++ b/test/asan/TestCases/debug_stacks.cc
@@ -2,6 +2,9 @@
 // malloc and free stacks.
 // RUN: %clangxx_asan -O0 %s -o %t && not %run %t 2>&1 | FileCheck %s
 
+// FIXME: Figure out why allocation/free stack traces may be too short on ARM.
+// REQUIRES: stable-runtime
+
 #include <sanitizer/asan_interface.h>
 #include <stdio.h>
 #include <stdlib.h>
diff --git a/test/asan/TestCases/heap-overflow-large.cc b/test/asan/TestCases/heap-overflow-large.cc
index eb2fcc3..566b115 100644
--- a/test/asan/TestCases/heap-overflow-large.cc
+++ b/test/asan/TestCases/heap-overflow-large.cc
@@ -15,9 +15,9 @@
   int *x = new int[5];
   memset(x, 0, sizeof(x[0]) * 5);
   int index = atoi(argv[1]);
-  int res = x[index];
+  unsigned res = x[index];
   // CHECK: main
   // CHECK-NOT: CHECK failed
   delete[] x;
-  return res ? res : 1;
+  return (res % 10) + 1;
 }
diff --git a/test/asan/TestCases/print_summary.cc b/test/asan/TestCases/print_summary.cc
index 79411c5..12dfa26 100644
--- a/test/asan/TestCases/print_summary.cc
+++ b/test/asan/TestCases/print_summary.cc
@@ -1,14 +1,16 @@
 // RUN: %clangxx_asan -O0 %s -o %t
-// RUN: not %run %t 2>&1 | FileCheck %s --check-prefix=YES
-// RUN: env ASAN_OPTIONS=print_summary=false not %run %t 2>&1 | FileCheck %s --check-prefix=NO
+// RUN: not %run %t 2>&1 | FileCheck %s --check-prefix=SOURCE
+// RUN: env ASAN_OPTIONS=symbolize=false not %run %t 2>&1 | FileCheck %s --check-prefix=MODULE
+// RUN: env ASAN_OPTIONS=print_summary=false not %run %t 2>&1 | FileCheck %s --check-prefix=MISSING
 
 int main() {
   char *x = new char[20];
   delete[] x;
   return x[0];
-  // YES: ERROR: AddressSanitizer: heap-use-after-free
-  // YES: SUMMARY: AddressSanitizer: heap-use-after-free
-  // NO: ERROR: AddressSanitizer: heap-use-after-free
-  // NO-NOT: SUMMARY: AddressSanitizer: heap-use-after-free
+  // SOURCE: ERROR: AddressSanitizer: heap-use-after-free
+  // SOURCE: SUMMARY: AddressSanitizer: heap-use-after-free {{.*}}print_summary.cc:[[@LINE-2]]{{.*}} main
+  // MODULE: ERROR: AddressSanitizer: heap-use-after-free
+  // MODULE: SUMMARY: AddressSanitizer: heap-use-after-free ({{.*}}+0x{{.*}})
+  // MISSING: ERROR: AddressSanitizer: heap-use-after-free
+  // MISSING-NOT: SUMMARY
 }
-
diff --git a/test/asan/TestCases/strip_path_prefix.c b/test/asan/TestCases/strip_path_prefix.c
index 4556e90..c441eac 100644
--- a/test/asan/TestCases/strip_path_prefix.c
+++ b/test/asan/TestCases/strip_path_prefix.c
@@ -1,5 +1,5 @@
 // RUN: %clang_asan -O2 %s -o %t
-// RUN: env ASAN_OPTIONS="strip_path_prefix='/'" not %run %t 2>&1 | FileCheck %s
+// RUN: env ASAN_OPTIONS="strip_path_prefix='%S/'" not %run %t 2>&1 | FileCheck %s
 
 #include <stdlib.h>
 int main() {
@@ -8,5 +8,5 @@
   return x[5];
   // Check that paths in error report don't start with slash.
   // CHECK: heap-use-after-free
-  // CHECK-NOT: #0 0x{{.*}} ({{[/].*}})
+  // CHECK: #0 0x{{.*}} in main strip_path_prefix.c:[[@LINE-3]]
 }
diff --git a/test/asan/TestCases/suppressions-exec-relative-location.cc b/test/asan/TestCases/suppressions-exec-relative-location.cc
new file mode 100644
index 0000000..cc69b7a
--- /dev/null
+++ b/test/asan/TestCases/suppressions-exec-relative-location.cc
@@ -0,0 +1,47 @@
+// Check that without suppressions, we catch the issue.
+// RUN: %clangxx_asan -O0 %s -o %t
+// RUN: not %run %t 2>&1 | FileCheck --check-prefix=CHECK-CRASH %s
+
+// If the executable is started from a different location, we should still
+// find the suppression file located relative to the location of the executable.
+// RUN: rm -rf %T/suppressions-exec-relative-location
+// RUN: mkdir -p %T/suppressions-exec-relative-location
+// RUN: %clangxx_asan -O0 %s -o %T/suppressions-exec-relative-location/exec
+// RUN: echo "interceptor_via_fun:crash_function" > \
+// RUN:   %T/suppressions-exec-relative-location/supp.txt
+// RUN: ASAN_OPTIONS="suppressions=supp.txt" \
+// RUN:   %run %T/suppressions-exec-relative-location/exec 2>&1 | \
+// RUN:   FileCheck --check-prefix=CHECK-IGNORE %s
+// RUN: rm -rf %T/suppressions-exec-relative-location
+
+// If the wrong absolute path is given, we don't try to construct
+// a relative path with it.
+// RUN: ASAN_OPTIONS="suppressions='/absolute/path'" not %run %t 2>&1 | \
+// RUN:   FileCheck --check-prefix=CHECK-WRONG-FILE-NAME %s
+
+// Test that we reject directory as filename.
+// RUN: ASAN_OPTIONS="suppressions='folder/only/'" not %run %t 2>&1 | \
+// RUN:   FileCheck --check-prefix=CHECK-WRONG-FILE-NAME %s
+
+// XFAIL: android
+// XFAIL: win32
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+void crash_function() {
+  char *a = (char *)malloc(6);
+  free(a);
+  size_t len = strlen(a); // BOOM
+  fprintf(stderr, "strlen ignored, len = %zu\n", len);
+}
+
+int main() {
+  crash_function();
+}
+
+// CHECK-CRASH: AddressSanitizer: heap-use-after-free
+// CHECK-IGNORE-NOT: AddressSanitizer: heap-buffer-overflow
+// CHECK-IGNORE: ignored
+// CHECK-WRONG-FILE-NAME: failed to read suppressions file
diff --git a/test/builtins/Unit/divtc3_test.c b/test/builtins/Unit/divtc3_test.c
index 7bb74d7..50918d6 100644
--- a/test/builtins/Unit/divtc3_test.c
+++ b/test/builtins/Unit/divtc3_test.c
@@ -11,12 +11,13 @@
 //
 //===----------------------------------------------------------------------===//
 
+#include <stdio.h>
+
 #if _ARCH_PPC
 
 #include "int_lib.h"
 #include <math.h>
 #include <complex.h>
-#include <stdio.h>
 
 // Returns: the quotient of (a + ib) / (c + id)
 
diff --git a/test/builtins/Unit/fixtfsi_test.c b/test/builtins/Unit/fixtfsi_test.c
new file mode 100644
index 0000000..45ad0d2
--- /dev/null
+++ b/test/builtins/Unit/fixtfsi_test.c
@@ -0,0 +1,65 @@
+//===--------------- fixtfsi_test.c - Test __fixtfsi ----------------------===//
+//
+//                     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 __fixtfsi for the compiler_rt library.
+//
+//===----------------------------------------------------------------------===//
+
+#include <stdio.h>
+
+#if __LDBL_MANT_DIG__ == 113
+
+#include "fp_test.h"
+
+int __fixtfsi(long double a);
+
+int test__fixtfsi(long double a, int expected)
+{
+    int x = __fixtfsi(a);
+    int ret = (x != expected);
+
+    if (ret){
+        printf("error in test__fixtfsi(%.20Lf) = %d, "
+               "expected %d\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__fixtfsi(makeInf128(), 0x7fffffff))
+        return 1;
+    if (test__fixtfsi(0, 0x0))
+        return 1;
+    if (test__fixtfsi(0x1.23456789abcdefp+5, 0x24))
+        return 1;
+    if (test__fixtfsi(0x1.23456789abcdefp-3, 0x0))
+        return 1;
+    if (test__fixtfsi(0x1.23456789abcdefp+20, 0x123456))
+        return 1;
+    if (test__fixtfsi(0x1.23456789abcdefp+40, 0x7fffffff))
+        return 1;
+    if (test__fixtfsi(0x1.23456789abcdefp+256, 0x7fffffff))
+        return 1;
+    if (test__fixtfsi(-0x1.23456789abcdefp+20, 0xffedcbaa))
+        return 1;
+    if (test__fixtfsi(-0x1.23456789abcdefp+40, 0x80000001))
+        return 1;
+
+#else
+    printf("skipped\n");
+
+#endif
+    return 0;
+}
diff --git a/test/builtins/Unit/fixunstfdi_test.c b/test/builtins/Unit/fixunstfdi_test.c
index d0a5db7..a5a9460 100644
--- a/test/builtins/Unit/fixunstfdi_test.c
+++ b/test/builtins/Unit/fixunstfdi_test.c
@@ -11,10 +11,11 @@
 //
 //===----------------------------------------------------------------------===//
 
+#include <stdio.h>
+
 #if _ARCH_PPC
 
 #include "int_lib.h"
-#include <stdio.h>
 
 // Returns: convert a to a unsigned long long, rounding toward zero.
 //          Negative values all become zero.
diff --git a/test/builtins/Unit/fixunstfsi_test.c b/test/builtins/Unit/fixunstfsi_test.c
new file mode 100644
index 0000000..4bf8fde
--- /dev/null
+++ b/test/builtins/Unit/fixunstfsi_test.c
@@ -0,0 +1,64 @@
+//===--------------- fixunstfsi_test.c - Test __fixunstfsi ----------------===//
+//
+//                     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 __fixunstfsi for the compiler_rt library.
+//
+//===----------------------------------------------------------------------===//
+
+#include <stdio.h>
+
+#if __LDBL_MANT_DIG__ == 113
+
+#include "fp_test.h"
+
+unsigned int __fixunstfsi(long double a);
+
+int test__fixunstfsi(long double a, unsigned int expected)
+{
+    unsigned int x = __fixunstfsi(a);
+    int ret = (x != expected);
+
+    if (ret)
+    {
+        printf("error in test__fixunstfsi(%.20Lf) = %u, "
+               "expected %u\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__fixunstfsi(makeInf128(), UINT32_C(0xffffffff)))
+        return 1;
+    if (test__fixunstfsi(0, UINT32_C(0x0)))
+        return 1;
+    if (test__fixunstfsi(0x1.23456789abcdefp+5, UINT32_C(0x24)))
+        return 1;
+    if (test__fixunstfsi(0x1.23456789abcdefp-3, UINT32_C(0x0)))
+        return 1;
+    if (test__fixunstfsi(0x1.23456789abcdefp+20, UINT32_C(0x123456)))
+        return 1;
+    if (test__fixunstfsi(0x1.23456789abcdefp+40, UINT32_C(0xffffffff)))
+        return 1;
+    if (test__fixunstfsi(0x1.23456789abcdefp+256, UINT32_C(0xffffffff)))
+        return 1;
+    if (test__fixunstfsi(-0x1.23456789abcdefp+3, UINT32_C(0x0)))
+        return 1;
+
+#else
+    printf("skipped\n");
+
+#endif
+    return 0;
+}
diff --git a/test/builtins/Unit/multc3_test.c b/test/builtins/Unit/multc3_test.c
index f8c66c0..8d34801 100644
--- a/test/builtins/Unit/multc3_test.c
+++ b/test/builtins/Unit/multc3_test.c
@@ -11,12 +11,13 @@
 //
 //===----------------------------------------------------------------------===//
 
+#include <stdio.h>
+
 #if _ARCH_PPC
 
 #include "int_lib.h"
 #include <math.h>
 #include <complex.h>
-#include <stdio.h>
 
 // Returns: the product of a + ib and c + id
 
diff --git a/test/builtins/Unit/powitf2_test.c b/test/builtins/Unit/powitf2_test.c
index 817cb11..dfe7588 100644
--- a/test/builtins/Unit/powitf2_test.c
+++ b/test/builtins/Unit/powitf2_test.c
@@ -11,10 +11,11 @@
 //
 //===----------------------------------------------------------------------===//
 
+#include <stdio.h>
+
 #if _ARCH_PPC
 
 #include "int_lib.h"
-#include <stdio.h>
 #include <math.h>
 
 // Returns: a ^ b
diff --git a/test/cfi/CMakeLists.txt b/test/cfi/CMakeLists.txt
index 5750bd8..625e3ff 100644
--- a/test/cfi/CMakeLists.txt
+++ b/test/cfi/CMakeLists.txt
@@ -15,6 +15,11 @@
       LLVMgold
     )
   endif()
+  if(APPLE)
+    list(APPEND CFI_TEST_DEPS
+      LTO
+    )
+  endif()
 endif()
 
 add_lit_testsuite(check-cfi "Running the cfi regression tests"
diff --git a/test/cfi/bad-cast.cpp b/test/cfi/bad-cast.cpp
new file mode 100644
index 0000000..39d8a35
--- /dev/null
+++ b/test/cfi/bad-cast.cpp
@@ -0,0 +1,136 @@
+// RUN: %clangxx_cfi -o %t %s
+// RUN: not --crash %t a 2>&1 | FileCheck --check-prefix=FAIL %s
+// RUN: not --crash %t b 2>&1 | FileCheck --check-prefix=FAIL %s
+// RUN: not --crash %t c 2>&1 | FileCheck --check-prefix=FAIL %s
+// RUN: %t d 2>&1 | FileCheck --check-prefix=PASS %s
+// RUN: %t e 2>&1 | FileCheck --check-prefix=PASS %s
+// RUN: %t f 2>&1 | FileCheck --check-prefix=PASS %s
+// RUN: not --crash %t g 2>&1 | FileCheck --check-prefix=FAIL %s
+// RUN: %t h 2>&1 | FileCheck --check-prefix=PASS %s
+
+// RUN: %clangxx_cfi -DB32 -o %t %s
+// RUN: not --crash %t a 2>&1 | FileCheck --check-prefix=FAIL %s
+// RUN: not --crash %t b 2>&1 | FileCheck --check-prefix=FAIL %s
+// RUN: not --crash %t c 2>&1 | FileCheck --check-prefix=FAIL %s
+// RUN: %t d 2>&1 | FileCheck --check-prefix=PASS %s
+// RUN: %t e 2>&1 | FileCheck --check-prefix=PASS %s
+// RUN: %t f 2>&1 | FileCheck --check-prefix=PASS %s
+// RUN: not --crash %t g 2>&1 | FileCheck --check-prefix=FAIL %s
+// RUN: %t h 2>&1 | FileCheck --check-prefix=PASS %s
+
+// RUN: %clangxx_cfi -DB64 -o %t %s
+// RUN: not --crash %t a 2>&1 | FileCheck --check-prefix=FAIL %s
+// RUN: not --crash %t b 2>&1 | FileCheck --check-prefix=FAIL %s
+// RUN: not --crash %t c 2>&1 | FileCheck --check-prefix=FAIL %s
+// RUN: %t d 2>&1 | FileCheck --check-prefix=PASS %s
+// RUN: %t e 2>&1 | FileCheck --check-prefix=PASS %s
+// RUN: %t f 2>&1 | FileCheck --check-prefix=PASS %s
+// RUN: not --crash %t g 2>&1 | FileCheck --check-prefix=FAIL %s
+// RUN: %t h 2>&1 | FileCheck --check-prefix=PASS %s
+
+// RUN: %clangxx_cfi -DBM -o %t %s
+// RUN: not --crash %t a 2>&1 | FileCheck --check-prefix=FAIL %s
+// RUN: not --crash %t b 2>&1 | FileCheck --check-prefix=FAIL %s
+// RUN: not --crash %t c 2>&1 | FileCheck --check-prefix=FAIL %s
+// RUN: %t d 2>&1 | FileCheck --check-prefix=PASS %s
+// RUN: %t e 2>&1 | FileCheck --check-prefix=PASS %s
+// RUN: %t f 2>&1 | FileCheck --check-prefix=PASS %s
+// RUN: not --crash %t g 2>&1 | FileCheck --check-prefix=FAIL %s
+// RUN: %t h 2>&1 | FileCheck --check-prefix=PASS %s
+
+// RUN: %clangxx_cfi -fsanitize=cfi-cast-strict -o %t %s
+// RUN: not --crash %t a 2>&1 | FileCheck --check-prefix=FAIL %s
+// RUN: not --crash %t b 2>&1 | FileCheck --check-prefix=FAIL %s
+// RUN: not --crash %t c 2>&1 | FileCheck --check-prefix=FAIL %s
+// RUN: not --crash %t d 2>&1 | FileCheck --check-prefix=FAIL %s
+// RUN: not --crash %t e 2>&1 | FileCheck --check-prefix=FAIL %s
+// RUN: not --crash %t f 2>&1 | FileCheck --check-prefix=FAIL %s
+// RUN: not --crash %t g 2>&1 | FileCheck --check-prefix=FAIL %s
+// RUN: not --crash %t h 2>&1 | FileCheck --check-prefix=FAIL %s
+
+// RUN: %clangxx -o %t %s
+// RUN: %t a 2>&1 | FileCheck --check-prefix=PASS %s
+// RUN: %t b 2>&1 | FileCheck --check-prefix=PASS %s
+// RUN: %t c 2>&1 | FileCheck --check-prefix=PASS %s
+// RUN: %t d 2>&1 | FileCheck --check-prefix=PASS %s
+// RUN: %t e 2>&1 | FileCheck --check-prefix=PASS %s
+// RUN: %t f 2>&1 | FileCheck --check-prefix=PASS %s
+// RUN: %t g 2>&1 | FileCheck --check-prefix=PASS %s
+// RUN: %t h 2>&1 | FileCheck --check-prefix=PASS %s
+
+// Tests that the CFI enforcement detects bad casts.
+
+#include <stdio.h>
+#include <utility>
+#include "utils.h"
+
+struct A {
+  virtual void f();
+};
+
+void A::f() {}
+
+struct B : A {
+  virtual void f();
+};
+
+void B::f() {}
+
+struct C : A {
+};
+
+int main(int argc, char **argv) {
+#ifdef B32
+  break_optimization(new Deriver<B, 0>);
+#endif
+
+#ifdef B64
+  break_optimization(new Deriver<B, 0>);
+  break_optimization(new Deriver<B, 1>);
+#endif
+
+#ifdef BM
+  break_optimization(new Deriver<B, 0>);
+  break_optimization(new Deriver<B, 1>);
+  break_optimization(new Deriver<B, 2>);
+#endif
+
+  B *b = new B;
+  break_optimization(b);
+
+  // FAIL: 1
+  // PASS: 1
+  fprintf(stderr, "1\n");
+
+  A a;
+  switch (argv[1][0]) {
+    case 'a':
+      static_cast<B *>(&a); // UB
+      break;
+    case 'b':
+      static_cast<B &>(a); // UB
+      break;
+    case 'c':
+      static_cast<B &&>(a); // UB
+      break;
+    case 'd':
+      static_cast<C *>(&a); // UB, strict only
+      break;
+    case 'e':
+      static_cast<C &>(a); // UB, strict only
+      break;
+    case 'f':
+      static_cast<C &&>(a); // UB, strict only
+      break;
+    case 'g':
+      static_cast<B *>(static_cast<void *>(&a)); // Non-UB bad cast
+      break;
+    case 'h':
+      static_cast<C *>(static_cast<void *>(&a)); // Non-UB bad cast, strict only
+      break;
+  }
+
+  // FAIL-NOT: 2
+  // PASS: 2
+  fprintf(stderr, "2\n");
+}
diff --git a/test/cfi/sibling.cpp b/test/cfi/sibling.cpp
new file mode 100644
index 0000000..c8b95e9
--- /dev/null
+++ b/test/cfi/sibling.cpp
@@ -0,0 +1,67 @@
+// XFAIL: *
+
+// RUN: %clangxx_cfi -o %t %s
+// RUN: not --crash %t 2>&1 | FileCheck --check-prefix=CFI %s
+
+// RUN: %clangxx_cfi -DB32 -o %t %s
+// RUN: not --crash %t 2>&1 | FileCheck --check-prefix=CFI %s
+
+// RUN: %clangxx_cfi -DB64 -o %t %s
+// RUN: not --crash %t 2>&1 | FileCheck --check-prefix=CFI %s
+
+// RUN: %clangxx_cfi -DBM -o %t %s
+// RUN: not --crash %t 2>&1 | FileCheck --check-prefix=CFI %s
+
+// RUN: %clangxx -o %t %s
+// RUN: %t 2>&1 | FileCheck --check-prefix=NCFI %s
+
+// Tests that the CFI enforcement distinguishes betwen non-overriding siblings.
+// XFAILed as not implemented yet.
+
+#include <stdio.h>
+#include "utils.h"
+
+struct A {
+  virtual void f();
+};
+
+void A::f() {}
+
+struct B : A {
+  virtual void f();
+};
+
+void B::f() {}
+
+struct C : A {
+};
+
+int main() {
+#ifdef B32
+  break_optimization(new Deriver<B, 0>);
+#endif
+
+#ifdef B64
+  break_optimization(new Deriver<B, 0>);
+  break_optimization(new Deriver<B, 1>);
+#endif
+
+#ifdef BM
+  break_optimization(new Deriver<B, 0>);
+  break_optimization(new Deriver<B, 1>);
+  break_optimization(new Deriver<B, 2>);
+#endif
+
+  B *b = new B;
+  break_optimization(b);
+
+  // CFI: 1
+  // NCFI: 1
+  fprintf(stderr, "1\n");
+
+  ((C *)b)->f(); // UB here
+
+  // CFI-NOT: 2
+  // NCFI: 2
+  fprintf(stderr, "2\n");
+}
diff --git a/test/dfsan/basic.c b/test/dfsan/basic.c
index 6582727..990fd11 100644
--- a/test/dfsan/basic.c
+++ b/test/dfsan/basic.c
@@ -1,5 +1,5 @@
-// RUN: %clang_dfsan -m64 %s -o %t && %run %t
-// RUN: %clang_dfsan -mllvm -dfsan-args-abi -m64 %s -o %t && %run %t
+// RUN: %clang_dfsan %s -o %t && %run %t
+// RUN: %clang_dfsan -mllvm -dfsan-args-abi %s -o %t && %run %t
 
 // Tests that labels are propagated through loads and stores.
 
diff --git a/test/dfsan/custom.cc b/test/dfsan/custom.cc
index d7bb3e3..bdd7cf5 100644
--- a/test/dfsan/custom.cc
+++ b/test/dfsan/custom.cc
@@ -1,7 +1,7 @@
-// RUN: %clang_dfsan -m64 %s -o %t && DFSAN_OPTIONS="strict_data_dependencies=0" %run %t
-// RUN: %clang_dfsan -mllvm -dfsan-args-abi -m64 %s -o %t && DFSAN_OPTIONS="strict_data_dependencies=0" %run %t
-// RUN: %clang_dfsan -DSTRICT_DATA_DEPENDENCIES -m64 %s -o %t && %run %t
-// RUN: %clang_dfsan -DSTRICT_DATA_DEPENDENCIES -mllvm -dfsan-args-abi -m64 %s -o %t && %run %t
+// RUN: %clang_dfsan %s -o %t && DFSAN_OPTIONS="strict_data_dependencies=0" %run %t
+// RUN: %clang_dfsan -mllvm -dfsan-args-abi %s -o %t && DFSAN_OPTIONS="strict_data_dependencies=0" %run %t
+// RUN: %clang_dfsan -DSTRICT_DATA_DEPENDENCIES %s -o %t && %run %t
+// RUN: %clang_dfsan -DSTRICT_DATA_DEPENDENCIES -mllvm -dfsan-args-abi %s -o %t && %run %t
 
 // Tests custom implementations of various glibc functions.
 
diff --git a/test/dfsan/dump_labels.c b/test/dfsan/dump_labels.c
index 67801af..3bbc1e2 100644
--- a/test/dfsan/dump_labels.c
+++ b/test/dfsan/dump_labels.c
@@ -1,4 +1,4 @@
-// RUN: %clang_dfsan -m64 %s -o %t
+// RUN: %clang_dfsan %s -o %t
 // RUN: DFSAN_OPTIONS=dump_labels_at_exit=/dev/stdout %run %t 2>&1 | FileCheck %s
 // RUN: DFSAN_OPTIONS=dump_labels_at_exit=/dev/stdout not %run %t c 2>&1 | FileCheck %s --check-prefix=CHECK-OOL
 // RUN: DFSAN_OPTIONS=dump_labels_at_exit=/dev/stdout not %run %t u 2>&1 | FileCheck %s --check-prefix=CHECK-OOL
diff --git a/test/dfsan/flags.c b/test/dfsan/flags.c
index 79069b9..914f54f 100644
--- a/test/dfsan/flags.c
+++ b/test/dfsan/flags.c
@@ -1,6 +1,6 @@
-// RUN: %clang_dfsan -m64 %s -fsanitize-blacklist=%S/Inputs/flags_abilist.txt -mllvm -dfsan-debug-nonzero-labels -o %t && %run %t 2>&1 | FileCheck %s
-// RUN: %clang_dfsan -m64 %s -fsanitize-blacklist=%S/Inputs/flags_abilist.txt -mllvm -dfsan-debug-nonzero-labels -o %t && DFSAN_OPTIONS=warn_unimplemented=0 %run %t 2>&1 | count 0
-// RUN: %clang_dfsan -m64 %s -fsanitize-blacklist=%S/Inputs/flags_abilist.txt -mllvm -dfsan-debug-nonzero-labels -o %t && DFSAN_OPTIONS=warn_nonzero_labels=1 %run %t 2>&1 | FileCheck --check-prefix=CHECK-NONZERO %s
+// RUN: %clang_dfsan %s -fsanitize-blacklist=%S/Inputs/flags_abilist.txt -mllvm -dfsan-debug-nonzero-labels -o %t && %run %t 2>&1 | FileCheck %s
+// RUN: %clang_dfsan %s -fsanitize-blacklist=%S/Inputs/flags_abilist.txt -mllvm -dfsan-debug-nonzero-labels -o %t && DFSAN_OPTIONS=warn_unimplemented=0 %run %t 2>&1 | count 0
+// RUN: %clang_dfsan %s -fsanitize-blacklist=%S/Inputs/flags_abilist.txt -mllvm -dfsan-debug-nonzero-labels -o %t && DFSAN_OPTIONS=warn_nonzero_labels=1 %run %t 2>&1 | FileCheck --check-prefix=CHECK-NONZERO %s
 
 // Tests that flags work correctly.
 
diff --git a/test/dfsan/fncall.c b/test/dfsan/fncall.c
index e780f31..458fba6 100644
--- a/test/dfsan/fncall.c
+++ b/test/dfsan/fncall.c
@@ -1,5 +1,5 @@
-// RUN: %clang_dfsan -m64 %s -o %t && %run %t
-// RUN: %clang_dfsan -mllvm -dfsan-args-abi -m64 %s -o %t && %run %t
+// RUN: %clang_dfsan %s -o %t && %run %t
+// RUN: %clang_dfsan -mllvm -dfsan-args-abi %s -o %t && %run %t
 
 // Tests that labels are propagated through function calls.
 
diff --git a/test/dfsan/label_count.c b/test/dfsan/label_count.c
index a4b6087..b42ce58 100644
--- a/test/dfsan/label_count.c
+++ b/test/dfsan/label_count.c
@@ -1,11 +1,11 @@
-// RUN: %clang_dfsan -DLIB -m64 -c %s -o %t.lib.o && \
-// RUN: %clang_dfsan       -m64 -c %s -o %t.o && \
-// RUN: %clang_dfsan -m64 %t.lib.o %t.o -o %t.bin && \
+// RUN: %clang_dfsan -DLIB -c %s -o %t.lib.o && \
+// RUN: %clang_dfsan       -c %s -o %t.o && \
+// RUN: %clang_dfsan %t.lib.o %t.o -o %t.bin && \
 // RUN: %run %t.bin
 
-// RUN: %clang_dfsan -mllvm -dfsan-args-abi -m64 -DLIB -c %s -o %t.lib.o && \
-// RUN: %clang_dfsan -mllvm -dfsan-args-abi -m64 -c %s -o %t.o && \
-// RUN: %clang_dfsan -mllvm -dfsan-args-abi -m64 %t.o %t.lib.o -o %t.bin && \
+// RUN: %clang_dfsan -mllvm -dfsan-args-abi -DLIB -c %s -o %t.lib.o && \
+// RUN: %clang_dfsan -mllvm -dfsan-args-abi -c %s -o %t.o && \
+// RUN: %clang_dfsan -mllvm -dfsan-args-abi %t.o %t.lib.o -o %t.bin && \
 // RUN: %run %t.bin
 
 #include <sanitizer/dfsan_interface.h>
diff --git a/test/dfsan/lit.cfg b/test/dfsan/lit.cfg
index d4adb9a..e4d4e8f 100644
--- a/test/dfsan/lit.cfg
+++ b/test/dfsan/lit.cfg
@@ -9,7 +9,7 @@
 config.test_source_root = os.path.dirname(__file__)
 
 # Setup default compiler flags used with -fsanitize=dataflow option.
-clang_dfsan_cflags = ["-fsanitize=dataflow"]
+clang_dfsan_cflags = ["-fsanitize=dataflow", "-m64"]
 clang_dfsan_cxxflags = config.cxx_mode_flags + clang_dfsan_cflags
 
 def build_invocation(compile_flags):
diff --git a/test/dfsan/propagate.c b/test/dfsan/propagate.c
index 733538c..c30a087 100644
--- a/test/dfsan/propagate.c
+++ b/test/dfsan/propagate.c
@@ -1,5 +1,5 @@
-// RUN: %clang_dfsan -m64 %s -o %t && %run %t
-// RUN: %clang_dfsan -mllvm -dfsan-args-abi -m64 %s -o %t && %run %t
+// RUN: %clang_dfsan %s -o %t && %run %t
+// RUN: %clang_dfsan -mllvm -dfsan-args-abi %s -o %t && %run %t
 
 // Tests that labels are propagated through computation and that union labels
 // are properly created.
diff --git a/test/dfsan/vararg.c b/test/dfsan/vararg.c
index 2227ba7..f51e39c 100644
--- a/test/dfsan/vararg.c
+++ b/test/dfsan/vararg.c
@@ -1,7 +1,7 @@
-// RUN: %clang_dfsan -m64 %s -o %t
+// RUN: %clang_dfsan %s -o %t
 // RUN: not %run %t 2>&1 | FileCheck %s
 // RUN: %run %t foo
-// RUN: %clang_dfsan -mllvm -dfsan-args-abi -m64 %s -o %t
+// RUN: %clang_dfsan -mllvm -dfsan-args-abi %s -o %t
 // RUN: not %run %t 2>&1 | FileCheck %s
 // RUN: %run %t foo
 
diff --git a/test/dfsan/write_callback.c b/test/dfsan/write_callback.c
index bb35f32..3ba027a 100644
--- a/test/dfsan/write_callback.c
+++ b/test/dfsan/write_callback.c
@@ -1,5 +1,5 @@
-// RUN: %clang_dfsan                         -m64 %s -o %t && %run %t | FileCheck %s
-// RUN: %clang_dfsan  -mllvm -dfsan-args-abi -m64 %s -o %t && %run %t | FileCheck %s
+// RUN: %clang_dfsan                         %s -o %t && %run %t | FileCheck %s
+// RUN: %clang_dfsan  -mllvm -dfsan-args-abi %s -o %t && %run %t | FileCheck %s
 
 // Tests that the custom implementation of write() does writes with or without
 // a callback set using dfsan_set_write_callback().
diff --git a/test/msan/Linux/getresid.cc b/test/msan/Linux/getresid.cc
index 385351d..f3c0914 100644
--- a/test/msan/Linux/getresid.cc
+++ b/test/msan/Linux/getresid.cc
@@ -1,6 +1,6 @@
-// RUN: %clangxx_msan -m64 -O0 %s -o %t && %run %t %p 2>&1
-// RUN: %clangxx_msan -m64 -O0 -D_FILE_OFFSET_BITS=64 %s -o %t && %run %t %p 2>&1
-// RUN: %clangxx_msan -m64 -O3 %s -o %t && %run %t %p 2>&1
+// RUN: %clangxx_msan -O0 %s -o %t && %run %t %p 2>&1
+// RUN: %clangxx_msan -O0 -D_FILE_OFFSET_BITS=64 %s -o %t && %run %t %p 2>&1
+// RUN: %clangxx_msan -O3 %s -o %t && %run %t %p 2>&1
 
 #include <assert.h>
 #include <unistd.h>
diff --git a/test/msan/Linux/glob.cc b/test/msan/Linux/glob.cc
index 8604e4d..1481861 100644
--- a/test/msan/Linux/glob.cc
+++ b/test/msan/Linux/glob.cc
@@ -1,6 +1,6 @@
-// RUN: %clangxx_msan -m64 -O0 %s -o %t && %run %t %p 2>&1 | FileCheck %s
-// RUN: %clangxx_msan -m64 -O0 -D_FILE_OFFSET_BITS=64 %s -o %t && %run %t %p 2>&1 | FileCheck %s
-// RUN: %clangxx_msan -m64 -O3 %s -o %t && %run %t %p 2>&1 | FileCheck %s
+// RUN: %clangxx_msan -O0 %s -o %t && %run %t %p 2>&1 | FileCheck %s
+// RUN: %clangxx_msan -O0 -D_FILE_OFFSET_BITS=64 %s -o %t && %run %t %p 2>&1 | FileCheck %s
+// RUN: %clangxx_msan -O3 %s -o %t && %run %t %p 2>&1 | FileCheck %s
 
 #include <assert.h>
 #include <glob.h>
diff --git a/test/msan/Linux/glob_altdirfunc.cc b/test/msan/Linux/glob_altdirfunc.cc
index 2c02e73..cb7fe09 100644
--- a/test/msan/Linux/glob_altdirfunc.cc
+++ b/test/msan/Linux/glob_altdirfunc.cc
@@ -1,6 +1,6 @@
-// RUN: %clangxx_msan -m64 -O0 %s -o %t && %run %t %p 2>&1 | FileCheck %s
-// RUN: %clangxx_msan -m64 -O0 -D_FILE_OFFSET_BITS=64 %s -o %t && %run %t %p 2>&1 | FileCheck %s
-// RUN: %clangxx_msan -m64 -O3 %s -o %t && %run %t %p 2>&1 | FileCheck %s
+// RUN: %clangxx_msan -O0 %s -o %t && %run %t %p 2>&1 | FileCheck %s
+// RUN: %clangxx_msan -O0 -D_FILE_OFFSET_BITS=64 %s -o %t && %run %t %p 2>&1 | FileCheck %s
+// RUN: %clangxx_msan -O3 %s -o %t && %run %t %p 2>&1 | FileCheck %s
 
 #include <assert.h>
 #include <glob.h>
diff --git a/test/msan/Linux/glob_nomatch.cc b/test/msan/Linux/glob_nomatch.cc
index bc35c30..fa132c8 100644
--- a/test/msan/Linux/glob_nomatch.cc
+++ b/test/msan/Linux/glob_nomatch.cc
@@ -1,5 +1,5 @@
-// RUN: %clangxx_msan -m64 -O0 %s -o %t && %run %t %p
-// RUN: %clangxx_msan -m64 -O3 %s -o %t && %run %t %p
+// RUN: %clangxx_msan -O0 %s -o %t && %run %t %p
+// RUN: %clangxx_msan -O3 %s -o %t && %run %t %p
 
 #include <assert.h>
 #include <glob.h>
diff --git a/test/msan/Linux/sunrpc.cc b/test/msan/Linux/sunrpc.cc
index 78645a7..c92ad63 100644
--- a/test/msan/Linux/sunrpc.cc
+++ b/test/msan/Linux/sunrpc.cc
@@ -1,14 +1,14 @@
-// RUN: %clangxx_msan -m64 -g -O0 -DTYPE=int -DFN=xdr_int %s -o %t && \
+// RUN: %clangxx_msan -g -O0 -DTYPE=int -DFN=xdr_int %s -o %t && \
 // RUN:     %run %t 2>&1
-// RUN: %clangxx_msan -m64 -g -O0 -DTYPE=int -DFN=xdr_int -DUNINIT=1 %s -o %t && \
+// RUN: %clangxx_msan -g -O0 -DTYPE=int -DFN=xdr_int -DUNINIT=1 %s -o %t && \
 // RUN:     not %run %t 2>&1 | FileCheck %s
-// RUN: %clangxx_msan -m64 -g -O0 -DTYPE=double -DFN=xdr_double %s -o %t && \
+// RUN: %clangxx_msan -g -O0 -DTYPE=double -DFN=xdr_double %s -o %t && \
 // RUN:     %run %t 2>&1
-// RUN: %clangxx_msan -m64 -g -O0 -DTYPE=double -DFN=xdr_double -DUNINIT=1 %s -o %t && \
+// RUN: %clangxx_msan -g -O0 -DTYPE=double -DFN=xdr_double -DUNINIT=1 %s -o %t && \
 // RUN:     not %run %t 2>&1 | FileCheck %s
-// RUN: %clangxx_msan -m64 -g -O0 -DTYPE=u_quad_t -DFN=xdr_u_longlong_t %s -o %t && \
+// RUN: %clangxx_msan -g -O0 -DTYPE=u_quad_t -DFN=xdr_u_longlong_t %s -o %t && \
 // RUN:     %run %t 2>&1
-// RUN: %clangxx_msan -m64 -g -O0 -DTYPE=u_quad_t -DFN=xdr_u_longlong_t -DUNINIT=1 %s -o %t && \
+// RUN: %clangxx_msan -g -O0 -DTYPE=u_quad_t -DFN=xdr_u_longlong_t -DUNINIT=1 %s -o %t && \
 // RUN:     not %run %t 2>&1 | FileCheck %s
 
 #include <assert.h>
diff --git a/test/msan/Linux/sunrpc_bytes.cc b/test/msan/Linux/sunrpc_bytes.cc
index f0c3574..477637a 100644
--- a/test/msan/Linux/sunrpc_bytes.cc
+++ b/test/msan/Linux/sunrpc_bytes.cc
@@ -1,6 +1,6 @@
-// RUN: %clangxx_msan -m64 -g -O0 %s -o %t && \
+// RUN: %clangxx_msan -g -O0 %s -o %t && \
 // RUN:     %run %t 2>&1
-// RUN: %clangxx_msan -m64 -g -O0 -DUNINIT=1 %s -o %t && \
+// RUN: %clangxx_msan -g -O0 -DUNINIT=1 %s -o %t && \
 // RUN:     not %run %t 2>&1 | FileCheck %s
 
 #include <assert.h>
diff --git a/test/msan/Linux/sunrpc_string.cc b/test/msan/Linux/sunrpc_string.cc
index 3f44a96..350222f 100644
--- a/test/msan/Linux/sunrpc_string.cc
+++ b/test/msan/Linux/sunrpc_string.cc
@@ -1,6 +1,6 @@
-// RUN: %clangxx_msan -m64 -g -O0 %s -o %t && \
+// RUN: %clangxx_msan -g -O0 %s -o %t && \
 // RUN:     %run %t 2>&1
-// RUN: %clangxx_msan -m64 -g -O0 -DUNINIT=1 %s -o %t && \
+// RUN: %clangxx_msan -g -O0 -DUNINIT=1 %s -o %t && \
 // RUN:     not %run %t 2>&1 | FileCheck %s
 
 #include <assert.h>
diff --git a/test/msan/Linux/syscalls.cc b/test/msan/Linux/syscalls.cc
index 4dd97e7..78dba36 100644
--- a/test/msan/Linux/syscalls.cc
+++ b/test/msan/Linux/syscalls.cc
@@ -1,5 +1,5 @@
-// RUN: %clangxx_msan -m64 -O0 %s -o %t && %run %t 2>&1
-// RUN: %clangxx_msan -m64 -O3 %s -o %t && %run %t 2>&1
+// RUN: %clangxx_msan -O0 %s -o %t && %run %t 2>&1
+// RUN: %clangxx_msan -O3 %s -o %t && %run %t 2>&1
 
 #include <assert.h>
 #include <errno.h>
diff --git a/test/msan/Linux/tcgetattr.cc b/test/msan/Linux/tcgetattr.cc
index e1425b8..454b7fd 100644
--- a/test/msan/Linux/tcgetattr.cc
+++ b/test/msan/Linux/tcgetattr.cc
@@ -1,4 +1,4 @@
-// RUN: %clangxx_msan -m64 -O0 %s -o %t && %run %t %p
+// RUN: %clangxx_msan -O0 %s -o %t && %run %t %p
 
 #include <assert.h>
 #include <glob.h>
diff --git a/test/msan/Linux/xattr.cc b/test/msan/Linux/xattr.cc
index 1beba11..86cc2cd 100644
--- a/test/msan/Linux/xattr.cc
+++ b/test/msan/Linux/xattr.cc
@@ -1,6 +1,6 @@
-// RUN: %clangxx_msan -m64 -O0 %s -o %t && %run %t %p 2>&1
-// RUN: %clangxx_msan -m64 -O0 -D_FILE_OFFSET_BITS=64 %s -o %t && %run %t %p 2>&1
-// RUN: %clangxx_msan -m64 -O3 %s -o %t && %run %t %p 2>&1
+// RUN: %clangxx_msan -O0 %s -o %t && %run %t %p 2>&1
+// RUN: %clangxx_msan -O0 -D_FILE_OFFSET_BITS=64 %s -o %t && %run %t %p 2>&1
+// RUN: %clangxx_msan -O3 %s -o %t && %run %t %p 2>&1
 
 #include <argz.h>
 #include <assert.h>
diff --git a/test/msan/backtrace.cc b/test/msan/backtrace.cc
index 473e0ae..b6cfcbe 100644
--- a/test/msan/backtrace.cc
+++ b/test/msan/backtrace.cc
@@ -1,4 +1,4 @@
-// RUN: %clangxx_msan -m64 -O0 %s -o %t && %run %t
+// RUN: %clangxx_msan -O0 %s -o %t && %run %t
 
 #include <assert.h>
 #include <execinfo.h>
diff --git a/test/msan/c-strdup.c b/test/msan/c-strdup.c
index 059300e..b1e02b9 100644
--- a/test/msan/c-strdup.c
+++ b/test/msan/c-strdup.c
@@ -1,7 +1,7 @@
-// RUN: %clang_msan -m64 -O0 %s -o %t && %run %t >%t.out 2>&1
-// RUN: %clang_msan -m64 -O1 %s -o %t && %run %t >%t.out 2>&1
-// RUN: %clang_msan -m64 -O2 %s -o %t && %run %t >%t.out 2>&1
-// RUN: %clang_msan -m64 -O3 %s -o %t && %run %t >%t.out 2>&1
+// RUN: %clang_msan -O0 %s -o %t && %run %t >%t.out 2>&1
+// RUN: %clang_msan -O1 %s -o %t && %run %t >%t.out 2>&1
+// RUN: %clang_msan -O2 %s -o %t && %run %t >%t.out 2>&1
+// RUN: %clang_msan -O3 %s -o %t && %run %t >%t.out 2>&1
 
 // Test that strdup in C programs is intercepted.
 // GLibC headers translate strdup to __strdup at -O1 and higher.
diff --git a/test/msan/chained_origin.cc b/test/msan/chained_origin.cc
index 336bbd8..ae72c10 100644
--- a/test/msan/chained_origin.cc
+++ b/test/msan/chained_origin.cc
@@ -1,17 +1,17 @@
-// RUN: %clangxx_msan -fsanitize-memory-track-origins=2 -m64 -O3 %s -o %t && \
+// RUN: %clangxx_msan -fsanitize-memory-track-origins=2 -O3 %s -o %t && \
 // RUN:     not %run %t >%t.out 2>&1
 // RUN: FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-STACK < %t.out
 
-// RUN: %clangxx_msan -fsanitize-memory-track-origins=2 -DHEAP=1 -m64 -O3 %s -o %t && \
+// RUN: %clangxx_msan -fsanitize-memory-track-origins=2 -DHEAP=1 -O3 %s -o %t && \
 // RUN:     not %run %t >%t.out 2>&1
 // RUN: FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-HEAP < %t.out
 
 
-// RUN: %clangxx_msan -mllvm -msan-instrumentation-with-call-threshold=0 -fsanitize-memory-track-origins=2 -m64 -O3 %s -o %t && \
+// RUN: %clangxx_msan -mllvm -msan-instrumentation-with-call-threshold=0 -fsanitize-memory-track-origins=2 -O3 %s -o %t && \
 // RUN:     not %run %t >%t.out 2>&1
 // RUN: FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-STACK < %t.out
 
-// RUN: %clangxx_msan -mllvm -msan-instrumentation-with-call-threshold=0 -fsanitize-memory-track-origins=2 -DHEAP=1 -m64 -O3 %s -o %t && \
+// RUN: %clangxx_msan -mllvm -msan-instrumentation-with-call-threshold=0 -fsanitize-memory-track-origins=2 -DHEAP=1 -O3 %s -o %t && \
 // RUN:     not %run %t >%t.out 2>&1
 // RUN: FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-HEAP < %t.out
 
diff --git a/test/msan/chained_origin_empty_stack.cc b/test/msan/chained_origin_empty_stack.cc
index 36727e3..f1ed66b 100644
--- a/test/msan/chained_origin_empty_stack.cc
+++ b/test/msan/chained_origin_empty_stack.cc
@@ -1,4 +1,4 @@
-// RUN: %clangxx_msan -fsanitize-memory-track-origins=2 -m64 -O3 %s -o %t && \
+// RUN: %clangxx_msan -fsanitize-memory-track-origins=2 -O3 %s -o %t && \
 // RUN:     MSAN_OPTIONS=store_context_size=1 not %run %t 2>&1 | FileCheck %s
 
 // Test that stack trace for the intermediate store is not empty.
diff --git a/test/msan/chained_origin_limits.cc b/test/msan/chained_origin_limits.cc
index 0cc57f3..90fd09a 100644
--- a/test/msan/chained_origin_limits.cc
+++ b/test/msan/chained_origin_limits.cc
@@ -1,7 +1,7 @@
 // This test program creates a very large number of unique histories.
 
 // Heap origin.
-// RUN: %clangxx_msan -fsanitize-memory-track-origins=2 -m64 -O3 %s -o %t
+// RUN: %clangxx_msan -fsanitize-memory-track-origins=2 -O3 %s -o %t
 
 // RUN: MSAN_OPTIONS=origin_history_size=7 not %run %t >%t.out 2>&1
 // RUN: FileCheck %s --check-prefix=CHECK7 < %t.out
@@ -16,7 +16,7 @@
 // RUN: FileCheck %s --check-prefix=CHECK7 < %t.out
 
 // Stack origin.
-// RUN: %clangxx_msan -DSTACK -fsanitize-memory-track-origins=2 -m64 -O3 %s -o %t
+// RUN: %clangxx_msan -DSTACK -fsanitize-memory-track-origins=2 -O3 %s -o %t
 
 // RUN: MSAN_OPTIONS=origin_history_size=7 not %run %t >%t.out 2>&1
 // RUN: FileCheck %s --check-prefix=CHECK7 < %t.out
@@ -32,7 +32,7 @@
 
 
 // Heap origin, with calls.
-// RUN: %clangxx_msan -mllvm -msan-instrumentation-with-call-threshold=0 -fsanitize-memory-track-origins=2 -m64 -O3 %s -o %t
+// RUN: %clangxx_msan -mllvm -msan-instrumentation-with-call-threshold=0 -fsanitize-memory-track-origins=2 -O3 %s -o %t
 
 // RUN: MSAN_OPTIONS=origin_history_size=7 not %run %t >%t.out 2>&1
 // RUN: FileCheck %s --check-prefix=CHECK7 < %t.out
@@ -48,7 +48,7 @@
 
 
 // Stack origin, with calls.
-// RUN: %clangxx_msan -DSTACK -mllvm -msan-instrumentation-with-call-threshold=0 -fsanitize-memory-track-origins=2 -m64 -O3 %s -o %t
+// RUN: %clangxx_msan -DSTACK -mllvm -msan-instrumentation-with-call-threshold=0 -fsanitize-memory-track-origins=2 -O3 %s -o %t
 
 // RUN: MSAN_OPTIONS=origin_history_size=7 not %run %t >%t.out 2>&1
 // RUN: FileCheck %s --check-prefix=CHECK7 < %t.out
diff --git a/test/msan/chained_origin_memcpy.cc b/test/msan/chained_origin_memcpy.cc
index f4c2f7f..3fe0b77 100644
--- a/test/msan/chained_origin_memcpy.cc
+++ b/test/msan/chained_origin_memcpy.cc
@@ -1,17 +1,17 @@
-// RUN: %clangxx_msan -fsanitize-memory-track-origins=2 -m64 -DOFFSET=0 -O3 %s -o %t && \
+// RUN: %clangxx_msan -fsanitize-memory-track-origins=2 -DOFFSET=0 -O3 %s -o %t && \
 // RUN:     not %run %t >%t.out 2>&1
 // RUN: FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-Z1 < %t.out
 
-// RUN: %clangxx_msan -fsanitize-memory-track-origins=2 -DOFFSET=10 -m64 -O3 %s -o %t && \
+// RUN: %clangxx_msan -fsanitize-memory-track-origins=2 -DOFFSET=10 -O3 %s -o %t && \
 // RUN:     not %run %t >%t.out 2>&1
 // RUN: FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-Z2 < %t.out
 
 
-// RUN: %clangxx_msan -mllvm -msan-instrumentation-with-call-threshold=0 -fsanitize-memory-track-origins=2 -m64 -DOFFSET=0 -O3 %s -o %t && \
+// RUN: %clangxx_msan -mllvm -msan-instrumentation-with-call-threshold=0 -fsanitize-memory-track-origins=2 -DOFFSET=0 -O3 %s -o %t && \
 // RUN:     not %run %t >%t.out 2>&1
 // RUN: FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-Z1 < %t.out
 
-// RUN: %clangxx_msan -mllvm -msan-instrumentation-with-call-threshold=0 -fsanitize-memory-track-origins=2 -DOFFSET=10 -m64 -O3 %s -o %t && \
+// RUN: %clangxx_msan -mllvm -msan-instrumentation-with-call-threshold=0 -fsanitize-memory-track-origins=2 -DOFFSET=10 -O3 %s -o %t && \
 // RUN:     not %run %t >%t.out 2>&1
 // RUN: FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-Z2 < %t.out
 
diff --git a/test/msan/chained_origin_with_signals.cc b/test/msan/chained_origin_with_signals.cc
index 2841e34..43dbdcc 100644
--- a/test/msan/chained_origin_with_signals.cc
+++ b/test/msan/chained_origin_with_signals.cc
@@ -2,11 +2,11 @@
 // This is, in fact, undesired behavior caused by our chained origins
 // implementation being not async-signal-safe.
 
-// RUN: %clangxx_msan -fsanitize-memory-track-origins=2 -m64 -O3 %s -o %t && \
+// RUN: %clangxx_msan -fsanitize-memory-track-origins=2 -O3 %s -o %t && \
 // RUN:     not %run %t >%t.out 2>&1
 // RUN: FileCheck %s < %t.out
 
-// RUN: %clangxx_msan -mllvm -msan-instrumentation-with-call-threshold=0 -fsanitize-memory-track-origins=2 -m64 -O3 %s -o %t && \
+// RUN: %clangxx_msan -mllvm -msan-instrumentation-with-call-threshold=0 -fsanitize-memory-track-origins=2 -O3 %s -o %t && \
 // RUN:     not %run %t >%t.out 2>&1
 // RUN: FileCheck %s < %t.out
 
diff --git a/test/msan/check_mem_is_initialized.cc b/test/msan/check_mem_is_initialized.cc
index 7d23288..e1d3b11 100644
--- a/test/msan/check_mem_is_initialized.cc
+++ b/test/msan/check_mem_is_initialized.cc
@@ -1,19 +1,19 @@
-// RUN: %clangxx_msan -m64 -O0 %s -o %t && not %run %t >%t.out 2>&1
+// RUN: %clangxx_msan -O0 %s -o %t && not %run %t >%t.out 2>&1
 // RUN: FileCheck %s < %t.out
-// RUN: %clangxx_msan -m64 -O1 %s -o %t && not %run %t >%t.out 2>&1
+// RUN: %clangxx_msan -O1 %s -o %t && not %run %t >%t.out 2>&1
 // RUN: FileCheck %s < %t.out
-// RUN: %clangxx_msan -m64 -O2 %s -o %t && not %run %t >%t.out 2>&1
+// RUN: %clangxx_msan -O2 %s -o %t && not %run %t >%t.out 2>&1
 // RUN: FileCheck %s < %t.out
-// RUN: %clangxx_msan -m64 -O3 %s -o %t && not %run %t >%t.out 2>&1
+// RUN: %clangxx_msan -O3 %s -o %t && not %run %t >%t.out 2>&1
 // RUN: FileCheck %s < %t.out
 
-// RUN: %clangxx_msan -fsanitize-memory-track-origins -m64 -O0 %s -o %t && not %run %t >%t.out 2>&1
+// RUN: %clangxx_msan -fsanitize-memory-track-origins -O0 %s -o %t && not %run %t >%t.out 2>&1
 // RUN: FileCheck %s < %t.out && FileCheck %s --check-prefix=CHECK-ORIGINS < %t.out
-// RUN: %clangxx_msan -fsanitize-memory-track-origins -m64 -O1 %s -o %t && not %run %t >%t.out 2>&1
+// RUN: %clangxx_msan -fsanitize-memory-track-origins -O1 %s -o %t && not %run %t >%t.out 2>&1
 // RUN: FileCheck %s < %t.out && FileCheck %s --check-prefix=CHECK-ORIGINS < %t.out
-// RUN: %clangxx_msan -fsanitize-memory-track-origins -m64 -O2 %s -o %t && not %run %t >%t.out 2>&1
+// RUN: %clangxx_msan -fsanitize-memory-track-origins -O2 %s -o %t && not %run %t >%t.out 2>&1
 // RUN: FileCheck %s < %t.out && FileCheck %s --check-prefix=CHECK-ORIGINS < %t.out
-// RUN: %clangxx_msan -fsanitize-memory-track-origins -m64 -O3 %s -o %t && not %run %t >%t.out 2>&1
+// RUN: %clangxx_msan -fsanitize-memory-track-origins -O3 %s -o %t && not %run %t >%t.out 2>&1
 // RUN: FileCheck %s < %t.out && FileCheck %s --check-prefix=CHECK-ORIGINS < %t.out
 
 #include <sanitizer/msan_interface.h>
diff --git a/test/msan/cxa_atexit.cc b/test/msan/cxa_atexit.cc
index 0aa36ec..70384b9 100644
--- a/test/msan/cxa_atexit.cc
+++ b/test/msan/cxa_atexit.cc
@@ -1,4 +1,4 @@
-// RUN: %clangxx_msan -m64 -O0 %s -o %t && %run %t %p
+// RUN: %clangxx_msan -O0 %s -o %t && %run %t %p
 
 // PR17377: C++ module destructors get stale argument shadow.
 
diff --git a/test/msan/death-callback.cc b/test/msan/death-callback.cc
index 6d04883..08cf291 100644
--- a/test/msan/death-callback.cc
+++ b/test/msan/death-callback.cc
@@ -1,10 +1,10 @@
-// RUN: %clangxx_msan -m64 -DERROR %s -o %t && not %run %t 2>&1 | \
+// RUN: %clangxx_msan -DERROR %s -o %t && not %run %t 2>&1 | \
 // RUN:     FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-NOCB
-// RUN: %clangxx_msan -m64 -DERROR -DMSANCB_SET %s -o %t && not %run %t 2>&1 | \
+// RUN: %clangxx_msan -DERROR -DMSANCB_SET %s -o %t && not %run %t 2>&1 | \
 // RUN:     FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-CB
-// RUN: %clangxx_msan -m64 -DERROR -DMSANCB_SET -DMSANCB_CLEAR %s -o %t && not %run %t 2>&1 | \
+// RUN: %clangxx_msan -DERROR -DMSANCB_SET -DMSANCB_CLEAR %s -o %t && not %run %t 2>&1 | \
 // RUN:     FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-NOCB
-// RUN: %clangxx_msan -m64 -DMSANCB_SET %s -o %t && %run %t 2>&1 | \
+// RUN: %clangxx_msan -DMSANCB_SET %s -o %t && %run %t 2>&1 | \
 // RUN:     FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-NOCB
 
 #include <sanitizer/msan_interface.h>
diff --git a/test/msan/dlerror.cc b/test/msan/dlerror.cc
index 2c726d3..d5510b6 100644
--- a/test/msan/dlerror.cc
+++ b/test/msan/dlerror.cc
@@ -1,4 +1,4 @@
-// RUN: %clangxx_msan -m64 -O0 %s -o %t && %run %t
+// RUN: %clangxx_msan -O0 %s -o %t && %run %t
 
 #include <assert.h>
 #include <dlfcn.h>
diff --git a/test/msan/dso-origin.cc b/test/msan/dso-origin.cc
index ba008c0..7f62449 100644
--- a/test/msan/dso-origin.cc
+++ b/test/msan/dso-origin.cc
@@ -1,7 +1,7 @@
 // Build a library with origin tracking and an executable w/o origin tracking.
 // Test that origin tracking is enabled at runtime.
-// RUN: %clangxx_msan -fsanitize-memory-track-origins -m64 -O0 %s -DBUILD_SO -fPIC -shared -o %t-so.so
-// RUN: %clangxx_msan -m64 -O0 %s %t-so.so -o %t && not %run %t 2>&1 | FileCheck %s
+// RUN: %clangxx_msan -fsanitize-memory-track-origins -O0 %s -DBUILD_SO -fPIC -shared -o %t-so.so
+// RUN: %clangxx_msan -O0 %s %t-so.so -o %t && not %run %t 2>&1 | FileCheck %s
 
 #ifdef BUILD_SO
 
diff --git a/test/msan/dtls_test.c b/test/msan/dtls_test.c
index cb88ede..4036f71 100644
--- a/test/msan/dtls_test.c
+++ b/test/msan/dtls_test.c
@@ -1,5 +1,5 @@
-/* RUN: %clang_msan -g -m64 %s -o %t
-   RUN: %clang_msan -g -m64 %s -DBUILD_SO -fPIC -o %t-so.so -shared
+/* RUN: %clang_msan -g %s -o %t
+   RUN: %clang_msan -g %s -DBUILD_SO -fPIC -o %t-so.so -shared
    RUN: %run %t 2>&1
 
    Regression test for a bug in msan/glibc integration,
diff --git a/test/msan/errno.cc b/test/msan/errno.cc
index 8af8eb5..6ed0fd4 100644
--- a/test/msan/errno.cc
+++ b/test/msan/errno.cc
@@ -1,4 +1,4 @@
-// RUN: %clangxx_msan -m64 -O0 %s -o %t && %run %t
+// RUN: %clangxx_msan -O0 %s -o %t && %run %t
 
 #include <assert.h>
 #include <errno.h>
diff --git a/test/msan/fork.cc b/test/msan/fork.cc
index 10de8a9..78a62d5 100644
--- a/test/msan/fork.cc
+++ b/test/msan/fork.cc
@@ -2,7 +2,7 @@
 // Run a number of threads that create new chained origins, then fork
 // and verify that origin reads do not deadlock in the child process.
 
-// RUN: %clangxx_msan -std=c++11 -fsanitize-memory-track-origins=2 -g -m64 -O3 %s -o %t
+// RUN: %clangxx_msan -std=c++11 -fsanitize-memory-track-origins=2 -g -O3 %s -o %t
 // RUN: MSAN_OPTIONS=store_context_size=1000,origin_history_size=0,origin_history_per_stack_limit=0 %run %t |& FileCheck %s
 
 // Fun fact: if test output is redirected to a file (as opposed to
diff --git a/test/msan/ftime.cc b/test/msan/ftime.cc
index 2d0935d..5ed9358 100644
--- a/test/msan/ftime.cc
+++ b/test/msan/ftime.cc
@@ -1,4 +1,4 @@
-// RUN: %clangxx_msan -m64 -O0 -g %s -o %t && %run %t
+// RUN: %clangxx_msan -O0 -g %s -o %t && %run %t
 
 #include <assert.h>
 #include <sys/timeb.h>
diff --git a/test/msan/getaddrinfo-positive.cc b/test/msan/getaddrinfo-positive.cc
index 7658cd5..45c1b60 100644
--- a/test/msan/getaddrinfo-positive.cc
+++ b/test/msan/getaddrinfo-positive.cc
@@ -1,6 +1,6 @@
-// RUN: %clangxx_msan -m64 -O0 %s -o %t && not %run %t >%t.out 2>&1
+// RUN: %clangxx_msan -O0 %s -o %t && not %run %t >%t.out 2>&1
 // RUN: FileCheck %s < %t.out
-// RUN: %clangxx_msan -m64 -O3 %s -o %t && not %run %t >%t.out 2>&1
+// RUN: %clangxx_msan -O3 %s -o %t && not %run %t >%t.out 2>&1
 // RUN: FileCheck %s < %t.out
 
 #include <sys/types.h>
diff --git a/test/msan/getaddrinfo.cc b/test/msan/getaddrinfo.cc
index abab8bd..c9dcf3e 100644
--- a/test/msan/getaddrinfo.cc
+++ b/test/msan/getaddrinfo.cc
@@ -1,4 +1,4 @@
-// RUN: %clangxx_msan -m64 -O0 %s -o %t && %run %t
+// RUN: %clangxx_msan -O0 %s -o %t && %run %t
 
 #include <sys/types.h>
 #include <sys/socket.h>
diff --git a/test/msan/getc_unlocked.c b/test/msan/getc_unlocked.c
index 7df958a..8468fed 100644
--- a/test/msan/getc_unlocked.c
+++ b/test/msan/getc_unlocked.c
@@ -1,12 +1,12 @@
-// RUN: %clangxx_msan -DGETC -m64 -O0 -g -xc++ %s -o %t && %run %t
-// RUN: %clangxx_msan -DGETC -m64 -O3 -g -xc++ %s -o %t && %run %t
-// RUN: %clang_msan -DGETC -m64 -O0 -g %s -o %t && %run %t
-// RUN: %clang_msan -DGETC -m64 -O3 -g %s -o %t && %run %t
+// RUN: %clangxx_msan -DGETC -O0 -g -xc++ %s -o %t && %run %t
+// RUN: %clangxx_msan -DGETC -O3 -g -xc++ %s -o %t && %run %t
+// RUN: %clang_msan -DGETC -O0 -g %s -o %t && %run %t
+// RUN: %clang_msan -DGETC -O3 -g %s -o %t && %run %t
 
-// RUN: %clangxx_msan -DGETCHAR -m64 -O0 -g -xc++ %s -o %t && %run %t
-// RUN: %clangxx_msan -DGETCHAR -m64 -O3 -g -xc++ %s -o %t && %run %t
-// RUN: %clang_msan -DGETCHAR -m64 -O0 -g %s -o %t && %run %t
-// RUN: %clang_msan -DGETCHAR -m64 -O3 -g %s -o %t && %run %t
+// RUN: %clangxx_msan -DGETCHAR -O0 -g -xc++ %s -o %t && %run %t
+// RUN: %clangxx_msan -DGETCHAR -O3 -g -xc++ %s -o %t && %run %t
+// RUN: %clang_msan -DGETCHAR -O0 -g %s -o %t && %run %t
+// RUN: %clang_msan -DGETCHAR -O3 -g %s -o %t && %run %t
 
 #include <assert.h>
 #include <stdio.h>
diff --git a/test/msan/heap-origin.cc b/test/msan/heap-origin.cc
index 0920001..4f170f0 100644
--- a/test/msan/heap-origin.cc
+++ b/test/msan/heap-origin.cc
@@ -1,19 +1,19 @@
-// RUN: %clangxx_msan -m64 -O0 %s -o %t && not %run %t >%t.out 2>&1
+// RUN: %clangxx_msan -O0 %s -o %t && not %run %t >%t.out 2>&1
 // RUN: FileCheck %s < %t.out
-// RUN: %clangxx_msan -m64 -O1 %s -o %t && not %run %t >%t.out 2>&1
+// RUN: %clangxx_msan -O1 %s -o %t && not %run %t >%t.out 2>&1
 // RUN: FileCheck %s < %t.out
-// RUN: %clangxx_msan -m64 -O2 %s -o %t && not %run %t >%t.out 2>&1
+// RUN: %clangxx_msan -O2 %s -o %t && not %run %t >%t.out 2>&1
 // RUN: FileCheck %s < %t.out
-// RUN: %clangxx_msan -m64 -O3 %s -o %t && not %run %t >%t.out 2>&1
+// RUN: %clangxx_msan -O3 %s -o %t && not %run %t >%t.out 2>&1
 // RUN: FileCheck %s < %t.out
 
-// RUN: %clangxx_msan -fsanitize-memory-track-origins -m64 -O0 %s -o %t && not %run %t >%t.out 2>&1
+// RUN: %clangxx_msan -fsanitize-memory-track-origins -O0 %s -o %t && not %run %t >%t.out 2>&1
 // RUN: FileCheck %s < %t.out && FileCheck %s --check-prefix=CHECK-ORIGINS < %t.out
-// RUN: %clangxx_msan -fsanitize-memory-track-origins -m64 -O1 %s -o %t && not %run %t >%t.out 2>&1
+// RUN: %clangxx_msan -fsanitize-memory-track-origins -O1 %s -o %t && not %run %t >%t.out 2>&1
 // RUN: FileCheck %s < %t.out && FileCheck %s --check-prefix=CHECK-ORIGINS < %t.out
-// RUN: %clangxx_msan -fsanitize-memory-track-origins -m64 -O2 %s -o %t && not %run %t >%t.out 2>&1
+// RUN: %clangxx_msan -fsanitize-memory-track-origins -O2 %s -o %t && not %run %t >%t.out 2>&1
 // RUN: FileCheck %s < %t.out && FileCheck %s --check-prefix=CHECK-ORIGINS < %t.out
-// RUN: %clangxx_msan -fsanitize-memory-track-origins -m64 -O3 %s -o %t && not %run %t >%t.out 2>&1
+// RUN: %clangxx_msan -fsanitize-memory-track-origins -O3 %s -o %t && not %run %t >%t.out 2>&1
 // RUN: FileCheck %s < %t.out && FileCheck %s --check-prefix=CHECK-ORIGINS < %t.out
 
 #include <stdlib.h>
diff --git a/test/msan/iconv.cc b/test/msan/iconv.cc
index ea6958b..c4f2534 100644
--- a/test/msan/iconv.cc
+++ b/test/msan/iconv.cc
@@ -1,5 +1,5 @@
-// RUN: %clangxx_msan -m64 -O0 -g %s -o %t && %run %t
-// RUN: %clangxx_msan -m64 -O0 -g -DPOSITIVE %s -o %t && not %run %t |& FileCheck %s
+// RUN: %clangxx_msan -O0 -g %s -o %t && %run %t
+// RUN: %clangxx_msan -O0 -g -DPOSITIVE %s -o %t && not %run %t |& FileCheck %s
 
 #include <assert.h>
 #include <iconv.h>
diff --git a/test/msan/if_indextoname.cc b/test/msan/if_indextoname.cc
index b74aec1..7f7dea7 100644
--- a/test/msan/if_indextoname.cc
+++ b/test/msan/if_indextoname.cc
@@ -1,6 +1,6 @@
-// RUN: %clangxx_msan -m64 -O0 %s -o %t && %run %t 2>&1
-// RUN: %clangxx_msan -m64 -O0 -D_FILE_OFFSET_BITS=64 %s -o %t && %run %t 2>&1
-// RUN: %clangxx_msan -m64 -O3 %s -o %t && %run %t 2>&1
+// RUN: %clangxx_msan -O0 %s -o %t && %run %t 2>&1
+// RUN: %clangxx_msan -O0 -D_FILE_OFFSET_BITS=64 %s -o %t && %run %t 2>&1
+// RUN: %clangxx_msan -O3 %s -o %t && %run %t 2>&1
 
 #include <assert.h>
 #include <errno.h>
diff --git a/test/msan/ifaddrs.cc b/test/msan/ifaddrs.cc
index 6a0db3a..568e661 100644
--- a/test/msan/ifaddrs.cc
+++ b/test/msan/ifaddrs.cc
@@ -1,6 +1,6 @@
-// RUN: %clangxx_msan -m64 -O0 %s -o %t && %run %t %p 2>&1
-// RUN: %clangxx_msan -m64 -O0 -D_FILE_OFFSET_BITS=64 %s -o %t && %run %t %p 2>&1
-// RUN: %clangxx_msan -m64 -O3 %s -o %t && %run %t %p 2>&1
+// RUN: %clangxx_msan -O0 %s -o %t && %run %t %p 2>&1
+// RUN: %clangxx_msan -O0 -D_FILE_OFFSET_BITS=64 %s -o %t && %run %t %p 2>&1
+// RUN: %clangxx_msan -O3 %s -o %t && %run %t %p 2>&1
 
 #include <assert.h>
 #include <errno.h>
diff --git a/test/msan/initgroups.cc b/test/msan/initgroups.cc
index 94f6cd8..d11fd58 100644
--- a/test/msan/initgroups.cc
+++ b/test/msan/initgroups.cc
@@ -1,4 +1,4 @@
-// RUN: %clangxx_msan -m64 -O0 %s -o %t && %run %t
+// RUN: %clangxx_msan -O0 %s -o %t && %run %t
 
 #include <sys/types.h>
 #include <grp.h>
diff --git a/test/msan/insertvalue_origin.cc b/test/msan/insertvalue_origin.cc
index 545debf..a0c7002 100644
--- a/test/msan/insertvalue_origin.cc
+++ b/test/msan/insertvalue_origin.cc
@@ -1,6 +1,6 @@
-// RUN: %clangxx_msan -fsanitize-memory-track-origins -m64 -O0 %s -o %t && not %run %t >%t.out 2>&1
+// RUN: %clangxx_msan -fsanitize-memory-track-origins -O0 %s -o %t && not %run %t >%t.out 2>&1
 // RUN: FileCheck %s < %t.out && FileCheck %s < %t.out
-// RUN: %clangxx_msan -fsanitize-memory-track-origins -m64 -O3 %s -o %t && not %run %t >%t.out 2>&1
+// RUN: %clangxx_msan -fsanitize-memory-track-origins -O3 %s -o %t && not %run %t >%t.out 2>&1
 // RUN: FileCheck %s < %t.out && FileCheck %s < %t.out
 
 // Test origin propagation through insertvalue IR instruction.
diff --git a/test/msan/ioctl.cc b/test/msan/ioctl.cc
index caa5c27..e21ef63 100644
--- a/test/msan/ioctl.cc
+++ b/test/msan/ioctl.cc
@@ -1,5 +1,5 @@
-// RUN: %clangxx_msan -m64 -O0 -g %s -o %t && %run %t
-// RUN: %clangxx_msan -m64 -O3 -g %s -o %t && %run %t
+// RUN: %clangxx_msan -O0 -g %s -o %t && %run %t
+// RUN: %clangxx_msan -O3 -g %s -o %t && %run %t
 
 #include <assert.h>
 #include <stdlib.h>
diff --git a/test/msan/ioctl_custom.cc b/test/msan/ioctl_custom.cc
index 7c7fde4..6df22d7 100644
--- a/test/msan/ioctl_custom.cc
+++ b/test/msan/ioctl_custom.cc
@@ -1,8 +1,8 @@
-// RUN: %clangxx_msan -m64 -O0 -g %s -o %t && %run %t
-// RUN: %clangxx_msan -m64 -O3 -g %s -o %t && %run %t
+// RUN: %clangxx_msan -O0 -g %s -o %t && %run %t
+// RUN: %clangxx_msan -O3 -g %s -o %t && %run %t
 
-// RUN: %clangxx_msan -DPOSITIVE -m64 -O0 -g %s -o %t && not %run %t 2>&1 | FileCheck %s
-// RUN: %clangxx_msan -DPOSITIVE -m64 -O3 -g %s -o %t && not %run %t 2>&1 | FileCheck %s
+// RUN: %clangxx_msan -DPOSITIVE -O0 -g %s -o %t && not %run %t 2>&1 | FileCheck %s
+// RUN: %clangxx_msan -DPOSITIVE -O3 -g %s -o %t && not %run %t 2>&1 | FileCheck %s
 
 #include <assert.h>
 #include <stdlib.h>
diff --git a/test/msan/ioctl_sound.cc b/test/msan/ioctl_sound.cc
index ed896f7..fb36c52 100644
--- a/test/msan/ioctl_sound.cc
+++ b/test/msan/ioctl_sound.cc
@@ -1,5 +1,5 @@
-// RUN: %clangxx_msan -m64 -O0 -g %s -o %t && %run %t
-// RUN: %clangxx_msan -m64 -O3 -g %s -o %t && %run %t
+// RUN: %clangxx_msan -O0 -g %s -o %t && %run %t
+// RUN: %clangxx_msan -O3 -g %s -o %t && %run %t
 
 #include <assert.h>
 #include <fcntl.h>
diff --git a/test/msan/keep-going-dso.cc b/test/msan/keep-going-dso.cc
index 7975306..f32a513 100644
--- a/test/msan/keep-going-dso.cc
+++ b/test/msan/keep-going-dso.cc
@@ -1,15 +1,15 @@
-// RUN: %clangxx_msan -m64 -O0 %s -o %t && not %run %t >%t.out 2>&1
+// RUN: %clangxx_msan -O0 %s -o %t && not %run %t >%t.out 2>&1
 // FileCheck --check-prefix=CHECK-KEEP-GOING %s <%t.out
-// RUN: %clangxx_msan -m64 -O0 %s -o %t && MSAN_OPTIONS=keep_going=0 not %run %t >%t.out 2>&1
+// RUN: %clangxx_msan -O0 %s -o %t && MSAN_OPTIONS=keep_going=0 not %run %t >%t.out 2>&1
 // FileCheck %s <%t.out
-// RUN: %clangxx_msan -m64 -O0 %s -o %t && MSAN_OPTIONS=keep_going=1 not %run %t >%t.out 2>&1
+// RUN: %clangxx_msan -O0 %s -o %t && MSAN_OPTIONS=keep_going=1 not %run %t >%t.out 2>&1
 // FileCheck --check-prefix=CHECK-KEEP-GOING %s <%t.out
 
-// RUN: %clangxx_msan -m64 -mllvm -msan-keep-going=1 -O0 %s -o %t && not %run %t >%t.out 2>&1
+// RUN: %clangxx_msan -mllvm -msan-keep-going=1 -O0 %s -o %t && not %run %t >%t.out 2>&1
 // FileCheck --check-prefix=CHECK-KEEP-GOING %s <%t.out
-// RUN: %clangxx_msan -m64 -mllvm -msan-keep-going=1 -O0 %s -o %t && MSAN_OPTIONS=keep_going=0 not %run %t >%t.out 2>&1
+// RUN: %clangxx_msan -mllvm -msan-keep-going=1 -O0 %s -o %t && MSAN_OPTIONS=keep_going=0 not %run %t >%t.out 2>&1
 // FileCheck %s <%t.out
-// RUN: %clangxx_msan -m64 -mllvm -msan-keep-going=1 -O0 %s -o %t && MSAN_OPTIONS=keep_going=1 not %run %t >%t.out 2>&1
+// RUN: %clangxx_msan -mllvm -msan-keep-going=1 -O0 %s -o %t && MSAN_OPTIONS=keep_going=1 not %run %t >%t.out 2>&1
 // FileCheck --check-prefix=CHECK-KEEP-GOING %s <%t.out
 
 // Test how -mllvm -msan-keep-going and MSAN_OPTIONS=keep_going affect reports
diff --git a/test/msan/keep-going.cc b/test/msan/keep-going.cc
index 6426574..5772975 100644
--- a/test/msan/keep-going.cc
+++ b/test/msan/keep-going.cc
@@ -1,19 +1,19 @@
-// RUN: %clangxx_msan -m64 -O0 %s -o %t && not %run %t >%t.out 2>&1
+// RUN: %clangxx_msan -O0 %s -o %t && not %run %t >%t.out 2>&1
 // FileCheck %s <%t.out
-// RUN: %clangxx_msan -m64 -O0 %s -o %t && MSAN_OPTIONS=keep_going=0 not %run %t >%t.out 2>&1
+// RUN: %clangxx_msan -O0 %s -o %t && MSAN_OPTIONS=keep_going=0 not %run %t >%t.out 2>&1
 // FileCheck %s <%t.out
-// RUN: %clangxx_msan -m64 -O0 %s -o %t && MSAN_OPTIONS=keep_going=1 not %run %t >%t.out 2>&1
+// RUN: %clangxx_msan -O0 %s -o %t && MSAN_OPTIONS=keep_going=1 not %run %t >%t.out 2>&1
 // FileCheck %s <%t.out
 
-// RUN: %clangxx_msan -m64 -mllvm -msan-keep-going=1 -O0 %s -o %t && not %run %t >%t.out 2>&1
+// RUN: %clangxx_msan -mllvm -msan-keep-going=1 -O0 %s -o %t && not %run %t >%t.out 2>&1
 // FileCheck --check-prefix=CHECK-KEEP-GOING %s <%t.out
-// RUN: %clangxx_msan -m64 -mllvm -msan-keep-going=1 -O0 %s -o %t && MSAN_OPTIONS=keep_going=0 not %run %t >%t.out 2>&1
+// RUN: %clangxx_msan -mllvm -msan-keep-going=1 -O0 %s -o %t && MSAN_OPTIONS=keep_going=0 not %run %t >%t.out 2>&1
 // FileCheck %s <%t.out
-// RUN: %clangxx_msan -m64 -mllvm -msan-keep-going=1 -O0 %s -o %t && MSAN_OPTIONS=keep_going=1 not %run %t >%t.out 2>&1
+// RUN: %clangxx_msan -mllvm -msan-keep-going=1 -O0 %s -o %t && MSAN_OPTIONS=keep_going=1 not %run %t >%t.out 2>&1
 // FileCheck --check-prefix=CHECK-KEEP-GOING %s <%t.out
-// RUN: %clangxx_msan -m64 -mllvm -msan-keep-going=1 -O0 %s -o %t && MSAN_OPTIONS=halt_on_error=1 not %run %t >%t.out 2>&1
+// RUN: %clangxx_msan -mllvm -msan-keep-going=1 -O0 %s -o %t && MSAN_OPTIONS=halt_on_error=1 not %run %t >%t.out 2>&1
 // FileCheck %s <%t.out
-// RUN: %clangxx_msan -m64 -mllvm -msan-keep-going=1 -O0 %s -o %t && MSAN_OPTIONS=halt_on_error=0 not %run %t >%t.out 2>&1
+// RUN: %clangxx_msan -mllvm -msan-keep-going=1 -O0 %s -o %t && MSAN_OPTIONS=halt_on_error=0 not %run %t >%t.out 2>&1
 // FileCheck --check-prefix=CHECK-KEEP-GOING %s <%t.out
 
 // Test behaviour of -mllvm -msan-keep-going and MSAN_OPTIONS=keep_going.
diff --git a/test/msan/mallinfo.cc b/test/msan/mallinfo.cc
index 3f30868..3c36929 100644
--- a/test/msan/mallinfo.cc
+++ b/test/msan/mallinfo.cc
@@ -1,4 +1,4 @@
-// RUN: %clangxx_msan -m64 -O0 -g %s -o %t && %run %t
+// RUN: %clangxx_msan -O0 -g %s -o %t && %run %t
 
 #include <assert.h>
 #include <malloc.h>
diff --git a/test/msan/mktime.cc b/test/msan/mktime.cc
index c419057..997fb0d 100644
--- a/test/msan/mktime.cc
+++ b/test/msan/mktime.cc
@@ -1,5 +1,5 @@
-// RUN: %clangxx_msan -m64 -O0 -g %s -o %t && %run %t
-// RUN: %clangxx_msan -m64 -O0 -g -DUNINIT %s -o %t && not %run %t 2>&1 | FileCheck %s
+// RUN: %clangxx_msan -O0 -g %s -o %t && %run %t
+// RUN: %clangxx_msan -O0 -g -DUNINIT %s -o %t && not %run %t 2>&1 | FileCheck %s
 
 #include <assert.h>
 #include <time.h>
diff --git a/test/msan/mmap_below_shadow.cc b/test/msan/mmap_below_shadow.cc
index 0b982d5..2b507d0 100644
--- a/test/msan/mmap_below_shadow.cc
+++ b/test/msan/mmap_below_shadow.cc
@@ -3,10 +3,10 @@
 // Without MAP_FIXED, we ignore the address hint and map somewhere in
 // application range.
 
-// RUN: %clangxx_msan -m64 -O0 -DFIXED=0 %s -o %t && %run %t
-// RUN: %clangxx_msan -m64 -O0 -DFIXED=1 %s -o %t && %run %t
-// RUN: %clangxx_msan -m64 -O0 -DFIXED=0 -D_FILE_OFFSET_BITS=64 %s -o %t && %run %t
-// RUN: %clangxx_msan -m64 -O0 -DFIXED=1 -D_FILE_OFFSET_BITS=64 %s -o %t && %run %t
+// RUN: %clangxx_msan -O0 -DFIXED=0 %s -o %t && %run %t
+// RUN: %clangxx_msan -O0 -DFIXED=1 %s -o %t && %run %t
+// RUN: %clangxx_msan -O0 -DFIXED=0 -D_FILE_OFFSET_BITS=64 %s -o %t && %run %t
+// RUN: %clangxx_msan -O0 -DFIXED=1 -D_FILE_OFFSET_BITS=64 %s -o %t && %run %t
 
 #include <assert.h>
 #include <errno.h>
diff --git a/test/msan/msan_check_mem_is_initialized.cc b/test/msan/msan_check_mem_is_initialized.cc
index 33558cd..599cf2d 100644
--- a/test/msan/msan_check_mem_is_initialized.cc
+++ b/test/msan/msan_check_mem_is_initialized.cc
@@ -1,9 +1,9 @@
-// RUN: %clangxx_msan -m64 -O0 -g -DPOSITIVE %s -o %t
+// RUN: %clangxx_msan -O0 -g -DPOSITIVE %s -o %t
 // RUN: not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK
 // RUN: MSAN_OPTIONS=verbosity=1 not %run %t 2>&1 | \
 // RUN:     FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-VERBOSE
 
-// RUN: %clangxx_msan -m64 -O0 -g %s -o %t && %run %t
+// RUN: %clangxx_msan -O0 -g %s -o %t && %run %t
 
 #include <sanitizer/msan_interface.h>
 
diff --git a/test/msan/msan_dump_shadow.cc b/test/msan/msan_dump_shadow.cc
index 08371e3..543fa70 100644
--- a/test/msan/msan_dump_shadow.cc
+++ b/test/msan/msan_dump_shadow.cc
@@ -1,10 +1,10 @@
-// RUN: %clangxx_msan -m64 -O0 -g %s -o %t && %run %t >%t.out 2>&1
+// RUN: %clangxx_msan -O0 -g %s -o %t && %run %t >%t.out 2>&1
 // RUN: FileCheck %s < %t.out
 
-// RUN: %clangxx_msan -fsanitize-memory-track-origins -m64 -O0 -g %s -o %t && %run %t >%t.out 2>&1
+// RUN: %clangxx_msan -fsanitize-memory-track-origins -O0 -g %s -o %t && %run %t >%t.out 2>&1
 // RUN: FileCheck %s < %t.out
 
-// RUN: %clangxx_msan -fsanitize-memory-track-origins=2 -m64 -O0 -g %s -o %t && %run %t >%t.out 2>&1
+// RUN: %clangxx_msan -fsanitize-memory-track-origins=2 -O0 -g %s -o %t && %run %t >%t.out 2>&1
 // RUN: FileCheck %s < %t.out
 
 #include <sanitizer/msan_interface.h>
diff --git a/test/msan/msan_print_shadow.cc b/test/msan/msan_print_shadow.cc
index f489459..9668be2 100644
--- a/test/msan/msan_print_shadow.cc
+++ b/test/msan/msan_print_shadow.cc
@@ -1,10 +1,10 @@
-// RUN: %clangxx_msan -m64 -O0 -g %s -o %t && %run %t >%t.out 2>&1
+// RUN: %clangxx_msan -O0 -g %s -o %t && %run %t >%t.out 2>&1
 // RUN: FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-NO-ORIGINS < %t.out
 
-// RUN: %clangxx_msan -fsanitize-memory-track-origins -m64 -O0 -g %s -o %t && %run %t >%t.out 2>&1
+// RUN: %clangxx_msan -fsanitize-memory-track-origins -O0 -g %s -o %t && %run %t >%t.out 2>&1
 // RUN: FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-ORIGINS < %t.out
 
-// RUN: %clangxx_msan -fsanitize-memory-track-origins=2 -m64 -O0 -g %s -o %t && %run %t >%t.out 2>&1
+// RUN: %clangxx_msan -fsanitize-memory-track-origins=2 -O0 -g %s -o %t && %run %t >%t.out 2>&1
 // RUN: FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-ORIGINS --check-prefix=CHECK-ORIGINS-2 < %t.out
 
 #include <sanitizer/msan_interface.h>
diff --git a/test/msan/msan_print_shadow2.cc b/test/msan/msan_print_shadow2.cc
index 343ee9e..5095081 100644
--- a/test/msan/msan_print_shadow2.cc
+++ b/test/msan/msan_print_shadow2.cc
@@ -1,10 +1,10 @@
-// RUN: %clangxx_msan -m64 -O0 -g %s -o %t && %run %t >%t.out 2>&1
+// RUN: %clangxx_msan -O0 -g %s -o %t && %run %t >%t.out 2>&1
 // RUN: FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-NO-ORIGINS < %t.out
 
-// RUN: %clangxx_msan -fsanitize-memory-track-origins -m64 -O0 -g %s -o %t && %run %t >%t.out 2>&1
+// RUN: %clangxx_msan -fsanitize-memory-track-origins -O0 -g %s -o %t && %run %t >%t.out 2>&1
 // RUN: FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-ORIGINS < %t.out
 
-// RUN: %clangxx_msan -fsanitize-memory-track-origins=2 -m64 -O0 -g %s -o %t && %run %t >%t.out 2>&1
+// RUN: %clangxx_msan -fsanitize-memory-track-origins=2 -O0 -g %s -o %t && %run %t >%t.out 2>&1
 // RUN: FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-ORIGINS < %t.out
 
 #include <sanitizer/msan_interface.h>
diff --git a/test/msan/msan_print_shadow3.cc b/test/msan/msan_print_shadow3.cc
index c605ef1..b29f322 100644
--- a/test/msan/msan_print_shadow3.cc
+++ b/test/msan/msan_print_shadow3.cc
@@ -1,4 +1,4 @@
-// RUN: %clangxx_msan -m64 -O0 -g %s -o %t && %run %t >%t.out 2>&1
+// RUN: %clangxx_msan -O0 -g %s -o %t && %run %t >%t.out 2>&1
 // RUN: FileCheck %s < %t.out
 
 #include <stdint.h>
diff --git a/test/msan/mul_by_const.cc b/test/msan/mul_by_const.cc
index a975bb9..8240fdb 100644
--- a/test/msan/mul_by_const.cc
+++ b/test/msan/mul_by_const.cc
@@ -1,4 +1,4 @@
-// RUN: %clangxx_msan -m64 -O2 %s -o %t && %run %t
+// RUN: %clangxx_msan -O2 %s -o %t && %run %t
 
 #include <sanitizer/msan_interface.h>
 
diff --git a/test/msan/no_sanitize_memory.cc b/test/msan/no_sanitize_memory.cc
index c564381..5c53ee4 100644
--- a/test/msan/no_sanitize_memory.cc
+++ b/test/msan/no_sanitize_memory.cc
@@ -1,12 +1,12 @@
-// RUN: %clangxx_msan -m64 -O0 %s -o %t && %run %t >%t.out 2>&1
-// RUN: %clangxx_msan -m64 -O1 %s -o %t && %run %t >%t.out 2>&1
-// RUN: %clangxx_msan -m64 -O2 %s -o %t && %run %t >%t.out 2>&1
-// RUN: %clangxx_msan -m64 -O3 %s -o %t && %run %t >%t.out 2>&1
+// RUN: %clangxx_msan -O0 %s -o %t && %run %t >%t.out 2>&1
+// RUN: %clangxx_msan -O1 %s -o %t && %run %t >%t.out 2>&1
+// RUN: %clangxx_msan -O2 %s -o %t && %run %t >%t.out 2>&1
+// RUN: %clangxx_msan -O3 %s -o %t && %run %t >%t.out 2>&1
 
-// RUN: %clangxx_msan -m64 -O0 %s -o %t -DCHECK_IN_F && %run %t >%t.out 2>&1
-// RUN: %clangxx_msan -m64 -O1 %s -o %t -DCHECK_IN_F && %run %t >%t.out 2>&1
-// RUN: %clangxx_msan -m64 -O2 %s -o %t -DCHECK_IN_F && %run %t >%t.out 2>&1
-// RUN: %clangxx_msan -m64 -O3 %s -o %t -DCHECK_IN_F && %run %t >%t.out 2>&1
+// RUN: %clangxx_msan -O0 %s -o %t -DCHECK_IN_F && %run %t >%t.out 2>&1
+// RUN: %clangxx_msan -O1 %s -o %t -DCHECK_IN_F && %run %t >%t.out 2>&1
+// RUN: %clangxx_msan -O2 %s -o %t -DCHECK_IN_F && %run %t >%t.out 2>&1
+// RUN: %clangxx_msan -O3 %s -o %t -DCHECK_IN_F && %run %t >%t.out 2>&1
 
 // Test that (no_sanitize_memory) functions
 // * don't check shadow values (-DCHECK_IN_F)
diff --git a/test/msan/no_sanitize_memory_prop.cc b/test/msan/no_sanitize_memory_prop.cc
index 4275ebb..bfd4194 100644
--- a/test/msan/no_sanitize_memory_prop.cc
+++ b/test/msan/no_sanitize_memory_prop.cc
@@ -1,7 +1,7 @@
-// RUN: %clangxx_msan -m64 -O0 %s -o %t && %run %t >%t.out 2>&1
-// RUN: %clangxx_msan -m64 -O1 %s -o %t && %run %t >%t.out 2>&1
-// RUN: %clangxx_msan -m64 -O2 %s -o %t && %run %t >%t.out 2>&1
-// RUN: %clangxx_msan -m64 -O3 %s -o %t && %run %t >%t.out 2>&1
+// RUN: %clangxx_msan -O0 %s -o %t && %run %t >%t.out 2>&1
+// RUN: %clangxx_msan -O1 %s -o %t && %run %t >%t.out 2>&1
+// RUN: %clangxx_msan -O2 %s -o %t && %run %t >%t.out 2>&1
+// RUN: %clangxx_msan -O3 %s -o %t && %run %t >%t.out 2>&1
 
 // Test that (no_sanitize_memory) functions DO NOT propagate shadow.
 
diff --git a/test/msan/obstack.cc b/test/msan/obstack.cc
index 222f43b..f1f53be 100644
--- a/test/msan/obstack.cc
+++ b/test/msan/obstack.cc
@@ -1,5 +1,5 @@
-// RUN: %clangxx_msan -m64 -O0 -g %s -o %t && %run %t
-// RUN: %clangxx_msan -m64 -O0 -g -DPOSITIVE %s -o %t && not %run %t |& FileCheck %s
+// RUN: %clangxx_msan -O0 -g %s -o %t && %run %t
+// RUN: %clangxx_msan -O0 -g -DPOSITIVE %s -o %t && not %run %t |& FileCheck %s
 
 #include <obstack.h>
 #include <sanitizer/msan_interface.h>
diff --git a/test/msan/origin-store-long.cc b/test/msan/origin-store-long.cc
index a7c2b7a..5c9fe04 100644
--- a/test/msan/origin-store-long.cc
+++ b/test/msan/origin-store-long.cc
@@ -1,7 +1,7 @@
 // Check that 8-byte store updates origin for the full store range.
-// RUN: %clangxx_msan -fsanitize-memory-track-origins -m64 -O0 %s -o %t && not %run %t >%t.out 2>&1
+// RUN: %clangxx_msan -fsanitize-memory-track-origins -O0 %s -o %t && not %run %t >%t.out 2>&1
 // RUN: FileCheck %s < %t.out && FileCheck %s < %t.out
-// RUN: %clangxx_msan -fsanitize-memory-track-origins -m64 -O2 %s -o %t && not %run %t >%t.out 2>&1
+// RUN: %clangxx_msan -fsanitize-memory-track-origins -O2 %s -o %t && not %run %t >%t.out 2>&1
 // RUN: FileCheck %s < %t.out && FileCheck %s < %t.out
 
 #include <sanitizer/msan_interface.h>
diff --git a/test/msan/param_tls_limit.cc b/test/msan/param_tls_limit.cc
index 869afc9..982ae1e 100644
--- a/test/msan/param_tls_limit.cc
+++ b/test/msan/param_tls_limit.cc
@@ -1,9 +1,9 @@
 // ParamTLS has limited size. Everything that does not fit is considered fully
 // initialized.
 
-// RUN: %clangxx_msan -m64 -O0 %s -o %t && %run %t
-// RUN: %clangxx_msan -fsanitize-memory-track-origins -m64 -O0 %s -o %t && %run %t
-// RUN: %clangxx_msan -fsanitize-memory-track-origins=2 -m64 -O0 %s -o %t && %run %t
+// RUN: %clangxx_msan -O0 %s -o %t && %run %t
+// RUN: %clangxx_msan -fsanitize-memory-track-origins -O0 %s -o %t && %run %t
+// RUN: %clangxx_msan -fsanitize-memory-track-origins=2 -O0 %s -o %t && %run %t
 
 #include <sanitizer/msan_interface.h>
 #include <assert.h>
diff --git a/test/msan/print_stats.cc b/test/msan/print_stats.cc
index 7494383..39af504 100644
--- a/test/msan/print_stats.cc
+++ b/test/msan/print_stats.cc
@@ -1,4 +1,4 @@
-// RUN: %clangxx_msan -fsanitize-memory-track-origins=2 -m64 -g %s -o %t 
+// RUN: %clangxx_msan -fsanitize-memory-track-origins=2 -g %s -o %t 
 // RUN: %run %t 2>&1 | \
 // RUN:   FileCheck --check-prefix=CHECK --check-prefix=CHECK-NOSTATS %s
 // RUN: MSAN_OPTIONS=print_stats=1 %run %t 2>&1 | \
@@ -6,13 +6,13 @@
 // RUN: MSAN_OPTIONS=print_stats=1,atexit=1 %run %t 2>&1 | \
 // RUN:   FileCheck --check-prefix=CHECK --check-prefix=CHECK-STATS %s
 
-// RUN: %clangxx_msan -fsanitize-memory-track-origins=2 -m64 -g -DPOSITIVE=1 %s -o %t 
+// RUN: %clangxx_msan -fsanitize-memory-track-origins=2 -g -DPOSITIVE=1 %s -o %t 
 // RUN: not %run %t 2>&1 | \
 // RUN:   FileCheck --check-prefix=CHECK --check-prefix=CHECK-NOSTATS %s
 // RUN: MSAN_OPTIONS=print_stats=1 not %run %t 2>&1 | \
 // RUN:   FileCheck --check-prefix=CHECK --check-prefix=CHECK-STATS %s
 
-// RUN: %clangxx_msan -fsanitize-memory-track-origins=2 -m64 -g -DPOSITIVE=1 -mllvm -msan-keep-going=1 %s -o %t 
+// RUN: %clangxx_msan -fsanitize-memory-track-origins=2 -g -DPOSITIVE=1 -mllvm -msan-keep-going=1 %s -o %t 
 // RUN: not %run %t 2>&1 | \
 // RUN:  FileCheck --check-prefix=CHECK --check-prefix=CHECK-NOSTATS --check-prefix=CHECK-KEEPGOING %s
 // RUN: MSAN_OPTIONS=print_stats=1 not %run %t 2>&1 | \
diff --git a/test/msan/pthread_getattr_np_deadlock.cc b/test/msan/pthread_getattr_np_deadlock.cc
index 07f19cb..0f52280 100644
--- a/test/msan/pthread_getattr_np_deadlock.cc
+++ b/test/msan/pthread_getattr_np_deadlock.cc
@@ -1,4 +1,4 @@
-// RUN: %clangxx_msan -m64 -fsanitize-memory-track-origins -O0 %s -o %t && %run %t
+// RUN: %clangxx_msan -fsanitize-memory-track-origins -O0 %s -o %t && %run %t
 
 // Regression test for a deadlock in pthread_getattr_np
 
diff --git a/test/msan/rand_r.cc b/test/msan/rand_r.cc
index d6bdb1d..f40cf9f 100644
--- a/test/msan/rand_r.cc
+++ b/test/msan/rand_r.cc
@@ -1,5 +1,5 @@
-// RUN: %clangxx_msan -m64 -O0 -g %s -o %t && %run %t
-// RUN: %clangxx_msan -m64 -O0 -g -DUNINIT %s -o %t && not %run %t 2>&1 | FileCheck %s
+// RUN: %clangxx_msan -O0 -g %s -o %t && %run %t
+// RUN: %clangxx_msan -O0 -g -DUNINIT %s -o %t && not %run %t 2>&1 | FileCheck %s
 
 #include <assert.h>
 #include <stdio.h>
diff --git a/test/msan/readdir64.cc b/test/msan/readdir64.cc
index 4f00d18..e77ada6 100644
--- a/test/msan/readdir64.cc
+++ b/test/msan/readdir64.cc
@@ -1,12 +1,12 @@
-// RUN: %clangxx_msan -m64 -O0 %s -o %t && %run %t
-// RUN: %clangxx_msan -m64 -O1 %s -o %t && %run %t
-// RUN: %clangxx_msan -m64 -O2 %s -o %t && %run %t
-// RUN: %clangxx_msan -m64 -O3 %s -o %t && %run %t
+// RUN: %clangxx_msan -O0 %s -o %t && %run %t
+// RUN: %clangxx_msan -O1 %s -o %t && %run %t
+// RUN: %clangxx_msan -O2 %s -o %t && %run %t
+// RUN: %clangxx_msan -O3 %s -o %t && %run %t
 
-// RUN: %clangxx_msan -m64 -O0 -D_FILE_OFFSET_BITS=64 %s -o %t && %run %t
-// RUN: %clangxx_msan -m64 -O1 -D_FILE_OFFSET_BITS=64 %s -o %t && %run %t
-// RUN: %clangxx_msan -m64 -O2 -D_FILE_OFFSET_BITS=64 %s -o %t && %run %t
-// RUN: %clangxx_msan -m64 -O3 -D_FILE_OFFSET_BITS=64 %s -o %t && %run %t
+// RUN: %clangxx_msan -O0 -D_FILE_OFFSET_BITS=64 %s -o %t && %run %t
+// RUN: %clangxx_msan -O1 -D_FILE_OFFSET_BITS=64 %s -o %t && %run %t
+// RUN: %clangxx_msan -O2 -D_FILE_OFFSET_BITS=64 %s -o %t && %run %t
+// RUN: %clangxx_msan -O3 -D_FILE_OFFSET_BITS=64 %s -o %t && %run %t
 
 // Test that readdir64 is intercepted as well as readdir.
 
diff --git a/test/msan/realloc-large-origin.cc b/test/msan/realloc-large-origin.cc
index de39394..ce25ad8 100644
--- a/test/msan/realloc-large-origin.cc
+++ b/test/msan/realloc-large-origin.cc
@@ -1,6 +1,6 @@
-// RUN: %clangxx_msan -fsanitize-memory-track-origins=2 -m64 -O0 %s -o %t && not %run %t >%t.out 2>&1
+// RUN: %clangxx_msan -fsanitize-memory-track-origins=2 -O0 %s -o %t && not %run %t >%t.out 2>&1
 // RUN: FileCheck %s < %t.out
-// RUN: %clangxx_msan -fsanitize-memory-track-origins=2 -m64 -O2 %s -o %t && not %run %t >%t.out 2>&1
+// RUN: %clangxx_msan -fsanitize-memory-track-origins=2 -O2 %s -o %t && not %run %t >%t.out 2>&1
 // RUN: FileCheck %s < %t.out
 
 // This is a regression test: there used to be broken "stored to memory at"
diff --git a/test/msan/realloc-origin.cc b/test/msan/realloc-origin.cc
index 6707cc9..e689371 100644
--- a/test/msan/realloc-origin.cc
+++ b/test/msan/realloc-origin.cc
@@ -1,6 +1,6 @@
-// RUN: %clangxx_msan -fsanitize-memory-track-origins -m64 -O0 %s -o %t && not %run %t >%t.out 2>&1
+// RUN: %clangxx_msan -fsanitize-memory-track-origins -O0 %s -o %t && not %run %t >%t.out 2>&1
 // RUN: FileCheck %s < %t.out
-// RUN: %clangxx_msan -fsanitize-memory-track-origins -m64 -O2 %s -o %t && not %run %t >%t.out 2>&1
+// RUN: %clangxx_msan -fsanitize-memory-track-origins -O2 %s -o %t && not %run %t >%t.out 2>&1
 // RUN: FileCheck %s < %t.out
 
 // This test relies on realloc from 100 to 101 being done in-place.
diff --git a/test/msan/report-demangling.cc b/test/msan/report-demangling.cc
index e6d5c27..e75ba87 100644
--- a/test/msan/report-demangling.cc
+++ b/test/msan/report-demangling.cc
@@ -1,7 +1,7 @@
 // Test that function name is mangled in the "created by an allocation" line,
 // and demangled in the single-frame "stack trace" that follows.
 
-// RUN: %clangxx_msan -fsanitize-memory-track-origins -m64 -O0 %s -o %t && not %run %t >%t.out 2>&1
+// RUN: %clangxx_msan -fsanitize-memory-track-origins -O0 %s -o %t && not %run %t >%t.out 2>&1
 // RUN: FileCheck %s < %t.out && FileCheck %s < %t.out
 
 __attribute__((noinline))
diff --git a/test/msan/scandir.cc b/test/msan/scandir.cc
index 571ba4f..8adfe00 100644
--- a/test/msan/scandir.cc
+++ b/test/msan/scandir.cc
@@ -1,6 +1,6 @@
-// RUN: %clangxx_msan -m64 -O0 %s -o %t && %run %t %p
-// RUN: %clangxx_msan -m64 -O0 -D_FILE_OFFSET_BITS=64 %s -o %t && %run %t %p
-// RUN: %clangxx_msan -m64 -O3 %s -o %t && %run %t %p
+// RUN: %clangxx_msan -O0 %s -o %t && %run %t %p
+// RUN: %clangxx_msan -O0 -D_FILE_OFFSET_BITS=64 %s -o %t && %run %t %p
+// RUN: %clangxx_msan -O3 %s -o %t && %run %t %p
 
 #include <assert.h>
 #include <glob.h>
diff --git a/test/msan/scandir_null.cc b/test/msan/scandir_null.cc
index e7663dc..94ac31a 100644
--- a/test/msan/scandir_null.cc
+++ b/test/msan/scandir_null.cc
@@ -1,6 +1,6 @@
-// RUN: %clangxx_msan -m64 -O0 %s -o %t && %run %t %p
-// RUN: %clangxx_msan -m64 -O0 -D_FILE_OFFSET_BITS=64 %s -o %t && %run %t %p
-// RUN: %clangxx_msan -m64 -O3 %s -o %t && %run %t %p
+// RUN: %clangxx_msan -O0 %s -o %t && %run %t %p
+// RUN: %clangxx_msan -O0 -D_FILE_OFFSET_BITS=64 %s -o %t && %run %t %p
+// RUN: %clangxx_msan -O3 %s -o %t && %run %t %p
 
 #include <assert.h>
 #include <glob.h>
diff --git a/test/msan/select.cc b/test/msan/select.cc
index 89de75e..7b8c347 100644
--- a/test/msan/select.cc
+++ b/test/msan/select.cc
@@ -1,10 +1,10 @@
-// RUN: %clangxx_msan -m64 -O0 %s -o %t && not %run %t >%t.out 2>&1
+// RUN: %clangxx_msan -O0 %s -o %t && not %run %t >%t.out 2>&1
 // RUN: FileCheck %s < %t.out
-// RUN: %clangxx_msan -m64 -O1 %s -o %t && not %run %t >%t.out 2>&1
+// RUN: %clangxx_msan -O1 %s -o %t && not %run %t >%t.out 2>&1
 // RUN: FileCheck %s < %t.out
-// RUN: %clangxx_msan -m64 -O2 %s -o %t && not %run %t >%t.out 2>&1
+// RUN: %clangxx_msan -O2 %s -o %t && not %run %t >%t.out 2>&1
 // RUN: FileCheck %s < %t.out
-// RUN: %clangxx_msan -m64 -O3 %s -o %t && not %run %t >%t.out 2>&1
+// RUN: %clangxx_msan -O3 %s -o %t && not %run %t >%t.out 2>&1
 // RUN: FileCheck %s < %t.out
 
 #include <stdlib.h>
diff --git a/test/msan/setlocale.cc b/test/msan/setlocale.cc
index b7007f7..796f445 100644
--- a/test/msan/setlocale.cc
+++ b/test/msan/setlocale.cc
@@ -1,4 +1,4 @@
-// RUN: %clangxx_msan -m64 -O0 %s -o %t && %run %t
+// RUN: %clangxx_msan -O0 %s -o %t && %run %t
 
 #include <assert.h>
 #include <locale.h>
diff --git a/test/msan/stack-origin.cc b/test/msan/stack-origin.cc
index c39c3a8..e69c072 100644
--- a/test/msan/stack-origin.cc
+++ b/test/msan/stack-origin.cc
@@ -1,19 +1,19 @@
-// RUN: %clangxx_msan -m64 -O0 %s -o %t && not %run %t >%t.out 2>&1
+// RUN: %clangxx_msan -O0 %s -o %t && not %run %t >%t.out 2>&1
 // RUN: FileCheck %s < %t.out
-// RUN: %clangxx_msan -m64 -O1 %s -o %t && not %run %t >%t.out 2>&1
+// RUN: %clangxx_msan -O1 %s -o %t && not %run %t >%t.out 2>&1
 // RUN: FileCheck %s < %t.out
-// RUN: %clangxx_msan -m64 -O2 %s -o %t && not %run %t >%t.out 2>&1
+// RUN: %clangxx_msan -O2 %s -o %t && not %run %t >%t.out 2>&1
 // RUN: FileCheck %s < %t.out
-// RUN: %clangxx_msan -m64 -O3 %s -o %t && not %run %t >%t.out 2>&1
+// RUN: %clangxx_msan -O3 %s -o %t && not %run %t >%t.out 2>&1
 // RUN: FileCheck %s < %t.out
 
-// RUN: %clangxx_msan -fsanitize-memory-track-origins -m64 -O0 %s -o %t && not %run %t >%t.out 2>&1
+// RUN: %clangxx_msan -fsanitize-memory-track-origins -O0 %s -o %t && not %run %t >%t.out 2>&1
 // RUN: FileCheck %s < %t.out && FileCheck %s --check-prefix=CHECK-ORIGINS < %t.out
-// RUN: %clangxx_msan -fsanitize-memory-track-origins -m64 -O1 %s -o %t && not %run %t >%t.out 2>&1
+// RUN: %clangxx_msan -fsanitize-memory-track-origins -O1 %s -o %t && not %run %t >%t.out 2>&1
 // RUN: FileCheck %s < %t.out && FileCheck %s --check-prefix=CHECK-ORIGINS < %t.out
-// RUN: %clangxx_msan -fsanitize-memory-track-origins -m64 -O2 %s -o %t && not %run %t >%t.out 2>&1
+// RUN: %clangxx_msan -fsanitize-memory-track-origins -O2 %s -o %t && not %run %t >%t.out 2>&1
 // RUN: FileCheck %s < %t.out && FileCheck %s --check-prefix=CHECK-ORIGINS < %t.out
-// RUN: %clangxx_msan -fsanitize-memory-track-origins -m64 -O3 %s -o %t && not %run %t >%t.out 2>&1
+// RUN: %clangxx_msan -fsanitize-memory-track-origins -O3 %s -o %t && not %run %t >%t.out 2>&1
 // RUN: FileCheck %s < %t.out && FileCheck %s --check-prefix=CHECK-ORIGINS < %t.out
 
 #include <stdlib.h>
diff --git a/test/msan/stack-origin2.cc b/test/msan/stack-origin2.cc
index 0ba5760..6c7428c 100644
--- a/test/msan/stack-origin2.cc
+++ b/test/msan/stack-origin2.cc
@@ -1,21 +1,21 @@
 // Test that on the second entry to a function the origins are still right.
 
-// RUN: %clangxx_msan -m64 -O0 %s -o %t && not %run %t >%t.out 2>&1
+// RUN: %clangxx_msan -O0 %s -o %t && not %run %t >%t.out 2>&1
 // RUN: FileCheck %s < %t.out
-// RUN: %clangxx_msan -m64 -O1 %s -o %t && not %run %t >%t.out 2>&1
+// RUN: %clangxx_msan -O1 %s -o %t && not %run %t >%t.out 2>&1
 // RUN: FileCheck %s < %t.out
-// RUN: %clangxx_msan -m64 -O2 %s -o %t && not %run %t >%t.out 2>&1
+// RUN: %clangxx_msan -O2 %s -o %t && not %run %t >%t.out 2>&1
 // RUN: FileCheck %s < %t.out
-// RUN: %clangxx_msan -m64 -O3 %s -o %t && not %run %t >%t.out 2>&1
+// RUN: %clangxx_msan -O3 %s -o %t && not %run %t >%t.out 2>&1
 // RUN: FileCheck %s < %t.out
 
-// RUN: %clangxx_msan -fsanitize-memory-track-origins -m64 -O0 %s -o %t && not %run %t >%t.out 2>&1
+// RUN: %clangxx_msan -fsanitize-memory-track-origins -O0 %s -o %t && not %run %t >%t.out 2>&1
 // RUN: FileCheck %s < %t.out && FileCheck %s --check-prefix=CHECK-ORIGINS < %t.out
-// RUN: %clangxx_msan -fsanitize-memory-track-origins -m64 -O1 %s -o %t && not %run %t >%t.out 2>&1
+// RUN: %clangxx_msan -fsanitize-memory-track-origins -O1 %s -o %t && not %run %t >%t.out 2>&1
 // RUN: FileCheck %s < %t.out && FileCheck %s --check-prefix=CHECK-ORIGINS < %t.out
-// RUN: %clangxx_msan -fsanitize-memory-track-origins -m64 -O2 %s -o %t && not %run %t >%t.out 2>&1
+// RUN: %clangxx_msan -fsanitize-memory-track-origins -O2 %s -o %t && not %run %t >%t.out 2>&1
 // RUN: FileCheck %s < %t.out && FileCheck %s --check-prefix=CHECK-ORIGINS < %t.out
-// RUN: %clangxx_msan -fsanitize-memory-track-origins -m64 -O3 %s -o %t && not %run %t >%t.out 2>&1
+// RUN: %clangxx_msan -fsanitize-memory-track-origins -O3 %s -o %t && not %run %t >%t.out 2>&1
 // RUN: FileCheck %s < %t.out && FileCheck %s --check-prefix=CHECK-ORIGINS < %t.out
 
 #include <stdlib.h>
diff --git a/test/msan/strlen_of_shadow.cc b/test/msan/strlen_of_shadow.cc
index 8f1b4e1..d6f8be7 100644
--- a/test/msan/strlen_of_shadow.cc
+++ b/test/msan/strlen_of_shadow.cc
@@ -1,4 +1,4 @@
-// RUN: %clangxx_msan -m64 -O0 %s -o %t && %run %t
+// RUN: %clangxx_msan -O0 %s -o %t && %run %t
 
 // Check that strlen() and similar intercepted functions can be called on shadow
 // memory.
diff --git a/test/msan/strxfrm.cc b/test/msan/strxfrm.cc
index b930a6a..9a30d03 100644
--- a/test/msan/strxfrm.cc
+++ b/test/msan/strxfrm.cc
@@ -1,4 +1,4 @@
-// RUN: %clangxx_msan -m64 -O0 -g %s -o %t && %run %t
+// RUN: %clangxx_msan -O0 -g %s -o %t && %run %t
 
 #include <assert.h>
 #include <sanitizer/msan_interface.h>
diff --git a/test/msan/sync_lock_set_and_test.cc b/test/msan/sync_lock_set_and_test.cc
index b6d344a..11fd14f 100644
--- a/test/msan/sync_lock_set_and_test.cc
+++ b/test/msan/sync_lock_set_and_test.cc
@@ -1,4 +1,4 @@
-// RUN: %clangxx_msan -m64 -O0 %s -o %t && %run %t
+// RUN: %clangxx_msan -O0 %s -o %t && %run %t
 
 int main(void) {
   int i;
diff --git a/test/msan/textdomain.cc b/test/msan/textdomain.cc
index 47e991e..760debd 100644
--- a/test/msan/textdomain.cc
+++ b/test/msan/textdomain.cc
@@ -1,4 +1,4 @@
-// RUN: %clangxx_msan -m64 -O0 -g %s -o %t && %run %t
+// RUN: %clangxx_msan -O0 -g %s -o %t && %run %t
 
 #include <libintl.h>
 #include <stdio.h>
diff --git a/test/msan/times.cc b/test/msan/times.cc
index a042f54..7c81884 100644
--- a/test/msan/times.cc
+++ b/test/msan/times.cc
@@ -1,4 +1,4 @@
-// RUN: %clangxx_msan -m64 -O0 -g %s -o %t && %run %t
+// RUN: %clangxx_msan -O0 -g %s -o %t && %run %t
 
 #include <assert.h>
 #include <stdlib.h>
diff --git a/test/msan/tls_reuse.cc b/test/msan/tls_reuse.cc
index e024a5a..78a328f 100644
--- a/test/msan/tls_reuse.cc
+++ b/test/msan/tls_reuse.cc
@@ -1,4 +1,4 @@
-// RUN: %clangxx_msan -m64 -O0 %s -o %t && %run %t
+// RUN: %clangxx_msan -O0 %s -o %t && %run %t
 
 // Check that when TLS block is reused between threads, its shadow is cleaned.
 
diff --git a/test/msan/tzset.cc b/test/msan/tzset.cc
index ed61d7b..05915e0 100644
--- a/test/msan/tzset.cc
+++ b/test/msan/tzset.cc
@@ -1,4 +1,4 @@
-// RUN: %clangxx_msan -m64 -O0 %s -o %t && %run %t
+// RUN: %clangxx_msan -O0 %s -o %t && %run %t
 
 #include <stdlib.h>
 #include <string.h>
diff --git a/test/msan/unaligned_read_origin.cc b/test/msan/unaligned_read_origin.cc
index e5618ef..b04800a 100644
--- a/test/msan/unaligned_read_origin.cc
+++ b/test/msan/unaligned_read_origin.cc
@@ -1,6 +1,6 @@
-// RUN: %clangxx_msan -fsanitize-memory-track-origins -m64 -O0 %s -o %t && not %run %t >%t.out 2>&1
+// RUN: %clangxx_msan -fsanitize-memory-track-origins -O0 %s -o %t && not %run %t >%t.out 2>&1
 // RUN: FileCheck %s < %t.out && FileCheck %s < %t.out
-// RUN: %clangxx_msan -fsanitize-memory-track-origins -m64 -O3 %s -o %t && not %run %t >%t.out 2>&1
+// RUN: %clangxx_msan -fsanitize-memory-track-origins -O3 %s -o %t && not %run %t >%t.out 2>&1
 // RUN: FileCheck %s < %t.out && FileCheck %s < %t.out
 
 #include <sanitizer/msan_interface.h>
diff --git a/test/msan/unpoison_string.cc b/test/msan/unpoison_string.cc
index ac947b9..84d9528 100644
--- a/test/msan/unpoison_string.cc
+++ b/test/msan/unpoison_string.cc
@@ -1,6 +1,6 @@
-// RUN: %clangxx_msan -fsanitize-memory-track-origins -m64 -O0 %s -o %t
+// RUN: %clangxx_msan -fsanitize-memory-track-origins -O0 %s -o %t
 // RUN: %run %t
-// RUN: %clangxx_msan -fsanitize-memory-track-origins -m64 -O3 %s -o %t
+// RUN: %clangxx_msan -fsanitize-memory-track-origins -O3 %s -o %t
 // RUN: %run %t
 
 #include <assert.h>
diff --git a/test/msan/use-after-free.cc b/test/msan/use-after-free.cc
index 869bad9..c505124 100644
--- a/test/msan/use-after-free.cc
+++ b/test/msan/use-after-free.cc
@@ -1,19 +1,19 @@
-// RUN: %clangxx_msan -m64 -O0 %s -o %t && not %run %t >%t.out 2>&1
+// RUN: %clangxx_msan -O0 %s -o %t && not %run %t >%t.out 2>&1
 // RUN: FileCheck %s < %t.out
-// RUN: %clangxx_msan -m64 -O1 %s -o %t && not %run %t >%t.out 2>&1
+// RUN: %clangxx_msan -O1 %s -o %t && not %run %t >%t.out 2>&1
 // RUN: FileCheck %s < %t.out
-// RUN: %clangxx_msan -m64 -O2 %s -o %t && not %run %t >%t.out 2>&1
+// RUN: %clangxx_msan -O2 %s -o %t && not %run %t >%t.out 2>&1
 // RUN: FileCheck %s < %t.out
-// RUN: %clangxx_msan -m64 -O3 %s -o %t && not %run %t >%t.out 2>&1
+// RUN: %clangxx_msan -O3 %s -o %t && not %run %t >%t.out 2>&1
 // RUN: FileCheck %s < %t.out
 
-// RUN: %clangxx_msan -fsanitize-memory-track-origins -m64 -O0 %s -o %t && not %run %t >%t.out 2>&1
+// RUN: %clangxx_msan -fsanitize-memory-track-origins -O0 %s -o %t && not %run %t >%t.out 2>&1
 // RUN: FileCheck %s < %t.out && FileCheck %s --check-prefix=CHECK-ORIGINS < %t.out
-// RUN: %clangxx_msan -fsanitize-memory-track-origins -m64 -O1 %s -o %t && not %run %t >%t.out 2>&1
+// RUN: %clangxx_msan -fsanitize-memory-track-origins -O1 %s -o %t && not %run %t >%t.out 2>&1
 // RUN: FileCheck %s < %t.out && FileCheck %s --check-prefix=CHECK-ORIGINS < %t.out
-// RUN: %clangxx_msan -fsanitize-memory-track-origins -m64 -O2 %s -o %t && not %run %t >%t.out 2>&1
+// RUN: %clangxx_msan -fsanitize-memory-track-origins -O2 %s -o %t && not %run %t >%t.out 2>&1
 // RUN: FileCheck %s < %t.out && FileCheck %s --check-prefix=CHECK-ORIGINS < %t.out
-// RUN: %clangxx_msan -fsanitize-memory-track-origins -m64 -O3 %s -o %t && not %run %t >%t.out 2>&1
+// RUN: %clangxx_msan -fsanitize-memory-track-origins -O3 %s -o %t && not %run %t >%t.out 2>&1
 // RUN: FileCheck %s < %t.out && FileCheck %s --check-prefix=CHECK-ORIGINS < %t.out
 
 #include <stdlib.h>
diff --git a/test/msan/vector_cvt.cc b/test/msan/vector_cvt.cc
index bd9b6a8..d08ec3e 100644
--- a/test/msan/vector_cvt.cc
+++ b/test/msan/vector_cvt.cc
@@ -1,5 +1,5 @@
-// RUN: %clangxx_msan -m64 -O0 %s -o %t && %run %t
-// RUN: %clangxx_msan -DPOSITIVE -m64 -O0 %s -o %t && not %run %t 2>&1 | FileCheck %s
+// RUN: %clangxx_msan -O0 %s -o %t && %run %t
+// RUN: %clangxx_msan -DPOSITIVE -O0 %s -o %t && not %run %t 2>&1 | FileCheck %s
 
 #include <emmintrin.h>
 
diff --git a/test/msan/vector_select.cc b/test/msan/vector_select.cc
index afeb1ad..4bfeba6 100644
--- a/test/msan/vector_select.cc
+++ b/test/msan/vector_select.cc
@@ -1,5 +1,5 @@
-// RUN: %clangxx_msan -m64 -O0 %s -c -o %t
-// RUN: %clangxx_msan -m64 -O3 %s -c -o %t
+// RUN: %clangxx_msan -O0 %s -c -o %t
+// RUN: %clangxx_msan -O3 %s -c -o %t
 
 // Regression test for MemorySanitizer instrumentation of a select instruction
 // with vector arguments.
diff --git a/test/sanitizer_common/CMakeLists.txt b/test/sanitizer_common/CMakeLists.txt
index 13eecbd..42f2690 100644
--- a/test/sanitizer_common/CMakeLists.txt
+++ b/test/sanitizer_common/CMakeLists.txt
@@ -16,16 +16,26 @@
 # Create a separate config for each tool we support.
 foreach(tool ${SUPPORTED_TOOLS})
   string(TOUPPER ${tool} tool_toupper)
-  if(${tool_toupper}_SUPPORTED_ARCH)
+  if(${tool_toupper}_SUPPORTED_ARCH AND NOT COMPILER_RT_STANDALONE_BUILD)
+    list(APPEND SANITIZER_COMMON_TEST_DEPS ${tool})
+  endif()
+  foreach(arch ${${tool_toupper}_SUPPORTED_ARCH})
     set(SANITIZER_COMMON_LIT_TEST_MODE ${tool})
+    set(SANITIZER_COMMON_TEST_TARGET_ARCH ${arch})
+    if(${arch} MATCHES "arm|aarch64")
+      # This is only true if we're cross-compiling.
+      set(SANITIZER_COMMON_TEST_TARGET_CFLAGS
+          ${COMPILER_RT_TEST_COMPILER_CFLAGS})
+    else()
+      get_target_flags_for_arch(${arch} SANITIZER_COMMON_TEST_TARGET_CFLAGS)
+    endif()
+    set(CONFIG_NAME ${tool}-${arch}-${OS_NAME})
     configure_lit_site_cfg(
       ${CMAKE_CURRENT_SOURCE_DIR}/lit.site.cfg.in
-      ${CMAKE_CURRENT_BINARY_DIR}/${tool}/lit.site.cfg)
-    list(APPEND SANITIZER_COMMON_TESTSUITES ${CMAKE_CURRENT_BINARY_DIR}/${tool})
-    if(NOT COMPILER_RT_STANDALONE_BUILD)
-      list(APPEND SANITIZER_COMMON_TEST_DEPS ${tool})
-    endif()
-  endif()
+      ${CMAKE_CURRENT_BINARY_DIR}/${CONFIG_NAME}/lit.site.cfg)
+    list(APPEND SANITIZER_COMMON_TESTSUITES
+         ${CMAKE_CURRENT_BINARY_DIR}/${CONFIG_NAME})
+  endforeach()
 endforeach()
 
 # Unit tests.
diff --git a/test/sanitizer_common/TestCases/Linux/open_memstream.cc b/test/sanitizer_common/TestCases/Linux/open_memstream.cc
index 6abe0bf..69097c0 100644
--- a/test/sanitizer_common/TestCases/Linux/open_memstream.cc
+++ b/test/sanitizer_common/TestCases/Linux/open_memstream.cc
@@ -1,5 +1,6 @@
 // RUN: %clangxx -m64 -O0 -g -xc++ %s -o %t && %run %t
 // RUN: %clangxx -m64 -O3 -g -xc++ %s -o %t && %run %t
+// REQUIRES: x86_64-supported-target
 
 #include <assert.h>
 #include <stdio.h>
diff --git a/test/tsan/signal_segv_handler.cc b/test/sanitizer_common/TestCases/Linux/signal_segv_handler.cc
similarity index 78%
rename from test/tsan/signal_segv_handler.cc
rename to test/sanitizer_common/TestCases/Linux/signal_segv_handler.cc
index 2d806ee..9ea9fef 100644
--- a/test/tsan/signal_segv_handler.cc
+++ b/test/sanitizer_common/TestCases/Linux/signal_segv_handler.cc
@@ -1,4 +1,4 @@
-// RUN: %clang_tsan -O1 %s -o %t && TSAN_OPTIONS="flush_memory_ms=1 memory_limit_mb=1" %run %t 2>&1 | FileCheck %s
+// RUN: %clangxx -O1 %s -o %t && TSAN_OPTIONS="flush_memory_ms=1 memory_limit_mb=1" ASAN_OPTIONS="handle_segv=0 allow_user_segv_handler=1" %run %t 2>&1 | FileCheck %s
 
 // JVM uses SEGV to preempt threads. All threads do a load from a known address
 // periodically. When runtime needs to preempt threads, it unmaps the page.
@@ -13,7 +13,8 @@
 // "benign" SEGVs that are handled by signal handler, and ensures that
 // the process survive.
 
-#include "test.h"
+#include <stdio.h>
+#include <stdlib.h>
 #include <signal.h>
 #include <sys/mman.h>
 
@@ -24,15 +25,16 @@
 }
 
 int main() {
-  struct sigaction a;
+  struct sigaction a, old;
   a.sa_sigaction = handler;
   a.sa_flags = SA_SIGINFO;
-  sigaction(SIGSEGV, &a, 0);
+  sigaction(SIGSEGV, &a, &old);
   guard = mmap(0, 4096, PROT_NONE, MAP_ANON | MAP_PRIVATE, -1, 0);
   for (int i = 0; i < 1000000; i++) {
     mprotect(guard, 4096, PROT_NONE);
     *(int*)guard = 1;
   }
+  sigaction(SIGSEGV, &old, 0);
   fprintf(stderr, "DONE\n");
 }
 
diff --git a/test/sanitizer_common/lit.site.cfg.in b/test/sanitizer_common/lit.site.cfg.in
index 1e94aa5..64a3edf 100644
--- a/test/sanitizer_common/lit.site.cfg.in
+++ b/test/sanitizer_common/lit.site.cfg.in
@@ -3,6 +3,8 @@
 
 # Tool-specific config options.
 config.tool_name = "@SANITIZER_COMMON_LIT_TEST_MODE@"
+config.target_cflags = "@SANITIZER_COMMON_TEST_TARGET_CFLAGS@"
+config.target_arch = "@SANITIZER_COMMON_TEST_TARGET_ARCH@"
 
 # Load tool-specific config that would do the real work.
 lit_config.load_config(config, "@SANITIZER_COMMON_LIT_SOURCE_DIR@/lit.common.cfg")
diff --git a/test/tsan/java_heap_init.cc b/test/tsan/java_heap_init.cc
new file mode 100644
index 0000000..bb7357c
--- /dev/null
+++ b/test/tsan/java_heap_init.cc
@@ -0,0 +1,28 @@
+// RUN: %clangxx_tsan -O1 %s -o %t && %run %t 2>&1 | FileCheck %s
+#include "java.h"
+#include <errno.h>
+#include <sys/mman.h>
+
+int main() {
+  // Test that munmap interceptor resets meta shadow for the memory range.
+  // Previously __tsan_java_move failed because it encountered non-zero meta
+  // shadow for the destination.
+  int const kHeapSize = 1024 * 1024;
+  jptr jheap = (jptr)mmap(0, kHeapSize, PROT_READ | PROT_WRITE,
+      MAP_ANON | MAP_PRIVATE, -1, 0);
+  if (jheap == (jptr)MAP_FAILED)
+    return printf("mmap failed with %d\n", errno);
+  __atomic_store_n((int*)jheap, 1, __ATOMIC_RELEASE);
+  munmap((void*)jheap, kHeapSize);
+  jheap = (jptr)mmap((void*)jheap, kHeapSize, PROT_READ | PROT_WRITE,
+      MAP_ANON | MAP_PRIVATE, -1, 0);
+  if (jheap == (jptr)MAP_FAILED)
+    return printf("second mmap failed with %d\n", errno);
+  __tsan_java_init(jheap, kHeapSize);
+  __tsan_java_move(jheap + 16, jheap, 16);
+  printf("DONE\n");
+  return __tsan_java_fini();
+}
+
+// CHECK-NOT: WARNING: ThreadSanitizer: data race
+// CHECK: DONE
diff --git a/test/tsan/mmap_large.cc b/test/tsan/mmap_large.cc
index 4ae4c08..0985304 100644
--- a/test/tsan/mmap_large.cc
+++ b/test/tsan/mmap_large.cc
@@ -4,6 +4,13 @@
 #include <errno.h>
 #include <sys/mman.h>
 
+#if defined(__FreeBSD__)
+// The MAP_NORESERVE define has been removed in FreeBSD 11.x, and even before
+// that, it was never implemented.  So just define it to zero.
+#undef  MAP_NORESERVE
+#define MAP_NORESERVE 0
+#endif
+
 int main() {
 #ifdef __x86_64__
   const size_t kLog2Size = 39;
diff --git a/test/tsan/mmap_stress.cc b/test/tsan/mmap_stress.cc
new file mode 100644
index 0000000..5e3904a
--- /dev/null
+++ b/test/tsan/mmap_stress.cc
@@ -0,0 +1,47 @@
+// RUN: %clang_tsan -O1 %s -o %t && %run %t 2>&1 | FileCheck %s
+#include "test.h"
+#include <errno.h>
+#include <sys/mman.h>
+
+void *SubWorker(void *arg) {
+  (void)arg;
+  const int kMmapSize =  65536;
+  for (int i = 0; i < 500; i++) {
+    int *ptr = (int*)mmap(0, kMmapSize, PROT_READ | PROT_WRITE,
+                          MAP_PRIVATE | MAP_ANON, -1, 0);
+    *ptr = 42;
+    munmap(ptr, kMmapSize);
+  }
+  return 0;
+}
+
+void *Worker1(void *arg) {
+  (void)arg;
+  pthread_t th[4];
+  for (int i = 0; i < 4; i++)
+    pthread_create(&th[i], 0, SubWorker, 0);
+  for (int i = 0; i < 4; i++)
+    pthread_join(th[i], 0);
+  return 0;
+}
+
+void *Worker(void *arg) {
+  (void)arg;
+  pthread_t th[4];
+  for (int i = 0; i < 4; i++)
+    pthread_create(&th[i], 0, Worker1, 0);
+  for (int i = 0; i < 4; i++)
+    pthread_join(th[i], 0);
+  return 0;
+}
+
+int main() {
+  pthread_t th[4];
+  for (int i = 0; i < 4; i++)
+    pthread_create(&th[i], 0, Worker, 0);
+  for (int i = 0; i < 4; i++)
+    pthread_join(th[i], 0);
+  fprintf(stderr, "DONE\n");
+}
+
+// CHECK: DONE
diff --git a/test/tsan/test.h b/test/tsan/test.h
index bb861b0..4e877f6 100644
--- a/test/tsan/test.h
+++ b/test/tsan/test.h
@@ -11,10 +11,16 @@
 __typeof(pthread_barrier_wait) *barrier_wait;
 
 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
+
   if (barrier_wait == 0) {
-    void *h = dlopen("libpthread.so.0", RTLD_LAZY);
+    void *h = dlopen(libpthread_name, RTLD_LAZY);
     if (h == 0) {
-      fprintf(stderr, "failed to dlopen libpthread.so.0, exiting\n");
+      fprintf(stderr, "failed to dlopen %s, exiting\n", libpthread_name);
       exit(1);
     }
     barrier_wait = (__typeof(barrier_wait))dlsym(h, "pthread_barrier_wait");
diff --git a/test/ubsan/TestCases/Integer/shift.cpp b/test/ubsan/TestCases/Integer/shift.cpp
index e86fac8..c8e01af 100644
--- a/test/ubsan/TestCases/Integer/shift.cpp
+++ b/test/ubsan/TestCases/Integer/shift.cpp
@@ -1,13 +1,20 @@
-// RUN: %clangxx -DLSH_OVERFLOW -DOP='<<' -fsanitize=shift %s -o %t && %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-LSH_OVERFLOW
-// RUN: %clangxx -DLSH_OVERFLOW -DOP='<<=' -fsanitize=shift %s -o %t && %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-LSH_OVERFLOW
-// RUN: %clangxx -DTOO_LOW -DOP='<<' -fsanitize=shift %s -o %t && %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-TOO_LOW
-// RUN: %clangxx -DTOO_LOW -DOP='>>' -fsanitize=shift %s -o %t && %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-TOO_LOW
-// RUN: %clangxx -DTOO_LOW -DOP='<<=' -fsanitize=shift %s -o %t && %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-TOO_LOW
-// RUN: %clangxx -DTOO_LOW -DOP='>>=' -fsanitize=shift %s -o %t && %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-TOO_LOW
-// RUN: %clangxx -DTOO_HIGH -DOP='<<' -fsanitize=shift %s -o %t && %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-TOO_HIGH
-// RUN: %clangxx -DTOO_HIGH -DOP='>>' -fsanitize=shift %s -o %t && %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-TOO_HIGH
-// RUN: %clangxx -DTOO_HIGH -DOP='<<=' -fsanitize=shift %s -o %t && %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-TOO_HIGH
-// RUN: %clangxx -DTOO_HIGH -DOP='>>=' -fsanitize=shift %s -o %t && %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-TOO_HIGH
+// RUN: %clangxx -DLSH_OVERFLOW -DOP='<<' -fsanitize=shift-base -fno-sanitize-recover=shift %s -o %t && not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-LSH_OVERFLOW
+// RUN: %clangxx -DLSH_OVERFLOW -DOP='<<=' -fsanitize=shift -fno-sanitize-recover=shift %s -o %t && not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-LSH_OVERFLOW
+// RUN: %clangxx -DTOO_LOW -DOP='<<' -fsanitize=shift-exponent -fno-sanitize-recover=shift %s -o %t && not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-TOO_LOW
+// RUN: %clangxx -DTOO_LOW -DOP='>>' -fsanitize=shift -fno-sanitize-recover=shift %s -o %t && not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-TOO_LOW
+// RUN: %clangxx -DTOO_LOW -DOP='<<=' -fsanitize=shift -fno-sanitize-recover=shift %s -o %t && not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-TOO_LOW
+// RUN: %clangxx -DTOO_LOW -DOP='>>=' -fsanitize=shift -fno-sanitize-recover=shift %s -o %t && not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-TOO_LOW
+// RUN: %clangxx -DTOO_HIGH -DOP='<<' -fsanitize=shift-exponent -fno-sanitize-recover=shift %s -o %t && not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-TOO_HIGH
+// RUN: %clangxx -DTOO_HIGH -DOP='>>' -fsanitize=shift -fno-sanitize-recover=shift %s -o %t && not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-TOO_HIGH
+// RUN: %clangxx -DTOO_HIGH -DOP='<<=' -fsanitize=shift -fno-sanitize-recover=shift %s -o %t && not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-TOO_HIGH
+// RUN: %clangxx -DTOO_HIGH -DOP='>>=' -fsanitize=shift -fno-sanitize-recover=shift %s -o %t && not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-TOO_HIGH
+
+// RUN: %clangxx -DLSH_OVERFLOW -DOP='<<' -fsanitize=shift-exponent -fno-sanitize-recover=shift %s -o %t && %run %t
+// RUN: %clangxx -DLSH_OVERFLOW -DOP='>>' -fsanitize=shift-exponent -fno-sanitize-recover=shift %s -o %t && %run %t
+// RUN: %clangxx -DTOO_LOW -DOP='<<' -fsanitize=shift-base -fno-sanitize-recover=shift %s -o %t && %run %t
+// RUN: %clangxx -DTOO_LOW -DOP='>>' -fsanitize=shift-base -fno-sanitize-recover=shift %s -o %t && %run %t
+// RUN: %clangxx -DTOO_HIGH -DOP='<<' -fsanitize=shift-base -fno-sanitize-recover=shift %s -o %t && %run %t
+// RUN: %clangxx -DTOO_HIGH -DOP='>>' -fsanitize=shift-base -fno-sanitize-recover=shift %s -o %t && %run %t
 
 #include <stdint.h>
 
@@ -20,18 +27,19 @@
   b <<= 1; // still ok, unsigned
 
 #ifdef LSH_OVERFLOW
-  // CHECK-LSH_OVERFLOW: shift.cpp:24:5: runtime error: left shift of negative value -2147483648
+  // CHECK-LSH_OVERFLOW: shift.cpp:[[@LINE+1]]:5: runtime error: left shift of negative value -2147483648
   a OP 1;
 #endif
 
 #ifdef TOO_LOW
-  // CHECK-TOO_LOW: shift.cpp:29:5: runtime error: shift exponent -3 is negative
+  a = 0;
+  // CHECK-TOO_LOW: shift.cpp:[[@LINE+1]]:5: runtime error: shift exponent -3 is negative
   a OP (-3);
 #endif
 
 #ifdef TOO_HIGH
   a = 0;
-  // CHECK-TOO_HIGH: shift.cpp:35:5: runtime error: shift exponent 32 is too large for 32-bit type 'int'
+  // CHECK-TOO_HIGH: shift.cpp:[[@LINE+1]]:5: runtime error: shift exponent 32 is too large for 32-bit type 'int'
   a OP 32;
 #endif
 }
diff --git a/test/ubsan/TestCases/Integer/summary.cpp b/test/ubsan/TestCases/Integer/summary.cpp
index 6e9aec6..21f537b 100644
--- a/test/ubsan/TestCases/Integer/summary.cpp
+++ b/test/ubsan/TestCases/Integer/summary.cpp
@@ -5,6 +5,6 @@
 
 int main() {
   (void)(uint64_t(10000000000000000000ull) + uint64_t(9000000000000000000ull));
-  // CHECK: SUMMARY: AddressSanitizer: undefined-behavior {{.*}}summary.cpp:[[@LINE-1]]
+  // CHECK: SUMMARY: AddressSanitizer: undefined-behavior {{.*}}summary.cpp:[[@LINE-1]]:44
   return 0;
 }
diff --git a/test/ubsan/TestCases/Misc/coverage-levels.cc b/test/ubsan/TestCases/Misc/Linux/coverage-levels.cc
similarity index 98%
rename from test/ubsan/TestCases/Misc/coverage-levels.cc
rename to test/ubsan/TestCases/Misc/Linux/coverage-levels.cc
index 2fe12ff..0252172 100644
--- a/test/ubsan/TestCases/Misc/coverage-levels.cc
+++ b/test/ubsan/TestCases/Misc/Linux/coverage-levels.cc
@@ -14,8 +14,6 @@
 // RUN: %clangxx -fsanitize=shift -O1 -fsanitize-coverage=3  %s -o %t
 // RUN: UBSAN_OPTIONS=$OPT ASAN_OPTIONS=$OPT %run %t 2>&1 | FileCheck %s --check-prefix=CHECK3 --check-prefix=CHECK_WARN
 
-// XFAIL: darwin
-
 volatile int sink;
 int main(int argc, char **argv) {
   int shift = argc * 32;
diff --git a/test/ubsan/TestCases/Misc/Linux/lit.local.cfg b/test/ubsan/TestCases/Misc/Linux/lit.local.cfg
new file mode 100644
index 0000000..57271b8
--- /dev/null
+++ b/test/ubsan/TestCases/Misc/Linux/lit.local.cfg
@@ -0,0 +1,9 @@
+def getRoot(config):
+  if not config.parent:
+    return config
+  return getRoot(config.parent)
+
+root = getRoot(config)
+
+if root.host_os not in ['Linux']:
+  config.unsupported = True
diff --git a/test/ubsan/TestCases/TypeCheck/vptr-virtual-base.cpp b/test/ubsan/TestCases/TypeCheck/vptr-virtual-base.cpp
index 806e45c..a77680e 100644
--- a/test/ubsan/TestCases/TypeCheck/vptr-virtual-base.cpp
+++ b/test/ubsan/TestCases/TypeCheck/vptr-virtual-base.cpp
@@ -1,9 +1,6 @@
 // RUN: %clangxx -frtti -fsanitize=vptr -fno-sanitize-recover=vptr -g %s -O3 -o %t
 // RUN: not %run %t 2>&1 | FileCheck %s
 
-// FIXME: This test produces linker errors on Darwin.
-// XFAIL: darwin
-
 struct S { virtual int f() { return 0; } };
 struct T : virtual S {};