Index: CMakeLists.txt
===================================================================
--- CMakeLists.txt
+++ CMakeLists.txt
@@ -1,3 +1,7 @@
+if(${COMPILER_RT_CROSS_COMPILING_NOANDROID})
+SET(ANDROID "0" CACHE STRING "ANDROID" FORCE)
+endif()
+
 # CMake build for CompilerRT.
 #
 # This build assumes that CompilerRT is checked out into the
Index: cmake/config-ix.cmake
===================================================================
--- cmake/config-ix.cmake
+++ cmake/config-ix.cmake
@@ -158,7 +158,15 @@
   detect_target_arch()
   set(COMPILER_RT_OS_SUFFIX "-android")
 else()
-  if("${LLVM_NATIVE_ARCH}" STREQUAL "X86")
+  # See If the user wants cross compiling, e.g. using clang for something
+  # other than android.
+  # This is useful if we want to use CMAKE_C_FLAGS and CMAKE_C_COMPILER to
+  # pass in cross compilation args, i.e. we are using a single version of clang
+  # that has a default target other than the host to generate compiler-rt for the
+  # host (or some other platform)
+  if(${COMPILER_RT_CROSS_COMPILING})
+    detect_target_arch()
+  elseif("${LLVM_NATIVE_ARCH}" STREQUAL "X86")
     if(NOT MSVC)
       test_target_arch(x86_64 "" "-m64")
       # FIXME: We build runtimes for both i686 and i386, as "clang -m32" may
@@ -221,8 +229,13 @@
 # Architectures supported by compiler-rt libraries.
 filter_available_targets(SANITIZER_COMMON_SUPPORTED_ARCH
   x86_64 i386 i686 powerpc64 powerpc64le arm aarch64 mips mips64 mipsel mips64el)
+if(${COMPILER_RT_FORCE_TSAN_AARCH64})
+filter_available_targets(ASAN_SUPPORTED_ARCH
+  x86_64 i386 i686 powerpc64 powerpc64le arm aarch64 mips mipsel mips64 mips64el)
+else()
 filter_available_targets(ASAN_SUPPORTED_ARCH
   x86_64 i386 i686 powerpc64 powerpc64le arm mips mipsel mips64 mips64el)
+endif()
 filter_available_targets(DFSAN_SUPPORTED_ARCH x86_64 mips64 mips64el)
 filter_available_targets(LSAN_SUPPORTED_ARCH x86_64 mips64 mips64el)
 # LSan common files should be available on all architectures supported
@@ -232,7 +245,11 @@
 filter_available_targets(MSAN_SUPPORTED_ARCH x86_64 mips64 mips64el)
 filter_available_targets(PROFILE_SUPPORTED_ARCH x86_64 i386 i686 arm mips mips64
   mipsel mips64el aarch64 powerpc64 powerpc64le)
+if(${COMPILER_RT_FORCE_TSAN_AARCH64})
+filter_available_targets(TSAN_SUPPORTED_ARCH x86_64 mips64 mips64el aarch64)
+else()
 filter_available_targets(TSAN_SUPPORTED_ARCH x86_64 mips64 mips64el)
+endif()
 filter_available_targets(UBSAN_SUPPORTED_ARCH x86_64 i386 i686 arm aarch64 mips mipsel mips64 mips64el)
 
 if(ANDROID)
@@ -299,7 +316,7 @@
 endif()
 
 if (COMPILER_RT_HAS_SANITIZER_COMMON AND TSAN_SUPPORTED_ARCH AND
-    OS_NAME MATCHES "Linux|FreeBSD")
+    OS_NAME MATCHES "Linux|FreeBSD|Android")
   set(COMPILER_RT_HAS_TSAN TRUE)
 else()
   set(COMPILER_RT_HAS_TSAN FALSE)
Index: lib/sanitizer_common/sanitizer_libc.h
===================================================================
--- lib/sanitizer_common/sanitizer_libc.h
+++ lib/sanitizer_common/sanitizer_libc.h
@@ -95,6 +95,9 @@
 uptr internal_getpid();
 uptr internal_getppid();
 
+void *internal_malloc(uptr s);
+void *internal_calloc(uptr s, uptr n);
+
 int internal_fork();
 
 // Threading
Index: lib/sanitizer_common/sanitizer_libc.cc
===================================================================
--- lib/sanitizer_common/sanitizer_libc.cc
+++ lib/sanitizer_common/sanitizer_libc.cc
@@ -71,6 +71,19 @@
   return dest;
 }
 
+void *internal_malloc(uptr n) {
+  return InternalAlloc(n);
+}
+
+void *internal_calloc(uptr n, uptr s) {
+  void *rtn = InternalAlloc(n * s);
+  if (rtn) {
+    internal_memset(rtn, 0, n * s);
+  }
+  return (void*)0;
+}
+
+
 // Semi-fast bzero for 16-aligned data. Still far from peak performance.
 void internal_bzero_aligned16(void *s, uptr n) {
   struct S16 { u64 a, b; } ALIGNED(16);
Index: lib/sanitizer_common/sanitizer_linux.h
===================================================================
--- lib/sanitizer_common/sanitizer_linux.h
+++ lib/sanitizer_common/sanitizer_linux.h
@@ -43,7 +43,7 @@
 // internal_sigaction instead.
 int internal_sigaction_norestorer(int signum, const void *act, void *oldact);
 void internal_sigdelset(__sanitizer_sigset_t *set, int signum);
-#if defined(__x86_64__) || defined(__mips__)
+#if defined(__x86_64__) || defined(__mips__) || defined(__aarch64__)
 uptr internal_clone(int (*fn)(void *), void *child_stack, int flags, void *arg,
                     int *parent_tidptr, void *newtls, int *child_tidptr);
 #endif
Index: lib/sanitizer_common/sanitizer_linux.cc
===================================================================
--- lib/sanitizer_common/sanitizer_linux.cc
+++ lib/sanitizer_common/sanitizer_linux.cc
@@ -870,6 +870,12 @@
   return clone(fn, child_stack, flags, arg, parent_tidptr,
                newtls, child_tidptr);
 }
