public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* libsanitizer merge from upstream r175042
@ 2013-02-13  9:20 Konstantin Serebryany
  2013-02-13  9:51 ` Jakub Jelinek
  2013-02-13 18:29 ` H.J. Lu
  0 siblings, 2 replies; 36+ messages in thread
From: Konstantin Serebryany @ 2013-02-13  9:20 UTC (permalink / raw)
  To: GCC Patches, Jakub Jelinek, Dodji Seketeli, Dmitry Vyukov,
	Evgeniy Stepanov

[-- Attachment #1: Type: text/plain, Size: 807 bytes --]

Hi,

The attached patch is the libsanitizer merge from upstream r175042.

Lots of changes. Among other things:
 - x86_64 linux: change the shadow offset to 0x7fff8000 (~5% speedup)
 - the new asan allocator is enabled on Mac (was enabled on Linux before).
 - tsan finds races between atomic and plain accesses
 - better scanf interceptor, enabled by default
 - don't include linux/futex.h (fixes PR56128)
 - simple tests seem to work (again?) on PowerPC64 with 44-bit address
space (46 AS not tested)

Patch for libsanitizer is automatically generated by libsanitizer/merge.sh
Tested with
rm -rf */{*/,}libsanitizer \
  && make -j 50 \
  && make -C gcc check-g{cc,++}
RUNTESTFLAGS='--target_board=unix\{-m32,-m64\} asan.exp'

Our internal LLVM bots (Linux, Mac and Android) are green.

Ok to commit?

--kcc

[-- Attachment #2: libsanitizer-r175042.patch --]
[-- Type: application/octet-stream, Size: 219062 bytes --]

Index: libsanitizer/sanitizer_common/sanitizer_stacktrace.h
===================================================================
--- libsanitizer/sanitizer_common/sanitizer_stacktrace.h	(revision 195997)
+++ libsanitizer/sanitizer_common/sanitizer_stacktrace.h	(working copy)
@@ -55,6 +55,10 @@
                               u32 *compressed, uptr size);
 };
 
+
+const char *StripPathPrefix(const char *filepath,
+                            const char *strip_file_prefix);
+
 }  // namespace __sanitizer
 
 // Use this macro if you want to print stack trace with the caller
Index: libsanitizer/sanitizer_common/sanitizer_platform_interceptors.h
===================================================================
--- libsanitizer/sanitizer_common/sanitizer_platform_interceptors.h	(revision 195997)
+++ libsanitizer/sanitizer_common/sanitizer_platform_interceptors.h	(working copy)
@@ -33,4 +33,4 @@
 # define SANITIZER_INTERCEPT_PWRITE64 SI_LINUX_NOT_ANDROID
 # define SANITIZER_INTERCEPT_PRCTL   SI_LINUX_NOT_ANDROID
 
-# define SANITIZER_INTERCEPT_SCANF 0
+# define SANITIZER_INTERCEPT_SCANF SI_NOT_WINDOWS
Index: libsanitizer/sanitizer_common/sanitizer_common.h
===================================================================
--- libsanitizer/sanitizer_common/sanitizer_common.h	(revision 195997)
+++ libsanitizer/sanitizer_common/sanitizer_common.h	(working copy)
@@ -17,6 +17,7 @@
 #include "sanitizer_internal_defs.h"
 
 namespace __sanitizer {
+struct StackTrace;
 
 // Constants.
 const uptr kWordSize = SANITIZER_WORDSIZE / 8;
@@ -28,6 +29,8 @@
 const uptr kCacheLineSize = 64;
 #endif
 
+extern const char *SanitizerToolName;  // Can be changed by the tool.
+
 uptr GetPageSize();
 uptr GetPageSizeCached();
 uptr GetMmapGranularity();
@@ -103,6 +106,7 @@
 void Report(const char *format, ...);
 void SetPrintfAndReportCallback(void (*callback)(const char *));
 
+fd_t OpenFile(const char *filename, bool write);
 // 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',
@@ -152,20 +156,79 @@
                                        u64, u64);
 void SetCheckFailedCallback(CheckFailedCallbackType callback);
 
+// Construct a one-line string like
+//  SanitizerToolName: error_type file:line function
+// and call __sanitizer_report_error_summary on it.
+void ReportErrorSummary(const char *error_type, const char *file,
+                        int line, const char *function);
+
 // Math
+#if defined(_WIN32) && !defined(__clang__)
+extern "C" {
+unsigned char _BitScanForward(unsigned long *index, unsigned long mask);  // NOLINT
+unsigned char _BitScanReverse(unsigned long *index, unsigned long mask);  // NOLINT
+#if defined(_WIN64)
+unsigned char _BitScanForward64(unsigned long *index, unsigned __int64 mask);  // NOLINT
+unsigned char _BitScanReverse64(unsigned long *index, unsigned __int64 mask);  // NOLINT
+#endif
+}
+#endif
+
+INLINE uptr MostSignificantSetBitIndex(uptr x) {
+  CHECK(x != 0);
+  unsigned long up;  // NOLINT
+#if !defined(_WIN32) || defined(__clang__)
+  up = SANITIZER_WORDSIZE - 1 - __builtin_clzl(x);
+#elif defined(_WIN64)
+  _BitScanReverse64(&up, x);
+#else
+  _BitScanReverse(&up, x);
+#endif
+  return up;
+}
+
 INLINE bool IsPowerOfTwo(uptr x) {
   return (x & (x - 1)) == 0;
 }
+
+INLINE uptr RoundUpToPowerOfTwo(uptr size) {
+  CHECK(size);
+  if (IsPowerOfTwo(size)) return size;
+
+  uptr up = MostSignificantSetBitIndex(size);
+  CHECK(size < (1ULL << (up + 1)));
+  CHECK(size > (1ULL << up));
+  return 1UL << (up + 1);
+}
+
 INLINE uptr RoundUpTo(uptr size, uptr boundary) {
   CHECK(IsPowerOfTwo(boundary));
   return (size + boundary - 1) & ~(boundary - 1);
 }
+
 INLINE uptr RoundDownTo(uptr x, uptr boundary) {
   return x & ~(boundary - 1);
 }
+
 INLINE bool IsAligned(uptr a, uptr alignment) {
   return (a & (alignment - 1)) == 0;
 }
+
+INLINE uptr Log2(uptr x) {
+  CHECK(IsPowerOfTwo(x));
+#if !defined(_WIN32) || defined(__clang__)
+  return __builtin_ctzl(x);
+#elif defined(_WIN64)
+  unsigned long ret;  // NOLINT
+  _BitScanForward64(&ret, x);
+  return ret;
+#else
+  unsigned long ret;  // NOLINT
+  _BitScanForward(&ret, x);
+  return ret;
+#endif
+}
+
 // Don't use std::min, std::max or std::swap, to minimize dependency
 // on libstdc++.
 template<class T> T Min(T a, T b) { return a < b ? a : b; }
Index: libsanitizer/sanitizer_common/sanitizer_win.cc
===================================================================
--- libsanitizer/sanitizer_common/sanitizer_win.cc	(revision 195997)
+++ libsanitizer/sanitizer_common/sanitizer_win.cc	(working copy)
@@ -95,6 +95,11 @@
                       MEM_RESERVE | MEM_COMMIT, PAGE_NOACCESS);
 }
 
+void FlushUnneededShadowMemory(uptr addr, uptr size) {
+  // This is almost useless on 32-bits.
+  // FIXME: add madvice-analog when we move to 64-bits.
+}
+
 bool MemoryRangeIsAvailable(uptr range_start, uptr range_end) {
   // FIXME: shall we do anything here on Windows?
   return true;
@@ -189,10 +194,18 @@
   return _isatty(fd);
 }
 
-fd_t internal_open(const char *filename, bool write) {
+fd_t internal_open(const char *filename, int flags) {
   UNIMPLEMENTED();
 }
 
+fd_t internal_open(const char *filename, int flags, u32 mode) {
+  UNIMPLEMENTED();
+}
+
+fd_t OpenFile(const char *filename, bool write) {
+  UNIMPLEMENTED();
+}
+
 uptr internal_read(fd_t fd, void *buf, uptr count) {
   UNIMPLEMENTED();
 }
@@ -209,6 +222,18 @@
   return ret;
 }
 
+int internal_stat(const char *path, void *buf) {
+  UNIMPLEMENTED();
+}
+
+int internal_lstat(const char *path, void *buf) {
+  UNIMPLEMENTED();
+}
+
+int internal_fstat(fd_t fd, void *buf) {
+  UNIMPLEMENTED();
+}
+
 uptr internal_filesize(fd_t fd) {
   UNIMPLEMENTED();
 }
@@ -227,10 +252,8 @@
 }
 
 // ---------------------- BlockingMutex ---------------- {{{1
-enum LockState {
-  LOCK_UNINITIALIZED = 0,
-  LOCK_READY = -1,
-};
+const uptr LOCK_UNINITIALIZED = 0;
+const uptr LOCK_READY = (uptr)-1;
 
 BlockingMutex::BlockingMutex(LinkerInitialized li) {
   // FIXME: see comments in BlockingMutex::Lock() for the details.
@@ -252,12 +275,12 @@
     // locks while we're starting in one thread to avoid double-init races.
   }
   EnterCriticalSection((LPCRITICAL_SECTION)opaque_storage_);
-  CHECK(owner_ == LOCK_READY);
+  CHECK_EQ(owner_, LOCK_READY);
   owner_ = GetThreadSelf();
 }
 
 void BlockingMutex::Unlock() {
-  CHECK(owner_ == GetThreadSelf());
+  CHECK_EQ(owner_, GetThreadSelf());
   owner_ = LOCK_READY;
   LeaveCriticalSection((LPCRITICAL_SECTION)opaque_storage_);
 }
Index: libsanitizer/sanitizer_common/sanitizer_symbolizer.cc
===================================================================
--- libsanitizer/sanitizer_common/sanitizer_symbolizer.cc	(revision 195997)
+++ libsanitizer/sanitizer_common/sanitizer_symbolizer.cc	(working copy)
@@ -174,6 +174,53 @@
 
 static LowLevelAllocator symbolizer_allocator;  // Linker initialized.
 
+#if SANITIZER_SUPPORTS_WEAK_HOOKS
+extern "C" {
+SANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE
+bool __sanitizer_symbolize_code(const char *ModuleName, u64 ModuleOffset,
+                                char *Buffer, int MaxLength);
+SANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE
+bool __sanitizer_symbolize_data(const char *ModuleName, u64 ModuleOffset,
+                                char *Buffer, int MaxLength);
+}  // extern "C"
+
+class InternalSymbolizer {
+ public:
+  typedef bool (*SanitizerSymbolizeFn)(const char*, u64, char*, int);
+  static InternalSymbolizer *get() {
+    if (__sanitizer_symbolize_code != 0 &&
+        __sanitizer_symbolize_data != 0) {
+      void *mem = symbolizer_allocator.Allocate(sizeof(InternalSymbolizer));
+      return new(mem) InternalSymbolizer();
+    }
+    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;
+  }
+
+ private:
+  InternalSymbolizer() { }
+
+  static const int kBufferSize = 16 * 1024;
+  char buffer_[kBufferSize];
+};
+#else  // SANITIZER_SUPPORTS_WEAK_HOOKS
+
+class InternalSymbolizer {
+ public:
+  static InternalSymbolizer *get() { return 0; }
+  char *SendCommand(bool is_data, const char *module_name, uptr module_offset) {
+    return 0;
+  }
+};
+
+#endif  // SANITIZER_SUPPORTS_WEAK_HOOKS
+
 class Symbolizer {
  public:
   uptr SymbolizeCode(uptr addr, AddressInfo *frames, uptr max_frames) {
@@ -266,8 +313,23 @@
     return true;
   }
 
+  bool IsSymbolizerAvailable() {
+    if (internal_symbolizer_ == 0)
+      internal_symbolizer_ = InternalSymbolizer::get();
+    return internal_symbolizer_ || external_symbolizer_;
+  }
+
  private:
   char *SendCommand(bool is_data, const char *module_name, uptr module_offset) {
+    // First, try to use internal symbolizer.
+    if (internal_symbolizer_ == 0) {
+      internal_symbolizer_ = InternalSymbolizer::get();
+    }
+    if (internal_symbolizer_) {
+      return internal_symbolizer_->SendCommand(is_data, module_name,
+                                               module_offset);
+    }
+    // Otherwise, fall back to external symbolizer.
     if (external_symbolizer_ == 0) {
       ReportExternalSymbolizerError(
           "WARNING: Trying to symbolize code, but external "
@@ -322,6 +384,7 @@
   uptr n_modules_;
 
   ExternalSymbolizer *external_symbolizer_;  // Leaked.
+  InternalSymbolizer *internal_symbolizer_;  // Leaked.
 };
 
 static Symbolizer symbolizer;  // Linker initialized.
@@ -338,4 +401,8 @@
   return symbolizer.InitializeExternalSymbolizer(path_to_symbolizer);
 }
 
+bool IsSymbolizerAvailable() {
+  return symbolizer.IsSymbolizerAvailable();
+}
+
 }  // namespace __sanitizer
Index: libsanitizer/sanitizer_common/sanitizer_linux.cc
===================================================================
--- libsanitizer/sanitizer_common/sanitizer_linux.cc	(revision 195997)
+++ libsanitizer/sanitizer_common/sanitizer_linux.cc	(working copy)
@@ -28,12 +28,15 @@
 #include <sys/syscall.h>
 #include <sys/time.h>
 #include <sys/types.h>
+#include <sys/prctl.h>
 #include <unistd.h>
 #include <unwind.h>
 #include <errno.h>
-#include <sys/prctl.h>
-#include <linux/futex.h>
 
+// <linux/futex.h> is broken on some linux distributions.
+const int FUTEX_WAIT = 0;
+const int FUTEX_WAKE = 1;
+
 // Are we using 32-bit or 64-bit syscalls?
 // x32 (which defines __x86_64__) has SANITIZER_WORDSIZE == 32
 // but it still needs to use 64-bit syscalls.
@@ -63,8 +66,16 @@
   return syscall(__NR_close, fd);
 }
 
-fd_t internal_open(const char *filename, bool write) {
-  return syscall(__NR_open, filename,
+fd_t internal_open(const char *filename, int flags) {
+  return syscall(__NR_open, filename, flags);
+}
+
+fd_t internal_open(const char *filename, int flags, u32 mode) {
+  return syscall(__NR_open, filename, flags, mode);
+}
+
+fd_t OpenFile(const char *filename, bool write) {
+  return internal_open(filename,
       write ? O_WRONLY | O_CREAT /*| O_CLOEXEC*/ : O_RDONLY, 0660);
 }
 
@@ -80,16 +91,38 @@
   return res;
 }
 
+int internal_stat(const char *path, void *buf) {
+#if SANITIZER_LINUX_USES_64BIT_SYSCALLS
+  return syscall(__NR_stat, path, buf);
+#else
+  return syscall(__NR_stat64, path, buf);
+#endif
+}
+
+int internal_lstat(const char *path, void *buf) {
+#if SANITIZER_LINUX_USES_64BIT_SYSCALLS
+  return syscall(__NR_lstat, path, buf);
+#else
+  return syscall(__NR_lstat64, path, buf);
+#endif
+}
+
+int internal_fstat(fd_t fd, void *buf) {
+#if SANITIZER_LINUX_USES_64BIT_SYSCALLS
+  return syscall(__NR_fstat, fd, buf);
+#else
+  return syscall(__NR_fstat64, fd, buf);
+#endif
+}
+
 uptr internal_filesize(fd_t fd) {
 #if SANITIZER_LINUX_USES_64BIT_SYSCALLS
   struct stat st;
-  if (syscall(__NR_fstat, fd, &st))
-    return -1;
 #else
   struct stat64 st;
-  if (syscall(__NR_fstat64, fd, &st))
+#endif
+  if (internal_fstat(fd, &st))
     return -1;
-#endif
   return (uptr)st.st_size;
 }
 
Index: libsanitizer/sanitizer_common/sanitizer_mac.cc
===================================================================
--- libsanitizer/sanitizer_common/sanitizer_mac.cc	(revision 195997)
+++ libsanitizer/sanitizer_common/sanitizer_mac.cc	(working copy)
@@ -11,6 +11,12 @@
 //===----------------------------------------------------------------------===//
 
 #ifdef __APPLE__
+// Use 64-bit inodes in file operations. ASan does not support OS X 10.5, so
+// the clients will most certainly use 64-bit ones as well.
+#ifndef _DARWIN_USE_64_BIT_INODE
+#define _DARWIN_USE_64_BIT_INODE 1
+#endif
+#include <stdio.h>
 
 #include "sanitizer_common.h"
 #include "sanitizer_internal_defs.h"
@@ -46,11 +52,19 @@
   return close(fd);
 }
 
-fd_t internal_open(const char *filename, bool write) {
-  return open(filename,
-              write ? O_WRONLY | O_CREAT : O_RDONLY, 0660);
+fd_t internal_open(const char *filename, int flags) {
+  return open(filename, flags);
 }
 
+fd_t internal_open(const char *filename, int flags, u32 mode) {
+  return open(filename, flags, mode);
+}
+
+fd_t 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);
 }
@@ -59,9 +73,21 @@
   return write(fd, buf, count);
 }
 
+int internal_stat(const char *path, void *buf) {
+  return stat(path, (struct stat *)buf);
+}
+
+int internal_lstat(const char *path, void *buf) {
+  return lstat(path, (struct stat *)buf);
+}
+
+int internal_fstat(fd_t fd, void *buf) {
+  return fstat(fd, (struct stat *)buf);
+}
+
 uptr internal_filesize(fd_t fd) {
   struct stat st;
-  if (fstat(fd, &st))
+  if (internal_fstat(fd, &st))
     return -1;
   return (uptr)st.st_size;
 }
Index: libsanitizer/sanitizer_common/sanitizer_symbolizer.h
===================================================================
--- libsanitizer/sanitizer_common/sanitizer_symbolizer.h	(revision 195997)
+++ libsanitizer/sanitizer_common/sanitizer_symbolizer.h	(working copy)
@@ -67,6 +67,8 @@
 uptr SymbolizeCode(uptr address, AddressInfo *frames, uptr max_frames);
 bool SymbolizeData(uptr address, DataInfo *info);
 
+bool IsSymbolizerAvailable();
+
 // Attempts to demangle the provided C++ mangled name.
 const char *Demangle(const char *Name);
 
Index: libsanitizer/sanitizer_common/sanitizer_internal_defs.h
===================================================================
--- libsanitizer/sanitizer_common/sanitizer_internal_defs.h	(revision 195997)
+++ libsanitizer/sanitizer_common/sanitizer_internal_defs.h	(working copy)
@@ -11,7 +11,85 @@
 #ifndef SANITIZER_DEFS_H
 #define SANITIZER_DEFS_H
 
-#include "sanitizer/common_interface_defs.h"
+#if defined(_WIN32)
+// FIXME find out what we need on Windows. __declspec(dllexport) ?
+# define SANITIZER_INTERFACE_ATTRIBUTE
+# define SANITIZER_WEAK_ATTRIBUTE
+#elif defined(SANITIZER_GO)
+# define SANITIZER_INTERFACE_ATTRIBUTE
+# define SANITIZER_WEAK_ATTRIBUTE
+#else
+# define SANITIZER_INTERFACE_ATTRIBUTE __attribute__((visibility("default")))
+# define SANITIZER_WEAK_ATTRIBUTE  __attribute__((weak))
+#endif
+
+#ifdef __linux__
+# define SANITIZER_SUPPORTS_WEAK_HOOKS 1
+#else
+# define SANITIZER_SUPPORTS_WEAK_HOOKS 0
+#endif
+
+// __has_feature
+#if !defined(__has_feature)
+# define __has_feature(x) 0
+#endif
+
+// For portability reasons we do not include stddef.h, stdint.h or any other
+// system header, but we do need some basic types that are not defined
+// in a portable way by the language itself.
+namespace __sanitizer {
+
+#if defined(_WIN64)
+// 64-bit Windows uses LLP64 data model.
+typedef unsigned long long uptr;  // NOLINT
+typedef signed   long long sptr;  // NOLINT
+#else
+typedef unsigned long uptr;  // NOLINT
+typedef signed   long sptr;  // NOLINT
+#endif  // defined(_WIN64)
+#if defined(__x86_64__)
+// Since x32 uses ILP32 data model in 64-bit hardware mode,  we must use
+// 64-bit pointer to unwind stack frame.
+typedef unsigned long long uhwptr;  // NOLINT
+#else
+typedef uptr uhwptr;   // NOLINT
+#endif
+typedef unsigned char u8;
+typedef unsigned short u16;  // NOLINT
+typedef unsigned int u32;
+typedef unsigned long long u64;  // NOLINT
+typedef signed   char s8;
+typedef signed   short s16;  // NOLINT
+typedef signed   int s32;
+typedef signed   long long s64;  // NOLINT
+typedef int fd_t;
+
+}  // namespace __sanitizer
+
+extern "C" {
+  // Tell the tools to write their reports to "path.<pid>" instead of stderr.
+  void __sanitizer_set_report_path(const char *path)
+      SANITIZER_INTERFACE_ATTRIBUTE;
+
+  // Tell the tools to write their reports to given file descriptor instead of
+  // stderr.
+  void __sanitizer_set_report_fd(int fd)
+      SANITIZER_INTERFACE_ATTRIBUTE;
+
+  // Notify the tools that the sandbox is going to be turned on. The reserved
+  // parameter will be used in the future to hold a structure with functions
+  // that the tools may call to bypass the sandbox.
+  void __sanitizer_sandbox_on_notify(void *reserved)
+      SANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE;
+
+  // This function is called by the tool when it has just finished reporting
+  // an error. 'error_summary' is a one-line string that summarizes
+  // the error message. This function can be overridden by the client.
+  void __sanitizer_report_error_summary(const char *error_summary)
+      SANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE;
+}  // extern "C"
+
+
 using namespace __sanitizer;  // NOLINT
 // ----------- ATTENTION -------------
 // This header should NOT include any other headers to avoid portability issues.
Index: libsanitizer/sanitizer_common/sanitizer_allocator.cc
===================================================================
--- libsanitizer/sanitizer_common/sanitizer_allocator.cc	(revision 195997)
+++ libsanitizer/sanitizer_common/sanitizer_allocator.cc	(working copy)
@@ -73,4 +73,10 @@
   low_level_alloc_callback = callback;
 }
 
+bool CallocShouldReturnNullDueToOverflow(uptr size, uptr n) {
+  if (!size) return false;
+  uptr max = (uptr)-1L;
+  return (max / size) < n;
+}
+
 }  // namespace __sanitizer
Index: libsanitizer/sanitizer_common/sanitizer_stacktrace.cc
===================================================================
--- libsanitizer/sanitizer_common/sanitizer_stacktrace.cc	(revision 195997)
+++ libsanitizer/sanitizer_common/sanitizer_stacktrace.cc	(working copy)
@@ -15,8 +15,9 @@
 #include "sanitizer_symbolizer.h"
 
 namespace __sanitizer {
-static const char *StripPathPrefix(const char *filepath,
-                                   const char *strip_file_prefix) {
+const char *StripPathPrefix(const char *filepath,
+                            const char *strip_file_prefix) {
+  if (filepath == 0) return 0;
   if (filepath == internal_strstr(filepath, strip_file_prefix))
     return filepath + internal_strlen(strip_file_prefix);
   return filepath;
Index: libsanitizer/sanitizer_common/sanitizer_common_interceptors_scanf.inc
===================================================================
--- libsanitizer/sanitizer_common/sanitizer_common_interceptors_scanf.inc	(revision 195997)
+++ libsanitizer/sanitizer_common/sanitizer_common_interceptors_scanf.inc	(working copy)
@@ -6,139 +6,302 @@
 //===----------------------------------------------------------------------===//
 //
 // Scanf implementation for use in *Sanitizer interceptors.
+// Follows http://pubs.opengroup.org/onlinepubs/9699919799/functions/fscanf.html
+// with a few common GNU extensions.
 //
 //===----------------------------------------------------------------------===//
 #include <stdarg.h>
 
-#ifdef _WIN32
-#define va_copy(dst, src) ((dst) = (src))
-#endif  // _WIN32
-
-struct ScanfSpec {
-  char c;
-  unsigned size;
+struct ScanfDirective {
+  int argIdx; // argument index, or -1 of not specified ("%n$")
+  int fieldWidth;
+  bool suppressed; // suppress assignment ("*")
+  bool allocate;   // allocate space ("m")
+  char lengthModifier[2];
+  char convSpecifier;
+  bool maybeGnuMalloc;
 };
 
-// One-letter specs.
-static const ScanfSpec scanf_specs[] = {
-  {'p', sizeof(void *)},
-  {'e', sizeof(float)},
-  {'E', sizeof(float)},
-  {'a', sizeof(float)},
-  {'f', sizeof(float)},
-  {'g', sizeof(float)},
-  {'d', sizeof(int)},
-  {'i', sizeof(int)},
-  {'o', sizeof(int)},
-  {'u', sizeof(int)},
-  {'x', sizeof(int)},
-  {'X', sizeof(int)},
-  {'n', sizeof(int)},
-  {'t', sizeof(PTRDIFF_T)},
-  {'z', sizeof(SIZE_T)},
-  {'j', sizeof(INTMAX_T)},
-  {'h', sizeof(short)}
-};
+static const char *parse_number(const char *p, int *out) {
+  *out = internal_atoll(p);
+  while (*p >= '0' && *p <= '9')
+    ++p;
+  return p;
+}
 
-static const unsigned scanf_specs_cnt =
-  sizeof(scanf_specs) / sizeof(scanf_specs[0]);
-
-// %ll?, %L?, %q? specs
-static const ScanfSpec scanf_llspecs[] = {
-  {'e', sizeof(long double)},
-  {'f', sizeof(long double)},
-  {'g', sizeof(long double)},
-  {'d', sizeof(long long)},
-  {'i', sizeof(long long)},
-  {'o', sizeof(long long)},
-  {'u', sizeof(long long)},
-  {'x', sizeof(long long)}
-};
-
-static const unsigned scanf_llspecs_cnt =
-  sizeof(scanf_llspecs) / sizeof(scanf_llspecs[0]);
-
-// %l? specs
-static const ScanfSpec scanf_lspecs[] = {
-  {'e', sizeof(double)},
-  {'f', sizeof(double)},
-  {'g', sizeof(double)},
-  {'d', sizeof(long)},
-  {'i', sizeof(long)},
-  {'o', sizeof(long)},
-  {'u', sizeof(long)},
-  {'x', sizeof(long)},
-  {'X', sizeof(long)},
-};
-
-static const unsigned scanf_lspecs_cnt =
-  sizeof(scanf_lspecs) / sizeof(scanf_lspecs[0]);
-
-static unsigned match_spec(const struct ScanfSpec *spec, unsigned n, char c) {
-  for (unsigned i = 0; i < n; ++i)
-    if (spec[i].c == c)
-      return spec[i].size;
-  return 0;
+static bool char_is_one_of(char c, const char *s) {
+  return !!internal_strchr(s, c);
 }
 
-static void scanf_common(void *ctx, const char *format, va_list ap_const) {
-  va_list aq;
-  va_copy(aq, ap_const);
+// Parse scanf format string. If a valid directive in encountered, it is
+// returned in dir. This function returns the pointer to the first
+// unprocessed character, or 0 in case of error.
+// In case of the end-of-string, a pointer to the closing \0 is returned.
+static const char *scanf_parse_next(const char *p, bool allowGnuMalloc,
+                                    ScanfDirective *dir) {
+  internal_memset(dir, 0, sizeof(*dir));
+  dir->argIdx = -1;
 
-  const char *p = format;
-  unsigned size;
-
   while (*p) {
     if (*p != '%') {
       ++p;
       continue;
     }
     ++p;
-    if (*p == '*' || *p == '%' || *p == 0) {
+    // %%
+    if (*p == '%') {
       ++p;
       continue;
     }
-    if (*p == '0' || (*p >= '1' && *p <= '9')) {
-      size = internal_atoll(p);
-      // +1 for the \0 at the end
-      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, va_arg(aq, void *), size + 1);
+    if (*p == '\0') {
+      return 0;
+    }
+    // %n$
+    if (*p >= '0' && *p <= '9') {
+      int number;
+      const char *q = parse_number(p, &number);
+      if (*q == '$') {
+        dir->argIdx = number;
+        p = q + 1;
+      }
+      // Otherwise, do not change p. This will be re-parsed later as the field
+      // width.
+    }
+    // *
+    if (*p == '*') {
+      dir->suppressed = true;
       ++p;
-      continue;
     }
-
-    if (*p == 'L' || *p == 'q') {
+    // Field width.
+    if (*p >= '0' && *p <= '9') {
+      p = parse_number(p, &dir->fieldWidth);
+      if (dir->fieldWidth <= 0)
+        return 0;
+    }
+    // m
+    if (*p == 'm') {
+      dir->allocate = true;
       ++p;
-      size = match_spec(scanf_llspecs, scanf_llspecs_cnt, *p);
-      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, va_arg(aq, void *), size);
-      continue;
     }
-
-    if (*p == 'l') {
+    // Length modifier.
+    if (char_is_one_of(*p, "jztLq")) {
+      dir->lengthModifier[0] = *p;
       ++p;
+    } else if (*p == 'h') {
+      dir->lengthModifier[0] = 'h';
+      ++p;
+      if (*p == 'h') {
+        dir->lengthModifier[1] = 'h';
+        ++p;
+      }
+    } else if (*p == 'l') {
+      dir->lengthModifier[0] = 'l';
+      ++p;
       if (*p == 'l') {
+        dir->lengthModifier[1] = 'l';
         ++p;
-        size = match_spec(scanf_llspecs, scanf_llspecs_cnt, *p);
-        COMMON_INTERCEPTOR_WRITE_RANGE(ctx, va_arg(aq, void *), size);
-        continue;
-      } else {
-        size = match_spec(scanf_lspecs, scanf_lspecs_cnt, *p);
-        COMMON_INTERCEPTOR_WRITE_RANGE(ctx, va_arg(aq, void *), size);
-        continue;
       }
     }
+    // Conversion specifier.
+    dir->convSpecifier = *p++;
+    // Consume %[...] expression.
+    if (dir->convSpecifier == '[') {
+      if (*p == '^')
+        ++p;
+      if (*p == ']')
+        ++p;
+      while (*p && *p != ']')
+        ++p;
+      if (*p == 0)
+        return 0; // unexpected end of string
+                  // Consume the closing ']'.
+      ++p;
+    }
+    // This is unfortunately ambiguous between old GNU extension
+    // of %as, %aS and %a[...] and newer POSIX %a followed by
+    // letters s, S or [.
+    if (allowGnuMalloc && dir->convSpecifier == 'a' &&
+        !dir->lengthModifier[0]) {
+      if (*p == 's' || *p == 'S') {
+        dir->maybeGnuMalloc = true;
+        ++p;
+      } else if (*p == '[') {
+        // Watch for %a[h-j%d], if % appears in the
+        // [...] range, then we need to give up, we don't know
+        // if scanf will parse it as POSIX %a [h-j %d ] or
+        // GNU allocation of string with range dh-j plus %.
+        const char *q = p + 1;
+        if (*q == '^')
+          ++q;
+        if (*q == ']')
+          ++q;
+        while (*q && *q != ']' && *q != '%')
+          ++q;
+        if (*q == 0 || *q == '%')
+          return 0;
+        p = q + 1; // Consume the closing ']'.
+        dir->maybeGnuMalloc = true;
+      }
+    }
+    break;
+  }
+  return p;
+}
 
-    if (*p == 'h' && *(p + 1) == 'h') {
-      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, va_arg(aq, void *), sizeof(char));
-      p += 2;
-      continue;
+// Returns true if the character is an integer conversion specifier.
+static bool scanf_is_integer_conv(char c) {
+  return char_is_one_of(c, "diouxXn");
+}
+
+// Returns true if the character is an floating point conversion specifier.
+static bool scanf_is_float_conv(char c) {
+  return char_is_one_of(c, "aAeEfFgG");
+}
+
+// Returns string output character size for string-like conversions,
+// or 0 if the conversion is invalid.
+static int scanf_get_char_size(ScanfDirective *dir) {
+  if (char_is_one_of(dir->convSpecifier, "CS")) {
+    // wchar_t
+    return 0;
+  }
+
+  if (char_is_one_of(dir->convSpecifier, "cs[")) {
+    if (dir->lengthModifier[0] == 'l')
+      // wchar_t
+      return 0;
+    else if (dir->lengthModifier[0] == 0)
+      return sizeof(char);
+    else
+      return 0;
+  }
+
+  return 0;
+}
+
+enum ScanfStoreSize {
+  // Store size not known in advance; can be calculated as strlen() of the
+  // destination buffer.
+  SSS_STRLEN = -1,
+  // Invalid conversion specifier.
+  SSS_INVALID = 0
+};
+
+// Returns the store size of a scanf directive (if >0), or a value of
+// ScanfStoreSize.
+static int scanf_get_store_size(ScanfDirective *dir) {
+  if (dir->allocate) {
+    if (!char_is_one_of(dir->convSpecifier, "cCsS["))
+      return SSS_INVALID;
+    return sizeof(char *);
+  }
+
+  if (dir->maybeGnuMalloc) {
+    if (dir->convSpecifier != 'a' || dir->lengthModifier[0])
+      return SSS_INVALID;
+    // This is ambiguous, so check the smaller size of char * (if it is
+    // a GNU extension of %as, %aS or %a[...]) and float (if it is
+    // POSIX %a followed by s, S or [ letters).
+    return sizeof(char *) < sizeof(float) ? sizeof(char *) : sizeof(float);
+  }
+
+  if (scanf_is_integer_conv(dir->convSpecifier)) {
+    switch (dir->lengthModifier[0]) {
+    case 'h':
+      return dir->lengthModifier[1] == 'h' ? sizeof(char) : sizeof(short);
+    case 'l':
+      return dir->lengthModifier[1] == 'l' ? sizeof(long long) : sizeof(long);
+    case 'L':
+      return sizeof(long long);
+    case 'j':
+      return sizeof(INTMAX_T);
+    case 'z':
+      return sizeof(SIZE_T);
+    case 't':
+      return sizeof(PTRDIFF_T);
+    case 0:
+      return sizeof(int);
+    default:
+      return SSS_INVALID;
     }
+  }
 
-    size = match_spec(scanf_specs, scanf_specs_cnt, *p);
-    if (size) {
-      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, va_arg(aq, void *), size);
-      ++p;
+  if (scanf_is_float_conv(dir->convSpecifier)) {
+    switch (dir->lengthModifier[0]) {
+    case 'L':
+    case 'q':
+      return sizeof(long double);
+    case 'l':
+      return dir->lengthModifier[1] == 'l' ? sizeof(long double)
+                                           : sizeof(double);
+    case 0:
+      return sizeof(float);
+    default:
+      return SSS_INVALID;
+    }
+  }
+
+  if (char_is_one_of(dir->convSpecifier, "sS[")) {
+    unsigned charSize = scanf_get_char_size(dir);
+    if (charSize == 0)
+      return SSS_INVALID;
+    if (dir->fieldWidth == 0)
+      return SSS_STRLEN;
+    return (dir->fieldWidth + 1) * charSize;
+  }
+
+  if (char_is_one_of(dir->convSpecifier, "cC")) {
+    unsigned charSize = scanf_get_char_size(dir);
+    if (charSize == 0)
+      return SSS_INVALID;
+    if (dir->fieldWidth == 0)
+      return charSize;
+    return dir->fieldWidth * charSize;
+  }
+
+  if (dir->convSpecifier == 'p') {
+    if (dir->lengthModifier[1] != 0)
+      return SSS_INVALID;
+    return sizeof(void *);
+  }
+
+  return SSS_INVALID;
+}
+
+// Common part of *scanf interceptors.
+// Process format string and va_list, and report all store ranges.
+// Stops when "consuming" n_inputs input items.
+static void scanf_common(void *ctx, int n_inputs, bool allowGnuMalloc,
+                         const char *format, va_list aq) {
+  CHECK_GT(n_inputs, 0);
+  const char *p = format;
+
+  while (*p && n_inputs) {
+    ScanfDirective dir;
+    p = scanf_parse_next(p, allowGnuMalloc, &dir);
+    if (!p)
+      break;
+    if (dir.convSpecifier == 0) {
+      // This can only happen at the end of the format string.
+      CHECK_EQ(*p, 0);
+      break;
+    }
+    // Here the directive is valid. Do what it says.
+    if (dir.argIdx != -1) {
+      // Unsupported.
+      break;
+    }
+    if (dir.suppressed)
       continue;
+    int size = scanf_get_store_size(&dir);
+    if (size == SSS_INVALID)
+      break;
+    void *argp = va_arg(aq, void *);
+    if (dir.convSpecifier != 'n')
+      --n_inputs;
+    if (size == SSS_STRLEN) {
+      size = internal_strlen((const char *)argp) + 1;
     }
+    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, argp, size);
   }
-  va_end(aq);
 }
Index: libsanitizer/sanitizer_common/sanitizer_common.cc
===================================================================
--- libsanitizer/sanitizer_common/sanitizer_common.cc	(revision 195997)
+++ libsanitizer/sanitizer_common/sanitizer_common.cc	(working copy)
@@ -14,6 +14,8 @@
 
 namespace __sanitizer {
 
+const char *SanitizerToolName = "SanitizerTool";
+
 uptr GetPageSizeCached() {
   static uptr PageSize;
   if (!PageSize)
@@ -64,7 +66,7 @@
   InternalScopedBuffer<char> report_path_full(4096);
   internal_snprintf(report_path_full.data(), report_path_full.size(),
                     "%s.%d", report_path_prefix, GetPid());
-  fd_t fd = internal_open(report_path_full.data(), true);
+  fd_t fd = OpenFile(report_path_full.data(), true);
   if (fd == kInvalidFd) {
     report_fd = kStderrFd;
     log_to_file = false;
@@ -103,7 +105,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) {
-    fd_t fd = internal_open(file_name, /*write*/ false);
+    fd_t fd = OpenFile(file_name, /*write*/ false);
     if (fd == kInvalidFd) return 0;
     UnmapOrDie(*buff, *buff_size);
     *buff = (char*)MmapOrDie(size, __FUNCTION__);
@@ -188,6 +190,16 @@
   return (void*)res;
 }
 
+void ReportErrorSummary(const char *error_type, const char *file,
+                        int line, const char *function) {
+  const int kMaxSize = 1024;  // We don't want a summary too long.
+  InternalScopedBuffer<char> buff(kMaxSize);
+  internal_snprintf(buff.data(), kMaxSize, "%s: %s %s:%d %s",
+                    SanitizerToolName, error_type,
+                    file ? file : "??", line, function ? function : "??");
+  __sanitizer_report_error_summary(buff.data());
+}
+
 }  // namespace __sanitizer
 
 using namespace __sanitizer;  // NOLINT
@@ -220,4 +232,8 @@
   (void)reserved;
   PrepareForSandboxing();
 }
+
+void __sanitizer_report_error_summary(const char *error_summary) {
+  Printf("SUMMARY: %s\n", error_summary);
+}
 }  // extern "C"
Index: libsanitizer/sanitizer_common/sanitizer_lfstack.h
===================================================================
--- libsanitizer/sanitizer_common/sanitizer_lfstack.h	(revision 195997)
+++ libsanitizer/sanitizer_common/sanitizer_lfstack.h	(working copy)
@@ -66,6 +66,6 @@
 
   atomic_uint64_t head_;
 };
-}
+}  // namespace __sanitizer
 
 #endif  // #ifndef SANITIZER_LFSTACK_H
Index: libsanitizer/sanitizer_common/sanitizer_posix.cc
===================================================================
--- libsanitizer/sanitizer_common/sanitizer_posix.cc	(revision 195997)
+++ libsanitizer/sanitizer_common/sanitizer_posix.cc	(working copy)
@@ -56,12 +56,12 @@
     if (recursion_count) {
       // The Report() and CHECK calls below may call mmap recursively and fail.
       // If we went into recursion, just die.
-      RawWrite("AddressSanitizer is unable to mmap\n");
+      RawWrite("ERROR: Failed to mmap\n");
       Die();
     }
     recursion_count++;
-    Report("ERROR: Failed to allocate 0x%zx (%zd) bytes of %s: %s\n",
-           size, size, mem_type, strerror(errno));
+    Report("ERROR: %s failed to allocate 0x%zx (%zd) bytes of %s: %s\n",
+           SanitizerToolName, size, size, mem_type, strerror(errno));
     DumpProcessMap();
     CHECK("unable to mmap" && 0);
   }
@@ -72,8 +72,8 @@
   if (!addr || !size) return;
   int res = internal_munmap(addr, size);
   if (res != 0) {
-    Report("ERROR: Failed to deallocate 0x%zx (%zd) bytes at address %p\n",
-           size, size, addr);
+    Report("ERROR: %s failed to deallocate 0x%zx (%zd) bytes at address %p\n",
+           SanitizerToolName, size, size, addr);
     CHECK("unable to unmap" && 0);
   }
 }
@@ -86,8 +86,9 @@
       MAP_PRIVATE | MAP_ANON | MAP_FIXED | MAP_NORESERVE,
       -1, 0);
   if (p == (void*)-1)
