[llvm-commits] [compiler-rt] r147326 - in /compiler-rt/trunk/lib/asan: asan_allocator.cc asan_interceptors.cc asan_interceptors.h asan_internal.h asan_linux.cc asan_mac.cc asan_printf.cc asan_rtl.cc

Kostya Serebryany kcc at google.com
Wed Dec 28 14:58:01 PST 2011


Author: kcc
Date: Wed Dec 28 16:58:01 2011
New Revision: 147326

URL: http://llvm.org/viewvc/llvm-project?rev=147326&view=rev
Log:
[asan] use custom libc-free getenv; a bit of refactoring around mmap calls

Modified:
    compiler-rt/trunk/lib/asan/asan_allocator.cc
    compiler-rt/trunk/lib/asan/asan_interceptors.cc
    compiler-rt/trunk/lib/asan/asan_interceptors.h
    compiler-rt/trunk/lib/asan/asan_internal.h
    compiler-rt/trunk/lib/asan/asan_linux.cc
    compiler-rt/trunk/lib/asan/asan_mac.cc
    compiler-rt/trunk/lib/asan/asan_printf.cc
    compiler-rt/trunk/lib/asan/asan_rtl.cc

Modified: compiler-rt/trunk/lib/asan/asan_allocator.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/asan/asan_allocator.cc?rev=147326&r1=147325&r2=147326&view=diff
==============================================================================
--- compiler-rt/trunk/lib/asan/asan_allocator.cc (original)
+++ compiler-rt/trunk/lib/asan/asan_allocator.cc Wed Dec 28 16:58:01 2011
@@ -60,32 +60,15 @@
 static const size_t kMaxAllowedMallocSize = 8UL << 30;  // 8G
 #endif
 
-static void OutOfMemoryMessage(const char *mem_type, size_t size) {
-  AsanThread *t = asanThreadRegistry().GetCurrent();
-  CHECK(t);
-  Report("ERROR: AddressSanitizer failed to allocate "
-         "0x%lx (%lu) bytes (%s) in T%d\n",
-         size, size, mem_type, t->tid());
-}
-
 static inline bool IsAligned(uintptr_t a, uintptr_t alignment) {
   return (a & (alignment - 1)) == 0;
 }
 
-static inline bool IsPowerOfTwo(size_t x) {
-  return (x & (x - 1)) == 0;
-}
-
 static inline size_t Log2(size_t x) {
   CHECK(IsPowerOfTwo(x));
   return __builtin_ctzl(x);
 }
 