+#elif defined(__aarch64__)
+uptr internal_clone(int (*fn)(void *), void *child_stack, int flags, void *arg,
+                    int *parent_tidptr, void *newtls, int *child_tidptr) {
+  return clone(fn, child_stack, flags, arg, parent_tidptr,
+               newtls, child_tidptr);
+}
 #endif  // defined(__x86_64__) && SANITIZER_LINUX
 
 #if SANITIZER_ANDROID
@@ -902,7 +908,8 @@
 
 void GetExtraActivationFlags(char *buf, uptr size) {
   CHECK(size > PROP_VALUE_MAX);
-  __system_property_get("asan.options", buf);
+  // fixme: below not available in android L and onwards
+  //__system_property_get("asan.options", buf);
 }
 #endif
 
Index: lib/sanitizer_common/sanitizer_platform_interceptors.h
===================================================================
--- lib/sanitizer_common/sanitizer_platform_interceptors.h
+++ lib/sanitizer_common/sanitizer_platform_interceptors.h
@@ -153,12 +153,12 @@
 #define SANITIZER_INTERCEPT_POLL SI_NOT_WINDOWS
 #define SANITIZER_INTERCEPT_PPOLL SI_LINUX_NOT_ANDROID
 #define SANITIZER_INTERCEPT_WORDEXP \
-  SI_FREEBSD || (SI_MAC && !SI_IOS) || SI_LINUX_NOT_ANDROID
+  (SI_FREEBSD || (SI_MAC && !SI_IOS) || SI_LINUX_NOT_ANDROID)
 #define SANITIZER_INTERCEPT_SIGWAIT SI_NOT_WINDOWS
 #define SANITIZER_INTERCEPT_SIGWAITINFO SI_LINUX_NOT_ANDROID
 #define SANITIZER_INTERCEPT_SIGTIMEDWAIT SI_LINUX_NOT_ANDROID
 #define SANITIZER_INTERCEPT_SIGSETOPS \
-  SI_FREEBSD || SI_MAC || SI_LINUX_NOT_ANDROID
+  (SI_FREEBSD || SI_MAC || SI_LINUX_NOT_ANDROID || __aarch64__)
 #define SANITIZER_INTERCEPT_SIGPENDING SI_NOT_WINDOWS
 #define SANITIZER_INTERCEPT_SIGPROCMASK SI_NOT_WINDOWS
 #define SANITIZER_INTERCEPT_BACKTRACE SI_LINUX_NOT_ANDROID
Index: lib/sanitizer_common/sanitizer_platform_limits_posix.h
===================================================================
--- lib/sanitizer_common/sanitizer_platform_limits_posix.h
+++ lib/sanitizer_common/sanitizer_platform_limits_posix.h
@@ -321,7 +321,8 @@
     long pw_change;
     char *pw_class;
 #endif
-#if !SANITIZER_ANDROID
+#if !SANITIZER_ANDROID || (SANITIZER_ANDROID && __aarch64__)
+    // this is defined in aarch64
     char *pw_gecos;
 #endif
     char *pw_dir;
@@ -383,7 +384,7 @@
   };
 #endif
 
-#if SANITIZER_ANDROID || SANITIZER_MAC || SANITIZER_FREEBSD
+#if SANITIZER_MAC || SANITIZER_FREEBSD
   struct __sanitizer_msghdr {
     void *msg_name;
     unsigned msg_namelen;
@@ -398,6 +399,23 @@
     int cmsg_level;
     int cmsg_type;
   };
+#elif SANITIZER_ANDROID
+struct __sanitizer_msghdr {
+  void* msg_name;
+  unsigned msg_namelen;
+  struct __sanitizer_iovec* msg_iov;
+  unsigned long msg_iovlen;
+  void* msg_control;
+  unsigned long msg_controllen;
+  int msg_flags;
+};
+
+struct __sanitizer_cmsghdr {
+  unsigned long cmsg_len;
+  int cmsg_level;
+  int cmsg_type;
+};
+
 #else
   struct __sanitizer_msghdr {
     void *msg_name;
@@ -519,6 +537,18 @@
   };
 #endif
 
+#if SANITIZER_ANDROID && __aarch64__
+  struct __sanitizer_sigaction {
+    unsigned int sa_flags;
+    union {
+      void (*handler)(int);
+      void (*sigaction)(int, void*, void*);
+    };
+    __sanitizer_sigset_t sa_mask;
+    void (*sa_restorer)(void);
+  };
+
+#else
   // Linux system headers define the 'sa_handler' and 'sa_sigaction' macros.
   struct __sanitizer_sigaction {
 #if defined(__mips__) && !SANITIZER_FREEBSD
@@ -544,6 +574,7 @@
     int sa_resv[1];
 #endif
   };
+#endif
 
 #if SANITIZER_FREEBSD
   typedef __sanitizer_sigset_t __sanitizer_kernel_sigset_t;
@@ -693,6 +724,57 @@
     int _fileno;
   };
 # define SANITIZER_HAS_STRUCT_FILE 1