-    Report("ERROR: Failed to allocate 0x%zx (%zd) bytes at address %p (%d)\n",
-           size, size, fixed_addr, errno);
+    Report("ERROR: "
+           "%s failed to allocate 0x%zx (%zd) bytes at address %p (%d)\n",
+           SanitizerToolName, size, size, fixed_addr, errno);
   return p;
 }
 
@@ -99,8 +100,9 @@
       MAP_PRIVATE | MAP_ANON | MAP_FIXED,
       -1, 0);
   if (p == (void*)-1) {
-    Report("ERROR: Failed to allocate 0x%zx (%zd) bytes at address %p (%d)\n",
-           size, size, fixed_addr, errno);
+    Report("ERROR:"
+           " %s failed to allocate 0x%zx (%zd) bytes at address %p (%d)\n",
+           SanitizerToolName, size, size, fixed_addr, errno);
     CHECK("unable to mmap" && 0);
   }
   return p;
@@ -118,7 +120,7 @@
 }
 
 void *MapFileToMemory(const char *file_name, uptr *buff_size) {
-  fd_t fd = internal_open(file_name, false);
+  fd_t fd = OpenFile(file_name, false);
   CHECK_NE(fd, kInvalidFd);
   uptr fsize = internal_filesize(fd);
   CHECK_NE(fsize, (uptr)-1);
@@ -187,7 +189,7 @@
   rlim.rlim_cur = limit;
   rlim.rlim_max = limit;
   if (setrlimit(RLIMIT_STACK, &rlim)) {
-    Report("setrlimit() failed %d\n", errno);
+    Report("ERROR: %s setrlimit() failed %d\n", SanitizerToolName, errno);
     Die();
   }
   CHECK(!StackSizeIsUnlimited());
Index: libsanitizer/sanitizer_common/sanitizer_stackdepot.h
===================================================================
--- libsanitizer/sanitizer_common/sanitizer_stackdepot.h	(revision 195997)
+++ libsanitizer/sanitizer_common/sanitizer_stackdepot.h	(working copy)
@@ -11,7 +11,7 @@
 #ifndef SANITIZER_STACKDEPOT_H
 #define SANITIZER_STACKDEPOT_H
 
-#include "sanitizer/common_interface_defs.h"
+#include "sanitizer_internal_defs.h"
 
 namespace __sanitizer {
 
Index: libsanitizer/sanitizer_common/sanitizer_libc.cc
===================================================================
--- libsanitizer/sanitizer_common/sanitizer_libc.cc	(revision 195997)
+++ libsanitizer/sanitizer_common/sanitizer_libc.cc	(working copy)
@@ -204,7 +204,7 @@
 }
 
 bool mem_is_zero(const char *beg, uptr size) {
-  CHECK_LE(size, 1UL << FIRST_32_SECOND_64(30, 40));  // Sanity check.
+  CHECK_LE(size, 1ULL << FIRST_32_SECOND_64(30, 40));  // Sanity check.
   const char *end = beg + size;
   uptr *aligned_beg = (uptr *)RoundUpTo((uptr)beg, sizeof(uptr));
   uptr *aligned_end = (uptr *)RoundDownTo((uptr)end, sizeof(uptr));
Index: libsanitizer/sanitizer_common/sanitizer_quarantine.h
===================================================================
--- libsanitizer/sanitizer_common/sanitizer_quarantine.h	(revision 195997)
+++ libsanitizer/sanitizer_common/sanitizer_quarantine.h	(working copy)
@@ -157,7 +157,7 @@
     atomic_store(&size_, Size() + add, memory_order_relaxed);
   }
 
-  QuarantineBatch *NOINLINE AllocBatch(Callback cb) {
+  NOINLINE QuarantineBatch* AllocBatch(Callback cb) {
     QuarantineBatch *b = (QuarantineBatch *)cb.Allocate(sizeof(*b));
     b->count = 0;
     b->size = 0;
@@ -165,6 +165,6 @@
     return b;
   }
 };
-}
+}  // namespace __sanitizer
 
 #endif  // #ifndef SANITIZER_QUARANTINE_H
Index: libsanitizer/sanitizer_common/sanitizer_libc.h
===================================================================
--- libsanitizer/sanitizer_common/sanitizer_libc.h	(revision 195997)
+++ libsanitizer/sanitizer_common/sanitizer_libc.h	(working copy)
@@ -9,14 +9,13 @@
 // run-time libraries.
 // These tools can not use some of the libc functions directly because those
 // functions are intercepted. Instead, we implement a tiny subset of libc here.
-// NOTE: This file may be included into user code.
 //===----------------------------------------------------------------------===//
 #ifndef SANITIZER_LIBC_H
 #define SANITIZER_LIBC_H
 
 // ----------- ATTENTION -------------
 // This header should NOT include any other headers from sanitizer runtime.
-#include "sanitizer/common_interface_defs.h"
+#include "sanitizer_internal_defs.h"
 
 namespace __sanitizer {
 
@@ -56,17 +55,24 @@
 int internal_munmap(void *addr, uptr length);
 
 // I/O
-typedef int fd_t;
 const fd_t kInvalidFd = -1;
 const fd_t kStdinFd = 0;
 const fd_t kStdoutFd = 1;
 const fd_t kStderrFd = 2;
 int internal_close(fd_t fd);
 int internal_isatty(fd_t fd);
-fd_t internal_open(const char *filename, bool write);
+
+// Use __sanitizer::OpenFile() instead.
+fd_t internal_open(const char *filename, int flags);
+fd_t internal_open(const char *filename, int flags, u32 mode);
+
 uptr internal_read(fd_t fd, void *buf, uptr count);
 uptr internal_write(fd_t fd, const void *buf, uptr count);
 uptr internal_filesize(fd_t fd);  // -1 on error.
+int internal_stat(const char *path, void *buf);
+int internal_lstat(const char *path, void *buf);
+int internal_fstat(fd_t fd, void *buf);
+
 int internal_dup2(int oldfd, int newfd);
 uptr internal_readlink(const char *path, char *buf, uptr bufsize);
 int internal_snprintf(char *buffer, uptr length, const char *format, ...);
Index: libsanitizer/sanitizer_common/sanitizer_common_interceptors.inc
===================================================================
--- libsanitizer/sanitizer_common/sanitizer_common_interceptors.inc	(revision 195997)
+++ libsanitizer/sanitizer_common/sanitizer_common_interceptors.inc	(working copy)
@@ -22,9 +22,13 @@
 
 #include <stdarg.h>
 
+#ifdef _WIN32
+#define va_copy(dst, src) ((dst) = (src))
+#endif // _WIN32
+
 #if SANITIZER_INTERCEPT_READ
 INTERCEPTOR(SSIZE_T, read, int fd, void *ptr, SIZE_T count) {
-  void* ctx;
+  void *ctx;
   COMMON_INTERCEPTOR_ENTER(ctx, read, fd, ptr, count);
   SSIZE_T res = REAL(read)(fd, ptr, count);
   if (res > 0)
@@ -33,14 +37,14 @@
     COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd);
   return res;
 }
-# define INIT_READ INTERCEPT_FUNCTION(read)
+#define INIT_READ INTERCEPT_FUNCTION(read)
 #else
-# define INIT_READ
+#define INIT_READ
 #endif
 
 #if SANITIZER_INTERCEPT_PREAD
 INTERCEPTOR(SSIZE_T, pread, int fd, void *ptr, SIZE_T count, OFF_T offset) {
-  void* ctx;
+  void *ctx;
   COMMON_INTERCEPTOR_ENTER(ctx, pread, fd, ptr, count, offset);
   SSIZE_T res = REAL(pread)(fd, ptr, count, offset);
   if (res > 0)
@@ -49,14 +53,14 @@
     COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd);
   return res;
 }
-# define INIT_PREAD INTERCEPT_FUNCTION(pread)
+#define INIT_PREAD INTERCEPT_FUNCTION(pread)
 #else
-# define INIT_PREAD
+#define INIT_PREAD
 #endif
 
 #if SANITIZER_INTERCEPT_PREAD64
 INTERCEPTOR(SSIZE_T, pread64, int fd, void *ptr, SIZE_T count, OFF64_T offset) {
-  void* ctx;
+  void *ctx;
   COMMON_INTERCEPTOR_ENTER(ctx, pread64, fd, ptr, count, offset);
   SSIZE_T res = REAL(pread64)(fd, ptr, count, offset);
   if (res > 0)
@@ -65,14 +69,14 @@
     COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd);
   return res;
 }
-# define INIT_PREAD64 INTERCEPT_FUNCTION(pread64)
+#define INIT_PREAD64 INTERCEPT_FUNCTION(pread64)
 #else
-# define INIT_PREAD64
+#define INIT_PREAD64
 #endif
 
 #if SANITIZER_INTERCEPT_WRITE
 INTERCEPTOR(SSIZE_T, write, int fd, void *ptr, SIZE_T count) {
-  void* ctx;
+  void *ctx;
   COMMON_INTERCEPTOR_ENTER(ctx, write, fd, ptr, count);
   if (fd >= 0)
     COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd);
@@ -81,142 +85,154 @@
     COMMON_INTERCEPTOR_READ_RANGE(ctx, ptr, res);
   return res;
 }
-# define INIT_WRITE INTERCEPT_FUNCTION(write)
+#define INIT_WRITE INTERCEPT_FUNCTION(write)
 #else
-# define INIT_WRITE
+#define INIT_WRITE
 #endif
 
 #if SANITIZER_INTERCEPT_PWRITE
-INTERCEPTOR(SSIZE_T, pwrite, int fd, void *ptr, SIZE_T count) {
-  void* ctx;
-  COMMON_INTERCEPTOR_ENTER(ctx, pwrite, fd, ptr, count);
+INTERCEPTOR(SSIZE_T, pwrite, int fd, void *ptr, SIZE_T count, OFF_T offset) {
+  void *ctx;
+  COMMON_INTERCEPTOR_ENTER(ctx, pwrite, fd, ptr, count, offset);
   if (fd >= 0)
     COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd);
-  SSIZE_T res = REAL(pwrite)(fd, ptr, count);
+  SSIZE_T res = REAL(pwrite)(fd, ptr, count, offset);
   if (res > 0)
     COMMON_INTERCEPTOR_READ_RANGE(ctx, ptr, res);
   return res;
 }
-# define INIT_PWRITE INTERCEPT_FUNCTION(pwrite)
+#define INIT_PWRITE INTERCEPT_FUNCTION(pwrite)
 #else
-# define INIT_PWRITE
+#define INIT_PWRITE
 #endif
 
 #if SANITIZER_INTERCEPT_PWRITE64
-INTERCEPTOR(SSIZE_T, pwrite64, int fd, void *ptr, OFF64_T count) {
-  void* ctx;
-  COMMON_INTERCEPTOR_ENTER(ctx, pwrite64, fd, ptr, count);
+INTERCEPTOR(SSIZE_T, pwrite64, int fd, void *ptr, OFF64_T count,
+            OFF64_T offset) {
+  void *ctx;
+  COMMON_INTERCEPTOR_ENTER(ctx, pwrite64, fd, ptr, count, offset);
   if (fd >= 0)
     COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd);
-  SSIZE_T res = REAL(pwrite64)(fd, ptr, count);
+  SSIZE_T res = REAL(pwrite64)(fd, ptr, count, offset);
   if (res > 0)
     COMMON_INTERCEPTOR_READ_RANGE(ctx, ptr, res);
   return res;
 }
-# define INIT_PWRITE64 INTERCEPT_FUNCTION(pwrite64)
+#define INIT_PWRITE64 INTERCEPT_FUNCTION(pwrite64)
 #else
-# define INIT_PWRITE64
+#define INIT_PWRITE64
 #endif
 
 #if SANITIZER_INTERCEPT_PRCTL
