Add descriptive names to sanitizer entries in /proc/self/maps. Helps debugging.
authorEvgeniy Stepanov <eugeni.stepanov@gmail.com>
Fri, 29 May 2015 22:31:28 +0000 (22:31 +0000)
committerEvgeniy Stepanov <eugeni.stepanov@gmail.com>
Fri, 29 May 2015 22:31:28 +0000 (22:31 +0000)
This is done by creating a named shared memory region, unlinking it
and setting up a private (i.e. copy-on-write) mapping of that instead
of a regular anonymous mapping. I've experimented with regular
(sparse) files, but they can not be scaled to the size of MSan shadow
mapping, at least on Linux/X86_64 and ext3 fs.

Controlled by a common flag, decorate_proc_maps, disabled by default.

This patch has a few shortcomings:
* not all mappings are annotated, especially in TSan.
* our handling of memset() of shadow via mmap() puts small anonymous
  mappings inside larger named mappings, which looks ugly and can, in
  theory, hit the mapping number limit.

llvm-svn: 238621

20 files changed:
compiler-rt/cmake/config-ix.cmake
compiler-rt/lib/asan/CMakeLists.txt
compiler-rt/lib/asan/asan_internal.h
compiler-rt/lib/asan/asan_poisoning.h
compiler-rt/lib/asan/asan_rtl.cc
compiler-rt/lib/asan/tests/CMakeLists.txt
compiler-rt/lib/msan/msan_linux.cc
compiler-rt/lib/sanitizer_common/sanitizer_common.h
compiler-rt/lib/sanitizer_common/sanitizer_flags.inc
compiler-rt/lib/sanitizer_common/sanitizer_posix.cc
compiler-rt/lib/sanitizer_common/sanitizer_posix_libcdep.cc
compiler-rt/lib/sanitizer_common/sanitizer_win.cc
compiler-rt/lib/sanitizer_common/tests/CMakeLists.txt
compiler-rt/lib/tsan/go/buildgo.sh
compiler-rt/lib/tsan/rtl/tsan_platform_linux.cc
compiler-rt/lib/tsan/rtl/tsan_rtl.cc
compiler-rt/lib/tsan/rtl/tsan_rtl.h
compiler-rt/test/sanitizer_common/TestCases/Posix/decorate_proc_maps.cc [new file with mode: 0644]
compiler-rt/test/sanitizer_common/TestCases/Posix/lit.local.cfg [new file with mode: 0644]
compiler-rt/test/sanitizer_common/lit.common.cfg

index d69d73d..114c2a5 100644 (file)
@@ -62,6 +62,7 @@ check_symbol_exists(__func__ "" COMPILER_RT_HAS_FUNC_SYMBOL)
 # Libraries.
 check_library_exists(c printf "" COMPILER_RT_HAS_LIBC)
 check_library_exists(dl dlopen "" COMPILER_RT_HAS_LIBDL)
+check_library_exists(rt shm_open "" COMPILER_RT_HAS_LIBRT)
 check_library_exists(m pow "" COMPILER_RT_HAS_LIBM)
 check_library_exists(pthread pthread_create "" COMPILER_RT_HAS_LIBPTHREAD)
 check_library_exists(stdc++ __cxa_throw "" COMPILER_RT_HAS_LIBSTDCXX)
index 389215b..28f354b 100644 (file)
@@ -66,6 +66,7 @@ append_list_if(MSVC /DEBUG ASAN_DYNAMIC_CFLAGS)
 
 append_list_if(COMPILER_RT_HAS_LIBC c ASAN_DYNAMIC_LIBS)
 append_list_if(COMPILER_RT_HAS_LIBDL dl ASAN_DYNAMIC_LIBS)
+append_list_if(COMPILER_RT_HAS_LIBRT rt ASAN_DYNAMIC_LIBS)
 append_list_if(COMPILER_RT_HAS_LIBM m ASAN_DYNAMIC_LIBS)
 append_list_if(COMPILER_RT_HAS_LIBPTHREAD pthread ASAN_DYNAMIC_LIBS)
 append_list_if(COMPILER_RT_HAS_LIBSTDCXX stdc++ ASAN_DYNAMIC_LIBS)
