[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