-static inline size_t RoundUpTo(size_t size, size_t boundary) {
-  CHECK(IsPowerOfTwo(boundary));
-  return (size + boundary - 1) & ~(boundary - 1);
-}
-
 static inline size_t RoundUpToPowerOfTwo(size_t size) {
   CHECK(size);
   if (IsPowerOfTwo(size)) return size;
@@ -132,14 +115,7 @@
 
 static uint8_t *MmapNewPagesAndPoisonShadow(size_t size) {
   CHECK(IsAligned(size, kPageSize));
-  uint8_t *res = (uint8_t*)asan_mmap(0, size,
-                   PROT_READ | PROT_WRITE,
-                   MAP_PRIVATE | MAP_ANON, -1, 0);
-  if (res == (uint8_t*)-1) {
-    OutOfMemoryMessage(__FUNCTION__, size);
-    PRINT_CURRENT_STACK();
-    ASAN_DIE;
-  }
+  uint8_t *res = (uint8_t*)AsanMmapSomewhereOrDie(size, __FUNCTION__);
   PoisonShadow((uintptr_t)res, size, kAsanHeapLeftRedzoneMagic);
   if (FLAG_debug) {
     Printf("ASAN_MMAP: [%p, %p)\n", res, res + size);
@@ -929,8 +905,7 @@
     if (mem) {
       PoisonShadow(mem, ClassMmapSize(i), 0);
       allocated_size_classes_[i] = 0;
-      int munmap_res = munmap((void*)mem, ClassMmapSize(i));
-      CHECK(munmap_res == 0);
+      AsanUnmapOrDie((void*)mem, ClassMmapSize(i));
     }
   }
 }
@@ -941,10 +916,8 @@
 
 void FakeStack::AllocateOneSizeClass(size_t size_class) {
   CHECK(ClassMmapSize(size_class) >= kPageSize);
-  uintptr_t new_mem = (uintptr_t)asan_mmap(0, ClassMmapSize(size_class),
-                                             PROT_READ | PROT_WRITE,
-                                             MAP_PRIVATE | MAP_ANON, -1, 0);
-  CHECK(new_mem != (uintptr_t)-1);
+  uintptr_t new_mem = (uintptr_t)AsanMmapSomewhereOrDie(
+      ClassMmapSize(size_class), __FUNCTION__);
   // Printf("T%d new_mem[%ld]: %p-%p mmap %ld\n",
   //       asanThreadRegistry().GetCurrent()->tid(),
   //       size_class, new_mem, new_mem + ClassMmapSize(size_class),

Modified: compiler-rt/trunk/lib/asan/asan_interceptors.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/asan/asan_interceptors.cc?rev=147326&r1=147325&r2=147326&view=diff
==============================================================================
--- compiler-rt/trunk/lib/asan/asan_interceptors.cc (original)
+++ compiler-rt/trunk/lib/asan/asan_interceptors.cc Wed Dec 28 16:58:01 2011
@@ -119,6 +119,23 @@
   return i;
 }
 
+void* internal_memchr(const void* s, int c, size_t n) {
+  const char* t = (char*)s;
+  for (size_t i = 0; i < n; ++i, ++t)
+    if (*t == c)
+      return (void*)t;
+  return NULL;
+}
+
+int internal_memcmp(const void* s1, const void* s2, size_t n) {
+  const char* t1 = (char*)s1;
+  const char* t2 = (char*)s2;
+  for (size_t i = 0; i < n; ++i, ++t1, ++t2)
+    if (*t1 != *t2)
+      return *t1 < *t2 ? -1 : 1;
+  return 0;
+}
+
 void InitializeAsanInterceptors() {
 #ifndef __APPLE__
   INTERCEPT_FUNCTION(index);

Modified: compiler-rt/trunk/lib/asan/asan_interceptors.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/asan/asan_interceptors.h?rev=147326&r1=147325&r2=147326&view=diff
==============================================================================
--- compiler-rt/trunk/lib/asan/asan_interceptors.h (original)
+++ compiler-rt/trunk/lib/asan/asan_interceptors.h Wed Dec 28 16:58:01 2011
@@ -123,6 +123,8 @@
 // __asan::internal_X() is the implementation of X() for use in RTL.
 size_t internal_strlen(const char *s);
 size_t internal_strnlen(const char *s, size_t maxlen);
+void* internal_memchr(const void* s, int c, size_t n);
+int internal_memcmp(const void* s1, const void* s2, size_t n);
 
 // Initializes pointers to str*/mem* functions.
 void InitializeAsanInterceptors();

Modified: compiler-rt/trunk/lib/asan/asan_internal.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/asan/asan_internal.h?rev=147326&r1=147325&r2=147326&view=diff
==============================================================================
--- compiler-rt/trunk/lib/asan/asan_internal.h (original)
+++ compiler-rt/trunk/lib/asan/asan_internal.h Wed Dec 28 16:58:01 2011
@@ -83,11 +83,20 @@
 // asan_malloc_linux.cc / asan_malloc_mac.cc
 void ReplaceSystemMalloc();
 
+void OutOfMemoryMessageAndDie(const char *mem_type, size_t size);
+
 // asan_linux.cc / asan_mac.cc
 void *AsanDoesNotSupportStaticLinkage();
+int AsanOpenReadonly(const char* filename);
 void *asan_mmap(void *addr, size_t length, int prot, int flags,
                 int fd, uint64_t offset);
-ssize_t asan_write(int fd, const void *buf, size_t count);
+
+void *AsanMmapSomewhereOrDie(size_t size, const char *where);
+void AsanUnmapOrDie(void *ptr, size_t size);
+
+ssize_t AsanRead(int fd, void *buf, size_t count);
+ssize_t AsanWrite(int fd, const void *buf, size_t count);
+int AsanClose(int fd);
 
 // asan_printf.cc
 void RawWrite(const char *buffer);
@@ -109,7 +118,6 @@
                                      uintptr_t redzone_size,
                                      uint8_t value);
 
-
 extern size_t FLAG_quarantine_size;
 extern int    FLAG_demangle;
 extern bool   FLAG_symbolize;
@@ -185,6 +193,16 @@
 static const uintptr_t kCurrentStackFrameMagic = 0x41B58AB3;
 static const uintptr_t kRetiredStackFrameMagic = 0x45E0360E;
 
+// --------------------------- Bit twiddling ------- {{{1
+inline bool IsPowerOfTwo(size_t x) {
+  return (x & (x - 1)) == 0;
+}
+
+inline size_t RoundUpTo(size_t size, size_t boundary) {
+  CHECK(IsPowerOfTwo(boundary));
+  return (size + boundary - 1) & ~(boundary - 1);
+}
+
 // -------------------------- LowLevelAllocator ----- {{{1
 // A simple low-level memory allocator for internal use.
 class LowLevelAllocator {

Modified: compiler-rt/trunk/lib/asan/asan_linux.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/asan/asan_linux.cc?rev=147326&r1=147325&r2=147326&view=diff
==============================================================================
--- compiler-rt/trunk/lib/asan/asan_linux.cc (original)
+++ compiler-rt/trunk/lib/asan/asan_linux.cc Wed Dec 28 16:58:01 2011
@@ -17,6 +17,8 @@
 
 #include <sys/mman.h>
 #include <sys/syscall.h>
+#include <sys/types.h>
+#include <fcntl.h>
 #include <unistd.h>
 
 extern char _DYNAMIC[];
@@ -28,22 +30,49 @@
   return &_DYNAMIC;
 }
 
-#ifdef ANDROID
-#define SYS_mmap2 __NR_mmap2
-#define SYS_write __NR_write
-#endif
-
 void *asan_mmap(void *addr, size_t length, int prot, int flags,
                 int fd, uint64_t offset) {
 # if __WORDSIZE == 64
-  return (void *)syscall(SYS_mmap, addr, length, prot, flags, fd, offset);
+  return (void *)syscall(__NR_mmap, addr, length, prot, flags, fd, offset);
 # else
-  return (void *)syscall(SYS_mmap2, addr, length, prot, flags, fd, offset);
+  return (void *)syscall(__NR_mmap2, addr, length, prot, flags, fd, offset);
 # endif
 }
 
-ssize_t asan_write(int fd, const void *buf, size_t count) {
-  return (ssize_t)syscall(SYS_write, fd, buf, count);
+void *AsanMmapSomewhereOrDie(size_t size, const char *mem_type) {
+  size = RoundUpTo(size, kPageSize);
+  void *res = asan_mmap(0, size,
+                        PROT_READ | PROT_WRITE,
+                        MAP_PRIVATE | MAP_ANON, -1, 0);
+  if (res == (void*)-1) {
+    OutOfMemoryMessageAndDie(mem_type, size);
+  }
+  return res;
+}
+
+void AsanUnmapOrDie(void *addr, size_t size) {
+  if (!addr || !size) return;
+  int res = syscall(__NR_munmap, addr, size);
+  if (res != 0) {
+    Report("Failed to unmap\n");
+    ASAN_DIE;
+  }
+}
+
+ssize_t AsanWrite(int fd, const void *buf, size_t count) {
+  return (ssize_t)syscall(__NR_write, fd, buf, count);
+}
+
+int AsanOpenReadonly(const char* filename) {
+  return open(filename, O_RDONLY);
+}
+
+ssize_t AsanRead(int fd, void *buf, size_t count) {
+  return (ssize_t)syscall(__NR_read, fd, buf, count);
+}
+
+int AsanClose(int fd) {
+  return close(fd);
 }
 
 }  // namespace __asan

Modified: compiler-rt/trunk/lib/asan/asan_mac.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/asan/asan_mac.cc?rev=147326&r1=147325&r2=147326&view=diff
==============================================================================
--- compiler-rt/trunk/lib/asan/asan_mac.cc (original)
+++ compiler-rt/trunk/lib/asan/asan_mac.cc Wed Dec 28 16:58:01 2011
@@ -49,6 +49,38 @@
   return write(fd, buf, count);
 }
 