+#elif SANITIZER_ANDROID
+#if defined(__LP64__)
+  struct __sanitizer__sbuf {
+    unsigned char* _base;
+    uptr _size;
+};
+#else
+  struct __sanitizer__sbuf {
+    unsigned char *_base;
+    int	_size;
+  };
+#endif
+
+  struct __sanitizer_FILE  {
+    unsigned char *_p;  /* current position in (some) buffer */
+    int         _r;     /* read space left for getc() */
+    int         _w;     /* write space left for putc() */
+#if defined(__LP64__)
+    int         _flags; /* flags, below; this FILE is free if 0 */
+    int         _file;  /* fileno, if Unix descriptor, else -1 */
+#else
+    short       _flags; /* flags, below; this FILE is free if 0 */
+    short       _file;  /* fileno, if Unix descriptor, else -1 */
+#endif
+     /* the buffer (at least 1 byte, if !NULL) */
+    struct      __sanitizer__sbuf _bf;
+    int         _lbfsize;       /* 0 or -_bf._size, for inline putc */
+
+    /* operations */
+    void        *_cookie;       /* cookie passed to io functions */
+    int         (*_close)(void *);
+    int         (*_read)(void *, char *, int);
+    uptr        (*_seek)(void *, uptr, int);
+    int         (*_write)(void *, const char *, int);
+
+    /* extension data, to avoid further ABI breakage */
+    struct      __sanitizer__sbuf _ext;
+    /* data for long sequences of ungetc() */
+    unsigned char *_up; /* saved _p when _p is doing ungetc data */
+    int           _ur;  /* saved _r when _r is counting ungetc data */
+
+    unsigned char _ubuf[3];     /* guarantee an ungetc() buffer */
+    unsigned char _nbuf[1];     /* guarantee a getc() buffer */
+
+    struct      __sanitizer__sbuf _lb;     /* buffer for fgetln() */
+
+    /* Unix stdio files get aligned to block boundaries on fseek() */
+    int         _blksize;       /* stat.st_blksize (may be != _bf._size) */
+    uptr        _offset;        /* current lseek offset */
+  };
+# define SANITIZER_HAS_STRUCT_FILE 0
 #else
   typedef void __sanitizer_FILE;
 # define SANITIZER_HAS_STRUCT_FILE 0
Index: lib/sanitizer_common/sanitizer_platform_limits_posix.cc
===================================================================
--- lib/sanitizer_common/sanitizer_platform_limits_posix.cc
+++ lib/sanitizer_common/sanitizer_platform_limits_posix.cc
@@ -164,6 +164,7 @@
 #include <linux/mtio.h>
 #include <linux/ppp_defs.h>
 #include <linux/if_ppp.h>
+#include <sys/socket.h>
 #endif
 
 #if SANITIZER_LINUX
@@ -1142,7 +1143,7 @@
 CHECK_SIZE_AND_OFFSET(passwd, pw_dir);
 CHECK_SIZE_AND_OFFSET(passwd, pw_shell);
 
-#if !SANITIZER_ANDROID
+#if !SANITIZER_ANDROID || (SANITIZER_ANDROID && __aarch64__)
 CHECK_SIZE_AND_OFFSET(passwd, pw_gecos);
 #endif
 
Index: lib/sanitizer_common/sanitizer_stoptheworld_linux_libcdep.cc
===================================================================
--- lib/sanitizer_common/sanitizer_stoptheworld_linux_libcdep.cc
+++ lib/sanitizer_common/sanitizer_stoptheworld_linux_libcdep.cc
@@ -14,7 +14,7 @@
 
 
 #include "sanitizer_platform.h"
-#if SANITIZER_LINUX && (defined(__x86_64__) || defined(__mips__))
+#if SANITIZER_LINUX && (defined(__x86_64__) || defined(__mips__) || defined(__aarch64__))
 
 #include "sanitizer_stoptheworld.h"
 
@@ -469,6 +469,9 @@
 typedef struct user regs_struct;
 #define REG_SP regs[EF_REG29]
 
+#elif defined(__aarch64__)
+typedef struct user_pt_regs regs_struct;
+#define REG_SP sp
 #else
 #error "Unsupported architecture"
 #endif // SANITIZER_ANDROID && defined(__arm__)
@@ -479,7 +482,7 @@
   pid_t tid = GetThreadID(index);
   regs_struct regs;
   int pterrno;