index 394e460..107e16e 100644 (file)
@@ -93,7 +93,7 @@ void AppendToErrorMessageBuffer(const char *buffer);
 
 void *AsanDlSymNext(const char *sym);
 
-void ReserveShadowMemoryRange(uptr beg, uptr end);
+void ReserveShadowMemoryRange(uptr beg, uptr end, const char *name);
 
 // Platform-specific options.
 #if SANITIZER_MAC
index 3fc9464..6344225 100644 (file)
@@ -64,7 +64,7 @@ ALWAYS_INLINE void FastPoisonShadow(uptr aligned_beg, uptr aligned_size,
       if (page_end != shadow_end) {
         REAL(memset)((void *)page_end, 0, shadow_end - page_end);
       }
-      ReserveShadowMemoryRange(page_beg, page_end - 1);
+      ReserveShadowMemoryRange(page_beg, page_end - 1, nullptr);
     }
   }
 }
index 10ddfc7..b829619 100644 (file)
@@ -89,12 +89,12 @@ void ShowStatsAndAbort() {
 // ---------------------- mmap -------------------- {{{1
 // Reserve memory range [beg, end].
 // We need to use inclusive range because end+1 may not be representable.
-void ReserveShadowMemoryRange(uptr beg, uptr end) {
+void ReserveShadowMemoryRange(uptr beg, uptr end, const char *name) {
   CHECK_EQ((beg % GetPageSizeCached()), 0);
   CHECK_EQ(((end + 1) % GetPageSizeCached()), 0);
   uptr size = end - beg + 1;
   DecreaseTotalMmap(size);  // Don't count the shadow against mmap_limit_mb.
-  void *res = MmapFixedNoReserve(beg, size);
+  void *res = MmapFixedNoReserve(beg, size, name);
   if (res != (void*)beg) {
     Report("ReserveShadowMemoryRange failed while trying to map 0x%zx bytes. "
            "Perhaps you're using ulimit -v\n", size);
@@ -298,7 +298,7 @@ static void InitializeHighMemEnd() {
 }
 
 static void ProtectGap(uptr addr, uptr size) {
-  void *res = MmapNoAccess(addr, size);
+  void *res = MmapNoAccess(addr, size, "shadow gap");
   if (addr == (uptr)res)
     return;
   Report("ERROR: Failed to protect the shadow gap. "
@@ -422,9 +422,9 @@ static void AsanInitInternal() {
   if (full_shadow_is_available) {
     // mmap the low shadow plus at least one page at the left.
     if (kLowShadowBeg)
-      ReserveShadowMemoryRange(shadow_start, kLowShadowEnd);
+      ReserveShadowMemoryRange(shadow_start, kLowShadowEnd, "low shadow");
     // mmap the high shadow.
-    ReserveShadowMemoryRange(kHighShadowBeg, kHighShadowEnd);
+    ReserveShadowMemoryRange(kHighShadowBeg, kHighShadowEnd, "high shadow");
     // protect the gap.
     ProtectGap(kShadowGapBeg, kShadowGapEnd - kShadowGapBeg + 1);
     CHECK_EQ(kShadowGapEnd, kHighShadowBeg - 1);
@@ -433,11 +433,11 @@ static void AsanInitInternal() {
       MemoryRangeIsAvailable(kMidMemEnd + 1, kHighShadowEnd)) {
     CHECK(kLowShadowBeg != kLowShadowEnd);
     // mmap the low shadow plus at least one page at the left.
-    ReserveShadowMemoryRange(shadow_start, kLowShadowEnd);
+    ReserveShadowMemoryRange(shadow_start, kLowShadowEnd, "low shadow");
     // mmap the mid shadow.
-    ReserveShadowMemoryRange(kMidShadowBeg, kMidShadowEnd);
+    ReserveShadowMemoryRange(kMidShadowBeg, kMidShadowEnd, "mid shadow");
     // mmap the high shadow.
-    ReserveShadowMemoryRange(kHighShadowBeg, kHighShadowEnd);
+    ReserveShadowMemoryRange(kHighShadowBeg, kHighShadowEnd, "high shadow");
     // protect the gaps.
     ProtectGap(kShadowGapBeg, kShadowGapEnd - kShadowGapBeg + 1);
     ProtectGap(kShadowGap2Beg, kShadowGap2End - kShadowGap2Beg + 1);
index 75b2282..122d151 100644 (file)
@@ -99,6 +99,7 @@ append_list_if(ANDROID atomic ASAN_UNITTEST_INSTRUMENTED_LIBS)
 set(ASAN_UNITTEST_NOINST_LINKFLAGS ${ASAN_UNITTEST_COMMON_LINKFLAGS})
 append_list_if(COMPILER_RT_HAS_LIBM -lm ASAN_UNITTEST_NOINST_LINKFLAGS)
 append_list_if(COMPILER_RT_HAS_LIBDL -ldl ASAN_UNITTEST_NOINST_LINKFLAGS)
+append_list_if(COMPILER_RT_HAS_LIBRT -lrt ASAN_UNITTEST_NOINST_LINKFLAGS)
 append_list_if(COMPILER_RT_HAS_LIBPTHREAD -pthread ASAN_UNITTEST_NOINST_LINKFLAGS)
 append_list_if(COMPILER_RT_HAS_LIBPTHREAD -pthread
           ASAN_DYNAMIC_UNITTEST_INSTRUMENTED_LINKFLAGS)
index 38c36d9..7025ef6 100644 (file)
@@ -53,16 +53,16 @@ static bool CheckMemoryRangeAvailability(uptr beg, uptr size) {
   return true;
 }
 
-static bool ProtectMemoryRange(uptr beg, uptr size) {
+static bool ProtectMemoryRange(uptr beg, uptr size, const char *name) {
   if (size > 0) {
-    void *addr = MmapNoAccess(beg, size);
+    void *addr = MmapNoAccess(beg, size, name);
     if (beg == 0 && addr != 0) {
       // Depending on the kernel configuration, we may not be able to protect
       // the page at address zero.
       uptr gap = 16 * GetPageSizeCached();
       beg += gap;
       size -= gap;
-      addr = MmapNoAccess(beg, size);
+      addr = MmapNoAccess(beg, size, name);
     }
     if ((uptr)addr != beg) {
       uptr end = beg + size - 1;
@@ -135,7 +135,7 @@ bool InitShadow(bool init_origins) {
     if (map) {
       if (!CheckMemoryRangeAvailability(start, size))
         return false;
-      if ((uptr)MmapFixedNoReserve(start, size) != start)
+      if ((uptr)MmapFixedNoReserve(start, size, kMemoryLayout[i].name) != start)
         return false;
       if (common_flags()->use_madv_dontdump)
         DontDumpShadowMemory(start, size);
@@ -143,7 +143,7 @@ bool InitShadow(bool init_origins) {
     if (protect) {
       if (!CheckMemoryRangeAvailability(start, size))
         return false;
-      if (!ProtectMemoryRange(start, size))
+      if (!ProtectMemoryRange(start, size, kMemoryLayout[i].name))
         return false;
     }
   }
index 01a15da..3048212 100644 (file)
@@ -69,10 +69,11 @@ void GetThreadStackAndTls(bool main, uptr *stk_addr, uptr *stk_size,
 // Memory management
 void *MmapOrDie(uptr size, const char *mem_type);
 void UnmapOrDie(void *addr, uptr size);
-void *MmapFixedNoReserve(uptr fixed_addr, uptr size);
+void *MmapFixedNoReserve(uptr fixed_addr, uptr size,
+                         const char *name = nullptr);
 void *MmapNoReserveOrDie(uptr size, const char *mem_type);
 void *MmapFixedOrDie(uptr fixed_addr, uptr size);
-void *MmapNoAccess(uptr fixed_addr, uptr size);
+void *MmapNoAccess(uptr fixed_addr, uptr size, const char *name = nullptr);
 // Map aligned chunk of address space; size and alignment are powers of two.
 void *MmapAlignedOrDie(uptr size, uptr alignment, const char *mem_type);
 // Disallow access to a memory range.  Use MmapNoAccess to allocate an
index c713fed..38de5d7 100644 (file)
@@ -163,3 +163,6 @@ COMMON_FLAG(bool, intercept_strspn, true,
 COMMON_FLAG(bool, intercept_strpbrk, true,
             "If set, uses custom wrappers for strpbrk function "
             "to find more errors.")
+COMMON_FLAG(bool, decorate_proc_maps, false, "If set, decorate sanitizer "
+                                             "mappings in /proc/self/maps with "
+                                             "user-readable names")
index 0b6d35e..de4b8d1 100644 (file)
@@ -165,22 +165,6 @@ void *MmapNoReserveOrDie(uptr size, const char *mem_type) {
   return (void *)p;
 }
 
-void *MmapFixedNoReserve(uptr fixed_addr, uptr size) {
-  uptr PageSize = GetPageSizeCached();
-  uptr p = internal_mmap((void*)(fixed_addr & ~(PageSize - 1)),
-      RoundUpTo(size, PageSize),
-      PROT_READ | PROT_WRITE,
-      MAP_PRIVATE | MAP_ANON | MAP_FIXED | MAP_NORESERVE,
-      -1, 0);
-  int reserrno;
-  if (internal_iserror(p, &reserrno))
-    Report("ERROR: %s failed to "
-           "allocate 0x%zx (%zd) bytes at address %zx (errno: %d)\n",
-           SanitizerToolName, size, size, fixed_addr, reserrno);
-  IncreaseTotalMmap(size);
-  return (void *)p;
-}
-
 void *MmapFixedOrDie(uptr fixed_addr, uptr size) {
   uptr PageSize = GetPageSizeCached();
   uptr p = internal_mmap((void*)(fixed_addr & ~(PageSize - 1)),
@@ -199,13 +183,6 @@ void *MmapFixedOrDie(uptr fixed_addr, uptr size) {
   return (void *)p;
 }
 
-void *MmapNoAccess(uptr fixed_addr, uptr size) {
-  return (void *)internal_mmap((void*)fixed_addr, size,
-                               PROT_NONE,
-                               MAP_PRIVATE | MAP_ANON | MAP_FIXED |
-                               MAP_NORESERVE, -1, 0);
-}
-
 bool MprotectNoAccess(uptr addr, uptr size) {
   return 0 == internal_mprotect((void*)addr, size, PROT_NONE);
 }
index e5e65fc..b36a0fa 100644 (file)
@@ -24,6 +24,7 @@
 #include "sanitizer_symbolizer.h"
 
 #include <errno.h>
+#include <fcntl.h>
 #include <pthread.h>
 #include <signal.h>
 #include <stdlib.h>
@@ -31,6 +32,7 @@
 #include <sys/resource.h>
 #include <sys/time.h>
 #include <sys/types.h>
+#include <sys/stat.h>
 #include <unistd.h>
 
 namespace __sanitizer {
@@ -217,6 +219,55 @@ void PrepareForSandboxing(__sanitizer_sandbox_arguments *args) {
 #endif
 }
 
+#if SANITIZER_ANDROID
+int GetNamedMappingFd(const char *name, uptr size) {
+  return -1;
+}
+#else
+int GetNamedMappingFd(const char *name, uptr size) {
+  if (!common_flags()->decorate_proc_maps)
+    return -1;
+  char shmname[200];
+  CHECK(internal_strlen(name) < sizeof(shmname) - 10);
+  internal_snprintf(shmname, sizeof(shmname), "%zu [%s]", internal_getpid(),
+                    name);
+  int fd = shm_open(shmname, O_RDWR | O_CREAT | O_TRUNC, S_IRWXU);
+  CHECK_GE(fd, 0);
+  int res = internal_ftruncate(fd, size);
+  CHECK_EQ(0, res);
+  res = shm_unlink(shmname);
+  CHECK_EQ(0, res);
+  return fd;
+}
+#endif
+
+void *MmapFixedNoReserve(uptr fixed_addr, uptr size, const char *name) {
+  int fd = name ? GetNamedMappingFd(name, size) : -1;
+  unsigned flags = MAP_PRIVATE | MAP_FIXED | MAP_NORESERVE;
+  if (fd == -1) flags |= MAP_ANON;
+
+  uptr PageSize = GetPageSizeCached();
+  uptr p = internal_mmap((void *)(fixed_addr & ~(PageSize - 1)),
+                         RoundUpTo(size, PageSize), PROT_READ | PROT_WRITE,
+                         flags, fd, 0);
+  int reserrno;
+  if (internal_iserror(p, &reserrno))
+    Report("ERROR: %s failed to "
+           "allocate 0x%zx (%zd) bytes at address %zx (errno: %d)\n",
+           SanitizerToolName, size, size, fixed_addr, reserrno);
+  IncreaseTotalMmap(size);
+  return (void *)p;
+}
+
+void *MmapNoAccess(uptr fixed_addr, uptr size, const char *name) {
+  int fd = name ? GetNamedMappingFd(name, size) : -1;
+  unsigned flags = MAP_PRIVATE | MAP_FIXED | MAP_NORESERVE;
+  if (fd == -1) flags |= MAP_ANON;
+
+  return (void *)internal_mmap((void *)fixed_addr, size, PROT_NONE, flags, fd,
+                               0);
+}
+
 }  // namespace __sanitizer
 
 #endif  // SANITIZER_POSIX
index 27e4b84..d37b25f 100644 (file)
@@ -104,9 +104,10 @@ void UnmapOrDie(void *addr, uptr size) {
   }
 }
 
-void *MmapFixedNoReserve(uptr fixed_addr, uptr size) {
+void *MmapFixedNoReserve(uptr fixed_addr, uptr size, const char *name) {
   // FIXME: is this really "NoReserve"? On Win32 this does not matter much,
   // but on Win64 it does.
+  (void)name; // unsupported
   void *p = VirtualAlloc((LPVOID)fixed_addr, size,
       MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
   if (p == 0)
@@ -125,7 +126,8 @@ void *MmapNoReserveOrDie(uptr size, const char *mem_type) {
   return MmapOrDie(size, mem_type);
 }
 
-void *MmapNoAccess(uptr fixed_addr, uptr size) {
+void *MmapNoAccess(uptr fixed_addr, uptr size, const char *name) {
+  (void)name; // unsupported
   void *res = VirtualAlloc((LPVOID)fixed_addr, size,
                            MEM_RESERVE | MEM_COMMIT, PAGE_NOACCESS);
   if (res == 0)
index 7379e52..540d506 100644 (file)
@@ -73,6 +73,7 @@ append_list_if(ANDROID log SANITIZER_TEST_LINK_LIBS)
 append_list_if(ANDROID atomic SANITIZER_TEST_LINK_LIBS)
 
 append_list_if(COMPILER_RT_HAS_LIBDL -ldl SANITIZER_TEST_LINK_FLAGS_COMMON)
+append_list_if(COMPILER_RT_HAS_LIBRT -lrt SANITIZER_TEST_LINK_FLAGS_COMMON)
 append_list_if(COMPILER_RT_HAS_LIBPTHREAD -pthread SANITIZER_TEST_LINK_FLAGS_COMMON)
 # x86_64 FreeBSD 9.2 additionally requires libc++ to build the tests. Also,
 # 'libm' shall be specified explicitly to build i386 tests.
index 5ac6034..7193b57 100755 (executable)
@@ -36,7 +36,7 @@ SRCS="
 if [ "`uname -a | grep Linux`" != "" ]; then
        SUFFIX="linux_amd64"
        OSCFLAGS="-fPIC -ffreestanding -Wno-maybe-uninitialized -Wno-unused-const-variable -Werror -Wno-unknown-warning-option"
-       OSLDFLAGS="-lpthread -fPIC -fpie"
+       OSLDFLAGS="-lpthread -lrt -fPIC -fpie"
        SRCS="
                $SRCS
                ../rtl/tsan_platform_linux.cc
index e408ba1..0359f5e 100644 (file)
@@ -202,8 +202,8 @@ static void MapRodata() {
 
 void InitializeShadowMemory() {
   // Map memory shadow.
-  uptr shadow = (uptr)MmapFixedNoReserve(kShadowBeg,
-    kShadowEnd - kShadowBeg);
+  uptr shadow =
+      (uptr)MmapFixedNoReserve(kShadowBeg, kShadowEnd - kShadowBeg, "shadow");
   if (shadow != kShadowBeg) {
     Printf("FATAL: ThreadSanitizer can not mmap the shadow memory\n");
     Printf("FATAL: Make sure to compile with -fPIE and "
@@ -232,7 +232,8 @@ void InitializeShadowMemory() {
 
   // Map meta shadow.
   uptr meta_size = kMetaShadowEnd - kMetaShadowBeg;
-  uptr meta = (uptr)MmapFixedNoReserve(kMetaShadowBeg, meta_size);
+  uptr meta =
+      (uptr)MmapFixedNoReserve(kMetaShadowBeg, meta_size, "meta shadow");
   if (meta != kMetaShadowBeg) {
     Printf("FATAL: ThreadSanitizer can not mmap the shadow memory\n");
     Printf("FATAL: Make sure to compile with -fPIE and "
index 3eddfcb..2f9c5ee 100644 (file)
@@ -67,9 +67,12 @@ static char thread_registry_placeholder[sizeof(ThreadRegistry)];
 
 static ThreadContextBase *CreateThreadContext(u32 tid) {
   // Map thread trace when context is created.
-  MapThreadTrace(GetThreadTrace(tid), TraceSize() * sizeof(Event));
+  char name[50];
+  internal_snprintf(name, sizeof(name), "trace %u", tid);
+  MapThreadTrace(GetThreadTrace(tid), TraceSize() * sizeof(Event), name);
   const uptr hdr = GetThreadTraceHeader(tid);
-  MapThreadTrace(hdr, sizeof(Trace));
+  internal_snprintf(name, sizeof(name), "trace header %u", tid);
+  MapThreadTrace(hdr, sizeof(Trace), name);
   new((void*)hdr) Trace();
   // We are going to use only a small part of the trace with the default
   // value of history_size. However, the constructor writes to the whole trace.
@@ -237,7 +240,7 @@ void MapShadow(uptr addr, uptr size) {
   // Global data is not 64K aligned, but there are no adjacent mappings,
   // so we can get away with unaligned mapping.
   // CHECK_EQ(addr, addr & ~((64 << 10) - 1));  // windows wants 64K alignment
-  MmapFixedNoReserve(MemToShadow(addr), size * kShadowMultiplier);
+  MmapFixedNoReserve(MemToShadow(addr), size * kShadowMultiplier, "shadow");
 
   // Meta shadow is 2:1, so tread carefully.
   static bool data_mapped = false;
@@ -249,7 +252,7 @@ void MapShadow(uptr addr, uptr size) {
   if (!data_mapped) {
     // First call maps data+bss.
     data_mapped = true;
-    MmapFixedNoReserve(meta_begin, meta_end - meta_begin);
+    MmapFixedNoReserve(meta_begin, meta_end - meta_begin, "meta shadow");
   } else {
     // Mapping continous heap.
     // Windows wants 64K alignment.
@@ -259,19 +262,19 @@ void MapShadow(uptr addr, uptr size) {
       return;
     if (meta_begin < mapped_meta_end)
       meta_begin = mapped_meta_end;
-    MmapFixedNoReserve(meta_begin, meta_end - meta_begin);
+    MmapFixedNoReserve(meta_begin, meta_end - meta_begin, "meta shadow");
     mapped_meta_end = meta_end;
   }
   VPrintf(2, "mapped meta shadow for (%p-%p) at (%p-%p)\n",
       addr, addr+size, meta_begin, meta_end);
 }
 
-void MapThreadTrace(uptr addr, uptr size) {
+void MapThreadTrace(uptr addr, uptr size, const char *name) {
   DPrintf("#0: Mapping trace at %p-%p(0x%zx)\n", addr, addr + size, size);
   CHECK_GE(addr, kTraceMemBeg);
   CHECK_LE(addr + size, kTraceMemEnd);
   CHECK_EQ(addr, addr & ~((64 << 10) - 1));  // windows wants 64K alignment
-  uptr addr1 = (uptr)MmapFixedNoReserve(addr, size);
+  uptr addr1 = (uptr)MmapFixedNoReserve(addr, size, name);
   if (addr1 != addr) {
     Printf("FATAL: ThreadSanitizer can not mmap thread trace (%p/%p->%p)\n",
         addr, size, addr1);
index dde908a..a13e4b6 100644 (file)
@@ -574,7 +574,7 @@ void ALWAYS_INLINE StatSet(ThreadState *thr, StatType typ, u64 n) {
 }
 
 void MapShadow(uptr addr, uptr size);
-void MapThreadTrace(uptr addr, uptr size);
+void MapThreadTrace(uptr addr, uptr size, const char *name);
 void DontNeedShadowFor(uptr addr, uptr size);
 void InitializeShadowMemory();
 void InitializeInterceptors();
diff --git a/compiler-rt/test/sanitizer_common/TestCases/Posix/decorate_proc_maps.cc b/compiler-rt/test/sanitizer_common/TestCases/Posix/decorate_proc_maps.cc
new file mode 100644 (file)
index 0000000..6224717
--- /dev/null
@@ -0,0 +1,60 @@
+// RUN: %clangxx -g %s -o %t
+// RUN: %tool_options=decorate_proc_maps=1 %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-%tool_name
+#include <errno.h>
+#include <fcntl.h>
+#include <pthread.h>
+#include <stdio.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+bool CopyFdToFd(int in_fd, int out_fd) {
+  const size_t kBufSize = 0x10000;
+  static char buf[kBufSize];
+  while (true) {
+    ssize_t got = read(in_fd, buf, kBufSize);
+    if (got > 0) {
+      write(out_fd, buf, got);
+    } else if (got == 0) {
+      break;
+    } else if (errno != EAGAIN || errno != EWOULDBLOCK || errno != EINTR) {
+      fprintf(stderr, "error reading file, errno %d\n", errno);
+      return false;
+    }
+  }
+  return true;
+}
+
+void *ThreadFn(void *arg) {
+  (void)arg;
+  int fd = open("/proc/self/maps", O_RDONLY);
+  bool res = CopyFdToFd(fd, 2);
+  close(fd);
+  return (void *)!res;
+}
+
+int main(void) {
+  pthread_t t;
+  void *res;
+  pthread_create(&t, 0, ThreadFn, 0);
+  pthread_join(t, &res);
+  return (int)(size_t)res;
+}
+
+// CHECK-asan: rw-p {{.*}} [low shadow]
+// CHECK-asan: ---p {{.*}} [shadow gap]
+// CHECK-asan: rw-p {{.*}} [high shadow]
+
+// CHECK-msan: ---p {{.*}} [invalid]
+// CHECK-msan: rw-p {{.*}} [shadow]
+// CHECK-msan: ---p {{.*}} [origin]
+
+// CHECK-tsan: rw-p {{.*}} [shadow]
+// CHECK-tsan: rw-p {{.*}} [meta shadow]
+// CHECK-tsan: rw-p {{.*}} [trace 0]
+// CHECK-tsan: rw-p {{.*}} [trace header 0]
+// CHECK-tsan: rw-p {{.*}} [trace 1]
+// CHECK-tsan: rw-p {{.*}} [trace header 1]
+
+// Nothing interesting with standalone LSan.
+// CHECK-lsan: decorate_proc_maps
diff --git a/compiler-rt/test/sanitizer_common/TestCases/Posix/lit.local.cfg b/compiler-rt/test/sanitizer_common/TestCases/Posix/lit.local.cfg
new file mode 100644 (file)
index 0000000..60a9460
--- /dev/null
@@ -0,0 +1,9 @@
+def getRoot(config):
+  if not config.parent:
+    return config
+  return getRoot(config.parent)
+
+root = getRoot(config)
+
+if root.host_os in ['Windows']:
+  config.unsupported = True
index fb37815..f2d3fec 100644 (file)
@@ -30,6 +30,7 @@ def build_invocation(compile_flags):
 
 config.substitutions.append( ("%clang ", build_invocation(clang_cflags)) )
 config.substitutions.append( ("%clangxx ", build_invocation(clang_cxxflags)) )
+config.substitutions.append( ("%tool_name", config.tool_name) )
 config.substitutions.append( ("%tool_options", tool_options) )
 
 config.suffixes = ['.c', '.cc', '.cpp']