-INTERCEPTOR(int, prctl, int option,
-            unsigned long arg2, unsigned long arg3,  // NOLINT
-            unsigned long arg4, unsigned long arg5) {  // NOLINT
-  void* ctx;
+INTERCEPTOR(int, prctl, int option, unsigned long arg2,
+            unsigned long arg3,                       // NOLINT
+            unsigned long arg4, unsigned long arg5) { // NOLINT
+  void *ctx;
   COMMON_INTERCEPTOR_ENTER(ctx, prctl, option, arg2, arg3, arg4, arg5);
   static const int PR_SET_NAME = 15;
   int res = REAL(prctl(option, arg2, arg3, arg4, arg5));
   if (option == PR_SET_NAME) {
     char buff[16];
-    internal_strncpy(buff, (char*)arg2, 15);
+    internal_strncpy(buff, (char *)arg2, 15);
     buff[15] = 0;
     COMMON_INTERCEPTOR_SET_THREAD_NAME(ctx, buff);
   }
   return res;
 }
-# define INIT_PRCTL INTERCEPT_FUNCTION(prctl)
+#define INIT_PRCTL INTERCEPT_FUNCTION(prctl)
 #else
-# define INIT_PRCTL
-#endif  // SANITIZER_INTERCEPT_PRCTL
+#define INIT_PRCTL
+#endif // SANITIZER_INTERCEPT_PRCTL
 
-
 #if SANITIZER_INTERCEPT_SCANF
 
 #include "sanitizer_common_interceptors_scanf.inc"
 
-INTERCEPTOR(int, vscanf, const char *format, va_list ap) {  // NOLINT
-  void* ctx;
-  COMMON_INTERCEPTOR_ENTER(ctx, vscanf, format, ap);
-  scanf_common(ctx, format, ap);
-  int res = REAL(vscanf)(format, ap);  // NOLINT
-  return res;
-}
+#define VSCANF_INTERCEPTOR_IMPL(vname, allowGnuMalloc, ...)                    \
+  {                                                                            \
+    void *ctx;                                                                 \
+    COMMON_INTERCEPTOR_ENTER(ctx, vname, __VA_ARGS__);                         \
+    va_list aq;                                                                \
+    va_copy(aq, ap);                                                           \
+    int res = REAL(vname)(__VA_ARGS__);                                        \
+    if (res > 0)                                                               \
+      scanf_common(ctx, res, allowGnuMalloc, format, aq);                      \
+    va_end(aq);                                                                \
+    return res;                                                                \
+  }
 
-INTERCEPTOR(int, vsscanf, const char *str, const char *format,  // NOLINT
-    va_list ap) {
-  void* ctx;
-  COMMON_INTERCEPTOR_ENTER(ctx, vsscanf, str, format, ap);
-  scanf_common(ctx, format, ap);
-  int res = REAL(vsscanf)(str, format, ap);  // NOLINT
-  // FIXME: read of str
-  return res;
-}
+INTERCEPTOR(int, vscanf, const char *format, va_list ap)
+VSCANF_INTERCEPTOR_IMPL(vscanf, true, format, ap)
 
-INTERCEPTOR(int, vfscanf, void *stream, const char *format,  // NOLINT
-    va_list ap) {
-  void* ctx;
-  COMMON_INTERCEPTOR_ENTER(ctx, vfscanf, stream, format, ap);
-  scanf_common(ctx, format, ap);
-  int res = REAL(vfscanf)(stream, format, ap);  // NOLINT
-  return res;
-}
+INTERCEPTOR(int, vsscanf, const char *str, const char *format, va_list ap)
+VSCANF_INTERCEPTOR_IMPL(vsscanf, true, str, format, ap)
 
-INTERCEPTOR(int, scanf, const char *format, ...) {  // NOLINT
-  void* ctx;
-  COMMON_INTERCEPTOR_ENTER(ctx, scanf, format);
-  va_list ap;
-  va_start(ap, format);
-  int res = vscanf(format, ap);  // NOLINT
-  va_end(ap);
-  return res;
-}
+INTERCEPTOR(int, vfscanf, void *stream, const char *format, va_list ap)
+VSCANF_INTERCEPTOR_IMPL(vfscanf, true, stream, format, ap)
 
-INTERCEPTOR(int, fscanf, void* stream, const char *format, ...) {  // NOLINT
-  void* ctx;
-  COMMON_INTERCEPTOR_ENTER(ctx, fscanf, stream, format);
-  va_list ap;
-  va_start(ap, format);
-  int res = vfscanf(stream, format, ap);  // NOLINT
-  va_end(ap);
-  return res;
-}
+INTERCEPTOR(int, __isoc99_vscanf, const char *format, va_list ap)
+VSCANF_INTERCEPTOR_IMPL(__isoc99_vscanf, false, format, ap)
 
-INTERCEPTOR(int, sscanf, const char *str, const char *format, ...) {  // NOLINT
-  void* ctx;
-  COMMON_INTERCEPTOR_ENTER(ctx, sscanf, str, format);  // NOLINT
-  va_list ap;
-  va_start(ap, format);
-  int res = vsscanf(str, format, ap);  // NOLINT
-  va_end(ap);
-  return res;
-}
+INTERCEPTOR(int, __isoc99_vsscanf, const char *str, const char *format,
+            va_list ap)
+VSCANF_INTERCEPTOR_IMPL(__isoc99_vsscanf, false, str, format, ap)
 
-#define INIT_SCANF \
-  INTERCEPT_FUNCTION(scanf);                    \
-  INTERCEPT_FUNCTION(sscanf);  /* NOLINT */     \
-  INTERCEPT_FUNCTION(fscanf);                   \
-  INTERCEPT_FUNCTION(vscanf);                   \
-  INTERCEPT_FUNCTION(vsscanf);                  \
-  INTERCEPT_FUNCTION(vfscanf)
+INTERCEPTOR(int, __isoc99_vfscanf, void *stream, const char *format, va_list ap)
+VSCANF_INTERCEPTOR_IMPL(__isoc99_vfscanf, false, stream, format, ap)
 
+#define SCANF_INTERCEPTOR_IMPL(name, vname, ...)                               \
+  {                                                                            \
+    void *ctx;                                                                 \
+    COMMON_INTERCEPTOR_ENTER(ctx, name, __VA_ARGS__);                          \
+    va_list ap;                                                                \
+    va_start(ap, format);                                                      \
+    int res = vname(__VA_ARGS__, ap);                                          \
+    va_end(ap);                                                                \
+    return res;                                                                \
+  }
+
+INTERCEPTOR(int, scanf, const char *format, ...)
+SCANF_INTERCEPTOR_IMPL(scanf, vscanf, format)
+
+INTERCEPTOR(int, fscanf, void *stream, const char *format, ...)
+SCANF_INTERCEPTOR_IMPL(fscanf, vfscanf, stream, format)
+
+INTERCEPTOR(int, sscanf, const char *str, const char *format, ...)
+SCANF_INTERCEPTOR_IMPL(sscanf, vsscanf, str, format)
+
+INTERCEPTOR(int, __isoc99_scanf, const char *format, ...)
+SCANF_INTERCEPTOR_IMPL(__isoc99_scanf, __isoc99_vscanf, format)
+
+INTERCEPTOR(int, __isoc99_fscanf, void *stream, const char *format, ...)
+SCANF_INTERCEPTOR_IMPL(__isoc99_fscanf, __isoc99_vfscanf, stream, format)
+
+INTERCEPTOR(int, __isoc99_sscanf, const char *str, const char *format, ...)
+SCANF_INTERCEPTOR_IMPL(__isoc99_sscanf, __isoc99_vsscanf, str, format)
+
+#define INIT_SCANF                                                             \
+  INTERCEPT_FUNCTION(scanf);                                                   \
+  INTERCEPT_FUNCTION(sscanf);                                                  \
+  INTERCEPT_FUNCTION(fscanf);                                                  \
+  INTERCEPT_FUNCTION(vscanf);                                                  \
+  INTERCEPT_FUNCTION(vsscanf);                                                 \
+  INTERCEPT_FUNCTION(vfscanf);                                                 \
+  INTERCEPT_FUNCTION(__isoc99_scanf);                                          \
+  INTERCEPT_FUNCTION(__isoc99_sscanf);                                         \
+  INTERCEPT_FUNCTION(__isoc99_fscanf);                                         \
+  INTERCEPT_FUNCTION(__isoc99_vscanf);                                         \
+  INTERCEPT_FUNCTION(__isoc99_vsscanf);                                        \
+  INTERCEPT_FUNCTION(__isoc99_vfscanf);
+
 #else
 #define INIT_SCANF
 #endif
 
-#define SANITIZER_COMMON_INTERCEPTORS_INIT \
-  INIT_READ;                               \
-  INIT_PREAD;                              \
-  INIT_PREAD64;                            \
-  INIT_PRCTL;                              \
-  INIT_WRITE;                              \
+#define SANITIZER_COMMON_INTERCEPTORS_INIT                                     \
+  INIT_READ;                                                                   \
+  INIT_PREAD;                                                                  \
+  INIT_PREAD64;                                                                \
+  INIT_PRCTL;                                                                  \
+  INIT_WRITE;                                                                  \
+  INIT_PWRITE;                                                                 \
+  INIT_PWRITE64;                                                               \
   INIT_SCANF;
Index: libsanitizer/sanitizer_common/sanitizer_allocator.h
===================================================================
--- libsanitizer/sanitizer_common/sanitizer_allocator.h	(revision 195997)
+++ libsanitizer/sanitizer_common/sanitizer_allocator.h	(working copy)
@@ -23,9 +23,9 @@
 
 // SizeClassMap maps allocation sizes into size classes and back.
 // Class 0 corresponds to size 0.
-// Classes 1 - 16 correspond to sizes 8 - 128 (size = class_id * 8).
-// Next 8 classes: 128 + i * 16 (i = 1 to 8).
+// Classes 1 - 16 correspond to sizes 16 to 256 (size = class_id * 16).
 // Next 8 classes: 256 + i * 32 (i = 1 to 8).
+// Next 8 classes: 512 + i * 64 (i = 1 to 8).
 // ...
 // Next 8 classes: 2^k + i * 2^(k-3) (i = 1 to 8).
 // Last class corresponds to kMaxSize = 1 << kMaxSizeLog.
@@ -40,33 +40,48 @@
 //  - (1 << kMaxBytesCachedLog) is the maximal number of bytes per size class.
 //
 // Part of output of SizeClassMap::Print():
-//    c00 => s: 0 diff: +0 00% l 0 cached: 0 0; id 0
-//    c01 => s: 8 diff: +8 00% l 3 cached: 256 2048; id 1
-//    c02 => s: 16 diff: +8 100% l 4 cached: 256 4096; id 2
-//    ...
-//    c07 => s: 56 diff: +8 16% l 5 cached: 256 14336; id 7
+// c00 => s: 0 diff: +0 00% l 0 cached: 0 0; id 0
+// c01 => s: 16 diff: +16 00% l 4 cached: 256 4096; id 1
+// c02 => s: 32 diff: +16 100% l 5 cached: 256 8192; id 2
+// c03 => s: 48 diff: +16 50% l 5 cached: 256 12288; id 3
+// c04 => s: 64 diff: +16 33% l 6 cached: 256 16384; id 4
+// c05 => s: 80 diff: +16 25% l 6 cached: 256 20480; id 5
+// c06 => s: 96 diff: +16 20% l 6 cached: 256 24576; id 6
+// c07 => s: 112 diff: +16 16% l 6 cached: 256 28672; id 7
 //
-//    c08 => s: 64 diff: +8 14% l 6 cached: 256 16384; id 8
-//    ...
-//    c15 => s: 120 diff: +8 07% l 6 cached: 256 30720; id 15
+// c08 => s: 128 diff: +16 14% l 7 cached: 256 32768; id 8
+// c09 => s: 144 diff: +16 12% l 7 cached: 256 36864; id 9
+// c10 => s: 160 diff: +16 11% l 7 cached: 256 40960; id 10
+// c11 => s: 176 diff: +16 10% l 7 cached: 256 45056; id 11
+// c12 => s: 192 diff: +16 09% l 7 cached: 256 49152; id 12
+// c13 => s: 208 diff: +16 08% l 7 cached: 256 53248; id 13
+// c14 => s: 224 diff: +16 07% l 7 cached: 256 57344; id 14
+// c15 => s: 240 diff: +16 07% l 7 cached: 256 61440; id 15
 //
-//    c16 => s: 128 diff: +8 06% l 7 cached: 256 32768; id 16
-//    c17 => s: 144 diff: +16 12% l 7 cached: 227 32688; id 17
-//    ...
-//    c23 => s: 240 diff: +16 07% l 7 cached: 136 32640; id 23
+// c16 => s: 256 diff: +16 06% l 8 cached: 256 65536; id 16
+// c17 => s: 288 diff: +32 12% l 8 cached: 227 65376; id 17
+// c18 => s: 320 diff: +32 11% l 8 cached: 204 65280; id 18
+// c19 => s: 352 diff: +32 10% l 8 cached: 186 65472; id 19
+// c20 => s: 384 diff: +32 09% l 8 cached: 170 65280; id 20
+// c21 => s: 416 diff: +32 08% l 8 cached: 157 65312; id 21
+// c22 => s: 448 diff: +32 07% l 8 cached: 146 65408; id 22
+// c23 => s: 480 diff: +32 07% l 8 cached: 136 65280; id 23
 //
-//    c24 => s: 256 diff: +16 06% l 8 cached: 128 32768; id 24
-//    c25 => s: 288 diff: +32 12% l 8 cached: 113 32544; id 25
-//    ...
-//    c31 => s: 480 diff: +32 07% l 8 cached: 68 32640; id 31
+// c24 => s: 512 diff: +32 06% l 9 cached: 128 65536; id 24
+// c25 => s: 576 diff: +64 12% l 9 cached: 113 65088; id 25
+// c26 => s: 640 diff: +64 11% l 9 cached: 102 65280; id 26
+// c27 => s: 704 diff: +64 10% l 9 cached: 93 65472; id 27
+// c28 => s: 768 diff: +64 09% l 9 cached: 85 65280; id 28
+// c29 => s: 832 diff: +64 08% l 9 cached: 78 64896; id 29
+// c30 => s: 896 diff: +64 07% l 9 cached: 73 65408; id 30
+// c31 => s: 960 diff: +64 07% l 9 cached: 68 65280; id 31
 //
-//    c32 => s: 512 diff: +32 06% l 9 cached: 64 32768; id 32
+// c32 => s: 1024 diff: +64 06% l 10 cached: 64 65536; id 32
 
-
 template <uptr kMaxSizeLog, uptr kMaxNumCachedT, uptr kMaxBytesCachedLog,
           uptr kMinBatchClassT>
 class SizeClassMap {
-  static const uptr kMinSizeLog = 3;
+  static const uptr kMinSizeLog = 4;
   static const uptr kMidSizeLog = kMinSizeLog + 4;
   static const uptr kMinSize = 1 << kMinSizeLog;
   static const uptr kMidSize = 1 << kMidSizeLog;
@@ -104,7 +119,7 @@
     if (size <= kMidSize)
       return (size + kMinSize - 1) >> kMinSizeLog;
     if (size > kMaxSize) return 0;
-    uptr l = SANITIZER_WORDSIZE - 1 - __builtin_clzl(size);
+    uptr l = MostSignificantSetBitIndex(size);
     uptr hbits = (size >> (l - S)) & M;
     uptr lbits = size & ((1 << (l - S)) - 1);
     uptr l1 = l - kMidSizeLog;
@@ -114,7 +129,7 @@
   static uptr MaxCached(uptr class_id) {
     if (class_id == 0) return 0;
     uptr n = (1UL << kMaxBytesCachedLog) / Size(class_id);
-    return Max(1UL, Min(kMaxNumCached, n));
+    return Max<uptr>(1, Min(kMaxNumCached, n));
   }
 
   static void Print() {
@@ -126,7 +141,7 @@
         Printf("\n");
       uptr d = s - prev_s;
       uptr p = prev_s ? (d * 100 / prev_s) : 0;
-      uptr l = SANITIZER_WORDSIZE - 1 - __builtin_clzl(s);
+      uptr l = MostSignificantSetBitIndex(s);
       uptr cached = MaxCached(i) * s;
       Printf("c%02zd => s: %zd diff: +%zd %02zd%% l %zd "
              "cached: %zd %zd; id %zd\n",
@@ -172,12 +187,92 @@
   }
 };
 
-typedef SizeClassMap<17, 256, 16, FIRST_32_SECOND_64(33, 36)>
+typedef SizeClassMap<17, 256, 16, FIRST_32_SECOND_64(25, 28)>
     DefaultSizeClassMap;
-typedef SizeClassMap<17, 64, 14, FIRST_32_SECOND_64(25, 28)>
+typedef SizeClassMap<17, 64, 14, FIRST_32_SECOND_64(17, 20)>
     CompactSizeClassMap;
 template<class SizeClassAllocator> struct SizeClassAllocatorLocalCache;
 
+// Memory allocator statistics
+enum AllocatorStat {
+  AllocatorStatMalloced,
+  AllocatorStatFreed,
+  AllocatorStatMmapped,
+  AllocatorStatUnmapped,
+  AllocatorStatCount
+};
+
+typedef u64 AllocatorStatCounters[AllocatorStatCount];
+
+// Per-thread stats, live in per-thread cache.
+class AllocatorStats {
+ public:
+  void Init() {
+    internal_memset(this, 0, sizeof(*this));
+  }
+
+  void Add(AllocatorStat i, u64 v) {
+    v += atomic_load(&stats_[i], memory_order_relaxed);
+    atomic_store(&stats_[i], v, memory_order_relaxed);
+  }
+
+  void Set(AllocatorStat i, u64 v) {
+    atomic_store(&stats_[i], v, memory_order_relaxed);
+  }
+
+  u64 Get(AllocatorStat i) const {
+    return atomic_load(&stats_[i], memory_order_relaxed);
+  }
+
+ private:
+  friend class AllocatorGlobalStats;
+  AllocatorStats *next_;
+  AllocatorStats *prev_;
+  atomic_uint64_t stats_[AllocatorStatCount];
+};
+
+// Global stats, used for aggregation and querying.
+class AllocatorGlobalStats : public AllocatorStats {
+ public:
+  void Init() {
+    internal_memset(this, 0, sizeof(*this));
+    next_ = this;
+    prev_ = this;
+  }
+
+  void Register(AllocatorStats *s) {
+    SpinMutexLock l(&mu_);
+    s->next_ = next_;
+    s->prev_ = this;
+    next_->prev_ = s;
+    next_ = s;
+  }
+
+  void Unregister(AllocatorStats *s) {
+    SpinMutexLock l(&mu_);
+    s->prev_->next_ = s->next_;
+    s->next_->prev_ = s->prev_;
+    for (int i = 0; i < AllocatorStatCount; i++)
+      Add(AllocatorStat(i), s->Get(AllocatorStat(i)));
+  }
+
+  void Get(AllocatorStatCounters s) const {
+    internal_memset(s, 0, AllocatorStatCount * sizeof(u64));
+    SpinMutexLock l(&mu_);
+    const AllocatorStats *stats = this;
+    for (;;) {
+      for (int i = 0; i < AllocatorStatCount; i++)
+        s[i] += stats->Get(AllocatorStat(i));
+      stats = stats->next_;
+      if (stats == this)
+        break;
+    }
+  }
+
+ private:
+  mutable SpinMutex mu_;
+};
+
 // Allocators call these callbacks on mmap/munmap.
 struct NoOpMapUnmapCallback {
   void OnMap(uptr p, uptr size) const { }
@@ -231,17 +326,18 @@
       alignment <= SizeClassMap::kMaxSize;
   }
 
-  Batch *NOINLINE AllocateBatch(AllocatorCache *c, uptr class_id) {
+  NOINLINE Batch* AllocateBatch(AllocatorStats *stat, AllocatorCache *c,
+                                uptr class_id) {
     CHECK_LT(class_id, kNumClasses);
     RegionInfo *region = GetRegionInfo(class_id);
     Batch *b = region->free_list.Pop();
     if (b == 0)
-      b = PopulateFreeList(c, class_id, region);
+      b = PopulateFreeList(stat, c, class_id, region);
     region->n_allocated += b->count;
     return b;
   }
 
-  void NOINLINE DeallocateBatch(uptr class_id, Batch *b) {
+  NOINLINE void DeallocateBatch(AllocatorStats *stat, uptr class_id, Batch *b) {
     RegionInfo *region = GetRegionInfo(class_id);
     region->free_list.Push(b);
     region->n_freed += b->count;
@@ -320,6 +416,20 @@
     }
   }
 
+  // ForceLock() and ForceUnlock() are needed to implement Darwin malloc zone
+  // introspection API.
+  void ForceLock() {
+    for (uptr i = 0; i < kNumClasses; i++) {
+      GetRegionInfo(i)->mutex.Lock();
+    }
+  }
+
+  void ForceUnlock() {
+    for (int i = (int)kNumClasses - 1; i >= 0; i--) {
+      GetRegionInfo(i)->mutex.Unlock();
+    }
+  }
+
   typedef SizeClassMap SizeClassMapT;
   static const uptr kNumClasses = SizeClassMap::kNumClasses;
   static const uptr kNumClassesRounded = SizeClassMap::kNumClassesRounded;
@@ -334,7 +444,7 @@
   // or with one element if its size is greater.
   static const uptr kPopulateSize = 1 << 14;
   // Call mmap for user memory with at least this size.
-  static const uptr kUserMapSize = 1 << 15;
+  static const uptr kUserMapSize = 1 << 16;
   // Call mmap for metadata memory with at least this size.
   static const uptr kMetaMapSize = 1 << 16;
 
@@ -368,8 +478,8 @@
     return offset / (u32)size;
   }
 
-  Batch *NOINLINE PopulateFreeList(AllocatorCache *c, uptr class_id,
-                                   RegionInfo *region) {
+  NOINLINE Batch* PopulateFreeList(AllocatorStats *stat, AllocatorCache *c,
+                                   uptr class_id, RegionInfo *region) {
     BlockingMutexLock l(&region->mutex);
     Batch *b = region->free_list.Pop();
     if (b)
@@ -386,6 +496,7 @@
         map_size += kUserMapSize;
       CHECK_GE(region->mapped_user + map_size, end_idx);
       MapWithCallback(region_beg + region->mapped_user, map_size);
+      stat->Add(AllocatorStatMmapped, map_size);
       region->mapped_user += map_size;
     }
     uptr total_count = (region->mapped_user - beg_idx - size)
@@ -467,6 +578,7 @@
     MapUnmapCallback().OnMap((uptr)res, size);
     return res;
   }
+
   void UnmapWithCallback(uptr beg, uptr size) {
     MapUnmapCallback().OnUnmap(beg, size);
     UnmapOrDie(reinterpret_cast<void *>(beg), size);
@@ -488,19 +600,20 @@
     return reinterpret_cast<void*>(meta);
   }
 
-  Batch *NOINLINE AllocateBatch(AllocatorCache *c, uptr class_id) {
+  NOINLINE Batch* AllocateBatch(AllocatorStats *stat, AllocatorCache *c,
+                                uptr class_id) {
     CHECK_LT(class_id, kNumClasses);
     SizeClassInfo *sci = GetSizeClassInfo(class_id);
     SpinMutexLock l(&sci->mutex);
     if (sci->free_list.empty())
-      PopulateFreeList(c, sci, class_id);
+      PopulateFreeList(stat, c, sci, class_id);
     CHECK(!sci->free_list.empty());
     Batch *b = sci->free_list.front();
     sci->free_list.pop_front();
     return b;
   }
 
-  void NOINLINE DeallocateBatch(uptr class_id, Batch *b) {
+  NOINLINE void DeallocateBatch(AllocatorStats *stat, uptr class_id, Batch *b) {
     CHECK_LT(class_id, kNumClasses);
     SizeClassInfo *sci = GetSizeClassInfo(class_id);
     SpinMutexLock l(&sci->mutex);
@@ -549,6 +662,20 @@
     UnmapWithCallback(reinterpret_cast<uptr>(state_), sizeof(State));
   }
 
+  // ForceLock() and ForceUnlock() are needed to implement Darwin malloc zone
+  // introspection API.
+  void ForceLock() {
+    for (uptr i = 0; i < kNumClasses; i++) {
+      GetSizeClassInfo(i)->mutex.Lock();
+    }
+  }
+
+  void ForceUnlock() {
+    for (int i = kNumClasses - 1; i >= 0; i--) {
+      GetSizeClassInfo(i)->mutex.Unlock();
+    }
+  }
+
   void PrintStats() {
   }
 
@@ -577,11 +704,12 @@
     return mem & ~(kRegionSize - 1);
   }
 
-  uptr AllocateRegion(uptr class_id) {
+  uptr AllocateRegion(AllocatorStats *stat, uptr class_id) {
     CHECK_LT(class_id, kNumClasses);
     uptr res = reinterpret_cast<uptr>(MmapAlignedOrDie(kRegionSize, kRegionSize,
                                       "SizeClassAllocator32"));
     MapUnmapCallback().OnMap(res, kRegionSize);
+    stat->Add(AllocatorStatMmapped, kRegionSize);
     CHECK_EQ(0U, (res & (kRegionSize - 1)));
     CHECK_EQ(0U, state_->possible_regions[ComputeRegionId(res)]);
     state_->possible_regions[ComputeRegionId(res)] = class_id;
@@ -593,9 +721,10 @@
     return &state_->size_class_info_array[class_id];
   }
 
-  void PopulateFreeList(AllocatorCache *c, SizeClassInfo *sci, uptr class_id) {
+  void PopulateFreeList(AllocatorStats *stat, AllocatorCache *c,
+                        SizeClassInfo *sci, uptr class_id) {
     uptr size = SizeClassMap::Size(class_id);
-    uptr reg = AllocateRegion(class_id);
+    uptr reg = AllocateRegion(stat, class_id);
     uptr n_chunks = kRegionSize / (size + kMetadataSize);
     uptr max_count = SizeClassMap::MaxCached(class_id);
     Batch *b = 0;
@@ -632,14 +761,22 @@
   typedef SizeClassAllocator Allocator;
   static const uptr kNumClasses = SizeClassAllocator::kNumClasses;
 
-  // Don't need to call Init if the object is a global (i.e. zero-initialized).
-  void Init() {
-    internal_memset(this, 0, sizeof(*this));
+  void Init(AllocatorGlobalStats *s) {
+    stats_.Init();
+    if (s)
+      s->Register(&stats_);
   }
 
+  void Destroy(SizeClassAllocator *allocator, AllocatorGlobalStats *s) {
+    Drain(allocator);
+    if (s)
+      s->Unregister(&stats_);
+  }
+
   void *Allocate(SizeClassAllocator *allocator, uptr class_id) {
     CHECK_NE(class_id, 0UL);
     CHECK_LT(class_id, kNumClasses);
+    stats_.Add(AllocatorStatMalloced, SizeClassMap::Size(class_id));
     PerClass *c = &per_class_[class_id];
     if (UNLIKELY(c->count == 0))
       Refill(allocator, class_id);
@@ -651,6 +788,7 @@
   void Deallocate(SizeClassAllocator *allocator, uptr class_id, void *p) {
     CHECK_NE(class_id, 0UL);
     CHECK_LT(class_id, kNumClasses);
+    stats_.Add(AllocatorStatFreed, SizeClassMap::Size(class_id));
     PerClass *c = &per_class_[class_id];
     if (UNLIKELY(c->count == c->max_count))
       Drain(allocator, class_id);
@@ -674,6 +812,7 @@
     void *batch[2 * SizeClassMap::kMaxNumCached];
   };
   PerClass per_class_[kNumClasses];
+  AllocatorStats stats_;
 
   void InitCache() {
     if (per_class_[0].max_count)
@@ -684,10 +823,11 @@
     }
   }
 
-  void NOINLINE Refill(SizeClassAllocator *allocator, uptr class_id) {
+  NOINLINE void Refill(SizeClassAllocator *allocator, uptr class_id) {
     InitCache();
     PerClass *c = &per_class_[class_id];
-    Batch *b = allocator->AllocateBatch(this, class_id);
+    Batch *b = allocator->AllocateBatch(&stats_, this, class_id);
+    CHECK_GT(b->count, 0);
     for (uptr i = 0; i < b->count; i++)
       c->batch[i] = b->batch[i];
     c->count = b->count;
@@ -695,7 +835,7 @@
       Deallocate(allocator, SizeClassMap::ClassID(sizeof(Batch)), b);
   }
 
-  void NOINLINE Drain(SizeClassAllocator *allocator, uptr class_id) {
+  NOINLINE void Drain(SizeClassAllocator *allocator, uptr class_id) {
     InitCache();
     PerClass *c = &per_class_[class_id];
     Batch *b;
@@ -710,7 +850,7 @@
     }
     b->count = cnt;
     c->count -= cnt;
-    allocator->DeallocateBatch(class_id, b);
+    allocator->DeallocateBatch(&stats_, class_id, b);
   }
 };
 
@@ -725,7 +865,7 @@
     page_size_ = GetPageSizeCached();
   }
 
-  void *Allocate(uptr size, uptr alignment) {
+  void *Allocate(AllocatorStats *stat, uptr size, uptr alignment) {
     CHECK(IsPowerOfTwo(alignment));
     uptr map_size = RoundUpMapSize(size);
     if (alignment > page_size_)
@@ -744,7 +884,7 @@
     h->size = size;
     h->map_beg = map_beg;
     h->map_size = map_size;
-    uptr size_log = SANITIZER_WORDSIZE - __builtin_clzl(map_size) - 1;
+    uptr size_log = MostSignificantSetBitIndex(map_size);
     CHECK_LT(size_log, ARRAY_SIZE(stats.by_size_log));
     {
       SpinMutexLock l(&mutex_);
@@ -756,11 +896,13 @@
       stats.currently_allocated += map_size;
       stats.max_allocated = Max(stats.max_allocated, stats.currently_allocated);
       stats.by_size_log[size_log]++;
+      stat->Add(AllocatorStatMalloced, map_size);
+      stat->Add(AllocatorStatMmapped, map_size);
     }
     return reinterpret_cast<void*>(res);
   }
 
-  void Deallocate(void *p) {
+  void Deallocate(AllocatorStats *stat, void *p) {
     Header *h = GetHeader(p);
     {
       SpinMutexLock l(&mutex_);
@@ -772,6 +914,8 @@
       n_chunks_--;
       stats.n_frees++;
       stats.currently_allocated -= h->map_size;
+      stat->Add(AllocatorStatFreed, h->map_size);
+      stat->Add(AllocatorStatUnmapped, h->map_size);
     }
     MapUnmapCallback().OnUnmap(h->map_beg, h->map_size);
     UnmapOrDie(reinterpret_cast<void*>(h->map_beg), h->map_size);
@@ -838,6 +982,16 @@
     Printf("\n");
   }
 
+  // ForceLock() and ForceUnlock() are needed to implement Darwin malloc zone
+  // introspection API.
+  void ForceLock() {
+    mutex_.Lock();
+  }
+
+  void ForceUnlock() {
+    mutex_.Unlock();
+  }
+
  private:
   static const int kMaxNumChunks = 1 << FIRST_32_SECOND_64(15, 18);
   struct Header {
@@ -884,6 +1038,7 @@
   void Init() {
     primary_.Init();
     secondary_.Init();
+    stats_.Init();
   }
 
   void *Allocate(AllocatorCache *cache, uptr size, uptr alignment,
@@ -899,7 +1054,7 @@
     if (primary_.CanAllocate(size, alignment))
       res = cache->Allocate(&primary_, primary_.ClassID(size));
     else
-      res = secondary_.Allocate(size, alignment);
+      res = secondary_.Allocate(&stats_, size, alignment);
     if (alignment > 8)
       CHECK_EQ(reinterpret_cast<uptr>(res) & (alignment - 1), 0);
     if (cleared && res)
@@ -912,7 +1067,7 @@
     if (primary_.PointerIsMine(p))
       cache->Deallocate(&primary_, primary_.GetSizeClass(p), p);
     else
-      secondary_.Deallocate(p);
+      secondary_.Deallocate(&stats_, p);
   }
 
   void *Reallocate(AllocatorCache *cache, void *p, uptr new_size,
@@ -967,20 +1122,48 @@
 
   void TestOnlyUnmap() { primary_.TestOnlyUnmap(); }
 
+  void InitCache(AllocatorCache *cache) {
+    cache->Init(&stats_);
+  }
+
+  void DestroyCache(AllocatorCache *cache) {
+    cache->Destroy(&primary_, &stats_);
+  }
+
   void SwallowCache(AllocatorCache *cache) {
     cache->Drain(&primary_);
   }
 
+  void GetStats(AllocatorStatCounters s) const {
+    stats_.Get(s);
+  }
+
   void PrintStats() {
     primary_.PrintStats();
     secondary_.PrintStats();
   }
 
+  // ForceLock() and ForceUnlock() are needed to implement Darwin malloc zone
+  // introspection API.
+  void ForceLock() {
+    primary_.ForceLock();
+    secondary_.ForceLock();
+  }
+
+  void ForceUnlock() {
+    secondary_.ForceUnlock();
+    primary_.ForceUnlock();
+  }
+
  private:
   PrimaryAllocator primary_;
   SecondaryAllocator secondary_;
+  AllocatorGlobalStats stats_;
 };
 
+// Returns true if calloc(size, n) should return 0 due to overflow in size*n.
+bool CallocShouldReturnNullDueToOverflow(uptr size, uptr n);
+
 }  // namespace __sanitizer
 
 #endif  // SANITIZER_ALLOCATOR_H
Index: libsanitizer/asan/asan_intercepted_functions.h
===================================================================
--- libsanitizer/asan/asan_intercepted_functions.h	(revision 195997)
+++ libsanitizer/asan/asan_intercepted_functions.h	(working copy)
@@ -17,6 +17,7 @@
 #include "sanitizer_common/sanitizer_platform_interceptors.h"
 
 #include <stdarg.h>
+#include <stddef.h>
 
 using __sanitizer::uptr;
 
@@ -64,9 +65,7 @@
 # define ASAN_INTERCEPT_SIGNAL_AND_SIGACTION 0
 #endif
 
-// On Darwin siglongjmp tailcalls longjmp, so we don't want to intercept it
-// there.
-#if !defined(_WIN32) && (!defined(__APPLE__) || MAC_INTERPOSE_FUNCTIONS)
+#if !defined(_WIN32)
 # define ASAN_INTERCEPT_SIGLONGJMP 1
 #else
 # define ASAN_INTERCEPT_SIGLONGJMP 0
@@ -169,7 +168,8 @@
 DECLARE_FUNCTION_AND_WRAPPER(SSIZE_T, write, int fd, void *ptr, SIZE_T count);
 # endif
 # if SANITIZER_INTERCEPT_PWRITE
-DECLARE_FUNCTION_AND_WRAPPER(SSIZE_T, pwrite, int fd, void *ptr, SIZE_T count);
+DECLARE_FUNCTION_AND_WRAPPER(SSIZE_T, pwrite,
+                             int fd, void *ptr, SIZE_T count, OFF_T offset);
 # endif
 
 # if ASAN_INTERCEPT_MLOCKX
@@ -193,6 +193,8 @@
                              void *(*start_routine)(void*), void *arg);
 # endif
 
+// stdio.h
+# if SANITIZER_INTERCEPT_SCANF
 DECLARE_FUNCTION_AND_WRAPPER(int, vscanf, const char *format, va_list ap);
 DECLARE_FUNCTION_AND_WRAPPER(int, vsscanf, const char *str, const char *format,
                              va_list ap);
@@ -203,6 +205,18 @@
                              void* stream, const char *format, ...);
 DECLARE_FUNCTION_AND_WRAPPER(int, sscanf,  // NOLINT
                              const char *str, const char *format, ...);
+DECLARE_FUNCTION_AND_WRAPPER(int, __isoc99_vscanf, const char *format,
+                             va_list ap);
+DECLARE_FUNCTION_AND_WRAPPER(int, __isoc99_vsscanf, const char *str,
+                             const char *format, va_list ap);
+DECLARE_FUNCTION_AND_WRAPPER(int, __isoc99_vfscanf, void *stream,
+                             const char *format, va_list ap);
+DECLARE_FUNCTION_AND_WRAPPER(int, __isoc99_scanf, const char *format, ...);
+DECLARE_FUNCTION_AND_WRAPPER(int, __isoc99_fscanf,
+                             void* stream, const char *format, ...);
+DECLARE_FUNCTION_AND_WRAPPER(int, __isoc99_sscanf,  // NOLINT
+                             const char *str, const char *format, ...);
+# endif
 
 # if defined(__APPLE__)
 typedef void* pthread_workqueue_t;
@@ -231,7 +245,7 @@
                              dispatch_group_t group, dispatch_queue_t dq,
                              void *ctxt, dispatch_function_t func);
 
-#  if MAC_INTERPOSE_FUNCTIONS && !defined(MISSING_BLOCKS_SUPPORT)
+#  if !defined(MISSING_BLOCKS_SUPPORT)
 DECLARE_FUNCTION_AND_WRAPPER(void, dispatch_group_async,
                              dispatch_group_t dg,
                              dispatch_queue_t dq, void (^work)(void));
@@ -243,7 +257,7 @@
                              dispatch_source_t ds, void (^work)(void));
 DECLARE_FUNCTION_AND_WRAPPER(void, dispatch_source_set_cancel_handler,
                              dispatch_source_t ds, void (^work)(void));
-#  endif  // MAC_INTERPOSE_FUNCTIONS
+#  endif  // MISSING_BLOCKS_SUPPORT
 
 typedef void malloc_zone_t;
 typedef size_t vm_size_t;
Index: libsanitizer/asan/asan_rtl.cc
===================================================================
--- libsanitizer/asan/asan_rtl.cc	(revision 195997)
+++ libsanitizer/asan/asan_rtl.cc	(working copy)
@@ -18,7 +18,6 @@
 #include "asan_stats.h"
 #include "asan_thread.h"
 #include "asan_thread_registry.h"
-#include "sanitizer/asan_interface.h"
 #include "sanitizer_common/sanitizer_atomic.h"
 #include "sanitizer_common/sanitizer_flags.h"
 #include "sanitizer_common/sanitizer_libc.h"
@@ -83,7 +82,6 @@
 
   ParseFlag(str, &f->replace_str, "replace_str");
   ParseFlag(str, &f->replace_intrin, "replace_intrin");
-  ParseFlag(str, &f->replace_cfallocator, "replace_cfallocator");
   ParseFlag(str, &f->mac_ignore_invalid_free, "mac_ignore_invalid_free");
   ParseFlag(str, &f->use_fake_stack, "use_fake_stack");
   ParseFlag(str, &f->max_malloc_fill_size, "max_malloc_fill_size");
@@ -95,6 +93,8 @@
   ParseFlag(str, &f->check_malloc_usable_size, "check_malloc_usable_size");
   ParseFlag(str, &f->unmap_shadow_on_exit, "unmap_shadow_on_exit");
   ParseFlag(str, &f->abort_on_error, "abort_on_error");
+  ParseFlag(str, &f->print_stats, "print_stats");
+  ParseFlag(str, &f->print_legend, "print_legend");
   ParseFlag(str, &f->atexit, "atexit");
   ParseFlag(str, &f->disable_core, "disable_core");
   ParseFlag(str, &f->strip_path_prefix, "strip_path_prefix");
@@ -121,7 +121,6 @@
   f->malloc_context_size = kDeafultMallocContextSize;
   f->replace_str = true;
   f->replace_intrin = true;
-  f->replace_cfallocator = true;
   f->mac_ignore_invalid_free = false;
   f->use_fake_stack = true;
   f->max_malloc_fill_size = 0;
@@ -133,6 +132,8 @@
   f->check_malloc_usable_size = true;
   f->unmap_shadow_on_exit = false;
   f->abort_on_error = false;
+  f->print_stats = false;
+  f->print_legend = true;
   f->atexit = false;
   f->disable_core = (SANITIZER_WORDSIZE == 64);
   f->strip_path_prefix = "";
@@ -142,9 +143,7 @@
   f->fast_unwind_on_fatal = false;
   f->fast_unwind_on_malloc = true;
   f->poison_heap = true;
-  // Turn off alloc/dealloc mismatch checker on Mac for now.
-  // TODO(glider): Fix known issues and enable this back.
-  f->alloc_dealloc_mismatch = (ASAN_MAC == 0);
+  f->alloc_dealloc_mismatch = true;
   f->use_stack_depot = true;  // Only affects allocator2.
 
   // Override from user-specified string.
@@ -162,6 +161,7 @@
 int asan_inited;
 bool asan_init_is_running;
 void (*death_callback)(void);
+uptr kHighMemEnd;
 
 // -------------------------- Misc ---------------- {{{1
 void ShowStatsAndAbort() {
@@ -261,6 +261,24 @@
   __asan_print_accumulated_stats();
 }
 
+static void InitializeHighMemEnd() {
+#if SANITIZER_WORDSIZE == 64
+# if defined(__powerpc64__)
+  // FIXME:
+  // On PowerPC64 we have two different address space layouts: 44- and 46-bit.
+  // We somehow need to figure our which one we are using now and choose
+  // one of 0x00000fffffffffffUL and 0x00003fffffffffffUL.
+  // Note that with 'ulimit -s unlimited' the stack is moved away from the top
+  // of the address space, so simply checking the stack address is not enough.
+  kHighMemEnd = (1ULL << 44) - 1;  // 0x00000fffffffffffUL
+# else
+  kHighMemEnd = (1ULL << 47) - 1;  // 0x00007fffffffffffUL;
+# endif
+#else  // SANITIZER_WORDSIZE == 32
+  kHighMemEnd = (1ULL << 32) - 1;  // 0xffffffff;
+#endif  // SANITIZER_WORDSIZE
+}
+
 }  // namespace __asan
 
 // ---------------------- Interface ---------------- {{{1
@@ -295,8 +313,10 @@
 
 void __asan_init() {
   if (asan_inited) return;
+  SanitizerToolName = "AddressSanitizer";
   CHECK(!asan_init_is_running && "ASan init calls itself!");
   asan_init_is_running = true;
+  InitializeHighMemEnd();
 
   // Make sure we are not statically linked.
   AsanDoesNotSupportStaticLinkage();
@@ -400,6 +420,8 @@
   asanThreadRegistry().GetMain()->ThreadStart();
   force_interface_symbols();  // no-op.
 
+  InitializeAllocator();
+
   if (flags()->verbosity) {
     Report("AddressSanitizer Init done\n");
   }
Index: libsanitizer/asan/asan_poisoning.cc
===================================================================
--- libsanitizer/asan/asan_poisoning.cc	(revision 195997)
+++ libsanitizer/asan/asan_poisoning.cc	(working copy)
@@ -13,7 +13,6 @@
 #include "asan_interceptors.h"
 #include "asan_internal.h"
 #include "asan_mapping.h"
-#include "sanitizer/asan_interface.h"
 #include "sanitizer_common/sanitizer_libc.h"
 
 namespace __asan {
Index: libsanitizer/asan/asan_new_delete.cc
===================================================================
--- libsanitizer/asan/asan_new_delete.cc	(revision 195997)
+++ libsanitizer/asan/asan_new_delete.cc	(working copy)
@@ -25,9 +25,9 @@
 
 using namespace __asan;  // NOLINT
 
-// On Mac and Android new() goes through malloc interceptors.
+// On Android new() goes through malloc interceptors.
 // See also https://code.google.com/p/address-sanitizer/issues/detail?id=131.
-#if !ASAN_ANDROID && !ASAN_MAC
+#if !ASAN_ANDROID
 
 // Fake std::nothrow_t to avoid including <new>.
 namespace std {
Index: libsanitizer/asan/asan_report.h
===================================================================
--- libsanitizer/asan/asan_report.h	(revision 195997)
+++ libsanitizer/asan/asan_report.h	(working copy)
@@ -13,15 +13,15 @@
 #include "asan_allocator.h"
 #include "asan_internal.h"
 #include "asan_thread.h"
-#include "sanitizer/asan_interface.h"
 
 namespace __asan {
 
 // The following functions prints address description depending
 // on the memory type (shadow/heap/stack/global).
 void DescribeHeapAddress(uptr addr, uptr access_size);
-bool DescribeAddressIfGlobal(uptr addr);
-bool DescribeAddressRelativeToGlobal(uptr addr, const __asan_global &g);
+bool DescribeAddressIfGlobal(uptr addr, uptr access_size);
+bool DescribeAddressRelativeToGlobal(uptr addr, uptr access_size,
+                                     const __asan_global &g);
 bool DescribeAddressIfShadow(uptr addr);
 bool DescribeAddressIfStack(uptr addr, uptr access_size);
 // Determines memory type on its own.
Index: libsanitizer/asan/asan_internal.h
===================================================================
--- libsanitizer/asan/asan_internal.h	(revision 195997)
+++ libsanitizer/asan/asan_internal.h	(working copy)
@@ -13,6 +13,7 @@
 #define ASAN_INTERNAL_H
 
 #include "asan_flags.h"
+#include "asan_interface_internal.h"
 #include "sanitizer_common/sanitizer_common.h"
 #include "sanitizer_common/sanitizer_internal_defs.h"
 #include "sanitizer_common/sanitizer_stacktrace.h"
Index: libsanitizer/asan/asan_globals.cc
===================================================================
--- libsanitizer/asan/asan_globals.cc	(revision 195997)
+++ libsanitizer/asan/asan_globals.cc	(working copy)
@@ -16,7 +16,6 @@
 #include "asan_stack.h"
 #include "asan_stats.h"
 #include "asan_thread.h"
-#include "sanitizer/asan_interface.h"
 #include "sanitizer_common/sanitizer_mutex.h"
 
 namespace __asan {
@@ -34,26 +33,20 @@
 static ListOfGlobals *list_of_dynamic_init_globals;
 
 void PoisonRedZones(const Global &g)  {
-  uptr shadow_rz_size = kGlobalAndStackRedzone >> SHADOW_SCALE;
-  CHECK(shadow_rz_size == 1 || shadow_rz_size == 2 || shadow_rz_size == 4);
-  // full right redzone
-  uptr g_aligned_size = kGlobalAndStackRedzone *
-      ((g.size + kGlobalAndStackRedzone - 1) / kGlobalAndStackRedzone);
-  PoisonShadow(g.beg + g_aligned_size,
-               kGlobalAndStackRedzone, kAsanGlobalRedzoneMagic);
-  if ((g.size % kGlobalAndStackRedzone) != 0) {
+  uptr aligned_size = RoundUpTo(g.size, SHADOW_GRANULARITY);
+  PoisonShadow(g.beg + aligned_size, g.size_with_redzone - aligned_size,
+               kAsanGlobalRedzoneMagic);
+  if (g.size != aligned_size) {
     // partial right redzone
-    u64 g_aligned_down_size = kGlobalAndStackRedzone *
-        (g.size / kGlobalAndStackRedzone);
-    CHECK(g_aligned_down_size == g_aligned_size - kGlobalAndStackRedzone);
-    PoisonShadowPartialRightRedzone(g.beg + g_aligned_down_size,
-                                    g.size % kGlobalAndStackRedzone,
-                                    kGlobalAndStackRedzone,
-                                    kAsanGlobalRedzoneMagic);
+    PoisonShadowPartialRightRedzone(
+        g.beg + RoundDownTo(g.size, SHADOW_GRANULARITY),
+        g.size % SHADOW_GRANULARITY,
+        SHADOW_GRANULARITY,
+        kAsanGlobalRedzoneMagic);
   }
 }
 
-bool DescribeAddressIfGlobal(uptr addr) {
+bool DescribeAddressIfGlobal(uptr addr, uptr size) {
   if (!flags()->report_globals) return false;
   BlockingMutexLock lock(&mu_for_globals);
   bool res = false;
@@ -62,7 +55,7 @@
     if (flags()->report_globals >= 2)
       Report("Search Global: beg=%p size=%zu name=%s\n",
              (void*)g.beg, g.size, (char*)g.name);
-    res |= DescribeAddressRelativeToGlobal(addr, g);
+    res |= DescribeAddressRelativeToGlobal(addr, size, g);
   }
   return res;
 }
Index: libsanitizer/asan/asan_interceptors.h
===================================================================
--- libsanitizer/asan/asan_interceptors.h	(revision 195997)
+++ libsanitizer/asan/asan_interceptors.h	(working copy)
@@ -30,9 +30,6 @@
 namespace __asan {
 
 void InitializeAsanInterceptors();
-#if defined(__APPLE__)
-void InitializeMacInterceptors();
-#endif  // __APPLE__
 
 }  // namespace __asan
 
Index: libsanitizer/asan/asan_malloc_linux.cc
===================================================================
--- libsanitizer/asan/asan_malloc_linux.cc	(revision 195997)
+++ libsanitizer/asan/asan_malloc_linux.cc	(working copy)
@@ -18,7 +18,6 @@
 #include "asan_internal.h"
 #include "asan_stack.h"
 #include "asan_thread_registry.h"
-#include "sanitizer/asan_interface.h"
 
 #if ASAN_ANDROID
 DECLARE_REAL_AND_INTERCEPTOR(void*, malloc, uptr size)
Index: libsanitizer/asan/asan_mapping.h
===================================================================
--- libsanitizer/asan/asan_mapping.h	(revision 195997)
+++ libsanitizer/asan/asan_mapping.h	(working copy)
@@ -34,27 +34,16 @@
 #   if defined(__powerpc64__)
 #    define SHADOW_OFFSET (1ULL << 41)
 #   else
-#    define SHADOW_OFFSET (1ULL << 44)
+#    define SHADOW_OFFSET 0x7fff8000ULL
 #   endif
 #  endif
 # endif
 #endif  // ASAN_FLEXIBLE_MAPPING_AND_OFFSET
 
 #define SHADOW_GRANULARITY (1ULL << SHADOW_SCALE)
-#define MEM_TO_SHADOW(mem) (((mem) >> SHADOW_SCALE) | (SHADOW_OFFSET))
+#define MEM_TO_SHADOW(mem) (((mem) >> SHADOW_SCALE) + (SHADOW_OFFSET))
 #define SHADOW_TO_MEM(shadow) (((shadow) - SHADOW_OFFSET) << SHADOW_SCALE)
 
-#if SANITIZER_WORDSIZE == 64
-# if defined(__powerpc64__)
-  static const uptr kHighMemEnd = 0x00000fffffffffffUL;
-# else
-  static const uptr kHighMemEnd = 0x00007fffffffffffUL;
-# endif
-#else  // SANITIZER_WORDSIZE == 32
-  static const uptr kHighMemEnd = 0xffffffff;
-#endif  // SANITIZER_WORDSIZE
-
-
 #define kLowMemBeg      0
 #define kLowMemEnd      (SHADOW_OFFSET ? SHADOW_OFFSET - 1 : 0)
 
@@ -74,11 +63,11 @@
                                        : kZeroBaseShadowStart)
 #define kShadowGapEnd   (kHighShadowBeg - 1)
 
-#define kGlobalAndStackRedzone \
-      (SHADOW_GRANULARITY < 32 ? 32 : SHADOW_GRANULARITY)
-
 namespace __asan {
 
+SANITIZER_INTERFACE_ATTRIBUTE
+extern uptr kHighMemEnd;  // Initialized in __asan_init.
+
 static inline bool AddrIsInLowMem(uptr a) {
   return a < kLowMemEnd;
 }
Index: libsanitizer/asan/asan_mac.cc
===================================================================
--- libsanitizer/asan/asan_mac.cc	(revision 195997)
+++ libsanitizer/asan/asan_mac.cc	(working copy)
@@ -89,10 +89,9 @@
 
 void MaybeReexec() {
   if (!flags()->allow_reexec) return;
-#if MAC_INTERPOSE_FUNCTIONS
-  // If the program is linked with the dynamic ASan runtime library, make sure
-  // the library is preloaded so that the wrappers work. If it is not, set
-  // DYLD_INSERT_LIBRARIES and re-exec ourselves.
+  // Make sure the dynamic ASan runtime library is preloaded so that the
+  // wrappers work. If it is not, set DYLD_INSERT_LIBRARIES and re-exec
+  // ourselves.
   Dl_info info;
   CHECK(dladdr((void*)((uptr)__asan_init), &info));
   const char *dyld_insert_libraries = GetEnv(kDyldInsertLibraries);
@@ -114,8 +113,6 @@
     }
     execv(program_name, *_NSGetArgv());
   }
-#endif  // MAC_INTERPOSE_FUNCTIONS
-  // If we're not using the dynamic runtime, do nothing.
 }
 
 // No-op. Mac does not support static linkage anyway.
@@ -146,57 +143,6 @@
   UNIMPLEMENTED();
 }
 
-// The range of pages to be used for escape islands.
-// TODO(glider): instead of mapping a fixed range we must find a range of
-// unmapped pages in vmmap and take them.
-// These constants were chosen empirically and may not work if the shadow
-// memory layout changes. Unfortunately they do necessarily depend on
-// kHighMemBeg or kHighMemEnd.
-static void *island_allocator_pos = 0;
-
-#if SANITIZER_WORDSIZE == 32
-# define kIslandEnd (0xffdf0000 - GetPageSizeCached())
-# define kIslandBeg (kIslandEnd - 256 * GetPageSizeCached())
-#else
-# define kIslandEnd (0x7fffffdf0000 - GetPageSizeCached())
-# define kIslandBeg (kIslandEnd - 256 * GetPageSizeCached())
-#endif
-
-extern "C"
-mach_error_t __interception_allocate_island(void **ptr,
-                                            uptr unused_size,
-                                            void *unused_hint) {
-  if (!island_allocator_pos) {
-    island_allocator_pos =
-        internal_mmap((void*)kIslandBeg, kIslandEnd - kIslandBeg,
-                      PROT_READ | PROT_WRITE | PROT_EXEC,
-                      MAP_PRIVATE | MAP_ANON | MAP_FIXED,
-                      -1, 0);
-    if (island_allocator_pos != (void*)kIslandBeg) {
-      return KERN_NO_SPACE;
-    }
-    if (flags()->verbosity) {
-      Report("Mapped pages %p--%p for branch islands.\n",
-             (void*)kIslandBeg, (void*)kIslandEnd);
-    }
-    // Should not be very performance-critical.
-    internal_memset(island_allocator_pos, 0xCC, kIslandEnd - kIslandBeg);
-  };
-  *ptr = island_allocator_pos;
-  island_allocator_pos = (char*)island_allocator_pos + GetPageSizeCached();
-  if (flags()->verbosity) {
-    Report("Branch island allocated at %p\n", *ptr);
-  }
-  return err_none;
-}
-
-extern "C"
-mach_error_t __interception_deallocate_island(void *ptr) {
-  // Do nothing.
-  // TODO(glider): allow to free and reuse the island memory.
-  return err_none;
-}
-
 // Support for the following functions from libdispatch on Mac OS:
 //   dispatch_async_f()
 //   dispatch_async()
@@ -350,14 +296,7 @@
                                asan_dispatch_call_block_and_release);
 }
 
-#if MAC_INTERPOSE_FUNCTIONS && !defined(MISSING_BLOCKS_SUPPORT)
-// dispatch_async, dispatch_group_async and others tailcall the corresponding
-// dispatch_*_f functions. When wrapping functions with mach_override, those
-// dispatch_*_f are intercepted automatically. But with dylib interposition
-// this does not work, because the calls within the same library are not
-// interposed.
-// Therefore we need to re-implement dispatch_async and friends.
-
+#if !defined(MISSING_BLOCKS_SUPPORT)
 extern "C" {
 // FIXME: consolidate these declarations with asan_intercepted_functions.h.
 void dispatch_async(dispatch_queue_t dq, void(^work)(void));
@@ -410,16 +349,4 @@
 }
 #endif
 
-namespace __asan {
-
-void InitializeMacInterceptors() {
-  CHECK(INTERCEPT_FUNCTION(dispatch_async_f));
-  CHECK(INTERCEPT_FUNCTION(dispatch_sync_f));
-  CHECK(INTERCEPT_FUNCTION(dispatch_after_f));
-  CHECK(INTERCEPT_FUNCTION(dispatch_barrier_async_f));
-  CHECK(INTERCEPT_FUNCTION(dispatch_group_async_f));
-}
-
-}  // namespace __asan
-
 #endif  // __APPLE__
Index: libsanitizer/asan/asan_allocator2.cc
===================================================================
--- libsanitizer/asan/asan_allocator2.cc	(revision 195997)
+++ libsanitizer/asan/asan_allocator2.cc	(working copy)
@@ -20,7 +20,6 @@
 #include "asan_report.h"
 #include "asan_thread.h"
 #include "asan_thread_registry.h"
-#include "sanitizer/asan_interface.h"
 #include "sanitizer_common/sanitizer_allocator.h"
 #include "sanitizer_common/sanitizer_internal_defs.h"
 #include "sanitizer_common/sanitizer_list.h"
@@ -55,7 +54,11 @@
 };
 
 #if SANITIZER_WORDSIZE == 64
+#if defined(__powerpc64__)
+const uptr kAllocatorSpace =  0xa0000000000ULL;
+#else
 const uptr kAllocatorSpace = 0x600000000000ULL;
+#endif
 const uptr kAllocatorSize  =  0x10000000000ULL;  // 1T.
 typedef DefaultSizeClassMap SizeClassMap;
 typedef SizeClassAllocator64<kAllocatorSpace, kAllocatorSize, 0 /*metadata*/,
@@ -89,8 +92,6 @@
 static const uptr kMaxThreadLocalQuarantine =
   FIRST_32_SECOND_64(1 << 18, 1 << 20);
 
-static const uptr kReturnOnZeroMalloc = 2048;  // Zero page is protected.
-
 // Every chunk of memory allocated by this allocator can be in one of 3 states:
 // CHUNK_AVAILABLE: the chunk is in the free list and ready to be allocated.
 // CHUNK_ALLOCATED: the chunk is allocated and not yet freed.
@@ -112,7 +113,7 @@
   CHECK_GE(rz_size, 16);
   CHECK_LE(rz_size, 2048);
   CHECK(IsPowerOfTwo(rz_size));
-  u32 res = __builtin_ctz(rz_size) - 4;
+  u32 res = Log2(rz_size) - 4;
   CHECK_EQ(rz_size, RZLog2Size(res));
   return res;
 }
@@ -289,27 +290,26 @@
   AllocatorCache *cache_;
 };
 
-static void Init() {
-  static int inited = 0;
-  if (inited) return;
-  __asan_init();
-  inited = true;  // this must happen before any threads are created.
+void InitializeAllocator() {
   allocator.Init();
   quarantine.Init((uptr)flags()->quarantine_size, kMaxThreadLocalQuarantine);
 }
 
 static void *Allocate(uptr size, uptr alignment, StackTrace *stack,
                       AllocType alloc_type) {
-  Init();
+  if (!asan_inited)
+    __asan_init();
   CHECK(stack);
   const uptr min_alignment = SHADOW_GRANULARITY;
   if (alignment < min_alignment)
     alignment = min_alignment;
   if (size == 0) {
-    if (alignment <= kReturnOnZeroMalloc)
-      return reinterpret_cast<void *>(kReturnOnZeroMalloc);
-    else
-      return 0;  // 0 bytes with large alignment requested. Just return 0.
+    // We'd be happy to avoid allocating memory for zero-size requests, but
+    // some programs/tests depend on this behavior and assume that malloc would
+    // not return NULL even for zero-size allocations. Moreover, it looks like
+    // operator new should never return NULL, and results of consecutive "new"
+    // calls must be different even if the allocated size is zero.
+    size = 1;
   }
   CHECK(IsPowerOfTwo(alignment));
   uptr rz_log = ComputeRZLog(size);
@@ -415,7 +415,8 @@
 
 static void Deallocate(void *ptr, StackTrace *stack, AllocType alloc_type) {
   uptr p = reinterpret_cast<uptr>(ptr);
-  if (p == 0 || p == kReturnOnZeroMalloc) return;
+  if (p == 0) return;
+  ASAN_FREE_HOOK(ptr);
   uptr chunk_beg = p - kChunkHeaderSize;
   AsanChunk *m = reinterpret_cast<AsanChunk *>(chunk_beg);
 
@@ -465,8 +466,6 @@
     quarantine.Put(&fallback_quarantine_cache, QuarantineCallback(ac),
                    m, m->UsedSize());
   }
-
-  ASAN_FREE_HOOK(ptr);
 }
 
 static void *Reallocate(void *old_ptr, uptr new_size, StackTrace *stack) {
@@ -546,7 +545,7 @@
       return right_chunk;
   }
   // Same chunk_state: choose based on offset.
-  uptr l_offset = 0, r_offset = 0;
+  sptr l_offset = 0, r_offset = 0;
   CHECK(AsanChunkView(left_chunk).AddrIsAtRight(addr, 1, &l_offset));
   CHECK(AsanChunkView(right_chunk).AddrIsAtLeft(addr, 1, &r_offset));
   if (l_offset < r_offset)
@@ -557,7 +556,7 @@
 AsanChunkView FindHeapChunkByAddress(uptr addr) {
   AsanChunk *m1 = GetAsanChunkByAddr(addr);
   if (!m1) return AsanChunkView(m1);
-  uptr offset = 0;
+  sptr offset = 0;
   if (AsanChunkView(m1).AddrIsAtLeft(addr, 1, &offset)) {
     // The address is in the chunk's left redzone, so maybe it is actually
     // a right buffer overflow from the other chunk to the left.
@@ -601,6 +600,7 @@
 }
 
 void *asan_calloc(uptr nmemb, uptr size, StackTrace *stack) {
+  if (CallocShouldReturnNullDueToOverflow(size, nmemb)) return 0;
   void *ptr = Allocate(nmemb * size, 8, stack, FROM_MALLOC);
   if (ptr)
     REAL(memset)(ptr, 0, nmemb * size);
@@ -649,16 +649,17 @@
 }
 
 uptr asan_mz_size(const void *ptr) {
-  UNIMPLEMENTED();
-  return 0;
+  return AllocationSize(reinterpret_cast<uptr>(ptr));
 }
 
 void asan_mz_force_lock() {
-  UNIMPLEMENTED();
+  allocator.ForceLock();
+  fallback_mutex.Lock();
 }
 
 void asan_mz_force_unlock() {
-  UNIMPLEMENTED();
+  fallback_mutex.Unlock();
+  allocator.ForceUnlock();
 }
 
 }  // namespace __asan
@@ -674,7 +675,7 @@
 
 bool __asan_get_ownership(const void *p) {
   uptr ptr = reinterpret_cast<uptr>(p);
-  return (ptr == kReturnOnZeroMalloc) || (AllocationSize(ptr) > 0);
+  return (AllocationSize(ptr) > 0);
 }
 
 uptr __asan_get_allocated_size(const void *p) {
@@ -682,7 +683,7 @@
   uptr ptr = reinterpret_cast<uptr>(p);
   uptr allocated_size = AllocationSize(ptr);
   // Die if p is not malloced or if it is already freed.
-  if (allocated_size == 0 && ptr != kReturnOnZeroMalloc) {
+  if (allocated_size == 0) {
     GET_STACK_TRACE_FATAL_HERE;
     ReportAsanGetAllocatedSizeNotOwned(ptr, &stack);
   }
Index: libsanitizer/asan/asan_stack.cc
===================================================================
--- libsanitizer/asan/asan_stack.cc	(revision 195997)
+++ libsanitizer/asan/asan_stack.cc	(working copy)
@@ -9,9 +9,9 @@
 //
 // Code for ASan stack trace.
 //===----------------------------------------------------------------------===//
+#include "asan_internal.h"
 #include "asan_flags.h"
 #include "asan_stack.h"
-#include "sanitizer/asan_interface.h"
 
 namespace __asan {
 
Index: libsanitizer/asan/asan_report.cc
===================================================================
--- libsanitizer/asan/asan_report.cc	(revision 195997)
+++ libsanitizer/asan/asan_report.cc	(working copy)
@@ -118,19 +118,7 @@
   Printf("\n");
 }
 
-static void PrintShadowMemoryForAddress(uptr addr) {
-  if (!AddrIsInMem(addr))
-    return;
-  uptr shadow_addr = MemToShadow(addr);
-  const uptr n_bytes_per_row = 16;
-  uptr aligned_shadow = shadow_addr & ~(n_bytes_per_row - 1);
-  Printf("Shadow bytes around the buggy address:\n");
-  for (int i = -5; i <= 5; i++) {
-    const char *prefix = (i == 0) ? "=>" : "  ";
-    PrintShadowBytes(prefix,
-                     (u8*)(aligned_shadow + i * n_bytes_per_row),
-                     (u8*)shadow_addr, n_bytes_per_row);
-  }
+static void PrintLegend() {
   Printf("Shadow byte legend (one shadow byte represents %d "
          "application bytes):\n", (int)SHADOW_GRANULARITY);
   PrintShadowByte("  Addressable:           ", 0);
@@ -153,6 +141,23 @@
   PrintShadowByte("  ASan internal:         ", kAsanInternalHeapMagic);
 }
 
+static void PrintShadowMemoryForAddress(uptr addr) {
+  if (!AddrIsInMem(addr))
+    return;
+  uptr shadow_addr = MemToShadow(addr);
+  const uptr n_bytes_per_row = 16;
+  uptr aligned_shadow = shadow_addr & ~(n_bytes_per_row - 1);
+  Printf("Shadow bytes around the buggy address:\n");
+  for (int i = -5; i <= 5; i++) {
+    const char *prefix = (i == 0) ? "=>" : "  ";
+    PrintShadowBytes(prefix,
+                     (u8*)(aligned_shadow + i * n_bytes_per_row),
+                     (u8*)shadow_addr, n_bytes_per_row);
+  }
+  if (flags()->print_legend)
+    PrintLegend();
+}
+
 static void PrintZoneForPointer(uptr ptr, uptr zone_ptr,
                                 const char *zone_name) {
   if (zone_ptr) {
@@ -183,18 +188,23 @@
   Printf("  '%s' is ascii string '%s'\n", g.name, (char*)g.beg);
 }
 
-bool DescribeAddressRelativeToGlobal(uptr addr, const __asan_global &g) {
-  if (addr < g.beg - kGlobalAndStackRedzone) return false;
+bool DescribeAddressRelativeToGlobal(uptr addr, uptr size,
+                                     const __asan_global &g) {
+  static const uptr kMinimalDistanceFromAnotherGlobal = 64;
+  if (addr <= g.beg - kMinimalDistanceFromAnotherGlobal) return false;
   if (addr >= g.beg + g.size_with_redzone) return false;
   Decorator d;
   Printf("%s", d.Location());
-  Printf("%p is located ", (void*)addr);
   if (addr < g.beg) {
-    Printf("%zd bytes to the left", g.beg - addr);
-  } else if (addr >= g.beg + g.size) {
-    Printf("%zd bytes to the right", addr - (g.beg + g.size));
+    Printf("%p is located %zd bytes to the left", (void*)addr, g.beg - addr);
+  } else if (addr + size > g.beg + g.size) {
+    if (addr < g.beg + g.size)
+      addr = g.beg + g.size;
+    Printf("%p is located %zd bytes to the right", (void*)addr,
+           addr - (g.beg + g.size));
   } else {
-    Printf("%zd bytes inside", addr - g.beg);  // Can it happen?
+    // Can it happen?
+    Printf("%p is located %zd bytes inside", (void*)addr, addr - g.beg);
   }
   Printf(" of global variable '%s' (0x%zx) of size %zu\n",
              g.name, g.beg, g.size);
@@ -280,18 +290,22 @@
 
 static void DescribeAccessToHeapChunk(AsanChunkView chunk, uptr addr,
                                       uptr access_size) {
-  uptr offset;
+  sptr offset;
   Decorator d;
   Printf("%s", d.Location());
-  Printf("%p is located ", (void*)addr);
-  if (chunk.AddrIsInside(addr, access_size, &offset)) {
-    Printf("%zu bytes inside of", offset);
-  } else if (chunk.AddrIsAtLeft(addr, access_size, &offset)) {
-    Printf("%zu bytes to the left of", offset);
+  if (chunk.AddrIsAtLeft(addr, access_size, &offset)) {
+    Printf("%p is located %zd bytes to the left of", (void*)addr, offset);
   } else if (chunk.AddrIsAtRight(addr, access_size, &offset)) {
-    Printf("%zu bytes to the right of", offset);
+    if (offset < 0) {
+      addr -= offset;
+      offset = 0;
+    }
+    Printf("%p is located %zd bytes to the right of", (void*)addr, offset);
+  } else if (chunk.AddrIsInside(addr, access_size, &offset)) {
+    Printf("%p is located %zd bytes inside of", (void*)addr, offset);
   } else {
-    Printf(" somewhere around (this is AddressSanitizer bug!)");
+    Printf("%p is located somewhere around (this is AddressSanitizer bug!)",
+           (void*)addr);
   }
   Printf(" %zu-byte region [%p,%p)\n", chunk.UsedSize(),
          (void*)(chunk.Beg()), (void*)(chunk.End()));
@@ -364,7 +378,7 @@
   if (DescribeAddressIfShadow(addr))
     return;
   CHECK(AddrIsInMem(addr));
-  if (DescribeAddressIfGlobal(addr))
+  if (DescribeAddressIfGlobal(addr, access_size))
     return;
   if (DescribeAddressIfStack(addr, access_size))
     return;
@@ -443,7 +457,8 @@
       DescribeThread(curr_thread->summary());
     }
     // Print memory stats.
-    __asan_print_accumulated_stats();
+    if (flags()->print_stats)
+      __asan_print_accumulated_stats();
     if (error_report_callback) {
       error_report_callback(error_message_buffer);
     }
@@ -452,6 +467,20 @@
   }
 };
 
+static void ReportSummary(const char *error_type, StackTrace *stack) {
+  if (!stack->size) return;
+  if (IsSymbolizerAvailable()) {
+    AddressInfo ai;
+    // Currently, we include the first stack frame into the report summary.
+    // Maybe sometimes we need to choose another frame (e.g. skip memcpy/etc).
+    SymbolizeCode(stack->trace[0], &ai, 1);
+    ReportErrorSummary(error_type,
+                       StripPathPrefix(ai.file, flags()->strip_path_prefix),
+                       ai.line, ai.function);
+  }
+  // FIXME: do we need to print anything at all if there is no symbolizer?
+}
+
 void ReportSIGSEGV(uptr pc, uptr sp, uptr bp, uptr addr) {
   ScopedInErrorReport in_report;
   Decorator d;
@@ -464,6 +493,7 @@
   Printf("AddressSanitizer can not provide additional info.\n");
   GET_STACK_TRACE_FATAL(pc, bp);
   PrintStack(&stack);
+  ReportSummary("SEGV", &stack);
 }
 
 void ReportDoubleFree(uptr addr, StackTrace *stack) {
@@ -474,6 +504,7 @@
   Printf("%s", d.EndWarning());
   PrintStack(stack);
   DescribeHeapAddress(addr, 1);
+  ReportSummary("double-free", stack);
 }
 
 void ReportFreeNotMalloced(uptr addr, StackTrace *stack) {
@@ -485,6 +516,7 @@
   Printf("%s", d.EndWarning());
   PrintStack(stack);
   DescribeHeapAddress(addr, 1);
+  ReportSummary("bad-free", stack);
 }
 
 void ReportAllocTypeMismatch(uptr addr, StackTrace *stack,
@@ -503,6 +535,7 @@
   Printf("%s", d.EndWarning());
   PrintStack(stack);
   DescribeHeapAddress(addr, 1);
+  ReportSummary("alloc-dealloc-mismatch", stack);
   Report("HINT: if you don't care about these warnings you may set "
          "ASAN_OPTIONS=alloc_dealloc_mismatch=0\n");
 }
@@ -517,6 +550,7 @@
   Printf("%s", d.EndWarning());
   PrintStack(stack);
   DescribeHeapAddress(addr, 1);
+  ReportSummary("bad-malloc_usable_size", stack);
 }
 
 void ReportAsanGetAllocatedSizeNotOwned(uptr addr, StackTrace *stack) {
@@ -529,6 +563,7 @@
   Printf("%s", d.EndWarning());
   PrintStack(stack);
   DescribeHeapAddress(addr, 1);
+  ReportSummary("bad-__asan_get_allocated_size", stack);
 }
 
 void ReportStringFunctionMemoryRangesOverlap(
@@ -536,14 +571,17 @@
     const char *offset2, uptr length2, StackTrace *stack) {
   ScopedInErrorReport in_report;
   Decorator d;
+  char bug_type[100];
+  internal_snprintf(bug_type, sizeof(bug_type), "%s-param-overlap", function);
   Printf("%s", d.Warning());
-  Report("ERROR: AddressSanitizer: %s-param-overlap: "
+  Report("ERROR: AddressSanitizer: %s: "
              "memory ranges [%p,%p) and [%p, %p) overlap\n", \
-             function, offset1, offset1 + length1, offset2, offset2 + length2);
+             bug_type, offset1, offset1 + length1, offset2, offset2 + length2);
   Printf("%s", d.EndWarning());
   PrintStack(stack);
   DescribeAddress((uptr)offset1, length1);
   DescribeAddress((uptr)offset2, length2);
+  ReportSummary(bug_type, stack);
 }
 
 // ----------------------- Mac-specific reports ----------------- {{{1
@@ -653,7 +691,7 @@
   PrintStack(&stack);
 
   DescribeAddress(addr, access_size);
-
+  ReportSummary(bug_descr, &stack);
   PrintShadowMemoryForAddress(addr);
 }
 
Index: libsanitizer/asan/asan_allocator.cc
===================================================================
--- libsanitizer/asan/asan_allocator.cc	(revision 195997)
+++ libsanitizer/asan/asan_allocator.cc	(working copy)
@@ -32,7 +32,7 @@
 #include "asan_report.h"
 #include "asan_thread.h"
 #include "asan_thread_registry.h"
-#include "sanitizer/asan_interface.h"
+#include "sanitizer_common/sanitizer_allocator.h"
 #include "sanitizer_common/sanitizer_atomic.h"
 #include "sanitizer_common/sanitizer_mutex.h"
 
@@ -367,7 +367,7 @@
         left_chunk->chunk_state != CHUNK_AVAILABLE)
       return left_chunk;
     // Choose based on offset.
-    uptr l_offset = 0, r_offset = 0;
+    sptr l_offset = 0, r_offset = 0;
     CHECK(AsanChunkView(left_chunk).AddrIsAtRight(addr, 1, &l_offset));
     CHECK(AsanChunkView(right_chunk).AddrIsAtLeft(addr, 1, &r_offset));
     if (l_offset < r_offset)
@@ -387,7 +387,7 @@
     CHECK(m->chunk_state == CHUNK_ALLOCATED ||
           m->chunk_state == CHUNK_AVAILABLE ||
           m->chunk_state == CHUNK_QUARANTINE);
-    uptr offset = 0;
+    sptr offset = 0;
     AsanChunkView m_view(m);
     if (m_view.AddrIsInside(addr, 1, &offset))
       return m;
@@ -685,6 +685,8 @@
 
 namespace __asan {
 
+void InitializeAllocator() { }
+
 void PrintInternalAllocatorStats() {
 }
 
@@ -710,6 +712,7 @@
 }
 
 void *asan_calloc(uptr nmemb, uptr size, StackTrace *stack) {
+  if (__sanitizer::CallocShouldReturnNullDueToOverflow(size, nmemb)) return 0;
   void *ptr = (void*)Allocate(0, nmemb * size, stack, FROM_MALLOC);
   if (ptr)
     REAL(memset)(ptr, 0, nmemb * size);
Index: libsanitizer/asan/asan_interceptors.cc
===================================================================
--- libsanitizer/asan/asan_interceptors.cc	(revision 195997)
+++ libsanitizer/asan/asan_interceptors.cc	(working copy)
@@ -20,7 +20,6 @@
 #include "asan_stats.h"
 #include "asan_thread_registry.h"
 #include "interception/interception.h"
-#include "sanitizer/asan_interface.h"
 #include "sanitizer_common/sanitizer_libc.h"
 
 namespace __asan {
@@ -30,12 +29,14 @@
 // that no extra frames are created, and stack trace contains
 // relevant information only.
 // We check all shadow bytes.
-#define ACCESS_MEMORY_RANGE(offset, size, isWrite) do {                  \
-  if (uptr __ptr = __asan_region_is_poisoned((uptr)(offset), size)) {    \
-    GET_CURRENT_PC_BP_SP;                                                \
-    __asan_report_error(pc, bp, sp, __ptr, isWrite, /* access_size */1); \
-  }                                                                      \
-} while (0)
+#define ACCESS_MEMORY_RANGE(offset, size, isWrite) do {                 \
+    uptr __offset = (uptr)(offset);                                     \
+    uptr __size = (uptr)(size);                                         \
+    if (__asan_region_is_poisoned(__offset, __size)) {                  \
+      GET_CURRENT_PC_BP_SP;                                             \
+      __asan_report_error(pc, bp, sp, __offset, isWrite, __size);       \
+    }                                                                   \
+  } while (0)
 
 #define ASAN_READ_RANGE(offset, size) ACCESS_MEMORY_RANGE(offset, size, false)
 #define ASAN_WRITE_RANGE(offset, size) ACCESS_MEMORY_RANGE(offset, size, true);
@@ -275,13 +276,9 @@
     ASAN_READ_RANGE(from, size);
     ASAN_WRITE_RANGE(to, size);
   }
-#if MAC_INTERPOSE_FUNCTIONS
   // Interposing of resolver functions is broken on Mac OS 10.7 and 10.8.
   // See also http://code.google.com/p/address-sanitizer/issues/detail?id=116.
   return internal_memcpy(to, from, size);
-#else
-  return REAL(memcpy)(to, from, size);
-#endif
 }
 
 INTERCEPTOR(void*, memmove, void *to, const void *from, uptr size) {
@@ -294,13 +291,9 @@
     ASAN_READ_RANGE(from, size);
     ASAN_WRITE_RANGE(to, size);
   }
-#if MAC_INTERPOSE_FUNCTIONS
   // Interposing of resolver functions is broken on Mac OS 10.7 and 10.8.
   // See also http://code.google.com/p/address-sanitizer/issues/detail?id=116.
   return internal_memmove(to, from, size);
-#else
-  return REAL(memmove)(to, from, size);
-#endif
 }
 
 INTERCEPTOR(void*, memset, void *block, int c, uptr size) {
@@ -398,7 +391,7 @@
 }
 
 INTERCEPTOR(char*, strcpy, char *to, const char *from) {  // NOLINT
-#if MAC_INTERPOSE_FUNCTIONS
+#if defined(__APPLE__)
   if (!asan_inited) return REAL(strcpy)(to, from);  // NOLINT
 #endif
   // strcpy is called from malloc_default_purgeable_zone()
@@ -418,7 +411,7 @@
 
 #if ASAN_INTERCEPT_STRDUP
 INTERCEPTOR(char*, strdup, const char *s) {
-#if MAC_INTERPOSE_FUNCTIONS
+#if defined(__APPLE__)
   // FIXME: because internal_strdup() uses InternalAlloc(), which currently
   // just calls malloc() on Mac, we can't use internal_strdup() with the
   // dynamic runtime. We can remove the call to REAL(strdup) once InternalAlloc
@@ -559,7 +552,7 @@
 }
 
 INTERCEPTOR(int, atoi, const char *nptr) {
-#if MAC_INTERPOSE_FUNCTIONS
+#if defined(__APPLE__)
   if (!asan_inited) return REAL(atoi)(nptr);
 #endif
   ENSURE_ASAN_INITED();
@@ -578,7 +571,7 @@
 }
 
 INTERCEPTOR(long, atol, const char *nptr) {  // NOLINT
-#if MAC_INTERPOSE_FUNCTIONS
+#if defined(__APPLE__)
   if (!asan_inited) return REAL(atol)(nptr);
 #endif
   ENSURE_ASAN_INITED();
@@ -659,10 +652,9 @@
   static bool was_called_once;
   CHECK(was_called_once == false);
   was_called_once = true;
-#if MAC_INTERPOSE_FUNCTIONS
+#if defined(__APPLE__)
   return;
-#endif
-
+#else
   SANITIZER_COMMON_INTERCEPTORS_INIT;
 
   // Intercept mem* functions.
@@ -671,12 +663,6 @@
   ASAN_INTERCEPT_FUNC(memset);
   if (PLATFORM_HAS_DIFFERENT_MEMCPY_AND_MEMMOVE) {
     ASAN_INTERCEPT_FUNC(memcpy);
-  } else {
-#if !MAC_INTERPOSE_FUNCTIONS
-    // If we're using dynamic interceptors on Mac, these two are just plain
-    // functions.
-    internal_memcpy(&REAL(memcpy), &REAL(memmove), sizeof(REAL(memmove)));
-#endif
   }
 
   // Intercept str* functions.
@@ -698,12 +684,8 @@
 #if ASAN_INTERCEPT_STRNLEN
   ASAN_INTERCEPT_FUNC(strnlen);
 #endif
-#if ASAN_INTERCEPT_INDEX
-# if ASAN_USE_ALIAS_ATTRIBUTE_FOR_INDEX
+#if ASAN_INTERCEPT_INDEX && ASAN_USE_ALIAS_ATTRIBUTE_FOR_INDEX
   ASAN_INTERCEPT_FUNC(index);
-# else
-  CHECK(OVERRIDE_FUNCTION(index, WRAP(strchr)));
-# endif
 #endif
 
   ASAN_INTERCEPT_FUNC(atoi);
@@ -753,14 +735,10 @@
   InitializeWindowsInterceptors();
 #endif
 
-  // Some Mac-specific interceptors.
-#if defined(__APPLE__)
-  InitializeMacInterceptors();
-#endif
-
   if (flags()->verbosity > 0) {
     Report("AddressSanitizer: libc interceptors initialized\n");
   }
+#endif  // __APPLE__
 }
 
 }  // namespace __asan
Index: libsanitizer/asan/asan_allocator.h
===================================================================
--- libsanitizer/asan/asan_allocator.h	(revision 195997)
+++ libsanitizer/asan/asan_allocator.h	(working copy)
@@ -22,7 +22,7 @@
 // will co-exist in the source base for a while. The actual allocator is chosen
 // at build time by redefining this macro.
 #ifndef ASAN_ALLOCATOR_VERSION
-# if ASAN_LINUX && !ASAN_ANDROID
+# if (ASAN_LINUX && !ASAN_ANDROID) || ASAN_MAC || ASAN_WINDOWS
 #  define ASAN_ALLOCATOR_VERSION 2
 # else
 #  define ASAN_ALLOCATOR_VERSION 1
@@ -40,6 +40,8 @@
 static const uptr kNumberOfSizeClasses = 255;
 struct AsanChunk;
 
+void InitializeAllocator();
+
 class AsanChunkView {
  public:
   explicit AsanChunkView(AsanChunk *chunk) : chunk_(chunk) {}
@@ -51,14 +53,14 @@
   uptr FreeTid();
   void GetAllocStack(StackTrace *stack);
   void GetFreeStack(StackTrace *stack);
-  bool AddrIsInside(uptr addr, uptr access_size, uptr *offset) {
+  bool AddrIsInside(uptr addr, uptr access_size, sptr *offset) {
     if (addr >= Beg() && (addr + access_size) <= End()) {
       *offset = addr - Beg();
       return true;
     }
     return false;
   }
-  bool AddrIsAtLeft(uptr addr, uptr access_size, uptr *offset) {
+  bool AddrIsAtLeft(uptr addr, uptr access_size, sptr *offset) {
     (void)access_size;
     if (addr < Beg()) {
       *offset = Beg() - addr;
@@ -66,12 +68,9 @@
     }
     return false;
   }
-  bool AddrIsAtRight(uptr addr, uptr access_size, uptr *offset) {
-    if (addr + access_size >= End()) {
-      if (addr <= End())
-        *offset = 0;
-      else
-        *offset = addr - End();
+  bool AddrIsAtRight(uptr addr, uptr access_size, sptr *offset) {
+    if (addr + access_size > End()) {
+      *offset = addr - End();
       return true;
     }
     return false;
@@ -225,50 +224,5 @@
 
 void PrintInternalAllocatorStats();
 
-// Log2 and RoundUpToPowerOfTwo should be inlined for performance.
-#if defined(_WIN32) && !defined(__clang__)
-extern "C" {
-unsigned char _BitScanForward(unsigned long *index, unsigned long mask);  // NOLINT
-unsigned char _BitScanReverse(unsigned long *index, unsigned long mask);  // NOLINT
-#if defined(_WIN64)
-unsigned char _BitScanForward64(unsigned long *index, unsigned __int64 mask);  // NOLINT
-unsigned char _BitScanReverse64(unsigned long *index, unsigned __int64 mask);  // NOLINT
-#endif
-}
-#endif
-
-static inline uptr Log2(uptr x) {
-  CHECK(IsPowerOfTwo(x));
-#if !defined(_WIN32) || defined(__clang__)
-  return __builtin_ctzl(x);
-#elif defined(_WIN64)
-  unsigned long ret;  // NOLINT
-  _BitScanForward64(&ret, x);
-  return ret;
-#else
-  unsigned long ret;  // NOLINT
-  _BitScanForward(&ret, x);
-  return ret;
-#endif
-}
-
-static inline uptr RoundUpToPowerOfTwo(uptr size) {
-  CHECK(size);
-  if (IsPowerOfTwo(size)) return size;
-
-  unsigned long up;  // NOLINT
-#if !defined(_WIN32) || defined(__clang__)
-  up = SANITIZER_WORDSIZE - 1 - __builtin_clzl(size);
-#elif defined(_WIN64)
-  _BitScanReverse64(&up, size);
-#else
-  _BitScanReverse(&up, size);
-#endif
-  CHECK(size < (1ULL << (up + 1)));
-  CHECK(size > (1ULL << up));
-  return 1UL << (up + 1);
-}
-
-
 }  // namespace __asan
 #endif  // ASAN_ALLOCATOR_H
Index: libsanitizer/asan/asan_fake_stack.cc
===================================================================
--- libsanitizer/asan/asan_fake_stack.cc	(revision 195997)
+++ libsanitizer/asan/asan_fake_stack.cc	(working copy)
@@ -12,7 +12,6 @@
 #include "asan_allocator.h"
 #include "asan_thread.h"
 #include "asan_thread_registry.h"
-#include "sanitizer/asan_interface.h"
 
 namespace __asan {
 
Index: libsanitizer/asan/asan_flags.h
===================================================================
--- libsanitizer/asan/asan_flags.h	(revision 195997)
+++ libsanitizer/asan/asan_flags.h	(working copy)
@@ -13,7 +13,7 @@
 #ifndef ASAN_FLAGS_H
 #define ASAN_FLAGS_H
 
-#include "sanitizer/common_interface_defs.h"
+#include "sanitizer_common/sanitizer_internal_defs.h"
 
 // ASan flag values can be defined in three ways:
 // 1) initialized with default values at startup.
@@ -50,8 +50,6 @@
   bool replace_str;
   // If set, uses custom wrappers for memset/memcpy/memmove intinsics.
   bool replace_intrin;
-  // Used on Mac only. See comments in asan_mac.cc and asan_malloc_mac.cc.
-  bool replace_cfallocator;
   // Used on Mac only.
   bool mac_ignore_invalid_free;
   // ASan allocator flag. See asan_allocator.cc.
@@ -77,6 +75,10 @@
   bool unmap_shadow_on_exit;
   // If set, calls abort() instead of _exit() after printing an error report.
   bool abort_on_error;
+  // Print various statistics after printing an error message or if atexit=1.
+  bool print_stats;
+  // Print the legend for the shadow bytes.
+  bool print_legend;
   // If set, prints ASan exit stats even after program terminates successfully.
   bool atexit;
   // By default, disable core dumper on 64-bit - it makes little sense
Index: libsanitizer/asan/dynamic/asan_interceptors_dynamic.cc
===================================================================
--- libsanitizer/asan/dynamic/asan_interceptors_dynamic.cc	(revision 195997)
+++ libsanitizer/asan/dynamic/asan_interceptors_dynamic.cc	(working copy)
@@ -17,11 +17,6 @@
 
 namespace __asan {
 
-#if !MAC_INTERPOSE_FUNCTIONS
-# error \
-  Dynamic interposing library should be built with -DMAC_INTERPOSE_FUNCTIONS
-#endif
-
 #define INTERPOSE_FUNCTION(function) \
     { reinterpret_cast<const uptr>(WRAP(function)), \
       reinterpret_cast<const uptr>(function) }
Index: libsanitizer/asan/asan_stats.cc
===================================================================
--- libsanitizer/asan/asan_stats.cc	(revision 195997)
+++ libsanitizer/asan/asan_stats.cc	(working copy)
@@ -13,7 +13,6 @@
 #include "asan_internal.h"
 #include "asan_stats.h"
 #include "asan_thread_registry.h"
-#include "sanitizer/asan_interface.h"
 #include "sanitizer_common/sanitizer_stackdepot.h"
 
 namespace __asan {
Index: libsanitizer/asan/asan_interface_internal.h
===================================================================
--- libsanitizer/asan/asan_interface_internal.h	(revision 0)
+++ libsanitizer/asan/asan_interface_internal.h	(revision 0)
@@ -0,0 +1,133 @@
+//===-- asan_interface_internal.h -------------------------------*- C++ -*-===//
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of AddressSanitizer, an address sanity checker.
+//
+// This header can be included by the instrumented program to fetch
+// data (mostly allocator statistics) from ASan runtime library.
+//===----------------------------------------------------------------------===//
+#ifndef ASAN_INTERFACE_INTERNAL_H
+#define ASAN_INTERFACE_INTERNAL_H
+
+#include "sanitizer_common/sanitizer_internal_defs.h"
+
+using __sanitizer::uptr;
+
+extern "C" {
+  // This function should be called at the very beginning of the process,
+  // before any instrumented code is executed and before any call to malloc.
+  // Everytime the asan ABI changes we also change the version number in this
+  // name. Objects build with incompatible asan ABI version
+  // will not link with run-time.
+  void __asan_init_v1() SANITIZER_INTERFACE_ATTRIBUTE;
+  #define __asan_init __asan_init_v1
+
+  // This structure describes an instrumented global variable.
+  struct __asan_global {
+    uptr beg;                // The address of the global.
+    uptr size;               // The original size of the global.
+    uptr size_with_redzone;  // The size with the redzone.
+    const char *name;        // Name as a C string.
+    uptr has_dynamic_init;   // Non-zero if the global has dynamic initializer.
+  };
+
+  // These two functions should be called by the instrumented code.
+  // 'globals' is an array of structures describing 'n' globals.
+  void __asan_register_globals(__asan_global *globals, uptr n)
+      SANITIZER_INTERFACE_ATTRIBUTE;
+  void __asan_unregister_globals(__asan_global *globals, uptr n)
+      SANITIZER_INTERFACE_ATTRIBUTE;
+
+  // These two functions should be called before and after dynamic initializers
+  // run, respectively.  They should be called with parameters describing all
+  // dynamically initialized globals defined in the calling TU.
+  void __asan_before_dynamic_init(uptr first_addr, uptr last_addr)
+      SANITIZER_INTERFACE_ATTRIBUTE;
+  void __asan_after_dynamic_init()
+      SANITIZER_INTERFACE_ATTRIBUTE;
+
+  // These two functions are used by the instrumented code in the
+  // use-after-return mode. __asan_stack_malloc allocates size bytes of
+  // fake stack and __asan_stack_free poisons it. real_stack is a pointer to
+  // the real stack region.
+  uptr __asan_stack_malloc(uptr size, uptr real_stack)
+      SANITIZER_INTERFACE_ATTRIBUTE;
+  void __asan_stack_free(uptr ptr, uptr size, uptr real_stack)
+      SANITIZER_INTERFACE_ATTRIBUTE;
+
+  // These two functions are used by instrumented code in the
+  // use-after-scope mode. They mark memory for local variables as
+  // unaddressable when they leave scope and addressable before the
+  // function exits.
+  void __asan_poison_stack_memory(uptr addr, uptr size)
+      SANITIZER_INTERFACE_ATTRIBUTE;
+  void __asan_unpoison_stack_memory(uptr addr, uptr size)
+      SANITIZER_INTERFACE_ATTRIBUTE;
+
+  // Performs cleanup before a NoReturn function. Must be called before things
+  // like _exit and execl to avoid false positives on stack.
+  void __asan_handle_no_return() SANITIZER_INTERFACE_ATTRIBUTE;
+
+  void __asan_poison_memory_region(void const volatile *addr, uptr size)
+      SANITIZER_INTERFACE_ATTRIBUTE;
+  void __asan_unpoison_memory_region(void const volatile *addr, uptr size)
+      SANITIZER_INTERFACE_ATTRIBUTE;
+
+  bool __asan_address_is_poisoned(void const volatile *addr)
+      SANITIZER_INTERFACE_ATTRIBUTE;
+
+  uptr __asan_region_is_poisoned(uptr beg, uptr size)
+      SANITIZER_INTERFACE_ATTRIBUTE;
+
+  void __asan_describe_address(uptr addr)
+      SANITIZER_INTERFACE_ATTRIBUTE;
+
+  void __asan_report_error(uptr pc, uptr bp, uptr sp,
+                           uptr addr, bool is_write, uptr access_size)
+    SANITIZER_INTERFACE_ATTRIBUTE;
+
+  int __asan_set_error_exit_code(int exit_code)
+      SANITIZER_INTERFACE_ATTRIBUTE;
+  void __asan_set_death_callback(void (*callback)(void))
+      SANITIZER_INTERFACE_ATTRIBUTE;
+  void __asan_set_error_report_callback(void (*callback)(const char*))
+      SANITIZER_INTERFACE_ATTRIBUTE;
+
+  /* OPTIONAL */ void __asan_on_error()
+      SANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE;
+
+  /* OPTIONAL */ bool __asan_symbolize(const void *pc, char *out_buffer,
+                                       int out_size)
+      SANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE;
+
+  uptr __asan_get_estimated_allocated_size(uptr size)
+      SANITIZER_INTERFACE_ATTRIBUTE;
+  bool __asan_get_ownership(const void *p)
+      SANITIZER_INTERFACE_ATTRIBUTE;
+  uptr __asan_get_allocated_size(const void *p)
+      SANITIZER_INTERFACE_ATTRIBUTE;
+  uptr __asan_get_current_allocated_bytes()
+      SANITIZER_INTERFACE_ATTRIBUTE;
+  uptr __asan_get_heap_size()
+      SANITIZER_INTERFACE_ATTRIBUTE;
+  uptr __asan_get_free_bytes()
+      SANITIZER_INTERFACE_ATTRIBUTE;
+  uptr __asan_get_unmapped_bytes()
+      SANITIZER_INTERFACE_ATTRIBUTE;
+  void __asan_print_accumulated_stats()
+      SANITIZER_INTERFACE_ATTRIBUTE;
+
+  /* OPTIONAL */ const char* __asan_default_options()
+      SANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE;
+
+  /* OPTIONAL */ void __asan_malloc_hook(void *ptr, uptr size)
+      SANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE;
+  /* OPTIONAL */ void __asan_free_hook(void *ptr)
+      SANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE;
+}  // extern "C"
+
+#endif  // ASAN_INTERFACE_INTERNAL_H
Index: libsanitizer/include/sanitizer/asan_interface.h
===================================================================
--- libsanitizer/include/sanitizer/asan_interface.h	(revision 195997)
+++ libsanitizer/include/sanitizer/asan_interface.h	(working copy)
@@ -5,69 +5,18 @@
 //
 //===----------------------------------------------------------------------===//
 //
-// This file is a part of AddressSanitizer, an address sanity checker.
+// This file is a part of AddressSanitizer.
 //
-// This header can be included by the instrumented program to fetch
-// data (mostly allocator statistics) from ASan runtime library.
+// Public interface header.
 //===----------------------------------------------------------------------===//
 #ifndef SANITIZER_ASAN_INTERFACE_H
 #define SANITIZER_ASAN_INTERFACE_H
 
 #include <sanitizer/common_interface_defs.h>
 
-// ----------- ATTENTION -------------
-// This header should NOT include any other headers from ASan runtime.
-// All functions in this header are extern "C" and start with __asan_.
-
-using __sanitizer::uptr;
-
+#ifdef __cplusplus
 extern "C" {
-  // This function should be called at the very beginning of the process,
-  // before any instrumented code is executed and before any call to malloc.
-  void __asan_init() SANITIZER_INTERFACE_ATTRIBUTE;
-
-  // This structure describes an instrumented global variable.
-  struct __asan_global {
-    uptr beg;                // The address of the global.
-    uptr size;               // The original size of the global.
-    uptr size_with_redzone;  // The size with the redzone.
-    const char *name;        // Name as a C string.
-    uptr has_dynamic_init;   // Non-zero if the global has dynamic initializer.
-  };
-
-  // These two functions should be called by the instrumented code.
-  // 'globals' is an array of structures describing 'n' globals.
-  void __asan_register_globals(__asan_global *globals, uptr n)
-      SANITIZER_INTERFACE_ATTRIBUTE;
-  void __asan_unregister_globals(__asan_global *globals, uptr n)
-      SANITIZER_INTERFACE_ATTRIBUTE;
-
-  // These two functions should be called before and after dynamic initializers
-  // run, respectively.  They should be called with parameters describing all
-  // dynamically initialized globals defined in the calling TU.
-  void __asan_before_dynamic_init(uptr first_addr, uptr last_addr)
-      SANITIZER_INTERFACE_ATTRIBUTE;
-  void __asan_after_dynamic_init()
-      SANITIZER_INTERFACE_ATTRIBUTE;
-
-  // These two functions are used by the instrumented code in the
-  // use-after-return mode. __asan_stack_malloc allocates size bytes of
-  // fake stack and __asan_stack_free poisons it. real_stack is a pointer to
-  // the real stack region.
-  uptr __asan_stack_malloc(uptr size, uptr real_stack)
-      SANITIZER_INTERFACE_ATTRIBUTE;
-  void __asan_stack_free(uptr ptr, uptr size, uptr real_stack)
-      SANITIZER_INTERFACE_ATTRIBUTE;
-
-  // These two functions are used by instrumented code in the
-  // use-after-scope mode. They mark memory for local variables as
-  // unaddressable when they leave scope and addressable before the
-  // function exits.
-  void __asan_poison_stack_memory(uptr addr, uptr size)
-      SANITIZER_INTERFACE_ATTRIBUTE;
-  void __asan_unpoison_stack_memory(uptr addr, uptr size)
-      SANITIZER_INTERFACE_ATTRIBUTE;
-
+#endif
   // Marks memory region [addr, addr+size) as unaddressable.
   // This memory must be previously allocated by the user program. Accessing
   // addresses in this region from instrumented code is forbidden until
@@ -76,8 +25,7 @@
   // to ASan alignment restrictions.
   // Method is NOT thread-safe in the sense that no two threads can
   // (un)poison memory in the same memory region simultaneously.
-  void __asan_poison_memory_region(void const volatile *addr, uptr size)
-      SANITIZER_INTERFACE_ATTRIBUTE;
+  void __asan_poison_memory_region(void const volatile *addr, size_t size);
   // Marks memory region [addr, addr+size) as addressable.
   // This memory must be previously allocated by the user program. Accessing
   // addresses in this region is allowed until this region is poisoned again.
@@ -85,14 +33,9 @@
   // ASan alignment restrictions.
   // Method is NOT thread-safe in the sense that no two threads can
   // (un)poison memory in the same memory region simultaneously.
-  void __asan_unpoison_memory_region(void const volatile *addr, uptr size)
-      SANITIZER_INTERFACE_ATTRIBUTE;
+  void __asan_unpoison_memory_region(void const volatile *addr, size_t size);
 
-  // Performs cleanup before a NoReturn function. Must be called before things
-  // like _exit and execl to avoid false positives on stack.
-  void __asan_handle_no_return() SANITIZER_INTERFACE_ATTRIBUTE;
-
-// User code should use macro instead of functions.
+  // User code should use macro instead of functions.
 #if __has_feature(address_sanitizer)
 #define ASAN_POISON_MEMORY_REGION(addr, size) \
   __asan_poison_memory_region((addr), (size))
@@ -107,104 +50,86 @@
 
   // Returns true iff addr is poisoned (i.e. 1-byte read/write access to this
   // address will result in error report from AddressSanitizer).
-  bool __asan_address_is_poisoned(void const volatile *addr)
-      SANITIZER_INTERFACE_ATTRIBUTE;
+  bool __asan_address_is_poisoned(void const volatile *addr);
 
   // If at least on byte in [beg, beg+size) is poisoned, return the address
   // of the first such byte. Otherwise return 0.
-  uptr __asan_region_is_poisoned(uptr beg, uptr size)
-      SANITIZER_INTERFACE_ATTRIBUTE;
+  void *__asan_region_is_poisoned(void *beg, size_t size);
 
   // Print the description of addr (useful when debugging in gdb).
-  void __asan_describe_address(uptr addr)
-      SANITIZER_INTERFACE_ATTRIBUTE;
+  void __asan_describe_address(void *addr);
 
   // This is an internal function that is called to report an error.
   // However it is still a part of the interface because users may want to
   // set a breakpoint on this function in a debugger.
-  void __asan_report_error(uptr pc, uptr bp, uptr sp,
-                           uptr addr, bool is_write, uptr access_size)
-    SANITIZER_INTERFACE_ATTRIBUTE;
+  void __asan_report_error(void *pc, void *bp, void *sp,
+                           void *addr, bool is_write, size_t access_size);
 
   // Sets the exit code to use when reporting an error.
   // Returns the old value.
-  int __asan_set_error_exit_code(int exit_code)
-      SANITIZER_INTERFACE_ATTRIBUTE;
+  int __asan_set_error_exit_code(int exit_code);
 
   // Sets the callback to be called right before death on error.
   // Passing 0 will unset the callback.
-  void __asan_set_death_callback(void (*callback)(void))
-      SANITIZER_INTERFACE_ATTRIBUTE;
+  void __asan_set_death_callback(void (*callback)(void));
 
-  void __asan_set_error_report_callback(void (*callback)(const char*))
-      SANITIZER_INTERFACE_ATTRIBUTE;
+  void __asan_set_error_report_callback(void (*callback)(const char*));
 
   // User may provide function that would be called right when ASan detects
   // an error. This can be used to notice cases when ASan detects an error, but
   // the program crashes before ASan report is printed.
-  /* OPTIONAL */ void __asan_on_error()
-      SANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE;
+  void __asan_on_error();
 
   // User may provide its own implementation for symbolization function.
   // It should print the description of instruction at address "pc" to
   // "out_buffer". Description should be at most "out_size" bytes long.
   // User-specified function should return true if symbolization was
   // successful.
-  /* OPTIONAL */ bool __asan_symbolize(const void *pc, char *out_buffer,
-                                       int out_size)
-      SANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE;
+  bool __asan_symbolize(const void *pc, char *out_buffer,
+                                       int out_size);
 
   // Returns the estimated number of bytes that will be reserved by allocator
   // for request of "size" bytes. If ASan allocator can't allocate that much
   // memory, returns the maximal possible allocation size, otherwise returns
   // "size".
-  uptr __asan_get_estimated_allocated_size(uptr size)
-      SANITIZER_INTERFACE_ATTRIBUTE;
+  size_t __asan_get_estimated_allocated_size(size_t size);
   // Returns true if p was returned by the ASan allocator and
   // is not yet freed.
-  bool __asan_get_ownership(const void *p)
-      SANITIZER_INTERFACE_ATTRIBUTE;
+  bool __asan_get_ownership(const void *p);
   // Returns the number of bytes reserved for the pointer p.
   // Requires (get_ownership(p) == true) or (p == 0).
-  uptr __asan_get_allocated_size(const void *p)
-      SANITIZER_INTERFACE_ATTRIBUTE;
+  size_t __asan_get_allocated_size(const void *p);
   // Number of bytes, allocated and not yet freed by the application.
-  uptr __asan_get_current_allocated_bytes()
-      SANITIZER_INTERFACE_ATTRIBUTE;
+  size_t __asan_get_current_allocated_bytes();
   // Number of bytes, mmaped by asan allocator to fulfill allocation requests.
   // Generally, for request of X bytes, allocator can reserve and add to free
   // lists a large number of chunks of size X to use them for future requests.
   // All these chunks count toward the heap size. Currently, allocator never
   // releases memory to OS (instead, it just puts freed chunks to free lists).
-  uptr __asan_get_heap_size()
-      SANITIZER_INTERFACE_ATTRIBUTE;
+  size_t __asan_get_heap_size();
   // Number of bytes, mmaped by asan allocator, which can be used to fulfill
   // allocation requests. When a user program frees memory chunk, it can first
   // fall into quarantine and will count toward __asan_get_free_bytes() later.
-  uptr __asan_get_free_bytes()
-      SANITIZER_INTERFACE_ATTRIBUTE;
+  size_t __asan_get_free_bytes();
   // Number of bytes in unmapped pages, that are released to OS. Currently,
   // always returns 0.
-  uptr __asan_get_unmapped_bytes()
-      SANITIZER_INTERFACE_ATTRIBUTE;
+  size_t __asan_get_unmapped_bytes();
   // Prints accumulated stats to stderr. Used for debugging.
-  void __asan_print_accumulated_stats()
-      SANITIZER_INTERFACE_ATTRIBUTE;
+  void __asan_print_accumulated_stats();
 
   // This function may be optionally provided by user and should return
   // a string containing ASan runtime options. See asan_flags.h for details.
-  /* OPTIONAL */ const char* __asan_default_options()
-      SANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE;
+  const char* __asan_default_options();
 
   // Malloc hooks that may be optionally provided by user.
   // __asan_malloc_hook(ptr, size) is called immediately after
   //   allocation of "size" bytes, which returned "ptr".
   // __asan_free_hook(ptr) is called immediately before
   //   deallocation of "ptr".
-  /* OPTIONAL */ void __asan_malloc_hook(void *ptr, uptr size)
-      SANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE;
-  /* OPTIONAL */ void __asan_free_hook(void *ptr)
-      SANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE;
+  void __asan_malloc_hook(void *ptr, size_t size);
+  void __asan_free_hook(void *ptr);
+#ifdef __cplusplus
 }  // extern "C"
+#endif
 
 #endif  // SANITIZER_ASAN_INTERFACE_H
Index: libsanitizer/include/sanitizer/common_interface_defs.h
===================================================================
--- libsanitizer/include/sanitizer/common_interface_defs.h	(revision 195997)
+++ libsanitizer/include/sanitizer/common_interface_defs.h	(working copy)
@@ -5,86 +5,37 @@
 //
 //===----------------------------------------------------------------------===//
 //
-// This file is shared between AddressSanitizer and ThreadSanitizer.
-// It contains basic macro and types.
-// NOTE: This file may be included into user code.
+// Common part of the public sanitizer interface.
 //===----------------------------------------------------------------------===//
 
 #ifndef SANITIZER_COMMON_INTERFACE_DEFS_H
 #define SANITIZER_COMMON_INTERFACE_DEFS_H
 
-// ----------- ATTENTION -------------
-// This header should NOT include any other headers to avoid portability issues.
+#include <stddef.h>
+#include <stdint.h>
 
-#if defined(_WIN32)
-// FIXME find out what we need on Windows. __declspec(dllexport) ?
-# define SANITIZER_INTERFACE_ATTRIBUTE
-# define SANITIZER_WEAK_ATTRIBUTE
-#elif defined(SANITIZER_GO)
-# define SANITIZER_INTERFACE_ATTRIBUTE
-# define SANITIZER_WEAK_ATTRIBUTE
-#else
-# define SANITIZER_INTERFACE_ATTRIBUTE __attribute__((visibility("default")))
-# define SANITIZER_WEAK_ATTRIBUTE  __attribute__((weak))
-#endif
-
-#ifdef __linux__
-# define SANITIZER_SUPPORTS_WEAK_HOOKS 1
-#else
-# define SANITIZER_SUPPORTS_WEAK_HOOKS 0
-#endif
-
-// __has_feature
-#if !defined(__has_feature)
-# define __has_feature(x) 0
-#endif
-
-// For portability reasons we do not include stddef.h, stdint.h or any other
-// system header, but we do need some basic types that are not defined
-// in a portable way by the language itself.
-namespace __sanitizer {
-
-#if defined(_WIN64)
-// 64-bit Windows uses LLP64 data model.
-typedef unsigned long long uptr;  // NOLINT
-typedef signed   long long sptr;  // NOLINT
-#else
-typedef unsigned long uptr;  // NOLINT
-typedef signed   long sptr;  // NOLINT
-#endif  // defined(_WIN64)
-#if defined(__x86_64__)
-// Since x32 uses ILP32 data model in 64-bit hardware mode,  we must use
-// 64-bit pointer to unwind stack frame.
-typedef unsigned long long uhwptr;  // NOLINT
-#else
-typedef uptr uhwptr;   // NOLINT
-#endif
-typedef unsigned char u8;
-typedef unsigned short u16;  // NOLINT
-typedef unsigned int u32;
-typedef unsigned long long u64;  // NOLINT
-typedef signed   char s8;
-typedef signed   short s16;  // NOLINT
-typedef signed   int s32;
-typedef signed   long long s64;  // NOLINT
-
-}  // namespace __sanitizer
-
+#ifdef __cplusplus
 extern "C" {
+#endif
   // Tell the tools to write their reports to "path.<pid>" instead of stderr.
-  void __sanitizer_set_report_path(const char *path)
-      SANITIZER_INTERFACE_ATTRIBUTE;
+  void __sanitizer_set_report_path(const char *path);
 
   // Tell the tools to write their reports to given file descriptor instead of
   // stderr.
-  void __sanitizer_set_report_fd(int fd)
-      SANITIZER_INTERFACE_ATTRIBUTE;
+  void __sanitizer_set_report_fd(int fd);
 
   // Notify the tools that the sandbox is going to be turned on. The reserved
   // parameter will be used in the future to hold a structure with functions
   // that the tools may call to bypass the sandbox.
-  void __sanitizer_sandbox_on_notify(void *reserved)
-      SANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE;
+  void __sanitizer_sandbox_on_notify(void *reserved);
+
+  // This function is called by the tool when it has just finished reporting
+  // an error. 'error_summary' is a one-line string that summarizes
+  // the error message. This function can be overridden by the client.
+  void __sanitizer_report_error_summary(const char *error_summary);
+
+#ifdef __cplusplus
 }  // extern "C"
+#endif
 
 #endif  // SANITIZER_COMMON_INTERFACE_DEFS_H
Index: libsanitizer/ChangeLog
===================================================================
--- libsanitizer/ChangeLog	(revision 195997)
+++ libsanitizer/ChangeLog	(working copy)
@@ -1,3 +1,10 @@
+2013-02-13  Kostya Serebryany  <kcc@google.com>
+
+        PR sanitizer/56128
+	* All source files: Merge from upstream r175042.
+	* interception/Makefile.am: added include path.
+	* interception/Makefile.in: Regenerated.
+
 2013-02-11  Jack Howarth  <howarth@bromo.med.uc.edu>
 
 	* configure.tgt: Disable build on darwin9 and earlier.
Index: libsanitizer/MERGE
===================================================================
--- libsanitizer/MERGE	(revision 195997)
+++ libsanitizer/MERGE	(working copy)
@@ -1,4 +1,4 @@
-173241
+175042
 
 The first line of this file holds the svn revision number of the
 last merge done from the master library sources.
Index: libsanitizer/interception/interception_mac.cc
===================================================================
--- libsanitizer/interception/interception_mac.cc	(revision 195997)
+++ libsanitizer/interception/interception_mac.cc	(working copy)
@@ -13,17 +13,6 @@
 #ifdef __APPLE__
 
 #include "interception.h"
-#include "mach_override/mach_override.h"
 
-namespace __interception {
-bool OverrideFunction(uptr old_func, uptr new_func, uptr *orig_old_func) {
-  *orig_old_func = 0;
-  int res = __asan_mach_override_ptr_custom((void*)old_func, (void*)new_func,
-                                            (void**)orig_old_func,
-                                            __interception_allocate_island,
-                                            __interception_deallocate_island);
-  return (res == 0) && (*orig_old_func != 0);
-}
-}  // namespace __interception
 
 #endif  // __APPLE__
Index: libsanitizer/interception/interception_type_test.cc
===================================================================
--- libsanitizer/interception/interception_type_test.cc	(revision 0)
+++ libsanitizer/interception/interception_type_test.cc	(revision 0)
@@ -0,0 +1,37 @@
+//===-- interception_type_test.cc -------------------------------*- C++ -*-===//
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of AddressSanitizer, an address sanity checker.
+//
+// Compile-time tests of the internal type definitions.
+//===----------------------------------------------------------------------===//
+
+#if defined(__linux__) || defined(__APPLE__)
+
+#include "interception.h"
+#include <sys/types.h>
+#include <stddef.h>
+#include <stdint.h>
+
+COMPILER_CHECK(sizeof(SIZE_T) == sizeof(size_t));
+COMPILER_CHECK(sizeof(SSIZE_T) == sizeof(ssize_t));
+COMPILER_CHECK(sizeof(PTRDIFF_T) == sizeof(ptrdiff_t));
+COMPILER_CHECK(sizeof(INTMAX_T) == sizeof(intmax_t));
+
+#ifndef __APPLE__
+COMPILER_CHECK(sizeof(OFF64_T) == sizeof(off64_t));
+#endif
+
+// The following are the cases when pread (and friends) is used instead of
+// pread64. In those cases we need OFF_T to match off_t. We don't care about the
+// rest (they depend on _FILE_OFFSET_BITS setting when building an application).
+# if defined(__ANDROID__) || !defined _FILE_OFFSET_BITS || \
+  _FILE_OFFSET_BITS != 64
+COMPILER_CHECK(sizeof(OFF_T) == sizeof(off_t));
+# endif
+
+#endif
Index: libsanitizer/interception/Makefile.am
===================================================================
--- libsanitizer/interception/Makefile.am	(revision 195997)
+++ libsanitizer/interception/Makefile.am	(working copy)
@@ -1,4 +1,4 @@
-AM_CPPFLAGS = -I $(top_srcdir)/include 
+AM_CPPFLAGS = -I $(top_srcdir)/include -I $(top_srcdir)
  
 # May be used by toolexeclibdir.
 gcc_version := $(shell cat $(top_srcdir)/../gcc/BASE-VER)
@@ -13,7 +13,8 @@
 interception_files = \
         interception_linux.cc \
         interception_mac.cc \
-        interception_win.cc
+        interception_win.cc \
+	interception_type_test.cc
 
 libinterception_la_SOURCES = $(interception_files)
 
Index: libsanitizer/interception/interception.h
===================================================================
--- libsanitizer/interception/interception.h	(revision 195997)
+++ libsanitizer/interception/interception.h	(working copy)
@@ -17,7 +17,7 @@
 # error "Interception doesn't work on this operating system."
 #endif
 
-#include "sanitizer/common_interface_defs.h"
+#include "sanitizer_common/sanitizer_internal_defs.h"
 
 // These typedefs should be used only in the interceptor definitions to replace
 // the standard system types (e.g. SSIZE_T instead of ssize_t)
@@ -25,21 +25,17 @@
 typedef __sanitizer::sptr SSIZE_T;
 typedef __sanitizer::sptr PTRDIFF_T;
 typedef __sanitizer::s64  INTMAX_T;
-typedef __sanitizer::u64  OFF_T;
+// WARNING: OFF_T may be different from OS type off_t, depending on the value of
+// _FILE_OFFSET_BITS. This definition of OFF_T matches the ABI of system calls
+// like pread and mmap, as opposed to pread64 and mmap64.
+// Mac is special.
+#ifdef __APPLE__
+typedef __sanitizer::u64 OFF_T;
+#else
+typedef __sanitizer::uptr OFF_T;
+#endif
 typedef __sanitizer::u64  OFF64_T;
 
-// How to use this library:
-//      1) Include this header to define your own interceptors
-//         (see details below).
-//      2) Build all *.cc files and link against them.
-// On Mac you will also need to:
-//      3) Provide your own implementation for the following functions:
-//           mach_error_t __interception::allocate_island(void **ptr,
-//                                                      size_t size,
-//                                                      void *hint);
-//           mach_error_t __interception::deallocate_island(void *ptr);
-//         See "interception_mac.h" for more details.
-
 // How to add an interceptor:
 // Suppose you need to wrap/replace system function (generally, from libc):
 //      int foo(const char *bar, double baz);
@@ -80,21 +76,13 @@
 // This is not so on Mac OS, where the two-level namespace makes
 // our replacement functions invisible to other libraries. This may be overcomed
 // using the DYLD_FORCE_FLAT_NAMESPACE, but some errors loading the shared
-// libraries in Chromium were noticed when doing so. Instead we use
-// mach_override, a handy framework for patching functions at runtime.
-// To avoid possible name clashes, our replacement functions have
-// the "wrap_" prefix on Mac.
-// An alternative to function patching is to create a dylib containing a
-// __DATA,__interpose section that associates library functions with their
-// wrappers. When this dylib is preloaded before an executable using
-// DYLD_INSERT_LIBRARIES, it routes all the calls to interposed functions done
-// through stubs to the wrapper functions. Such a library is built with
-// -DMAC_INTERPOSE_FUNCTIONS=1.
+// libraries in Chromium were noticed when doing so.
+// Instead we create a dylib containing a __DATA,__interpose section that
+// associates library functions with their wrappers. When this dylib is
+// preloaded before an executable using DYLD_INSERT_LIBRARIES, it routes all
+// the calls to interposed functions done through stubs to the wrapper
+// functions.
 
-#if !defined(MAC_INTERPOSE_FUNCTIONS) || !defined(__APPLE__)
-# define MAC_INTERPOSE_FUNCTIONS 0
-#endif
-
 #if defined(__APPLE__)
 # define WRAP(x) wrap_##x
 # define WRAPPER_NAME(x) "wrap_"#x
@@ -120,7 +108,7 @@
     __attribute__((weak, alias("__interceptor_" #func), visibility("default")));
 #endif
 
-#if !MAC_INTERPOSE_FUNCTIONS
+#if !defined(__APPLE__)
 # define PTR_TO_REAL(x) real_##x
 # define REAL(x) __interception::PTR_TO_REAL(x)
 # define FUNC_TYPE(x) x##_f
@@ -130,11 +118,11 @@
     namespace __interception { \
       extern FUNC_TYPE(func) PTR_TO_REAL(func); \
     }
-#else  // MAC_INTERPOSE_FUNCTIONS
+#else  // __APPLE__
 # define REAL(x) x
 # define DECLARE_REAL(ret_type, func, ...) \
     extern "C" ret_type func(__VA_ARGS__);
-#endif  // MAC_INTERPOSE_FUNCTIONS
+#endif  // __APPLE__
 
 #define DECLARE_REAL_AND_INTERCEPTOR(ret_type, func, ...) \
   DECLARE_REAL(ret_type, func, __VA_ARGS__) \
@@ -144,7 +132,7 @@
 // macros does its job. In exceptional cases you may need to call REAL(foo)
 // without defining INTERCEPTOR(..., foo, ...). For example, if you override
 // foo with an interceptor for other function.
-#if !MAC_INTERPOSE_FUNCTIONS
+#if !defined(__APPLE__)
 # define DEFINE_REAL(ret_type, func, ...) \
     typedef ret_type (*FUNC_TYPE(func))(__VA_ARGS__); \
     namespace __interception { \
Index: libsanitizer/interception/interception_mac.h
===================================================================
--- libsanitizer/interception/interception_mac.h	(revision 195997)
+++ libsanitizer/interception/interception_mac.h	(working copy)
@@ -19,29 +19,7 @@
 #ifndef INTERCEPTION_MAC_H
 #define INTERCEPTION_MAC_H
 
-#include <mach/mach_error.h>
-#include <stddef.h>
+#define INTERCEPT_FUNCTION_MAC(func)
 
-// Allocate memory for the escape island. This cannot be moved to
-// mach_override, because each user of interceptors may specify its
-// own memory range for escape islands.
-extern "C" {
-mach_error_t __interception_allocate_island(void **ptr, size_t unused_size,
-                                            void *unused_hint);
-mach_error_t __interception_deallocate_island(void *ptr);
-}  // extern "C"
-
-namespace __interception {
-// returns true if the old function existed.
-bool OverrideFunction(uptr old_func, uptr new_func, uptr *orig_old_func);
-}  // namespace __interception
-
-# define OVERRIDE_FUNCTION_MAC(old_func, new_func) \
-    ::__interception::OverrideFunction( \
-          (::__interception::uptr)old_func, \
-          (::__interception::uptr)new_func, \
-          (::__interception::uptr*)((::__interception::uptr)&REAL(old_func)))
-# define INTERCEPT_FUNCTION_MAC(func) OVERRIDE_FUNCTION_MAC(func, WRAP(func))
-
 #endif  // INTERCEPTION_MAC_H
 #endif  // __APPLE__
Index: libsanitizer/interception/Makefile.in
===================================================================
--- libsanitizer/interception/Makefile.in	(revision 195997)
+++ libsanitizer/interception/Makefile.in	(working copy)
@@ -56,7 +56,7 @@
 LTLIBRARIES = $(noinst_LTLIBRARIES)
 libinterception_la_LIBADD =
 am__objects_1 = interception_linux.lo interception_mac.lo \
-	interception_win.lo
+	interception_win.lo interception_type_test.lo
 am_libinterception_la_OBJECTS = $(am__objects_1)
 libinterception_la_OBJECTS = $(am_libinterception_la_OBJECTS)
 DEFAULT_INCLUDES = -I.@am__isrc@
@@ -208,7 +208,7 @@
 top_build_prefix = @top_build_prefix@
 top_builddir = @top_builddir@
 top_srcdir = @top_srcdir@
-AM_CPPFLAGS = -I $(top_srcdir)/include 
+AM_CPPFLAGS = -I $(top_srcdir)/include -I $(top_srcdir)
 
 # May be used by toolexeclibdir.
 gcc_version := $(shell cat $(top_srcdir)/../gcc/BASE-VER)
@@ -221,7 +221,8 @@
 interception_files = \
         interception_linux.cc \
         interception_mac.cc \
-        interception_win.cc
+        interception_win.cc \
+	interception_type_test.cc
 
 libinterception_la_SOURCES = $(interception_files)
 
@@ -318,6 +319,7 @@
 
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/interception_linux.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/interception_mac.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/interception_type_test.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/interception_win.Plo@am__quote@
 
 .cc.o:
Index: libsanitizer/tsan/tsan_suppressions.h
===================================================================
--- libsanitizer/tsan/tsan_suppressions.h	(revision 195997)
+++ libsanitizer/tsan/tsan_suppressions.h	(working copy)
@@ -33,7 +33,7 @@
   char *templ;
 };
 
-Suppression *SuppressionParse(const char* supp);
+Suppression *SuppressionParse(Suppression *head, const char* supp);
 bool SuppressionMatch(char *templ, const char *str);
 
 }  // namespace __tsan
Index: libsanitizer/tsan/tsan_interceptors.cc
===================================================================
--- libsanitizer/tsan/tsan_interceptors.cc	(revision 195997)
+++ libsanitizer/tsan/tsan_interceptors.cc	(working copy)
@@ -51,9 +51,12 @@
 extern "C" int sigfillset(sigset_t *set);
 extern "C" void *pthread_self();
 extern "C" void _exit(int status);
-extern "C" int __cxa_atexit(void (*func)(void *arg), void *arg, void *dso);
 extern "C" int *__errno_location();
 extern "C" int fileno_unlocked(void *stream);
+extern "C" void *__libc_malloc(uptr size);
+extern "C" void *__libc_calloc(uptr size, uptr n);
+extern "C" void *__libc_realloc(void *ptr, uptr size);
+extern "C" void __libc_free(void *ptr);
 const int PTHREAD_MUTEX_RECURSIVE = 1;
 const int PTHREAD_MUTEX_RECURSIVE_NP = 1;
 const int kPthreadAttrSize = 56;
@@ -122,7 +125,7 @@
   int pending_signal_count;
   SignalDesc pending_signals[kSigCount];
 };
-}
+}  // namespace __tsan
 
 static SignalContext *SigCtx(ThreadState *thr) {
   SignalContext *ctx = (SignalContext*)thr->signal_ctx;
@@ -238,12 +241,15 @@
 
   typedef void(*atexit_t)();
 
-  int atexit(ThreadState *thr, uptr pc, atexit_t f) {
+  int atexit(ThreadState *thr, uptr pc, bool is_on_exit,
+             atexit_t f, void *arg) {
     Lock l(&mtx_);
     if (pos_ == kMaxAtExit)
       return 1;
     Release(thr, pc, (uptr)this);
     stack_[pos_] = f;
+    args_[pos_] = arg;
+    is_on_exits_[pos_] = is_on_exit;
     pos_++;
     return 0;
   }
@@ -252,11 +258,15 @@
     CHECK_EQ(thr->in_rtl, 0);
     for (;;) {
       atexit_t f = 0;
+      void *arg = 0;
+      bool is_on_exit = false;
       {
         Lock l(&mtx_);
         if (pos_) {
           pos_--;
           f = stack_[pos_];
+          arg = args_[pos_];
+          is_on_exit = is_on_exits_[pos_];
           ScopedInRtl in_rtl;
           Acquire(thr, pc, (uptr)this);
         }
@@ -265,7 +275,10 @@
         break;
       DPrintf("#%d: executing atexit func %p\n", thr->tid, f);
       CHECK_EQ(thr->in_rtl, 0);
-      f();
+      if (is_on_exit)
+        ((void(*)(int status, void *arg))f)(0, arg);
+      else
+        ((void(*)(void *arg, void *dso))f)(arg, 0);
     }
   }
 
@@ -273,6 +286,8 @@
   static const int kMaxAtExit = 128;
   Mutex mtx_;
   atexit_t stack_[kMaxAtExit];
+  void *args_[kMaxAtExit];
+  bool is_on_exits_[kMaxAtExit];
   int pos_;
 };
 
@@ -282,20 +297,34 @@
   ThreadState * thr = cur_thread();
   uptr pc = 0;
   atexit_ctx->exit(thr, pc);
-  {
-    ScopedInRtl in_rtl;
-    DestroyAndFree(atexit_ctx);
-  }
   int status = Finalize(cur_thread());
   if (status)
     _exit(status);
 }
 
 TSAN_INTERCEPTOR(int, atexit, void (*f)()) {
+  if (cur_thread()->in_symbolizer)
+    return 0;
   SCOPED_TSAN_INTERCEPTOR(atexit, f);
-  return atexit_ctx->atexit(thr, pc, f);
+  return atexit_ctx->atexit(thr, pc, false, (void(*)())f, 0);
 }
 
+TSAN_INTERCEPTOR(int, on_exit, void(*f)(int, void*), void *arg) {
+  if (cur_thread()->in_symbolizer)
+    return 0;
+  SCOPED_TSAN_INTERCEPTOR(on_exit, f, arg);
+  return atexit_ctx->atexit(thr, pc, true, (void(*)())f, arg);
+}
+
+TSAN_INTERCEPTOR(int, __cxa_atexit, void (*f)(void *a), void *arg, void *dso) {
+  if (cur_thread()->in_symbolizer)
+    return 0;
+  SCOPED_TSAN_INTERCEPTOR(__cxa_atexit, f, arg, dso);
+  if (dso)
+    return REAL(__cxa_atexit)(f, arg, dso);
+  return atexit_ctx->atexit(thr, pc, false, (void(*)())f, arg);
+}
+
 TSAN_INTERCEPTOR(void, longjmp, void *env, int val) {
   SCOPED_TSAN_INTERCEPTOR(longjmp, env, val);
   Printf("ThreadSanitizer: longjmp() is not supported\n");
@@ -309,6 +338,8 @@
 }
 
 TSAN_INTERCEPTOR(void*, malloc, uptr size) {
+  if (cur_thread()->in_symbolizer)
+    return __libc_malloc(size);
   void *p = 0;
   {
     SCOPED_INTERCEPTOR_RAW(malloc, size);
@@ -324,6 +355,9 @@
 }
 
 TSAN_INTERCEPTOR(void*, calloc, uptr size, uptr n) {
+  if (cur_thread()->in_symbolizer)
+    return __libc_calloc(size, n);
+  if (__sanitizer::CallocShouldReturnNullDueToOverflow(size, n)) return 0;
   void *p = 0;
   {
     SCOPED_INTERCEPTOR_RAW(calloc, size, n);
@@ -335,6 +369,8 @@
 }
 
 TSAN_INTERCEPTOR(void*, realloc, void *p, uptr size) {
+  if (cur_thread()->in_symbolizer)
+    return __libc_realloc(p, size);
   if (p)
     invoke_free_hook(p);
   {
@@ -348,6 +384,8 @@
 TSAN_INTERCEPTOR(void, free, void *p) {
   if (p == 0)
     return;
+  if (cur_thread()->in_symbolizer)
+    return __libc_free(p);
   invoke_free_hook(p);
   SCOPED_INTERCEPTOR_RAW(free, p);
   user_free(thr, pc, p);
@@ -356,12 +394,16 @@
 TSAN_INTERCEPTOR(void, cfree, void *p) {
   if (p == 0)
     return;
+  if (cur_thread()->in_symbolizer)
+    return __libc_free(p);
   invoke_free_hook(p);
   SCOPED_INTERCEPTOR_RAW(cfree, p);
   user_free(thr, pc, p);
 }
 
 #define OPERATOR_NEW_BODY(mangled_name) \
+  if (cur_thread()->in_symbolizer) \
+    return __libc_malloc(size); \
   void *p = 0; \
   {  \
     SCOPED_INTERCEPTOR_RAW(mangled_name, size); \
@@ -385,6 +427,8 @@
 
 #define OPERATOR_DELETE_BODY(mangled_name) \
   if (ptr == 0) return;  \
+  if (cur_thread()->in_symbolizer) \
+    return __libc_free(ptr); \
   invoke_free_hook(ptr);  \
   SCOPED_INTERCEPTOR_RAW(mangled_name, ptr);  \
   user_free(thr, pc, ptr);
@@ -549,6 +593,8 @@
     return MAP_FAILED;
   void *res = REAL(mmap)(addr, sz, prot, flags, fd, off);
   if (res != MAP_FAILED) {
+    if (fd > 0)
+      FdAccess(thr, pc, fd);
     MemoryResetRange(thr, pc, (uptr)res, sz);
   }
   return res;
@@ -561,6 +607,8 @@
     return MAP_FAILED;
   void *res = REAL(mmap64)(addr, sz, prot, flags, fd, off);
   if (res != MAP_FAILED) {
+    if (fd > 0)
+      FdAccess(thr, pc, fd);
     MemoryResetRange(thr, pc, (uptr)res, sz);
   }
   return res;
@@ -958,14 +1006,14 @@
 
 TSAN_INTERCEPTOR(int, pthread_barrier_init, void *b, void *a, unsigned count) {
   SCOPED_TSAN_INTERCEPTOR(pthread_barrier_init, b, a, count);
-  MemoryWrite1Byte(thr, pc, (uptr)b);
+  MemoryWrite(thr, pc, (uptr)b, kSizeLog1);
   int res = REAL(pthread_barrier_init)(b, a, count);
   return res;
 }
 
 TSAN_INTERCEPTOR(int, pthread_barrier_destroy, void *b) {
   SCOPED_TSAN_INTERCEPTOR(pthread_barrier_destroy, b);
-  MemoryWrite1Byte(thr, pc, (uptr)b);
+  MemoryWrite(thr, pc, (uptr)b, kSizeLog1);
   int res = REAL(pthread_barrier_destroy)(b);
   return res;
 }
@@ -973,9 +1021,9 @@
 TSAN_INTERCEPTOR(int, pthread_barrier_wait, void *b) {
   SCOPED_TSAN_INTERCEPTOR(pthread_barrier_wait, b);
   Release(thr, pc, (uptr)b);
-  MemoryRead1Byte(thr, pc, (uptr)b);
+  MemoryRead(thr, pc, (uptr)b, kSizeLog1);
   int res = REAL(pthread_barrier_wait)(b);
-  MemoryRead1Byte(thr, pc, (uptr)b);
+  MemoryRead(thr, pc, (uptr)b, kSizeLog1);
   if (res == 0 || res == PTHREAD_BARRIER_SERIAL_THREAD) {
     Acquire(thr, pc, (uptr)b);
   }
@@ -1062,6 +1110,74 @@
   return res;
 }
 
+TSAN_INTERCEPTOR(int, __xstat, int version, const char *path, void *buf) {
+  SCOPED_TSAN_INTERCEPTOR(__xstat, version, path, buf);
+  return REAL(__xstat)(version, path, buf);
+}
+
+TSAN_INTERCEPTOR(int, stat, const char *path, void *buf) {
+  SCOPED_TSAN_INTERCEPTOR(__xstat, 0, path, buf);
+  return REAL(__xstat)(0, path, buf);
+}
+
+TSAN_INTERCEPTOR(int, __xstat64, int version, const char *path, void *buf) {
+  SCOPED_TSAN_INTERCEPTOR(__xstat64, version, path, buf);
+  return REAL(__xstat64)(version, path, buf);
+}
+
+TSAN_INTERCEPTOR(int, stat64, const char *path, void *buf) {
+  SCOPED_TSAN_INTERCEPTOR(__xstat64, 0, path, buf);
+  return REAL(__xstat64)(0, path, buf);
+}
+
+TSAN_INTERCEPTOR(int, __lxstat, int version, const char *path, void *buf) {
+  SCOPED_TSAN_INTERCEPTOR(__lxstat, version, path, buf);
+  return REAL(__lxstat)(version, path, buf);
+}
+
+TSAN_INTERCEPTOR(int, lstat, const char *path, void *buf) {
+  SCOPED_TSAN_INTERCEPTOR(__lxstat, 0, path, buf);
+  return REAL(__lxstat)(0, path, buf);
+}
+
+TSAN_INTERCEPTOR(int, __lxstat64, int version, const char *path, void *buf) {
+  SCOPED_TSAN_INTERCEPTOR(__lxstat64, version, path, buf);
+  return REAL(__lxstat64)(version, path, buf);
+}
+
+TSAN_INTERCEPTOR(int, lstat64, const char *path, void *buf) {
+  SCOPED_TSAN_INTERCEPTOR(__lxstat64, 0, path, buf);
+  return REAL(__lxstat64)(0, path, buf);
+}
+
+TSAN_INTERCEPTOR(int, __fxstat, int version, int fd, void *buf) {
+  SCOPED_TSAN_INTERCEPTOR(__fxstat, version, fd, buf);
+  if (fd > 0)
+    FdAccess(thr, pc, fd);
+  return REAL(__fxstat)(version, fd, buf);
+}
+
+TSAN_INTERCEPTOR(int, fstat, int fd, void *buf) {
+  SCOPED_TSAN_INTERCEPTOR(__fxstat, 0, fd, buf);
+  if (fd > 0)
+    FdAccess(thr, pc, fd);
+  return REAL(__fxstat)(0, fd, buf);
+}
+
+TSAN_INTERCEPTOR(int, __fxstat64, int version, int fd, void *buf) {
+  SCOPED_TSAN_INTERCEPTOR(__fxstat64, version, fd, buf);
+  if (fd > 0)
+    FdAccess(thr, pc, fd);
+  return REAL(__fxstat64)(version, fd, buf);
+}
+
+TSAN_INTERCEPTOR(int, fstat64, int fd, void *buf) {
+  SCOPED_TSAN_INTERCEPTOR(__fxstat64, 0, fd, buf);
+  if (fd > 0)
+    FdAccess(thr, pc, fd);
+  return REAL(__fxstat64)(0, fd, buf);
+}
+
 TSAN_INTERCEPTOR(int, open, const char *name, int flags, int mode) {
   SCOPED_TSAN_INTERCEPTOR(open, name, flags, mode);
   int fd = REAL(open)(name, flags, mode);
@@ -1177,6 +1293,22 @@
   return res;
 }
 
+TSAN_INTERCEPTOR(int, bind, int fd, void *addr, unsigned addrlen) {
+  SCOPED_TSAN_INTERCEPTOR(bind, fd, addr, addrlen);
+  int res = REAL(bind)(fd, addr, addrlen);
+  if (fd > 0 && res == 0)
+    FdAccess(thr, pc, fd);
+  return res;
+}
+
+TSAN_INTERCEPTOR(int, listen, int fd, int backlog) {
+  SCOPED_TSAN_INTERCEPTOR(listen, fd, backlog);
+  int res = REAL(listen)(fd, backlog);
+  if (fd > 0 && res == 0)
+    FdAccess(thr, pc, fd);
+  return res;
+}
+
 TSAN_INTERCEPTOR(int, accept, int fd, void *addr, unsigned *addrlen) {
   SCOPED_TSAN_INTERCEPTOR(accept, fd, addr, addrlen);
   int fd2 = REAL(accept)(fd, addr, addrlen);
@@ -1223,6 +1355,18 @@
   return REAL(__close)(fd);
 }
 
+// glibc guts
+TSAN_INTERCEPTOR(void, __res_iclose, void *state, bool free_addr) {
+  SCOPED_TSAN_INTERCEPTOR(__res_iclose, state, free_addr);
+  int fds[64];
+  int cnt = ExtractResolvFDs(state, fds, ARRAY_SIZE(fds));
+  for (int i = 0; i < cnt; i++) {
+    if (fds[i] > 0)
+      FdClose(thr, pc, fds[i]);
+  }
+  REAL(__res_iclose)(state, free_addr);
+}
+
 TSAN_INTERCEPTOR(int, pipe, int *pipefd) {
   SCOPED_TSAN_INTERCEPTOR(pipe, pipefd);
   int res = REAL(pipe)(pipefd);
@@ -1765,6 +1909,18 @@
   TSAN_INTERCEPT(sem_post);
   TSAN_INTERCEPT(sem_getvalue);
 
+  TSAN_INTERCEPT(stat);
+  TSAN_INTERCEPT(__xstat);
+  TSAN_INTERCEPT(stat64);
+  TSAN_INTERCEPT(__xstat64);
+  TSAN_INTERCEPT(lstat);
+  TSAN_INTERCEPT(__lxstat);
+  TSAN_INTERCEPT(lstat64);
+  TSAN_INTERCEPT(__lxstat64);
+  TSAN_INTERCEPT(fstat);
+  TSAN_INTERCEPT(__fxstat);
+  TSAN_INTERCEPT(fstat64);
+  TSAN_INTERCEPT(__fxstat64);
   TSAN_INTERCEPT(open);
   TSAN_INTERCEPT(open64);
   TSAN_INTERCEPT(creat);
@@ -1779,11 +1935,15 @@
   TSAN_INTERCEPT(socket);
   TSAN_INTERCEPT(socketpair);
   TSAN_INTERCEPT(connect);
+  TSAN_INTERCEPT(bind);
+  TSAN_INTERCEPT(listen);
   TSAN_INTERCEPT(accept);
   TSAN_INTERCEPT(accept4);
   TSAN_INTERCEPT(epoll_create);
   TSAN_INTERCEPT(epoll_create1);
   TSAN_INTERCEPT(close);
+  TSAN_INTERCEPT(__close);
+  TSAN_INTERCEPT(__res_iclose);
   TSAN_INTERCEPT(pipe);
   TSAN_INTERCEPT(pipe2);
 
@@ -1826,6 +1986,8 @@
   TSAN_INTERCEPT(munlockall);
 
   TSAN_INTERCEPT(fork);
+  TSAN_INTERCEPT(on_exit);
+  TSAN_INTERCEPT(__cxa_atexit);
 
   // Need to setup it, because interceptors check that the function is resolved.
   // But atexit is emitted directly into the module, so can't be resolved.
@@ -1833,7 +1995,7 @@
   atexit_ctx = new(internal_alloc(MBlockAtExit, sizeof(AtExitContext)))
       AtExitContext();
 
-  if (__cxa_atexit(&finalize, 0, 0)) {
+  if (REAL(__cxa_atexit)(&finalize, 0, 0)) {
     Printf("ThreadSanitizer: failed to setup atexit callback\n");
     Die();
   }
Index: libsanitizer/tsan/tsan_defs.h
===================================================================
--- libsanitizer/tsan/tsan_defs.h	(revision 195997)
+++ libsanitizer/tsan/tsan_defs.h	(working copy)
@@ -26,16 +26,19 @@
 const bool kGoMode = true;
 const bool kCppMode = false;
 const char *const kTsanOptionsEnv = "GORACE";
+// Go linker does not support weak symbols.
+#define CPP_WEAK
 #else
 const bool kGoMode = false;
 const bool kCppMode = true;
 const char *const kTsanOptionsEnv = "TSAN_OPTIONS";
+#define CPP_WEAK WEAK
 #endif
 
 const int kTidBits = 13;
 const unsigned kMaxTid = 1 << kTidBits;
 const unsigned kMaxTidInClock = kMaxTid * 2;  // This includes msb 'freed' bit.
-const int kClkBits = 43;
+const int kClkBits = 42;
 #ifndef TSAN_GO
 const int kShadowStackSize = 4 * 1024;
 const int kTraceStackSize = 256;
Index: libsanitizer/tsan/tsan_rtl_thread.cc
===================================================================
--- libsanitizer/tsan/tsan_rtl_thread.cc	(revision 195997)
+++ libsanitizer/tsan/tsan_rtl_thread.cc	(working copy)
@@ -207,6 +207,9 @@
   thr->shadow_stack_pos = thr->shadow_stack;
   thr->shadow_stack_end = thr->shadow_stack + kInitStackSize;
 #endif
+#ifndef TSAN_GO
+  AllocatorThreadStart(thr);
+#endif
   tctx->thr = thr;
   thr->fast_synch_epoch = tctx->epoch0;
   thr->clock.set(tid, tctx->epoch0);
@@ -267,7 +270,7 @@
   tctx->epoch1 = thr->fast_state.epoch();
 
 #ifndef TSAN_GO
-  AlloctorThreadFinish(thr);
+  AllocatorThreadFinish(thr);
 #endif
   thr->~ThreadState();
   StatAggregate(ctx->stat, thr->stat);
@@ -392,7 +395,7 @@
     Shadow cur(fast_state);
     cur.SetWrite(is_write);
     cur.SetAddr0AndSizeLog(addr & (kShadowCell - 1), kAccessSizeLog);
-    MemoryAccessImpl(thr, addr, kAccessSizeLog, is_write,
+    MemoryAccessImpl(thr, addr, kAccessSizeLog, is_write, false,
         shadow_mem, cur);
   }
   if (unaligned)
@@ -403,7 +406,7 @@
     Shadow cur(fast_state);
     cur.SetWrite(is_write);
     cur.SetAddr0AndSizeLog(0, kAccessSizeLog);
-    MemoryAccessImpl(thr, addr, kAccessSizeLog, is_write,
+    MemoryAccessImpl(thr, addr, kAccessSizeLog, is_write, false,
         shadow_mem, cur);
     shadow_mem += kShadowCnt;
   }
@@ -413,24 +416,8 @@
     Shadow cur(fast_state);
     cur.SetWrite(is_write);
     cur.SetAddr0AndSizeLog(addr & (kShadowCell - 1), kAccessSizeLog);
-    MemoryAccessImpl(thr, addr, kAccessSizeLog, is_write,
+    MemoryAccessImpl(thr, addr, kAccessSizeLog, is_write, false,
         shadow_mem, cur);
   }
 }
-
-void MemoryRead1Byte(ThreadState *thr, uptr pc, uptr addr) {
-  MemoryAccess(thr, pc, addr, 0, 0);
-}
-
-void MemoryWrite1Byte(ThreadState *thr, uptr pc, uptr addr) {
-  MemoryAccess(thr, pc, addr, 0, 1);
-}
-
-void MemoryRead8Byte(ThreadState *thr, uptr pc, uptr addr) {
-  MemoryAccess(thr, pc, addr, 3, 0);
-}
-
-void MemoryWrite8Byte(ThreadState *thr, uptr pc, uptr addr) {
-  MemoryAccess(thr, pc, addr, 3, 1);
-}
 }  // namespace __tsan
Index: libsanitizer/tsan/tsan_mman.h
===================================================================
--- libsanitizer/tsan/tsan_mman.h	(revision 195997)
+++ libsanitizer/tsan/tsan_mman.h	(working copy)
@@ -18,7 +18,9 @@
 const uptr kDefaultAlignment = 16;
 
 void InitializeAllocator();
-void AlloctorThreadFinish(ThreadState *thr);
+void AllocatorThreadStart(ThreadState *thr);
+void AllocatorThreadFinish(ThreadState *thr);
+void AllocatorPrintStats();
 
 // For user allocations.
 void *user_alloc(ThreadState *thr, uptr pc, uptr sz,
Index: libsanitizer/tsan/tsan_rtl_report.cc
===================================================================
--- libsanitizer/tsan/tsan_rtl_report.cc	(revision 195997)
+++ libsanitizer/tsan/tsan_rtl_report.cc	(working copy)
@@ -13,6 +13,7 @@
 #include "sanitizer_common/sanitizer_placement_new.h"
 #include "sanitizer_common/sanitizer_stackdepot.h"
 #include "sanitizer_common/sanitizer_common.h"
+#include "sanitizer_common/sanitizer_stacktrace.h"
 #include "tsan_platform.h"
 #include "tsan_rtl.h"
 #include "tsan_suppressions.h"
@@ -27,12 +28,15 @@
 
 using namespace __sanitizer;  // NOLINT
 
+static ReportStack *SymbolizeStack(const StackTrace& trace);
+
 void TsanCheckFailed(const char *file, int line, const char *cond,
                      u64 v1, u64 v2) {
   ScopedInRtl in_rtl;
   Printf("FATAL: ThreadSanitizer CHECK failed: "
          "%s:%d \"%s\" (0x%zx, 0x%zx)\n",
          file, line, cond, (uptr)v1, (uptr)v2);
+  PrintCurrentStackSlow();
   Die();
 }
 
@@ -144,7 +148,8 @@
   mop->tid = s.tid();
   mop->addr = addr + s.addr0();
   mop->size = s.size();
-  mop->write = s.is_write();
+  mop->write = s.IsWrite();
+  mop->atomic = s.IsAtomic();
   mop->stack = SymbolizeStack(*stack);
   for (uptr i = 0; i < mset->Size(); i++) {
     MutexSet::Desc d = mset->Get(i);
@@ -458,9 +463,12 @@
 
 bool OutputReport(Context *ctx,
                   const ScopedReport &srep,
-                  const ReportStack *suppress_stack) {
+                  const ReportStack *suppress_stack1,
+                  const ReportStack *suppress_stack2) {
   const ReportDesc *rep = srep.GetReport();
-  const uptr suppress_pc = IsSuppressed(rep->typ, suppress_stack);
+  uptr suppress_pc = IsSuppressed(rep->typ, suppress_stack1);
+  if (suppress_pc == 0)
+    suppress_pc = IsSuppressed(rep->typ, suppress_stack2);
   if (suppress_pc != 0) {
     FiredSuppression supp = {srep.GetReport()->typ, suppress_pc};
     ctx->fired_suppressions.PushBack(supp);
@@ -486,6 +494,13 @@
   return false;
 }
 
+bool FrameIsInternal(const ReportStack *frame) {
+  return frame != 0 && frame->file != 0
+      && (internal_strstr(frame->file, "tsan_interceptors.cc") ||
+          internal_strstr(frame->file, "sanitizer_common_interceptors.inc") ||
+          internal_strstr(frame->file, "tsan_interface_"));
+}
+
 // On programs that use Java we see weird reports like:
 // WARNING: ThreadSanitizer: data race (pid=22512)
 //   Read of size 8 at 0x7d2b00084318 by thread 100:
@@ -495,22 +510,20 @@
 //     #0 strncpy tsan_interceptors.cc:501 (foo+0x00000d8e0919)
 //     #1 <null> <null>:0 (0x7f7ad9b42707)
 static bool IsJavaNonsense(const ReportDesc *rep) {
+#ifndef TSAN_GO
   for (uptr i = 0; i < rep->mops.Size(); i++) {
     ReportMop *mop = rep->mops[i];
     ReportStack *frame = mop->stack;
-    if (frame != 0 && frame->func != 0
-        && (internal_strcmp(frame->func, "memset") == 0
-        || internal_strcmp(frame->func, "memcpy") == 0
-        || internal_strcmp(frame->func, "memmove") == 0
-        || internal_strcmp(frame->func, "strcmp") == 0
-        || internal_strcmp(frame->func, "strncpy") == 0
-        || internal_strcmp(frame->func, "strlen") == 0
-        || internal_strcmp(frame->func, "free") == 0
-        || internal_strcmp(frame->func, "pthread_mutex_lock") == 0)) {
+    if (frame == 0
+        || (frame->func == 0 && frame->file == 0 && frame->line == 0
+          && frame->module == 0)) {
+      return true;
+    }
+    if (FrameIsInternal(frame)) {
       frame = frame->next;
       if (frame == 0
           || (frame->func == 0 && frame->file == 0 && frame->line == 0
-            && frame->module == 0)) {
+          && frame->module == 0)) {
         if (frame) {
           FiredSuppression supp = {rep->typ, frame->pc};
           CTX()->fired_suppressions.PushBack(supp);
@@ -519,14 +532,31 @@
       }
     }
   }
+#endif
   return false;
 }
 
+static bool RaceBetweenAtomicAndFree(ThreadState *thr) {
+  Shadow s0(thr->racy_state[0]);
+  Shadow s1(thr->racy_state[1]);
+  CHECK(!(s0.IsAtomic() && s1.IsAtomic()));
+  if (!s0.IsAtomic() && !s1.IsAtomic())
+    return true;
+  if (s0.IsAtomic() && s1.IsFreed())
+    return true;
+  if (s1.IsAtomic() && thr->is_freeing)
+    return true;
+  return false;
+}
+
 void ReportRace(ThreadState *thr) {
   if (!flags()->report_bugs)
     return;
   ScopedInRtl in_rtl;
 
+  if (!flags()->report_atomic_races && !RaceBetweenAtomicAndFree(thr))
+    return;
+
   if (thr->in_signal_handler)
     Printf("ThreadSanitizer: printing report from signal handler."
            " Can crash or hang.\n");
@@ -597,7 +627,8 @@
   }
 #endif
 
-  if (!OutputReport(ctx, rep, rep.GetReport()->mops[0]->stack))
+  if (!OutputReport(ctx, rep, rep.GetReport()->mops[0]->stack,
+                              rep.GetReport()->mops[1]->stack))
     return;
 
   AddRacyStacks(thr, traces, addr_min, addr_max);
@@ -609,4 +640,16 @@
   PrintStack(SymbolizeStack(trace));
 }
 
+void PrintCurrentStackSlow() {
+#ifndef TSAN_GO
+  __sanitizer::StackTrace *ptrace = new(internal_alloc(MBlockStackTrace,
+      sizeof(__sanitizer::StackTrace))) __sanitizer::StackTrace;
+  ptrace->SlowUnwindStack(__sanitizer::StackTrace::GetCurrentPc(),
+      kStackTraceMax);
+  StackTrace trace;
+  trace.Init(ptrace->trace, ptrace->size);
+  PrintStack(SymbolizeStack(trace));
+#endif
+}
+
 }  // namespace __tsan
Index: libsanitizer/tsan/tsan_interface_atomic.cc
===================================================================
--- libsanitizer/tsan/tsan_interface_atomic.cc	(revision 195997)
+++ libsanitizer/tsan/tsan_interface_atomic.cc	(working copy)
@@ -18,25 +18,42 @@
 // http://www.hpl.hp.com/personal/Hans_Boehm/c++mm/
 
 #include "sanitizer_common/sanitizer_placement_new.h"
+#include "sanitizer_common/sanitizer_stacktrace.h"
 #include "tsan_interface_atomic.h"
 #include "tsan_flags.h"
 #include "tsan_rtl.h"
 
 using namespace __tsan;  // NOLINT
 
+#define SCOPED_ATOMIC(func, ...) \
+    const uptr callpc = (uptr)__builtin_return_address(0); \
+    uptr pc = __sanitizer::StackTrace::GetCurrentPc(); \
+    pc = __sanitizer::StackTrace::GetPreviousInstructionPc(pc); \
+    mo = ConvertOrder(mo); \
+    mo = flags()->force_seq_cst_atomics ? (morder)mo_seq_cst : mo; \
+    ThreadState *const thr = cur_thread(); \
+    AtomicStatInc(thr, sizeof(*a), mo, StatAtomic##func); \
+    ScopedAtomic sa(thr, callpc, __FUNCTION__); \
+    return Atomic##func(thr, pc, __VA_ARGS__); \
+/**/
+
 class ScopedAtomic {
  public:
   ScopedAtomic(ThreadState *thr, uptr pc, const char *func)
       : thr_(thr) {
-    CHECK_EQ(thr_->in_rtl, 1);  // 1 due to our own ScopedInRtl member.
+    CHECK_EQ(thr_->in_rtl, 0);
+    ProcessPendingSignals(thr);
+    FuncEntry(thr_, pc);
     DPrintf("#%d: %s\n", thr_->tid, func);
+    thr_->in_rtl++;
   }
   ~ScopedAtomic() {
-    CHECK_EQ(thr_->in_rtl, 1);
+    thr_->in_rtl--;
+    CHECK_EQ(thr_->in_rtl, 0);
+    FuncExit(thr_);
   }
  private:
   ThreadState *thr_;
-  ScopedInRtl in_rtl_;
 };
 
 // Some shortcuts.
@@ -210,16 +227,19 @@
 }
 #endif
 
-#define SCOPED_ATOMIC(func, ...) \
-    mo = ConvertOrder(mo); \
-    mo = flags()->force_seq_cst_atomics ? (morder)mo_seq_cst : mo; \
-    ThreadState *const thr = cur_thread(); \
-    ProcessPendingSignals(thr); \
-    const uptr pc = (uptr)__builtin_return_address(0); \
-    AtomicStatInc(thr, sizeof(*a), mo, StatAtomic##func); \
-    ScopedAtomic sa(thr, pc, __FUNCTION__); \
-    return Atomic##func(thr, pc, __VA_ARGS__); \
-/**/
+template<typename T>
+static int SizeLog() {
+  if (sizeof(T) <= 1)
+    return kSizeLog1;
+  else if (sizeof(T) <= 2)
+    return kSizeLog2;
+  else if (sizeof(T) <= 4)
+    return kSizeLog4;
+  else
+    return kSizeLog8;
+  // For 16-byte atomics we also use 8-byte memory access,
+  // this leads to false negatives only in very obscure cases.
+}
 
 template<typename T>
 static T AtomicLoad(ThreadState *thr, uptr pc, const volatile T *a,
@@ -227,14 +247,17 @@
   CHECK(IsLoadOrder(mo));
   // This fast-path is critical for performance.
   // Assume the access is atomic.
-  if (!IsAcquireOrder(mo) && sizeof(T) <= sizeof(a))
+  if (!IsAcquireOrder(mo) && sizeof(T) <= sizeof(a)) {
+    MemoryReadAtomic(thr, pc, (uptr)a, SizeLog<T>());
     return *a;
+  }
   SyncVar *s = CTX()->synctab.GetOrCreateAndLock(thr, pc, (uptr)a, false);
   thr->clock.set(thr->tid, thr->fast_state.epoch());
   thr->clock.acquire(&s->clock);
   T v = *a;
   s->mtx.ReadUnlock();
   __sync_synchronize();
+  MemoryReadAtomic(thr, pc, (uptr)a, SizeLog<T>());
   return v;
 }
 
@@ -242,6 +265,7 @@
 static void AtomicStore(ThreadState *thr, uptr pc, volatile T *a, T v,
     morder mo) {
   CHECK(IsStoreOrder(mo));
+  MemoryWriteAtomic(thr, pc, (uptr)a, SizeLog<T>());
   // This fast-path is critical for performance.
   // Assume the access is atomic.
   // Strictly saying even relaxed store cuts off release sequence,
@@ -263,6 +287,7 @@
 
 template<typename T, T (*F)(volatile T *v, T op)>
 static T AtomicRMW(ThreadState *thr, uptr pc, volatile T *a, T v, morder mo) {
+  MemoryWriteAtomic(thr, pc, (uptr)a, SizeLog<T>());
   SyncVar *s = CTX()->synctab.GetOrCreateAndLock(thr, pc, (uptr)a, true);
   thr->clock.set(thr->tid, thr->fast_state.epoch());
   if (IsAcqRelOrder(mo))
@@ -322,6 +347,7 @@
 static bool AtomicCAS(ThreadState *thr, uptr pc,
     volatile T *a, T *c, T v, morder mo, morder fmo) {
   (void)fmo;  // Unused because llvm does not pass it yet.
+  MemoryWriteAtomic(thr, pc, (uptr)a, SizeLog<T>());
   SyncVar *s = CTX()->synctab.GetOrCreateAndLock(thr, pc, (uptr)a, true);
   thr->clock.set(thr->tid, thr->fast_state.epoch());
   if (IsAcqRelOrder(mo))
Index: libsanitizer/tsan/tsan_interface_ann.h
===================================================================
--- libsanitizer/tsan/tsan_interface_ann.h	(revision 195997)
+++ libsanitizer/tsan/tsan_interface_ann.h	(working copy)
@@ -12,7 +12,7 @@
 #ifndef TSAN_INTERFACE_ANN_H
 #define TSAN_INTERFACE_ANN_H
 
-#include <sanitizer/common_interface_defs.h>
+#include <sanitizer_common/sanitizer_internal_defs.h>
 
 // This header should NOT include any other headers.
 // All functions in this header are extern "C" and start with __tsan_.
Index: libsanitizer/tsan/tsan_flags.h
===================================================================
--- libsanitizer/tsan/tsan_flags.h	(revision 195997)
+++ libsanitizer/tsan/tsan_flags.h	(working copy)
@@ -41,6 +41,8 @@
   // Report violations of async signal-safety
   // (e.g. malloc() call from a signal handler).
   bool report_signal_unsafe;
+  // Report races between atomic and plain memory accesses.
+  bool report_atomic_races;
   // If set, all atomics are effectively sequentially consistent (seq_cst),
   // regardless of what user actually specified.
   bool force_seq_cst_atomics;
@@ -84,6 +86,6 @@
 
 Flags *flags();
 void InitializeFlags(Flags *flags, const char *env);
-}
+}  // namespace __tsan
 
 #endif  // TSAN_FLAGS_H
Index: libsanitizer/tsan/tsan_interface.h
===================================================================
--- libsanitizer/tsan/tsan_interface.h	(revision 195997)
+++ libsanitizer/tsan/tsan_interface.h	(working copy)
@@ -14,7 +14,7 @@
 #ifndef TSAN_INTERFACE_H
 #define TSAN_INTERFACE_H
 
-#include <sanitizer/common_interface_defs.h>
+#include <sanitizer_common/sanitizer_internal_defs.h>
 
 // This header should NOT include any other headers.
 // All functions in this header are extern "C" and start with __tsan_.
Index: libsanitizer/tsan/tsan_platform_linux.cc
===================================================================
--- libsanitizer/tsan/tsan_platform_linux.cc	(revision 195997)
+++ libsanitizer/tsan/tsan_platform_linux.cc	(working copy)
@@ -38,6 +38,8 @@
 #include <errno.h>
 #include <sched.h>
 #include <dlfcn.h>
+#define __need_res_state
+#include <resolv.h>
 
 extern "C" int arch_prctl(int code, __sanitizer::uptr *addr);
 
@@ -287,6 +289,19 @@
   return g_data_start && addr >= g_data_start && addr < g_data_end;
 }
 
+#ifndef TSAN_GO
+int ExtractResolvFDs(void *state, int *fds, int nfd) {
+  int cnt = 0;
+  __res_state *statp = (__res_state*)state;
+  for (int i = 0; i < MAXNS && cnt < nfd; i++) {
+    if (statp->_u._ext.nsaddrs[i] && statp->_u._ext.nssocks[i] != -1)
+      fds[cnt++] = statp->_u._ext.nssocks[i];
+  }
+  return cnt;
+}
+#endif
+
+
 }  // namespace __tsan
 
 #endif  // #ifdef __linux__
Index: libsanitizer/tsan/tsan_interface_inl.h
===================================================================
--- libsanitizer/tsan/tsan_interface_inl.h	(revision 195997)
+++ libsanitizer/tsan/tsan_interface_inl.h	(working copy)
@@ -17,41 +17,41 @@
 using namespace __tsan;  // NOLINT
 
 void __tsan_read1(void *addr) {
-  MemoryAccess(cur_thread(), CALLERPC, (uptr)addr, 0, 0);
+  MemoryRead(cur_thread(), CALLERPC, (uptr)addr, kSizeLog1);
 }
 
 void __tsan_read2(void *addr) {
-  MemoryAccess(cur_thread(), CALLERPC, (uptr)addr, 1, 0);
+  MemoryRead(cur_thread(), CALLERPC, (uptr)addr, kSizeLog2);
 }
 
 void __tsan_read4(void *addr) {
-  MemoryAccess(cur_thread(), CALLERPC, (uptr)addr, 2, 0);
+  MemoryRead(cur_thread(), CALLERPC, (uptr)addr, kSizeLog4);
 }
 
 void __tsan_read8(void *addr) {
-  MemoryAccess(cur_thread(), CALLERPC, (uptr)addr, 3, 0);
+  MemoryRead(cur_thread(), CALLERPC, (uptr)addr, kSizeLog8);
 }
 
 void __tsan_write1(void *addr) {
-  MemoryAccess(cur_thread(), CALLERPC, (uptr)addr, 0, 1);
+  MemoryWrite(cur_thread(), CALLERPC, (uptr)addr, kSizeLog1);
 }
 
 void __tsan_write2(void *addr) {
-  MemoryAccess(cur_thread(), CALLERPC, (uptr)addr, 1, 1);
+  MemoryWrite(cur_thread(), CALLERPC, (uptr)addr, kSizeLog2);
 }
 
 void __tsan_write4(void *addr) {
-  MemoryAccess(cur_thread(), CALLERPC, (uptr)addr, 2, 1);
+  MemoryWrite(cur_thread(), CALLERPC, (uptr)addr, kSizeLog4);
 }
 
 void __tsan_write8(void *addr) {
-  MemoryAccess(cur_thread(), CALLERPC, (uptr)addr, 3, 1);
+  MemoryWrite(cur_thread(), CALLERPC, (uptr)addr, kSizeLog8);
 }
 
 void __tsan_vptr_update(void **vptr_p, void *new_val) {
   CHECK_EQ(sizeof(vptr_p), 8);
   if (*vptr_p != new_val)
-    MemoryAccess(cur_thread(), CALLERPC, (uptr)vptr_p, 3, 1);
+    MemoryWrite(cur_thread(), CALLERPC, (uptr)vptr_p, kSizeLog8);
 }
 
 void __tsan_func_entry(void *pc) {
Index: libsanitizer/tsan/tsan_stat.cc
===================================================================
--- libsanitizer/tsan/tsan_stat.cc	(revision 195997)
+++ libsanitizer/tsan/tsan_stat.cc	(working copy)
@@ -179,6 +179,18 @@
   name[StatInt_sem_timedwait]            = "  sem_timedwait                   ";
   name[StatInt_sem_post]                 = "  sem_post                        ";
   name[StatInt_sem_getvalue]             = "  sem_getvalue                    ";
+  name[StatInt_stat]                     = "  stat                            ";
+  name[StatInt___xstat]                  = "  __xstat                         ";
+  name[StatInt_stat64]                   = "  stat64                          ";
+  name[StatInt___xstat64]                = "  __xstat64                       ";
+  name[StatInt_lstat]                    = "  lstat                           ";
+  name[StatInt___lxstat]                 = "  __lxstat                        ";
+  name[StatInt_lstat64]                  = "  lstat64                         ";
+  name[StatInt___lxstat64]               = "  __lxstat64                      ";
+  name[StatInt_fstat]                    = "  fstat                           ";
+  name[StatInt___fxstat]                 = "  __fxstat                        ";
+  name[StatInt_fstat64]                  = "  fstat64                         ";
+  name[StatInt___fxstat64]               = "  __fxstat64                      ";
   name[StatInt_open]                     = "  open                            ";
   name[StatInt_open64]                   = "  open64                          ";
   name[StatInt_creat]                    = "  creat                           ";
@@ -193,12 +205,15 @@
   name[StatInt_socket]                   = "  socket                          ";
   name[StatInt_socketpair]               = "  socketpair                      ";
   name[StatInt_connect]                  = "  connect                         ";
+  name[StatInt_bind]                     = "  bind                            ";
+  name[StatInt_listen]                   = "  listen                          ";
   name[StatInt_accept]                   = "  accept                          ";
   name[StatInt_accept4]                  = "  accept4                         ";
   name[StatInt_epoll_create]             = "  epoll_create                    ";
   name[StatInt_epoll_create1]            = "  epoll_create1                   ";
   name[StatInt_close]                    = "  close                           ";
   name[StatInt___close]                  = "  __close                         ";
+  name[StatInt___res_iclose]             = "  __res_iclose                    ";
   name[StatInt_pipe]                     = "  pipe                            ";
   name[StatInt_pipe2]                    = "  pipe2                           ";
   name[StatInt_read]                     = "  read                            ";
@@ -240,6 +255,14 @@
   name[StatInt_scanf]                    = "  scanf                           ";
   name[StatInt_sscanf]                   = "  sscanf                          ";
   name[StatInt_fscanf]                   = "  fscanf                          ";
+  name[StatInt___isoc99_vscanf]          = "  vscanf                          ";
+  name[StatInt___isoc99_vsscanf]         = "  vsscanf                         ";
+  name[StatInt___isoc99_vfscanf]         = "  vfscanf                         ";
+  name[StatInt___isoc99_scanf]           = "  scanf                           ";
+  name[StatInt___isoc99_sscanf]          = "  sscanf                          ";
+  name[StatInt___isoc99_fscanf]          = "  fscanf                          ";
+  name[StatInt_on_exit]                  = "  on_exit                         ";
+  name[StatInt___cxa_atexit]             = "  __cxa_atexit                    ";
 
   name[StatAnnotation]                   = "Dynamic annotations               ";
   name[StatAnnotateHappensBefore]        = "  HappensBefore                   ";
@@ -285,6 +308,7 @@
   name[StatMtxAnnotations]               = "  Annotations                     ";
   name[StatMtxMBlock]                    = "  MBlock                          ";
   name[StatMtxJavaMBlock]                = "  JavaMBlock                      ";
+  name[StatMtxFD]                        = "  FD                              ";
 
   Printf("Statistics:\n");
   for (int i = 0; i < StatCnt; i++)
Index: libsanitizer/tsan/tsan_symbolize.cc
===================================================================
--- libsanitizer/tsan/tsan_symbolize.cc	(revision 195997)
+++ libsanitizer/tsan/tsan_symbolize.cc	(working copy)
@@ -16,9 +16,24 @@
 #include "sanitizer_common/sanitizer_symbolizer.h"
 #include "tsan_flags.h"
 #include "tsan_report.h"
+#include "tsan_rtl.h"
 
 namespace __tsan {
 
+struct ScopedInSymbolizer {
+  ScopedInSymbolizer() {
+    ThreadState *thr = cur_thread();
+    CHECK(!thr->in_symbolizer);
+    thr->in_symbolizer = true;
+  }
+
+  ~ScopedInSymbolizer() {
+    ThreadState *thr = cur_thread();
+    CHECK(thr->in_symbolizer);
+    thr->in_symbolizer = false;
+  }
+};
+
 ReportStack *NewReportStackEntry(uptr addr) {
   ReportStack *ent = (ReportStack*)internal_alloc(MBlockReportStack,
                                                   sizeof(ReportStack));
@@ -53,35 +68,36 @@
 }
 
 ReportStack *SymbolizeCode(uptr addr) {
-  if (flags()->external_symbolizer_path[0]) {
-    static const uptr kMaxAddrFrames = 16;
-    InternalScopedBuffer<AddressInfo> addr_frames(kMaxAddrFrames);
-    for (uptr i = 0; i < kMaxAddrFrames; i++)
-      new(&addr_frames[i]) AddressInfo();
-    uptr addr_frames_num = __sanitizer::SymbolizeCode(addr, addr_frames.data(),
-                                                      kMaxAddrFrames);
-    if (addr_frames_num == 0)
-      return NewReportStackEntry(addr);
-    ReportStack *top = 0;
-    ReportStack *bottom = 0;
-    for (uptr i = 0; i < addr_frames_num; i++) {
-      ReportStack *cur_entry = NewReportStackEntry(addr_frames[i]);
-      CHECK(cur_entry);
-      addr_frames[i].Clear();
-      if (i == 0)
-        top = cur_entry;
-      else
-        bottom->next = cur_entry;
-      bottom = cur_entry;
-    }
-    return top;
+  if (!IsSymbolizerAvailable())
+    return SymbolizeCodeAddr2Line(addr);
+  ScopedInSymbolizer in_symbolizer;
+  static const uptr kMaxAddrFrames = 16;
+  InternalScopedBuffer<AddressInfo> addr_frames(kMaxAddrFrames);
+  for (uptr i = 0; i < kMaxAddrFrames; i++)
+    new(&addr_frames[i]) AddressInfo();
+  uptr addr_frames_num = __sanitizer::SymbolizeCode(addr, addr_frames.data(),
+                                                    kMaxAddrFrames);
+  if (addr_frames_num == 0)
+    return NewReportStackEntry(addr);
+  ReportStack *top = 0;
+  ReportStack *bottom = 0;
+  for (uptr i = 0; i < addr_frames_num; i++) {
+    ReportStack *cur_entry = NewReportStackEntry(addr_frames[i]);
+    CHECK(cur_entry);
+    addr_frames[i].Clear();
+    if (i == 0)
+      top = cur_entry;
+    else
+      bottom->next = cur_entry;
+    bottom = cur_entry;
   }
-  return SymbolizeCodeAddr2Line(addr);
+  return top;
 }
 
 ReportLocation *SymbolizeData(uptr addr) {
-  if (flags()->external_symbolizer_path[0] == 0)
+  if (!IsSymbolizerAvailable())
     return 0;
+  ScopedInSymbolizer in_symbolizer;
   DataInfo info;
   if (!__sanitizer::SymbolizeData(addr, &info))
     return 0;
Index: libsanitizer/tsan/tsan_stat.h
===================================================================
--- libsanitizer/tsan/tsan_stat.h	(revision 195997)
+++ libsanitizer/tsan/tsan_stat.h	(working copy)
@@ -174,6 +174,18 @@
   StatInt_sem_timedwait,
   StatInt_sem_post,
   StatInt_sem_getvalue,
+  StatInt_stat,
+  StatInt___xstat,
+  StatInt_stat64,
+  StatInt___xstat64,
+  StatInt_lstat,
+  StatInt___lxstat,
+  StatInt_lstat64,
+  StatInt___lxstat64,
+  StatInt_fstat,
+  StatInt___fxstat,
+  StatInt_fstat64,
+  StatInt___fxstat64,
   StatInt_open,
   StatInt_open64,
   StatInt_creat,
@@ -188,12 +200,15 @@
   StatInt_socket,
   StatInt_socketpair,
   StatInt_connect,
+  StatInt_bind,
+  StatInt_listen,
   StatInt_accept,
   StatInt_accept4,
   StatInt_epoll_create,
   StatInt_epoll_create1,
   StatInt_close,
   StatInt___close,
+  StatInt___res_iclose,
   StatInt_pipe,
   StatInt_pipe2,
   StatInt_read,
@@ -239,6 +254,14 @@
   StatInt_scanf,
   StatInt_sscanf,
   StatInt_fscanf,
+  StatInt___isoc99_vscanf,
+  StatInt___isoc99_vsscanf,
+  StatInt___isoc99_vfscanf,
+  StatInt___isoc99_scanf,
+  StatInt___isoc99_sscanf,
+  StatInt___isoc99_fscanf,
+  StatInt_on_exit,
+  StatInt___cxa_atexit,
 
   // Dynamic annotations.
   StatAnnotation,
@@ -287,6 +310,7 @@
   StatMtxAtExit,
   StatMtxMBlock,
   StatMtxJavaMBlock,
+  StatMtxFD,
 
   // This must be the last.
   StatCnt
Index: libsanitizer/tsan/tsan_rtl_mutex.cc
===================================================================
--- libsanitizer/tsan/tsan_rtl_mutex.cc	(revision 195997)
+++ libsanitizer/tsan/tsan_rtl_mutex.cc	(working copy)
@@ -24,8 +24,12 @@
   CHECK_GT(thr->in_rtl, 0);
   DPrintf("#%d: MutexCreate %zx\n", thr->tid, addr);
   StatInc(thr, StatMutexCreate);
-  if (!linker_init && IsAppMem(addr))
-    MemoryWrite1Byte(thr, pc, addr);
+  if (!linker_init && IsAppMem(addr)) {
+    CHECK(!thr->is_freeing);
+    thr->is_freeing = true;
+    MemoryWrite(thr, pc, addr, kSizeLog1);
+    thr->is_freeing = false;
+  }
   SyncVar *s = ctx->synctab.GetOrCreateAndLock(thr, pc, addr, true);
   s->is_rw = rw;
   s->is_recursive = recursive;
@@ -47,8 +51,12 @@
   SyncVar *s = ctx->synctab.GetAndRemove(thr, pc, addr);
   if (s == 0)
     return;
-  if (IsAppMem(addr))
-    MemoryWrite1Byte(thr, pc, addr);
+  if (IsAppMem(addr)) {
+    CHECK(!thr->is_freeing);
+    thr->is_freeing = true;
+    MemoryWrite(thr, pc, addr, kSizeLog1);
+    thr->is_freeing = false;
+  }
   if (flags()->report_destroy_locked
       && s->owner_tid != SyncVar::kInvalidTid
       && !s->is_broken) {
@@ -73,7 +81,7 @@
   CHECK_GT(thr->in_rtl, 0);
   DPrintf("#%d: MutexLock %zx\n", thr->tid, addr);
   if (IsAppMem(addr))
-    MemoryRead1Byte(thr, pc, addr);
+    MemoryReadAtomic(thr, pc, addr, kSizeLog1);
   SyncVar *s = CTX()->synctab.GetOrCreateAndLock(thr, pc, addr, true);
   thr->fast_state.IncrementEpoch();
   TraceAddEvent(thr, thr->fast_state, EventTypeLock, s->GetId());
@@ -106,7 +114,7 @@
   CHECK_GT(thr->in_rtl, 0);
   DPrintf("#%d: MutexUnlock %zx\n", thr->tid, addr);
   if (IsAppMem(addr))
-    MemoryRead1Byte(thr, pc, addr);
+    MemoryReadAtomic(thr, pc, addr, kSizeLog1);
   SyncVar *s = CTX()->synctab.GetOrCreateAndLock(thr, pc, addr, true);
   thr->fast_state.IncrementEpoch();
   TraceAddEvent(thr, thr->fast_state, EventTypeUnlock, s->GetId());
@@ -144,7 +152,7 @@
   DPrintf("#%d: MutexReadLock %zx\n", thr->tid, addr);
   StatInc(thr, StatMutexReadLock);
   if (IsAppMem(addr))
-    MemoryRead1Byte(thr, pc, addr);
+    MemoryReadAtomic(thr, pc, addr, kSizeLog1);
   SyncVar *s = CTX()->synctab.GetOrCreateAndLock(thr, pc, addr, false);
   thr->fast_state.IncrementEpoch();
   TraceAddEvent(thr, thr->fast_state, EventTypeRLock, s->GetId());
@@ -165,7 +173,7 @@
   DPrintf("#%d: MutexReadUnlock %zx\n", thr->tid, addr);
   StatInc(thr, StatMutexReadUnlock);
   if (IsAppMem(addr))
-    MemoryRead1Byte(thr, pc, addr);
+    MemoryReadAtomic(thr, pc, addr, kSizeLog1);
   SyncVar *s = CTX()->synctab.GetOrCreateAndLock(thr, pc, addr, true);
   thr->fast_state.IncrementEpoch();
   TraceAddEvent(thr, thr->fast_state, EventTypeRUnlock, s->GetId());
@@ -186,7 +194,7 @@
   CHECK_GT(thr->in_rtl, 0);
   DPrintf("#%d: MutexReadOrWriteUnlock %zx\n", thr->tid, addr);
   if (IsAppMem(addr))
-    MemoryRead1Byte(thr, pc, addr);
+    MemoryReadAtomic(thr, pc, addr, kSizeLog1);
   SyncVar *s = CTX()->synctab.GetOrCreateAndLock(thr, pc, addr, true);
   bool write = true;
   if (s->owner_tid == SyncVar::kInvalidTid) {
Index: libsanitizer/tsan/tsan_md5.cc
===================================================================
--- libsanitizer/tsan/tsan_md5.cc	(revision 195997)
+++ libsanitizer/tsan/tsan_md5.cc	(working copy)
@@ -240,4 +240,4 @@
   MD5_Final((unsigned char*)&res.hash[0], &ctx);
   return res;
 }
-}
+}  // namespace __tsan
Index: libsanitizer/tsan/tsan_platform.h
===================================================================
--- libsanitizer/tsan/tsan_platform.h	(revision 195997)
+++ libsanitizer/tsan/tsan_platform.h	(working copy)
@@ -149,6 +149,7 @@
 uptr GetTlsSize();
 void GetThreadStackAndTls(bool main, uptr *stk_addr, uptr *stk_size,
                           uptr *tls_addr, uptr *tls_size);
+int ExtractResolvFDs(void *state, int *fds, int nfd);
 
 }  // namespace __tsan
 
Index: libsanitizer/tsan/tsan_update_shadow_word_inl.h
===================================================================
--- libsanitizer/tsan/tsan_update_shadow_word_inl.h	(revision 195997)
+++ libsanitizer/tsan/tsan_update_shadow_word_inl.h	(working copy)
@@ -32,7 +32,7 @@
     if (Shadow::TidsAreEqual(old, cur)) {
       StatInc(thr, StatShadowSameThread);
       if (OldIsInSameSynchEpoch(old, thr)) {
-        if (OldIsRWNotWeaker(old, kAccessIsWrite)) {
+        if (old.IsRWNotWeaker(kAccessIsWrite, kIsAtomic)) {
           // found a slot that holds effectively the same info
           // (that is, same tid, same sync epoch and same size)
           StatInc(thr, StatMopSame);
@@ -41,7 +41,7 @@
         StoreIfNotYetStored(sp, &store_word);
         break;
       }
-      if (OldIsRWWeakerOrEqual(old, kAccessIsWrite))
+      if (old.IsRWWeakerOrEqual(kAccessIsWrite, kIsAtomic))
         StoreIfNotYetStored(sp, &store_word);
       break;
     }
@@ -50,25 +50,23 @@
       StoreIfNotYetStored(sp, &store_word);
       break;
     }
-    if (BothReads(old, kAccessIsWrite))
+    if (old.IsBothReadsOrAtomic(kAccessIsWrite, kIsAtomic))
       break;
     goto RACE;
   }
-
   // Do the memory access intersect?
-  if (Shadow::TwoRangesIntersect(old, cur, kAccessSize)) {
+  // In Go all memory accesses are 1 byte, so there can be no intersections.
+  if (kCppMode && Shadow::TwoRangesIntersect(old, cur, kAccessSize)) {
     StatInc(thr, StatShadowIntersect);
     if (Shadow::TidsAreEqual(old, cur)) {
       StatInc(thr, StatShadowSameThread);
       break;
     }
     StatInc(thr, StatShadowAnotherThread);
+    if (old.IsBothReadsOrAtomic(kAccessIsWrite, kIsAtomic))
+      break;
     if (HappensBefore(old, thr))
       break;
-
-    if (BothReads(old, kAccessIsWrite))
-      break;
-
     goto RACE;
   }
   // The accesses do not intersect.
Index: libsanitizer/tsan/tsan_mman.cc
===================================================================
--- libsanitizer/tsan/tsan_mman.cc	(revision 195997)
+++ libsanitizer/tsan/tsan_mman.cc	(working copy)
@@ -36,10 +36,18 @@
   allocator()->Init();
 }
 
-void AlloctorThreadFinish(ThreadState *thr) {
-  allocator()->SwallowCache(&thr->alloc_cache);
+void AllocatorThreadStart(ThreadState *thr) {
+  allocator()->InitCache(&thr->alloc_cache);
 }
 
+void AllocatorThreadFinish(ThreadState *thr) {
+  allocator()->DestroyCache(&thr->alloc_cache);
+}
+
+void AllocatorPrintStats() {
+  allocator()->PrintStats();
+}
+
 static void SignalUnsafeCall(ThreadState *thr, uptr pc) {
   if (!thr->in_signal_handler || !flags()->report_signal_unsafe)
     return;
@@ -162,3 +170,49 @@
 }
 
 }  // namespace __tsan
+
+using namespace __tsan;
+
+extern "C" {
+uptr __tsan_get_current_allocated_bytes() {
+  u64 stats[AllocatorStatCount];
+  allocator()->GetStats(stats);
+  u64 m = stats[AllocatorStatMalloced];
+  u64 f = stats[AllocatorStatFreed];
+  return m >= f ? m - f : 1;
+}
+
+uptr __tsan_get_heap_size() {
+  u64 stats[AllocatorStatCount];
+  allocator()->GetStats(stats);
+  u64 m = stats[AllocatorStatMmapped];
+  u64 f = stats[AllocatorStatUnmapped];
+  return m >= f ? m - f : 1;
+}
+
+uptr __tsan_get_free_bytes() {
+  return 1;
+}
+
+uptr __tsan_get_unmapped_bytes() {
+  return 1;
+}
+
+uptr __tsan_get_estimated_allocated_size(uptr size) {
+  return size;
+}
+
+bool __tsan_get_ownership(void *p) {
+  return allocator()->GetBlockBegin(p) != 0;
+}
+
+uptr __tsan_get_allocated_size(void *p) {
+  if (p == 0)
+    return 0;
+  p = allocator()->GetBlockBegin(p);
+  if (p == 0)
+    return 0;
+  MBlock *b = (MBlock*)allocator()->GetMetaData(p);
+  return b->size;
+}
+}  // extern "C"
Index: libsanitizer/tsan/tsan_fd.cc
===================================================================
--- libsanitizer/tsan/tsan_fd.cc	(revision 195997)
+++ libsanitizer/tsan/tsan_fd.cc	(working copy)
@@ -148,7 +148,7 @@
   FdDesc *d = fddesc(thr, pc, fd);
   FdSync *s = d->sync;
   DPrintf("#%d: FdAcquire(%d) -> %p\n", thr->tid, fd, s);
-  MemoryRead8Byte(thr, pc, (uptr)d);
+  MemoryRead(thr, pc, (uptr)d, kSizeLog8);
   if (s)
     Acquire(thr, pc, (uptr)s);
 }
@@ -159,20 +159,20 @@
   DPrintf("#%d: FdRelease(%d) -> %p\n", thr->tid, fd, s);
   if (s)
     Release(thr, pc, (uptr)s);
-  MemoryRead8Byte(thr, pc, (uptr)d);
+  MemoryRead(thr, pc, (uptr)d, kSizeLog8);
 }
 
 void FdAccess(ThreadState *thr, uptr pc, int fd) {
   DPrintf("#%d: FdAccess(%d)\n", thr->tid, fd);
   FdDesc *d = fddesc(thr, pc, fd);
-  MemoryRead8Byte(thr, pc, (uptr)d);
+  MemoryRead(thr, pc, (uptr)d, kSizeLog8);
 }
 
 void FdClose(ThreadState *thr, uptr pc, int fd) {
   DPrintf("#%d: FdClose(%d)\n", thr->tid, fd);
   FdDesc *d = fddesc(thr, pc, fd);
   // To catch races between fd usage and close.
-  MemoryWrite8Byte(thr, pc, (uptr)d);
+  MemoryWrite(thr, pc, (uptr)d, kSizeLog8);
   // We need to clear it, because if we do not intercept any call out there
   // that creates fd, we will hit false postives.
   MemoryResetRange(thr, pc, (uptr)d, 8);
@@ -191,7 +191,7 @@
   DPrintf("#%d: FdDup(%d, %d)\n", thr->tid, oldfd, newfd);
   // Ignore the case when user dups not yet connected socket.
   FdDesc *od = fddesc(thr, pc, oldfd);
-  MemoryRead8Byte(thr, pc, (uptr)od);
+  MemoryRead(thr, pc, (uptr)od, kSizeLog8);
   FdClose(thr, pc, newfd);
   init(thr, pc, newfd, ref(od->sync));
 }
Index: libsanitizer/tsan/tsan_flags.cc
===================================================================
--- libsanitizer/tsan/tsan_flags.cc	(revision 195997)
+++ libsanitizer/tsan/tsan_flags.cc	(working copy)
@@ -43,6 +43,7 @@
   f->report_thread_leaks = true;
   f->report_destroy_locked = true;
   f->report_signal_unsafe = true;
+  f->report_atomic_races = true;
   f->force_seq_cst_atomics = false;
   f->strip_path_prefix = "";
   f->suppressions = "";
@@ -70,6 +71,7 @@
   ParseFlag(env, &f->report_thread_leaks, "report_thread_leaks");
   ParseFlag(env, &f->report_destroy_locked, "report_destroy_locked");
   ParseFlag(env, &f->report_signal_unsafe, "report_signal_unsafe");
+  ParseFlag(env, &f->report_atomic_races, "report_atomic_races");
   ParseFlag(env, &f->force_seq_cst_atomics, "force_seq_cst_atomics");
   ParseFlag(env, &f->strip_path_prefix, "strip_path_prefix");
   ParseFlag(env, &f->suppressions, "suppressions");
Index: libsanitizer/tsan/tsan_interface.cc
===================================================================
--- libsanitizer/tsan/tsan_interface.cc	(revision 195997)
+++ libsanitizer/tsan/tsan_interface.cc	(working copy)
@@ -22,13 +22,13 @@
 }
 
 void __tsan_read16(void *addr) {
-  MemoryRead8Byte(cur_thread(), CALLERPC, (uptr)addr);
-  MemoryRead8Byte(cur_thread(), CALLERPC, (uptr)addr + 8);
+  MemoryRead(cur_thread(), CALLERPC, (uptr)addr, kSizeLog8);
+  MemoryRead(cur_thread(), CALLERPC, (uptr)addr + 8, kSizeLog8);
 }
 
 void __tsan_write16(void *addr) {
-  MemoryWrite8Byte(cur_thread(), CALLERPC, (uptr)addr);
-  MemoryWrite8Byte(cur_thread(), CALLERPC, (uptr)addr + 8);
+  MemoryWrite(cur_thread(), CALLERPC, (uptr)addr, kSizeLog8);
+  MemoryWrite(cur_thread(), CALLERPC, (uptr)addr + 8, kSizeLog8);
 }
 
 void __tsan_acquire(void *addr) {
Index: libsanitizer/tsan/tsan_interface_java.cc
===================================================================
--- libsanitizer/tsan/tsan_interface_java.cc	(revision 195997)
+++ libsanitizer/tsan/tsan_interface_java.cc	(working copy)
@@ -150,7 +150,7 @@
   return 0;
 }
 
-}  // namespace __tsan {
+}  // namespace __tsan
 
 #define SCOPED_JAVA_FUNC(func) \
   ThreadState *thr = cur_thread(); \
Index: libsanitizer/tsan/tsan_rtl.cc
===================================================================
--- libsanitizer/tsan/tsan_rtl.cc	(revision 195997)
+++ libsanitizer/tsan/tsan_rtl.cc	(working copy)
@@ -35,6 +35,11 @@
 #endif
 static char ctx_placeholder[sizeof(Context)] ALIGNED(64);
 
+// Can be overriden by a front-end.
+bool CPP_WEAK OnFinalize(bool failed) {
+  return failed;
+}
+
 static Context *ctx;
 Context *CTX() {
   return ctx;
@@ -136,7 +141,7 @@
   InternalScopedBuffer<char> filename(4096);
   internal_snprintf(filename.data(), filename.size(), "%s.%d",
       flags()->profile_memory, GetPid());
-  fd_t fd = internal_open(filename.data(), true);
+  fd_t fd = OpenFile(filename.data(), true);
   if (fd == kInvalidFd) {
     Printf("Failed to open memory profile file '%s'\n", &filename[0]);
     Die();
@@ -180,6 +185,7 @@
   if (is_initialized)
     return;
   is_initialized = true;
+  SanitizerToolName = "ThreadSanitizer";
   // Install tool-specific callbacks in sanitizer_common.
   SetCheckFailedCallback(TsanCheckFailed);
 
@@ -237,7 +243,7 @@
     Printf("ThreadSanitizer is suspended at startup (pid %d)."
            " Call __tsan_resume().\n",
            GetPid());
-    while (__tsan_resumed == 0);
+    while (__tsan_resumed == 0) {}
   }
 }
 
@@ -253,6 +259,11 @@
   ctx->report_mtx.Lock();
   ctx->report_mtx.Unlock();
 
+#ifndef TSAN_GO
+  if (ctx->flags.verbosity)
+    AllocatorPrintStats();
+#endif
+
   ThreadFinalize(thr);
 
   if (ctx->nreported) {
@@ -270,6 +281,8 @@
         ctx->nmissed_expected);
   }
 
+  failed = OnFinalize(failed);
+
   StatAggregate(ctx->stat, thr->stat);
   StatOutput(ctx->stat);
   return failed ? flags()->exitcode : 0;
@@ -356,18 +369,6 @@
 #endif
 }
 
-static inline bool BothReads(Shadow s, int kAccessIsWrite) {
-  return !kAccessIsWrite && !s.is_write();
-}
-
-static inline bool OldIsRWNotWeaker(Shadow old, int kAccessIsWrite) {
-  return old.is_write() || !kAccessIsWrite;
-}
-
-static inline bool OldIsRWWeakerOrEqual(Shadow old, int kAccessIsWrite) {
-  return !old.is_write() || kAccessIsWrite;
-}
-
 static inline bool OldIsInSameSynchEpoch(Shadow old, ThreadState *thr) {
   return old.epoch() >= thr->fast_synch_epoch;
 }
@@ -378,7 +379,7 @@
 
 ALWAYS_INLINE
 void MemoryAccessImpl(ThreadState *thr, uptr addr,
-    int kAccessSizeLog, bool kAccessIsWrite,
+    int kAccessSizeLog, bool kAccessIsWrite, bool kIsAtomic,
     u64 *shadow_mem, Shadow cur) {
   StatInc(thr, StatMop);
   StatInc(thr, kAccessIsWrite ? StatMopWrite : StatMopRead);
@@ -452,7 +453,7 @@
 
 ALWAYS_INLINE
 void MemoryAccess(ThreadState *thr, uptr pc, uptr addr,
-    int kAccessSizeLog, bool kAccessIsWrite) {
+    int kAccessSizeLog, bool kAccessIsWrite, bool kIsAtomic) {
   u64 *shadow_mem = (u64*)MemToShadow(addr);
   DPrintf2("#%d: MemoryAccess: @%p %p size=%d"
       " is_write=%d shadow_mem=%p {%zx, %zx, %zx, %zx}\n",
@@ -479,12 +480,13 @@
   Shadow cur(fast_state);
   cur.SetAddr0AndSizeLog(addr & 7, kAccessSizeLog);
   cur.SetWrite(kAccessIsWrite);
+  cur.SetAtomic(kIsAtomic);
 
   // We must not store to the trace if we do not store to the shadow.
   // That is, this call must be moved somewhere below.
   TraceAddEvent(thr, fast_state, EventTypeMop, pc);
 
-  MemoryAccessImpl(thr, addr, kAccessSizeLog, kAccessIsWrite,
+  MemoryAccessImpl(thr, addr, kAccessSizeLog, kAccessIsWrite, kIsAtomic,
       shadow_mem, cur);
 }
 
@@ -531,7 +533,10 @@
 }
 
 void MemoryRangeFreed(ThreadState *thr, uptr pc, uptr addr, uptr size) {
+  CHECK_EQ(thr->is_freeing, false);
+  thr->is_freeing = true;
   MemoryAccessRange(thr, pc, addr, size, true);
+  thr->is_freeing = false;
   Shadow s(thr->fast_state);
   s.ClearIgnoreBit();
   s.MarkAsFreed();
Index: libsanitizer/tsan/tsan_rtl.h
===================================================================
--- libsanitizer/tsan/tsan_rtl.h	(revision 195997)
+++ libsanitizer/tsan/tsan_rtl.h	(working copy)
@@ -171,7 +171,8 @@
 //   freed           : 1
 //   tid             : kTidBits
 //   epoch           : kClkBits
-//   is_write        : 1
+//   is_atomic       : 1
+//   is_read         : 1
 //   size_log        : 2
 //   addr0           : 3
 class Shadow : public FastState {
@@ -195,14 +196,27 @@
   }
 
   void SetWrite(unsigned kAccessIsWrite) {
-    DCHECK_EQ(x_ & 32, 0);
-    if (kAccessIsWrite)
-      x_ |= 32;
-    DCHECK_EQ(kAccessIsWrite, is_write());
+    DCHECK_EQ(x_ & kReadBit, 0);
+    if (!kAccessIsWrite)
+      x_ |= kReadBit;
+    DCHECK_EQ(kAccessIsWrite, IsWrite());
   }
 
-  bool IsZero() const { return x_ == 0; }
+  void SetAtomic(bool kIsAtomic) {
+    DCHECK(!IsAtomic());
+    if (kIsAtomic)
+      x_ |= kAtomicBit;
+    DCHECK_EQ(IsAtomic(), kIsAtomic);
+  }
 
+  bool IsAtomic() const {
+    return x_ & kAtomicBit;
+  }
+
+  bool IsZero() const {
+    return x_ == 0;
+  }
+
   static inline bool TidsAreEqual(const Shadow s1, const Shadow s2) {
     u64 shifted_xor = (s1.x_ ^ s2.x_) >> kTidShift;
     DCHECK_EQ(shifted_xor == 0, s1.TidWithIgnore() == s2.TidWithIgnore());
@@ -248,7 +262,8 @@
   }
   u64 addr0() const { return x_ & 7; }
   u64 size() const { return 1ull << size_log(); }
-  bool is_write() const { return x_ & 32; }
+  bool IsWrite() const { return !IsRead(); }
+  bool IsRead() const { return x_ & kReadBit; }
 
   // The idea behind the freed bit is as follows.
   // When the memory is freed (or otherwise unaccessible) we write to the shadow
@@ -263,13 +278,46 @@
      x_ |= kFreedBit;
   }
 
+  bool IsFreed() const {
+    return x_ & kFreedBit;
+  }
+
   bool GetFreedAndReset() {
     bool res = x_ & kFreedBit;
     x_ &= ~kFreedBit;
     return res;
   }
 
+  bool IsBothReadsOrAtomic(bool kIsWrite, bool kIsAtomic) const {
+    // analyzes 5-th bit (is_read) and 6-th bit (is_atomic)
+    bool v = x_ & u64(((kIsWrite ^ 1) << kReadShift)
+        | (kIsAtomic << kAtomicShift));
+    DCHECK_EQ(v, (!IsWrite() && !kIsWrite) || (IsAtomic() && kIsAtomic));
+    return v;
+  }
+
+  bool IsRWNotWeaker(bool kIsWrite, bool kIsAtomic) const {
+    bool v = ((x_ >> kReadShift) & 3)
+        <= u64((kIsWrite ^ 1) | (kIsAtomic << 1));
+    DCHECK_EQ(v, (IsAtomic() < kIsAtomic) ||
+        (IsAtomic() == kIsAtomic && !IsWrite() <= !kIsWrite));
+    return v;
+  }
+
+  bool IsRWWeakerOrEqual(bool kIsWrite, bool kIsAtomic) const {
+    bool v = ((x_ >> kReadShift) & 3)
+        >= u64((kIsWrite ^ 1) | (kIsAtomic << 1));
+    DCHECK_EQ(v, (IsAtomic() > kIsAtomic) ||
+        (IsAtomic() == kIsAtomic && !IsWrite() >= !kIsWrite));
+    return v;
+  }
+
  private:
+  static const u64 kReadShift   = 5;
+  static const u64 kReadBit     = 1ull << kReadShift;
+  static const u64 kAtomicShift = 6;
+  static const u64 kAtomicBit   = 1ull << kAtomicShift;
+
   u64 size_log() const { return (x_ >> 3) & 3; }
 
   static bool TwoRangesIntersectSLOW(const Shadow s1, const Shadow s2) {
@@ -324,7 +372,9 @@
   const int tid;
   const int unique_id;
   int in_rtl;
+  bool in_symbolizer;
   bool is_alive;
+  bool is_freeing;
   const uptr stk_addr;
   const uptr stk_size;
   const uptr tls_addr;
@@ -501,11 +551,14 @@
 void ReportRace(ThreadState *thr);
 bool OutputReport(Context *ctx,
                   const ScopedReport &srep,
-                  const ReportStack *suppress_stack = 0);
+                  const ReportStack *suppress_stack1 = 0,
+                  const ReportStack *suppress_stack2 = 0);
 bool IsFiredSuppression(Context *ctx,
                         const ScopedReport &srep,
                         const StackTrace &trace);
 bool IsExpectedReport(uptr addr, uptr size);
+bool FrameIsInternal(const ReportStack *frame);
+ReportStack *SkipTsanInternalFrames(ReportStack *ent);
 
 #if defined(TSAN_DEBUG_OUTPUT) && TSAN_DEBUG_OUTPUT >= 1
 # define DPrintf Printf
@@ -521,6 +574,7 @@
 
 u32 CurrentStackId(ThreadState *thr, uptr pc);
 void PrintCurrentStack(ThreadState *thr, uptr pc);
+void PrintCurrentStackSlow();  // uses libunwind
 
 void Initialize(ThreadState *thr);
 int Finalize(ThreadState *thr);
@@ -530,16 +584,38 @@
 SyncVar* GetAndRemoveJavaSync(ThreadState *thr, uptr pc, uptr addr);
 
 void MemoryAccess(ThreadState *thr, uptr pc, uptr addr,
-    int kAccessSizeLog, bool kAccessIsWrite);
+    int kAccessSizeLog, bool kAccessIsWrite, bool kIsAtomic);
 void MemoryAccessImpl(ThreadState *thr, uptr addr,
-    int kAccessSizeLog, bool kAccessIsWrite,
+    int kAccessSizeLog, bool kAccessIsWrite, bool kIsAtomic,
     u64 *shadow_mem, Shadow cur);
-void MemoryRead1Byte(ThreadState *thr, uptr pc, uptr addr);
-void MemoryWrite1Byte(ThreadState *thr, uptr pc, uptr addr);
-void MemoryRead8Byte(ThreadState *thr, uptr pc, uptr addr);
-void MemoryWrite8Byte(ThreadState *thr, uptr pc, uptr addr);
 void MemoryAccessRange(ThreadState *thr, uptr pc, uptr addr,
-                       uptr size, bool is_write);
+    uptr size, bool is_write);
+
+const int kSizeLog1 = 0;
+const int kSizeLog2 = 1;
+const int kSizeLog4 = 2;
+const int kSizeLog8 = 3;
+
+void ALWAYS_INLINE INLINE MemoryRead(ThreadState *thr, uptr pc,
+                                     uptr addr, int kAccessSizeLog) {
+  MemoryAccess(thr, pc, addr, kAccessSizeLog, false, false);
+}
+
+void ALWAYS_INLINE INLINE MemoryWrite(ThreadState *thr, uptr pc,
+                                      uptr addr, int kAccessSizeLog) {
+  MemoryAccess(thr, pc, addr, kAccessSizeLog, true, false);
+}
+
+void ALWAYS_INLINE INLINE MemoryReadAtomic(ThreadState *thr, uptr pc,
+                                           uptr addr, int kAccessSizeLog) {
+  MemoryAccess(thr, pc, addr, kAccessSizeLog, false, true);
+}
+
+void ALWAYS_INLINE INLINE MemoryWriteAtomic(ThreadState *thr, uptr pc,
+                                            uptr addr, int kAccessSizeLog) {
+  MemoryAccess(thr, pc, addr, kAccessSizeLog, true, true);
+}
+
 void MemoryResetRange(ThreadState *thr, uptr pc, uptr addr, uptr size);
 void MemoryRangeFreed(ThreadState *thr, uptr pc, uptr addr, uptr size);
 void MemoryRangeImitateWrite(ThreadState *thr, uptr pc, uptr addr, uptr size);
Index: libsanitizer/tsan/tsan_vector.h
===================================================================
--- libsanitizer/tsan/tsan_vector.h	(revision 195997)
+++ libsanitizer/tsan/tsan_vector.h	(working copy)
@@ -103,6 +103,6 @@
   Vector(const Vector&);
   void operator=(const Vector&);
 };
-}
+}  // namespace __tsan
 
 #endif  // #ifndef TSAN_VECTOR_H
Index: libsanitizer/tsan/tsan_report.cc
===================================================================
--- libsanitizer/tsan/tsan_report.cc	(revision 195997)
+++ libsanitizer/tsan/tsan_report.cc	(working copy)
@@ -41,23 +41,20 @@
   return buf;
 }
 
-static void PrintHeader(ReportType typ) {
-  Printf("WARNING: ThreadSanitizer: ");
-
+static const char *ReportTypeString(ReportType typ) {
   if (typ == ReportTypeRace)
-    Printf("data race");
-  else if (typ == ReportTypeUseAfterFree)
-    Printf("heap-use-after-free");
-  else if (typ == ReportTypeThreadLeak)
-    Printf("thread leak");
-  else if (typ == ReportTypeMutexDestroyLocked)
-    Printf("destroy of a locked mutex");
-  else if (typ == ReportTypeSignalUnsafe)
-    Printf("signal-unsafe call inside of a signal");
-  else if (typ == ReportTypeErrnoInSignal)
-    Printf("signal handler spoils errno");
-
-  Printf(" (pid=%d)\n", GetPid());
+    return "data race";
+  if (typ == ReportTypeUseAfterFree)
+    return "heap-use-after-free";
+  if (typ == ReportTypeThreadLeak)
+    return "thread leak";
+  if (typ == ReportTypeMutexDestroyLocked)
+    return "destroy of a locked mutex";
+  if (typ == ReportTypeSignalUnsafe)
+    return "signal-unsafe call inside of a signal";
+  if (typ == ReportTypeErrnoInSignal)
+    return "signal handler spoils errno";
+  return "";
 }
 
 void PrintStack(const ReportStack *ent) {
@@ -87,11 +84,17 @@
   }
 }
 
+static const char *MopDesc(bool first, bool write, bool atomic) {
+  return atomic ? (first ? (write ? "Atomic write" : "Atomic read")
+                : (write ? "Previous atomic write" : "Previous atomic read"))
+                : (first ? (write ? "Write" : "Read")
+                : (write ? "Previous write" : "Previous read"));
+}
+
 static void PrintMop(const ReportMop *mop, bool first) {
   char thrbuf[kThreadBufSize];
   Printf("  %s of size %d at %p by %s",
-      (first ? (mop->write ? "Write" : "Read")
-             : (mop->write ? "Previous write" : "Previous read")),
+      MopDesc(first, mop->write, mop->atomic),
       mop->size, (void*)mop->addr,
       thread_name(thrbuf, mop->tid));
   PrintMutexSet(mop->mset);
@@ -150,9 +153,28 @@
   PrintStack(s);
 }
 
+static ReportStack *ChooseSummaryStack(const ReportDesc *rep) {
+  if (rep->mops.Size())
+    return rep->mops[0]->stack;
+  if (rep->stacks.Size())
+    return rep->stacks[0];
+  if (rep->mutexes.Size())
+    return rep->mutexes[0]->stack;
+  if (rep->threads.Size())
+    return rep->threads[0]->stack;
+  return 0;
+}
+
+ReportStack *SkipTsanInternalFrames(ReportStack *ent) {
+  while (FrameIsInternal(ent) && ent->next)
+    ent = ent->next;
+  return ent;
+}
+
 void PrintReport(const ReportDesc *rep) {
   Printf("==================\n");
-  PrintHeader(rep->typ);
+  const char *rep_typ_str = ReportTypeString(rep->typ);
+  Printf("WARNING: ThreadSanitizer: %s (pid=%d)\n", rep_typ_str, GetPid());
 
   for (uptr i = 0; i < rep->stacks.Size(); i++) {
     if (i)
@@ -175,6 +197,9 @@
   for (uptr i = 0; i < rep->threads.Size(); i++)
     PrintThread(rep->threads[i]);
 
+  if (ReportStack *ent = SkipTsanInternalFrames(ChooseSummaryStack(rep)))
+    ReportErrorSummary(rep_typ_str, ent->file, ent->line, ent->func);
+
   Printf("==================\n");
 }
 
Index: libsanitizer/tsan/tsan_suppressions.cc
===================================================================
--- libsanitizer/tsan/tsan_suppressions.cc	(revision 195997)
+++ libsanitizer/tsan/tsan_suppressions.cc	(working copy)
@@ -17,6 +17,13 @@
 #include "tsan_mman.h"
 #include "tsan_platform.h"
 
+// Can be overriden in frontend.
+#ifndef TSAN_GO
+extern "C" const char *WEAK __tsan_default_suppressions() {
+  return 0;
+}
+#endif
+
 namespace __tsan {
 
 static Suppression *g_suppressions;
@@ -29,7 +36,7 @@
     internal_snprintf(tmp.data(), tmp.size(), "%s", filename);
   else
     internal_snprintf(tmp.data(), tmp.size(), "%s/%s", GetPwd(), filename);
-  fd_t fd = internal_open(tmp.data(), false);
+  fd_t fd = OpenFile(tmp.data(), false);
   if (fd == kInvalidFd) {
     Printf("ThreadSanitizer: failed to open suppressions file '%s'\n",
                tmp.data());
@@ -78,8 +85,7 @@
   return true;
 }
 
-Suppression *SuppressionParse(const char* supp) {
-  Suppression *head = 0;
+Suppression *SuppressionParse(Suppression *head, const char* supp) {
   const char *line = supp;
   while (line) {
     while (line[0] == ' ' || line[0] == '\t')
@@ -128,8 +134,12 @@
 }
 
 void InitializeSuppressions() {
-  char *supp = ReadFile(flags()->suppressions);
-  g_suppressions = SuppressionParse(supp);
+  const char *supp = ReadFile(flags()->suppressions);
+  g_suppressions = SuppressionParse(0, supp);
+#ifndef TSAN_GO
+  supp = __tsan_default_suppressions();
+  g_suppressions = SuppressionParse(0, supp);
+#endif
 }
 
 uptr IsSuppressed(ReportType typ, const ReportStack *stack) {
@@ -150,7 +160,8 @@
     for (Suppression *supp = g_suppressions; supp; supp = supp->next) {
       if (stype == supp->type &&
           (SuppressionMatch(supp->templ, frame->func) ||
-          SuppressionMatch(supp->templ, frame->file))) {
+           SuppressionMatch(supp->templ, frame->file) ||
+           SuppressionMatch(supp->templ, frame->module))) {
         DPrintf("ThreadSanitizer: matched suppression '%s'\n", supp->templ);
         return frame->pc;
       }
Index: libsanitizer/tsan/tsan_report.h
===================================================================
--- libsanitizer/tsan/tsan_report.h	(revision 195997)
+++ libsanitizer/tsan/tsan_report.h	(working copy)
@@ -46,6 +46,7 @@
   uptr addr;
   int size;
   bool write;
+  bool atomic;
   Vector<ReportMopMutex> mset;
   ReportStack *stack;
 
Index: gcc/config/i386/i386.c
===================================================================
--- gcc/config/i386/i386.c	(revision 195997)
+++ gcc/config/i386/i386.c	(working copy)
@@ -5436,7 +5436,9 @@
 static unsigned HOST_WIDE_INT
 ix86_asan_shadow_offset (void)
 {
-  return (unsigned HOST_WIDE_INT) 1 << (TARGET_LP64 ? 44 : 29);
+  return TARGET_LP64 ? (TARGET_MACHO ? (HOST_WIDE_INT_1 << 44)
+                     : HOST_WIDE_INT_C (0x7fff8000))
+             : (HOST_WIDE_INT_1 << 29);
 }
 \f
 /* Argument support functions.  */
Index: gcc/sanitizer.def
===================================================================
--- gcc/sanitizer.def	(revision 195997)
+++ gcc/sanitizer.def	(working copy)
@@ -27,7 +27,7 @@
    for other FEs by asan.c.  */
 
 /* Address Sanitizer */
-DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_INIT, "__asan_init",
+DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_INIT, "__asan_init_v1",
 		      BT_FN_VOID, ATTR_NOTHROW_LEAF_LIST)
 /* Do not reorder the BUILT_IN_ASAN_REPORT* builtins, e.g. cfgcleanup.c
    relies on this order.  */
Index: gcc/ChangeLog
===================================================================
--- gcc/ChangeLog	(revision 195997)
+++ gcc/ChangeLog	(working copy)
@@ -1,3 +1,12 @@
+2013-02-13  Kostya Serebryany  <kcc@google.com>
+
+	* config/i386/i386.c: use 0x7fff8000 as asan_shadow_offset on x86_64
+	linux.
+	* sanitizer.def: rename __asan_init to __asan_init_v1.
+	* testsuite/c-c++-common/asan/strncpy-overflow-1.c: update the test
+	to match the fresh asan run-time.
+	* testsuite/c-c++-common/asan/rlimit-mmap-test-1.c: Ditto.
+
 2013-02-12  Vladimir Makarov  <vmakarov@redhat.com>
 
 	PR inline-asm/56148
Index: gcc/testsuite/c-c++-common/asan/strncpy-overflow-1.c
===================================================================
--- gcc/testsuite/c-c++-common/asan/strncpy-overflow-1.c	(revision 195997)
+++ gcc/testsuite/c-c++-common/asan/strncpy-overflow-1.c	(working copy)
@@ -12,7 +12,7 @@
   return short_buffer[8];
 }
 
-/* { dg-output "WRITE of size 1 at 0x\[0-9a-f\]+ thread T0\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "WRITE of size \[0-9\]* at 0x\[0-9a-f\]+ thread T0\[^\n\r]*(\n|\r\n|\r)" } */
 /* { dg-output "    #0 0x\[0-9a-f\]+ (in _*(interceptor_|)strncpy|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */
 /* { dg-output "    #1 0x\[0-9a-f\]+ (in _*main (\[^\n\r]*strncpy-overflow-1.c:11|\[^\n\r]*:0)|\[(\]).*(\n|\r\n|\r)" } */
 /* { dg-output "0x\[0-9a-f\]+ is located 0 bytes to the right of 9-byte region\[^\n\r]*(\n|\r\n|\r)" } */
Index: gcc/testsuite/c-c++-common/asan/rlimit-mmap-test-1.c
===================================================================
--- gcc/testsuite/c-c++-common/asan/rlimit-mmap-test-1.c	(revision 195997)
+++ gcc/testsuite/c-c++-common/asan/rlimit-mmap-test-1.c	(working copy)
@@ -18,4 +18,4 @@
   return 0;
 }
 
-/* { dg-output "AddressSanitizer is unable to mmap" } */
+/* { dg-output "ERROR: Failed to mmap" } */

^ permalink raw reply	[flat|nested] 36+ messages in thread

end of thread, other threads:[~2013-02-28 19:56 UTC | newest]

Thread overview: 36+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2013-02-13  9:20 libsanitizer merge from upstream r175042 Konstantin Serebryany
2013-02-13  9:51 ` Jakub Jelinek
2013-02-13 10:28   ` Konstantin Serebryany
2013-02-13 10:32     ` Jakub Jelinek
2013-02-13 11:59       ` Jakub Jelinek
2013-02-13 12:33         ` Konstantin Serebryany
2013-02-13 12:48           ` Jakub Jelinek
2013-02-13 12:58             ` Konstantin Serebryany
2013-02-13 13:07               ` Jakub Jelinek
2013-02-13 13:28                 ` Richard Biener
2013-02-13 13:33                   ` Jakub Jelinek
2013-02-13 13:39                 ` Konstantin Serebryany
2013-02-13 15:19                   ` Jakub Jelinek
2013-02-13 16:48                     ` Jack Howarth
2013-02-13 20:12                       ` Jakub Jelinek
2013-02-14  8:48                     ` Jakub Jelinek
2013-02-14 11:56                       ` Konstantin Serebryany
2013-02-14 12:19                         ` Jakub Jelinek
2013-02-14 12:56                           ` Konstantin Serebryany
2013-02-15  7:45                           ` Konstantin Serebryany
2013-02-15  8:26                             ` Jakub Jelinek
2013-02-15  8:48                               ` Konstantin Serebryany
2013-02-15  9:06                                 ` Jakub Jelinek
2013-02-15  9:30                                   ` Konstantin Serebryany
2013-02-15  9:37                                     ` Jakub Jelinek
2013-02-15  9:47                                       ` Konstantin Serebryany
2013-02-15 12:02                                         ` Konstantin Serebryany
2013-02-22 16:32                                 ` Jakub Jelinek
2013-02-28 12:30                                   ` Konstantin Serebryany
2013-02-28 19:56                                     ` Jakub Jelinek
2013-02-15 15:39                             ` Ian Lance Taylor
2013-02-18  8:21                               ` Jakub Jelinek
2013-02-18  8:40                                 ` Konstantin Serebryany
2013-02-13 14:46       ` Jack Howarth
2013-02-13 18:29 ` H.J. Lu
2013-02-14  8:08   ` Konstantin Serebryany

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).