-  if (internal_iserror(internal_ptrace(PTRACE_GETREGS, tid, NULL, &regs),
+  if (internal_iserror(internal_ptrace(PTRACE_GETREGSET, tid, NULL, &regs),
                        &pterrno)) {
     VReport(1, "Could not get registers from thread %d (errno %d).\n", tid,
             pterrno);
Index: lib/tsan/CMakeLists.txt
===================================================================
--- lib/tsan/CMakeLists.txt
+++ lib/tsan/CMakeLists.txt
@@ -17,6 +17,7 @@
 # FIXME: Add support for --sysroot=. compile flag:
 
 set(TSAN_SOURCES
+  rtl/tsan_aarch64_tls_workaround.cc
   rtl/tsan_clock.cc
   rtl/tsan_flags.cc
   rtl/tsan_fd.cc
@@ -50,6 +51,7 @@
 endif()
 
 set(TSAN_HEADERS
+  rtl/tsan_aarch64_tls_workaround.h
   rtl/tsan_clock.h
   rtl/tsan_defs.h
   rtl/tsan_dense_alloc.h
Index: lib/tsan/rtl/tsan.syms.extra
===================================================================
--- lib/tsan/rtl/tsan.syms.extra
+++ lib/tsan/rtl/tsan.syms.extra
@@ -8,6 +8,7 @@
 __tsan_unaligned*
 __tsan_release
 __tsan_acquire
+InitTSanWorkAround
 Annotate*
 WTFAnnotate*
 RunningOnValgrind
Index: lib/tsan/rtl/tsan_aarch64_tls_workaround.h
===================================================================
--- /dev/null
+++ lib/tsan/rtl/tsan_aarch64_tls_workaround.h
@@ -0,0 +1,42 @@
+//===-- tsan_android_aarch64_tls_workaround.h -----------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of ThreadSanitizer (TSan), a race detector.
+//
+// This file presents some macros
+//===----------------------------------------------------------------------===//
+
+#ifndef TSAN_AARCH64_TLS_WORKAROUND_H
+#define TSAN_AARCH64_TLS_WORKAROUND_H
+
+// This file implements a few macros
+// For OSs that properly implement __thread, this will devolve to a no-op.
+// For others (notably Android on AArch64), we get around the lack of support
+// via using pthread calls internally to implement it.
+#include "sanitizer_common/sanitizer_platform.h"
+
+namespace __tsan {
+extern "C" bool InitTSanWorkAround();
+};
+
+#if defined(__aarch64__)
+#define SANITIZER_TLS_WORKAROUND_NEEDED 1
+#define GetFromTLS(tlsvar) get_from_tls_##tlsvar()
+
+// Due to chicken-vs-egg decl issues, these are the real accessor functions
+// these accessor functions are defined elsewhere
+// char &get_from_tls_cur_thread_placeholder() (used in tsan_rtl.cc)
+//  __sanitizer_sigset_t &get_from_tls_emptset() (used in tsan_interceptors.cc)
+//  __sanitizer_sigset_t &get_from_tls_oldset();
+
+#else
+#define GetFromTLS(tlsvar) tlsvar
+#endif
+
+#endif
Index: lib/tsan/rtl/tsan_aarch64_tls_workaround.cc
===================================================================
--- /dev/null
+++ lib/tsan/rtl/tsan_aarch64_tls_workaround.cc
@@ -0,0 +1,95 @@
+#include <cassert>
+
+#include "sanitizer_common/sanitizer_atomic.h"
+#include "sanitizer_common/sanitizer_libc.h"
+#include "sanitizer_common/sanitizer_linux.h"
+#include "sanitizer_common/sanitizer_platform_limits_posix.h"
+#include "sanitizer_common/sanitizer_placement_new.h"
+#include "sanitizer_common/sanitizer_stacktrace.h"
+#include "interception/interception.h"
+
+#include "tsan_interface.h"
+#include "tsan_platform.h"
+#include "tsan_rtl.h"
+#include "interception/interception.h"
+#include <dlfcn.h>
+
+
+extern "C" {
+  int pthread_key_create(unsigned *key, void (*destructor)(void* v));
+  void *pthread_getspecific(unsigned key);
+  int pthread_setspecific(unsigned key, const void *v);
+};
+
+using namespace __tsan;
+
+// This needs to be aligned(64)
+struct TSanTLSHack {
+  uptr tid;
+  char cur_thread_placeholder[sizeof(ThreadState)] ALIGNED(64);
+  __sanitizer_sigset_t emptyset, oldset;
+};
+
+static const int PrimeNumber = 2053;
+static TSanTLSHack* TLSHack[PrimeNumber];
+static int Count = 0;
+
+DECLARE_REAL_AND_INTERCEPTOR(void *, memset, void *dst, int v, uptr size);
+DECLARE_REAL_AND_INTERCEPTOR(void *, memcpy, void *dst, const void *src, uptr size);
+DECLARE_REAL_AND_INTERCEPTOR(int, memcmp, const void *dst, const void *src, uptr size);
+// uhoh dlsym() uses these too!
+DECLARE_REAL_AND_INTERCEPTOR(void *, malloc, uptr size);
+DECLARE_REAL_AND_INTERCEPTOR(void *, calloc, uptr nmeb, uptr size);
+
+namespace __tsan {
+
+static bool TSanTLSWorkAroundHasInited=0;
+
+void InitTLSHack() {
+  internal_memset(TLSHack, 0, sizeof(TLSHack));
+  Count = 0;
+}
+
+bool InitTSanWorkAround() {
+  // We need to setup it early, because functions like dlsym() can call it.
+  REAL(memset) = internal_memset;
+  REAL(memcpy) = internal_memcpy;
+  REAL(memcmp) = internal_memcmp;
+  REAL(malloc) = internal_malloc;
+  REAL(calloc) = internal_calloc;
+  if (TSanTLSWorkAroundHasInited == 0)
+    InitTLSHack();
+  TSanTLSWorkAroundHasInited = 1;
+  return TSanTLSWorkAroundHasInited;
+}
+
+extern
+TSanTLSHack *GetTSanTLSHack() {
+  CHECK_EQ(TSanTLSWorkAroundHasInited, 1);
+  uptr tid = GetThreadSelf();
+  uptr hash = tid % PrimeNumber;
+
+  if (TLSHack[hash] == 0ll) {
+    TLSHack[hash] = (TSanTLSHack*)InternalAlloc(sizeof(TSanTLSHack));
+    TLSHack[hash]->tid = tid;
+    DPrintf("Thread %p at slot %p getting ThreadState %p\n",
+            tid, hash, &(TLSHack[hash]->cur_thread_placeholder[0]));
+    return TLSHack[hash];
+  }
+  CHECK_EQ(TLSHack[hash]->tid, tid);
+  return TLSHack[hash];
+}
+
+char &get_from_tls_cur_thread_placeholder() {
+  return GetTSanTLSHack()->cur_thread_placeholder[0];
+};
+
+__sanitizer_sigset_t &get_from_tls_emptyset() {
+  return GetTSanTLSHack()->emptyset;
+};
+
+__sanitizer_sigset_t &get_from_tls_oldset() {
+  return GetTSanTLSHack()->oldset;
+};
+
+}
Index: lib/tsan/rtl/tsan_interceptors.cc
===================================================================
--- lib/tsan/rtl/tsan_interceptors.cc
+++ lib/tsan/rtl/tsan_interceptors.cc
@@ -13,6 +13,8 @@
 // sanitizer_common/sanitizer_common_interceptors.inc
 //===----------------------------------------------------------------------===//
 
+static unsigned long long GLOBAL_interceptor_count = 0;
+
 #include "sanitizer_common/sanitizer_atomic.h"
 #include "sanitizer_common/sanitizer_libc.h"
 #include "sanitizer_common/sanitizer_linux.h"
@@ -39,6 +41,11 @@
 #define stderr __stderrp
 #endif
 
+#if SANITIZER_ANDROID
+#define __errno_location __errno
+#define fileno_unlocked fileno
+#endif
+
 #ifdef __mips__
 const int kSigCount = 129;
 #else
@@ -68,7 +75,9 @@
 extern "C" int pthread_key_create(unsigned *key, void (*destructor)(void* v));
 extern "C" int pthread_setspecific(unsigned key, const void *v);
 DECLARE_REAL(int, pthread_mutexattr_gettype, void *, void *)
+#if !SANITIZER_ANDROID
 extern "C" int pthread_yield();
+#endif
 extern "C" int pthread_sigmask(int how, const __sanitizer_sigset_t *set,
                                __sanitizer_sigset_t *oldset);
 // REAL(sigfillset) defined in common interceptors.
@@ -76,17 +85,43 @@
 DECLARE_REAL(int, fflush, __sanitizer_FILE *fp)
 extern "C" void *pthread_self();
 extern "C" void _exit(int status);
+
 extern "C" int *__errno_location();
 extern "C" int fileno_unlocked(void *stream);
+
+#if SANITIZER_ANDROID && __aarch64__
+// bionic does not have __libc_(malloc/realloc/calloc/free)
+DECLARE_REAL(void *, malloc, uptr);
+DECLARE_REAL(void *, calloc, uptr, uptr);
+DECLARE_REAL(void *, realloc, void *, uptr);
+DECLARE_REAL(void, free, void *);
+
+#define __libc_malloc  REAL(malloc)
+#define __libc_realloc REAL(realloc)
+#define __libc_calloc  REAL(calloc)
+#define __libc_free    REAL(free)
+#else
 extern "C" void *__libc_malloc(uptr size);
+extern "C" void __libc_free(void *ptr);
 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);
+#endif
+
+
 extern "C" int dirfd(void *dirp);
 #if !SANITIZER_FREEBSD
 extern "C" int mallopt(int param, int value);
 #endif
+
+#if SANITIZER_ANDROID
+extern __sanitizer_FILE __sF[];
+#define         stdout  (&__sF[1])
+#define         stderr  (&__sF[2])
+#else
 extern __sanitizer_FILE *stdout, *stderr;
+#endif // SANITIZER_ANDROID
+
+
 const int PTHREAD_MUTEX_RECURSIVE = 1;
 const int PTHREAD_MUTEX_RECURSIVE_NP = 1;
 const int EINVAL = 22;
@@ -117,7 +152,7 @@
 # define F_TLOCK 2      /* Test and lock a region for exclusive use.  */
 # define F_TEST  3      /* Test a region for other processes locks.  */
 
-#define errno (*__errno_location())
+#define get_errno_lval (*__errno_location())
 
 typedef void (*sighandler_t)(int sig);
 typedef void (*sigactionhandler_t)(int sig, my_siginfo_t *siginfo, void *uctx);
@@ -249,8 +284,10 @@
 }
 
 #define SCOPED_INTERCEPTOR_RAW(func, ...) \
+    ++GLOBAL_interceptor_count; \
     ThreadState *thr = cur_thread(); \
     const uptr caller_pc = GET_CALLER_PC(); \
+    DPrintf2("INTERCEPT: " #func " %s:%d:%s\n", __FILE__, __LINE__, __PRETTY_FUNCTION__); \
     ScopedInterceptor si(thr, #func, caller_pc); \
     const uptr pc = StackTrace::GetCurrentPc(); \
     (void)pc; \
@@ -540,7 +577,11 @@
 
 TSAN_INTERCEPTOR(void*, calloc, uptr size, uptr n) {
   if (cur_thread()->in_symbolizer)
+#if SANITIZER_ANDROID
+    return REAL(calloc)(size, n);
+#else
     return __libc_calloc(size, n);
+#endif
   void *p = 0;
   {
     SCOPED_INTERCEPTOR_RAW(calloc, size, n);
@@ -552,7 +593,12 @@
 
 TSAN_INTERCEPTOR(void*, realloc, void *p, uptr size) {
   if (cur_thread()->in_symbolizer)
+#if SANITIZER_ANDROID
+    return REAL(realloc)(p, size);
+#else
     return __libc_realloc(p, size);
+#endif
+
   if (p)
     invoke_free_hook(p);
   {
@@ -757,7 +803,7 @@
   if (*addr) {
     if (!IsAppMem((uptr)*addr) || !IsAppMem((uptr)*addr + sz - 1)) {
       if (flags & MAP_FIXED) {
-        errno = EINVAL;
+        get_errno_lval = EINVAL;
         return false;
       } else {
         *addr = 0;
@@ -917,7 +963,7 @@
     }
     ThreadIgnoreEnd(thr, 0);
     while ((tid = atomic_load(&p->tid, memory_order_acquire)) == 0)
-      pthread_yield();
+      internal_sched_yield();
     atomic_store(&p->tid, 0, memory_order_release);
     ThreadStart(thr, tid, GetTid());
   }
@@ -969,7 +1015,7 @@
     CHECK_NE(tid, 0);
     atomic_store(&p.tid, tid, memory_order_release);
     while (atomic_load(&p.tid, memory_order_acquire) != 0)
-      pthread_yield();
+      internal_sched_yield();
   }
   if (attr == &myattr)
     pthread_attr_destroy(&myattr);
@@ -1322,7 +1368,7 @@
     atomic_store(a, 2, memory_order_release);
   } else {
     while (v != 2) {
-      pthread_yield();
+      internal_sched_yield();
       v = atomic_load(a, memory_order_acquire);
     }
     if (!thr->in_ignored_lib)
@@ -1466,7 +1512,7 @@
 #define TSAN_MAYBE_INTERCEPT_LSTAT64
 #endif
 
-#if !SANITIZER_FREEBSD
+#if !SANITIZER_FREEBSD && ! SANITIZER_ANDROID
 TSAN_INTERCEPTOR(int, __fxstat, int version, int fd, void *buf) {
   SCOPED_TSAN_INTERCEPTOR(__fxstat, version, fd, buf);
   if (fd > 0)
@@ -1479,7 +1525,9 @@
 #endif
 
 TSAN_INTERCEPTOR(int, fstat, int fd, void *buf) {
-#if SANITIZER_FREEBSD
+// SANITIZER_TLS_WORKAROUND_NEEDED is for ANDROID&&__aarch64__
+// ANDROID does not have fxstat and friends
+#if SANITIZER_FREEBSD||SANITIZER_TLS_WORKAROUND_NEEDED
   SCOPED_TSAN_INTERCEPTOR(fstat, fd, buf);
   if (fd > 0)
     FdAccess(thr, pc, fd);
@@ -1492,7 +1540,7 @@
 #endif
 }
 
-#if !SANITIZER_FREEBSD
+#if !SANITIZER_FREEBSD&&!SANITIZER_TLS_WORKAROUND_NEEDED
 TSAN_INTERCEPTOR(int, __fxstat64, int version, int fd, void *buf) {
   SCOPED_TSAN_INTERCEPTOR(__fxstat64, version, fd, buf);
   if (fd > 0)
@@ -1504,7 +1552,7 @@
 #define TSAN_MAYBE_INTERCEPT___FXSTAT64
 #endif
 
-#if !SANITIZER_FREEBSD
+#if !SANITIZER_FREEBSD&&!SANITIZER_TLS_WORKAROUND_NEEDED
 TSAN_INTERCEPTOR(int, fstat64, int fd, void *buf) {
   SCOPED_TSAN_INTERCEPTOR(__fxstat64, 0, fd, buf);
   if (fd > 0)
@@ -1513,8 +1561,18 @@
 }
 #define TSAN_MAYBE_INTERCEPT_FSTAT64 TSAN_INTERCEPT(fstat64)
 #else
+#if SANITIZER_TLS_WORKAROUND_NEEDED
+TSAN_INTERCEPTOR(int, fstat64, int fd, void *buf) {
+  SCOPED_TSAN_INTERCEPTOR(fstat64, fd, buf);
+  if (fd > 0)
+    FdAccess(thr, pc, fd);
+  return REAL(fstat64)(fd, buf);
+}
+#define TSAN_MAYBE_INTERCEPT_FSTAT64 TSAN_INTERCEPT(fstat64)
+#else
 #define TSAN_MAYBE_INTERCEPT_FSTAT64
 #endif
+#endif
 
 TSAN_INTERCEPTOR(int, open, const char *name, int flags, int mode) {
   SCOPED_TSAN_INTERCEPTOR(open, name, flags, mode);
@@ -1910,8 +1968,8 @@
   if (acquire)
     Acquire(thr, 0, (uptr)&sigactions[sig]);
   // Ensure that the handler does not spoil errno.
-  const int saved_errno = errno;
-  errno = 99;
+  const int saved_errno = get_errno_lval;
+  get_errno_lval = 99;
   // This code races with sigaction. Be careful to not read sa_sigaction twice.
   // Also need to remember pc for reporting before the call,
   // because the handler can reset it.
@@ -1931,7 +1989,7 @@
   // because in async signal processing case (when handler is called directly
   // from rtl_generic_sighandler) we have not yet received the reraised
   // signal; and it looks too fragile to intercept all ways to reraise a signal.
-  if (flags()->report_bugs && !sync && sig != SIGTERM && errno != 99) {
+  if (flags()->report_bugs && !sync && sig != SIGTERM && get_errno_lval != 99) {
     VarSizeStackTrace stack;
     // StackTrace::GetNestInstructionPc(pc) is used because return address is
     // expected, OutputReport() will undo this.
@@ -1943,7 +2001,7 @@
       OutputReport(thr, rep);
     }
   }
-  errno = saved_errno;
+  get_errno_lval = saved_errno;
 }
 
 void ProcessPendingSignals(ThreadState *thr) {
@@ -1953,10 +2011,22 @@
     return;
   atomic_store(&sctx->have_pending_signals, 0, memory_order_relaxed);
   atomic_fetch_add(&thr->in_signal_handler, 1, memory_order_relaxed);
+#if SANITIZER_TLS_WORKAROUND_NEEDED
+  extern __sanitizer_sigset_t &get_from_tls_emptyset();
+  extern __sanitizer_sigset_t &get_from_tls_oldset();
+  extern void internal_sigfillset(__sanitizer_sigset_t *);
+  //
+#else
   // These are too big for stack.
   static THREADLOCAL __sanitizer_sigset_t emptyset, oldset;
-  CHECK_EQ(0, REAL(sigfillset)(&emptyset));
-  CHECK_EQ(0, pthread_sigmask(SIG_SETMASK, &emptyset, &oldset));
+#endif
+  __sanitizer_sigset_t *P =  & GetFromTLS(emptyset);
+  CHECK_EQ(0, REAL(sigfillset)(P));
+  __sanitizer_sigset_t *E = &GetFromTLS(emptyset);
+  __sanitizer_sigset_t *O = &GetFromTLS(oldset);
+
+  CHECK_EQ(0, pthread_sigmask(SIG_SETMASK, E, O));
+
   for (int sig = 0; sig < kSigCount; sig++) {
     SignalDesc *signal = &sctx->pending_signals[sig];
     if (signal->armed) {
@@ -1965,7 +2035,7 @@
           &signal->siginfo, &signal->ctx);
     }
   }
-  CHECK_EQ(0, pthread_sigmask(SIG_SETMASK, &oldset, 0));
+  CHECK_EQ(0, pthread_sigmask(SIG_SETMASK, &GetFromTLS(oldset), 0));
   atomic_fetch_add(&thr->in_signal_handler, -1, memory_order_relaxed);
 }
 
@@ -2455,7 +2525,7 @@
   REAL(memcmp) = internal_memcmp;
 
   // Instruct libc malloc to consume less memory.
-#if !SANITIZER_FREEBSD
+#if !SANITIZER_FREEBSD && !SANITIZER_ANDROID
   mallopt(1, 0);  // M_MXFAST
   mallopt(-3, 32*1024);  // M_MMAP_THRESHOLD
 #endif
Index: lib/tsan/rtl/tsan_interface.cc
===================================================================
--- lib/tsan/rtl/tsan_interface.cc
+++ lib/tsan/rtl/tsan_interface.cc
@@ -23,11 +23,23 @@
 typedef u16 uint16_t;
 typedef u32 uint32_t;
 typedef u64 uint64_t;
+static u64 __tsan_init_count=0;
 
 void __tsan_init() {
+  __tsan_init_count++;
+#if SANITIZER_TLS_WORKAROUND_NEEDED
+  bool C = InitTSanWorkAround(); (void)C;
+  DPrintf("__tsan_init called %lld times -- InitTSanWorkAround()  == %d\n",
+          __tsan_init_count, C);
+#endif
   Initialize(cur_thread());
 }
 
+#if SANITIZER_TLS_WORKAROUND_NEEDED
+__attribute__((section(".preinit_array"), used))
+void (*__local_tsan_preinitc)(void) = __tsan_init;
+#endif // SANITIZER_TLS_WORKAROUND_NEEDED
+
 void __tsan_read16(void *addr) {
   MemoryRead(cur_thread(), CALLERPC, (uptr)addr, kSizeLog8);
   MemoryRead(cur_thread(), CALLERPC, (uptr)addr + 8, kSizeLog8);
Index: lib/tsan/rtl/tsan_platform.h
===================================================================
--- lib/tsan/rtl/tsan_platform.h
+++ lib/tsan/rtl/tsan_platform.h
@@ -14,7 +14,7 @@
 
 #ifndef TSAN_PLATFORM_H
 #define TSAN_PLATFORM_H
-
+// #define TSAN_DEBUG_OUTPUT 2
 #if !defined(__LP64__) && !defined(_WIN64)
 # error "Only 64-bit is supported"
 #endif
@@ -88,6 +88,32 @@
 const uptr kVdsoBeg       = 0xfffff00000ull;
 #endif
 
+#if defined(__aarch64__)
+/*
+// aarch64: -- memory maps are wierd here.
+*/
+#if !defined(__ANDROID__)
+#error "please fix for aarch64 !ANDROID"
+#endif
+
+const uptr kShadowBeg     = 0x1400000000ull;
+const uptr kShadowEnd     = 0x2400000000ull;
+const uptr kMetaShadowBeg = 0x3000000000ull;
+const uptr kMetaShadowEnd = 0x4000000000ull;
+const uptr kLoAppMemBeg   = 0x5500000000ull;
+const uptr kLoAppMemEnd   = 0x5600000000ull;
+const uptr kTraceMemBeg   = 0x6000000000ull;
+const uptr kTraceMemEnd   = 0x6200000000ull;
+const uptr kHeapMemBeg    = 0x7e00000000ull;
+const uptr kHeapMemEnd    = 0x7f00000000ull;
+const uptr kHiAppMemBeg   = 0x7f00000000ull;
+const uptr kHiAppMemEnd   = 0x8000000000ull;
+const uptr kAppMemMsk     = 0xfc00000000ull;
+const uptr kAppMemMskRtn  = 0x7c00000000ull;
+const uptr kAppMemXor     = 0x0400000000ull;
+const uptr kVdsoBeg       = 0xf000000000ull;
+#endif
+
 ALWAYS_INLINE
 bool IsAppMem(uptr mem) {
   return (mem >= kHeapMemBeg && mem < kHeapMemEnd) ||
@@ -119,6 +145,16 @@
       ^ kAppMemXor) / kMetaShadowCell * kMetaShadowSize) | kMetaShadowBeg);
 }
 
+#if defined(__aarch64__)
+ALWAYS_INLINE
+uptr ShadowToMem(uptr s) {
+  CHECK(IsShadowMem(s));
+  if (s >= MemToShadow(kLoAppMemBeg) && s <= MemToShadow(kLoAppMemEnd - 1))
+    return (s / kShadowCnt) ^ kAppMemXor | kLoAppMemBeg;
+  else
+    return ((s / kShadowCnt) ^ kAppMemXor) | kAppMemMskRtn;
+}
+#else // __mips64 and __x86_64__
 ALWAYS_INLINE
 uptr ShadowToMem(uptr s) {
   CHECK(IsShadowMem(s));
@@ -127,6 +163,7 @@
   else
     return ((s / kShadowCnt) ^ kAppMemXor) | kAppMemMsk;
 }
+#endif
 
 static USED uptr UserRegions[] = {
   kLoAppMemBeg, kLoAppMemEnd,
Index: lib/tsan/rtl/tsan_platform_linux.cc
===================================================================
--- lib/tsan/rtl/tsan_platform_linux.cc
+++ lib/tsan/rtl/tsan_platform_linux.cc
@@ -220,6 +220,9 @@
 #elif defined(__mips64)
   const uptr kMadviseRangeBeg  = 0xff00000000ull;
   const uptr kMadviseRangeSize = 0x0100000000ull;
+#elif SANITIZER_TLS_WORKAROUND_NEEDED
+  const uptr kMadviseRangeBeg  = kHiAppMemBeg;
+  const uptr kMadviseRangeSize = kHiAppMemEnd - kHiAppMemBeg;
 #endif
   NoHugePagesInRegion(MemToShadow(kMadviseRangeBeg),
                       kMadviseRangeSize * kShadowMultiplier);
@@ -302,6 +305,18 @@
     Die();
   }
 
+#if SANITIZER_TLS_WORKAROUND_NEEDED
+  // on aaarch64/android, the memory maps are significantly different
+  ProtectRange(kShadowEnd, kMetaShadowBeg);
+  ProtectRange(kMetaShadowEnd, kLoAppMemBeg);
+  ProtectRange(kLoAppMemEnd, kTraceMemBeg);
+
+  // Memory for traces is mapped lazily in MapThreadTrace.
+  // Protect the whole range for now, so that user does not map something here.
+  ProtectRange(kTraceMemBeg, kTraceMemEnd);
+  ProtectRange(kTraceMemEnd, kHeapMemBeg);
+  //ProtectRange(HeapEnd(), kHiAppMemBeg);
+#else
   ProtectRange(kLoAppMemEnd, kShadowBeg);
   ProtectRange(kShadowEnd, kMetaShadowBeg);
   ProtectRange(kMetaShadowEnd, kTraceMemBeg);
@@ -310,6 +325,7 @@
   ProtectRange(kTraceMemBeg, kTraceMemEnd);
   ProtectRange(kTraceMemEnd, kHeapMemBeg);
   ProtectRange(HeapEnd(), kHiAppMemBeg);
+#endif
 }
 #endif  // #ifndef SANITIZER_GO
 
@@ -361,7 +377,7 @@
 // This is required to properly "close" the fds, because we do not see internal
 // closes within glibc. The code is a pure hack.
 int ExtractResolvFDs(void *state, int *fds, int nfd) {
-#if SANITIZER_LINUX
+#if SANITIZER_LINUX && !SANITIZER_ANDROID
   int cnt = 0;
   __res_state *statp = (__res_state*)state;
   for (int i = 0; i < MAXNS && cnt < nfd; i++) {
Index: lib/tsan/rtl/tsan_rtl.h
===================================================================
--- lib/tsan/rtl/tsan_rtl.h
+++ lib/tsan/rtl/tsan_rtl.h
@@ -34,6 +34,9 @@
 #include "sanitizer_common/sanitizer_libignore.h"
 #include "sanitizer_common/sanitizer_suppressions.h"
 #include "sanitizer_common/sanitizer_thread_registry.h"
+
+// this needs to be pulled in first
+#include "tsan_aarch64_tls_workaround.h"
 #include "tsan_clock.h"
 #include "tsan_defs.h"
 #include "tsan_flags.h"
@@ -54,7 +57,7 @@
 
 #ifndef SANITIZER_GO
 struct MapUnmapCallback;
-#ifdef __mips64
+#if defined(__mips64) || defined(__aarch64__)
 static const uptr kAllocatorSpace = 0;
 static const uptr kAllocatorSize = SANITIZER_MMAP_RANGE_SIZE;
 static const uptr kAllocatorRegionSizeLog = 20;
@@ -410,11 +413,18 @@
 };
 
 #ifndef SANITIZER_GO
+#if !SANITIZER_TLS_WORKAROUND_NEEDED
 __attribute__((tls_model("initial-exec")))
 extern THREADLOCAL char cur_thread_placeholder[];
 INLINE ThreadState *cur_thread() {
-  return reinterpret_cast<ThreadState *>(&cur_thread_placeholder);
+  return reinterpret_cast<ThreadState *>(&GetFromTLS(cur_thread_placeholder));
 }
+#else
+extern char &get_from_tls_cur_thread_placeholder();
+INLINE ThreadState *cur_thread() {
+  return reinterpret_cast<ThreadState *>(&get_from_tls_cur_thread_placeholder());
+}
+#endif
 #endif
 
 class ThreadContext : public ThreadContextBase {
Index: lib/tsan/rtl/tsan_rtl.cc
===================================================================
--- lib/tsan/rtl/tsan_rtl.cc
+++ lib/tsan/rtl/tsan_rtl.cc
@@ -44,7 +44,11 @@
 namespace __tsan {
 
 #ifndef SANITIZER_GO
+#if !SANITIZER_TLS_WORKAROUND_NEEDED
 THREADLOCAL char cur_thread_placeholder[sizeof(ThreadState)] ALIGNED(64);
+// these are the real accessor functions
+extern char &get_from_tls_cur_thread_placeholder();
+#endif
 #endif
 static char ctx_placeholder[sizeof(Context)] ALIGNED(64);
 Context *ctx;
@@ -290,7 +294,8 @@
           continue;
         const uptr s = MemToShadow(p);
         const uptr m = (uptr)MemToMeta(p);
-        VPrintf(3, "  checking pointer %p: shadow=%p meta=%p\n", p, s, m);
+        const uptr s1 = ShadowToMem(s);
+        VPrintf(3, "  checking pointer %p: shadow=%p meta=%p s2m=%p\n", p, s, m, s1);
         CHECK(IsAppMem(p));
         CHECK(IsShadowMem(s));
         CHECK_EQ(p & ~(kShadowCell - 1), ShadowToMem(s));
@@ -335,7 +340,7 @@
   // On MIPS, TSan initialization is run before
   // __pthread_initialize_minimal_internal() is finished, so we can not spawn
   // new threads.
-#ifndef __mips__
+#if !defined(__mips__)&&!SANITIZER_TLS_WORKAROUND_NEEDED
   StartBackgroundThread();
   SetSandboxingCallback(StopBackgroundThread);
 #endif