+void *AsanMmapSomewhereOrDie(size_t size, const char *mem_type) {
+  size = RoundUpTo(size, kPageSize);
+  void *res = asan_mmap(0, size,
+                        PROT_READ | PROT_WRITE,
+                        MAP_PRIVATE | MAP_ANON, -1, 0);
+  if (res == (void*)-1) {
+    OutOfMemoryMessageAndDie(mem_type, size);
+  }
+  return res;
+}
+
+void AsanUnmapOrDie(void *addr, size_t size) {
+  if (!addr || !size) return;
+  int res = munmap(addr, size);
+  if (res != 0) {
+    Report("Failed to unmap\n");
+    ASAN_DIE;
+  }
+}
+
+int AsanOpenReadonly(const char* filename) {
+  return open(filename, O_RDONLY);
+}
+
+ssize_t AsanRead(int fd, void *buf, size_t count) {
+  return read(fd, buf, count);
+}
+
+int AsanClose(int fd) {
+  return close(fd);
+}
+
 // Support for the following functions from libdispatch on Mac OS:
 //   dispatch_async_f()
 //   dispatch_async()

Modified: compiler-rt/trunk/lib/asan/asan_printf.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/asan/asan_printf.cc?rev=147326&r1=147325&r2=147326&view=diff
==============================================================================
--- compiler-rt/trunk/lib/asan/asan_printf.cc (original)
+++ compiler-rt/trunk/lib/asan/asan_printf.cc Wed Dec 28 16:58:01 2011
@@ -24,8 +24,8 @@
 void RawWrite(const char *buffer) {
   static const char *kRawWriteError = "RawWrite can't output requested buffer!";
   ssize_t length = (ssize_t)internal_strlen(buffer);
-  if (length != asan_write(2, buffer, length)) {
-    asan_write(2, kRawWriteError, internal_strlen(kRawWriteError));
+  if (length != AsanWrite(2, buffer, length)) {
+    AsanWrite(2, kRawWriteError, internal_strlen(kRawWriteError));
     ASAN_DIE;
   }
 }

Modified: compiler-rt/trunk/lib/asan/asan_rtl.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/asan/asan_rtl.cc?rev=147326&r1=147325&r2=147326&view=diff
==============================================================================
--- compiler-rt/trunk/lib/asan/asan_rtl.cc (original)
+++ compiler-rt/trunk/lib/asan/asan_rtl.cc Wed Dec 28 16:58:01 2011
@@ -122,6 +122,56 @@
   Printf("\n");
 }
 
+// Opens the file 'file_name" and reads up to 'max_len' bytes.
+// The resulting buffer is mmaped and stored in '*buff'.
+// Returns the number of read bytes or -1 if file can not be opened.
+static ssize_t ReadFileToBuffer(const char *file_name, char **buff,
+                                size_t max_len) {
+  const size_t kMinFileLen = kPageSize;
+  ssize_t read_len = -1;
+  *buff = 0;
+  size_t maped_size = 0;
+  // The files we usually open are not seekable, so try different buffer sizes.
+  for (size_t size = kMinFileLen; size <= max_len; size *= 2) {
+    int fd = AsanOpenReadonly(file_name);
+    if (fd < 0) return -1;
+    AsanUnmapOrDie(*buff, maped_size);
+    maped_size = size;
+    *buff = (char*)AsanMmapSomewhereOrDie(size, __FUNCTION__);
+    read_len = AsanRead(fd, *buff, size);
+    AsanClose(fd);
+    if (read_len < size)  // We've read the whole file.
+      break;
+  }
+  return read_len;
+}
+
+// Like getenv, but reads env directly from /proc and does not use libc.
+// This function should be called first inside __asan_init.
+static const char* GetEnvFromProcSelfEnviron(const char* name) {
+  static char *environ;
+  static ssize_t len;
+  static bool inited;
+  if (!inited) {
+    inited = true;
+    len = ReadFileToBuffer("/proc/self/environ", &environ, 1 << 20);
+  }
+  if (!environ || len <= 0) return NULL;
+  size_t namelen = internal_strlen(name);
+  const char *p = environ;
+  while (*p != '\0') {  // will happen at the \0\0 that terminates the buffer
+    // proc file has the format NAME=value\0NAME=value\0NAME=value\0...
+    const char* endp =
+        (char*)internal_memchr(p, '\0', len - (p - environ));
+    if (endp == NULL)  // this entry isn't NUL terminated
+      return NULL;
+    else if (!internal_memcmp(p, name, namelen) && p[namelen] == '=')  // Match.
+      return p + namelen + 1;  // point after =
+    p = endp + 1;
+  }
+  return NULL;  // Not found.
+}
+
 // ---------------------- Thread ------------------------- {{{1
 static void *asan_thread_start(void *arg) {
   AsanThread *t= (AsanThread*)arg;
@@ -130,10 +180,12 @@
 }
 
 // ---------------------- mmap -------------------- {{{1
-static void OutOfMemoryMessage(const char *mem_type, size_t size) {
+void OutOfMemoryMessageAndDie(const char *mem_type, size_t size) {
   Report("ERROR: AddressSanitizer failed to allocate "
          "0x%lx (%ld) bytes of %s\n",
          size, size, mem_type);
+  PRINT_CURRENT_STACK();
+  ShowStatsAndAbort();
 }
 
 static char *mmap_pages(size_t start_page, size_t n_pages, const char *mem_type,
@@ -144,8 +196,7 @@
   // Printf("%p => %p\n", (void*)start_page, res);
   char *ch = (char*)res;
   if (res == (void*)-1L && abort_on_failure) {
-    OutOfMemoryMessage(mem_type, n_pages * kPageSize);
-    ShowStatsAndAbort();
+    OutOfMemoryMessageAndDie(mem_type, n_pages * kPageSize);
   }
   CHECK(res == (void*)start_page || res == (void*)-1L);
   return ch;
@@ -175,10 +226,8 @@
   CHECK((size & (size - 1)) == 0 && "size must be a power of two");
   if (allocated_end_ - allocated_current_ < size) {
     size_t size_to_allocate = Max(size, kPageSize);
-    allocated_current_ = (char*)asan_mmap(0, size_to_allocate,
-                                          PROT_READ | PROT_WRITE,
-                                          MAP_PRIVATE | MAP_ANON, -1, 0);
-    CHECK((allocated_current_ != (char*)-1) && "Can't mmap");
+    allocated_current_ =
+        (char*)AsanMmapSomewhereOrDie(size_to_allocate, __FUNCTION__);
     allocated_end_ = allocated_current_ + size_to_allocate;
     PoisonShadow((uintptr_t)allocated_current_, size_to_allocate,
                  kAsanInternalHeapMagic);
@@ -306,7 +355,7 @@
     return;
   }
   // Write the first message using the bullet-proof write.
-  if (13 != asan_write(2, "ASAN:SIGSEGV\n", 13)) ASAN_DIE;
+  if (13 != AsanWrite(2, "ASAN:SIGSEGV\n", 13)) ASAN_DIE;
   uintptr_t pc, sp, bp, ax;
   GetPcSpBpAx(context, &pc, &sp, &bp, &ax);
   Report("ERROR: AddressSanitizer crashed on unknown address %p"
@@ -321,7 +370,7 @@
 
 static void     ASAN_OnSIGILL(int, siginfo_t *siginfo, void *context) {
   // Write the first message using the bullet-proof write.
-  if (12 != asan_write(2, "ASAN:SIGILL\n", 12)) ASAN_DIE;
+  if (12 != AsanWrite(2, "ASAN:SIGILL\n", 12)) ASAN_DIE;
   uintptr_t pc, sp, bp, ax;
   GetPcSpBpAx(context, &pc, &sp, &bp, &ax);
 
@@ -656,7 +705,7 @@
   AsanDoesNotSupportStaticLinkage();
 
   // flags
-  const char *options = getenv("ASAN_OPTIONS");
+  const char *options = GetEnvFromProcSelfEnviron("ASAN_OPTIONS");
   FLAG_malloc_context_size =
       IntFlagValue(options, "malloc_context_size=", kMallocContextSize);
   CHECK(FLAG_malloc_context_size <= kMallocContextSize);





More information about the llvm-commits mailing list