diff options
Diffstat (limited to 'compiler-rt/lib/asan/asan_rtl.cc')
| -rw-r--r-- | compiler-rt/lib/asan/asan_rtl.cc | 69 |
1 files changed, 59 insertions, 10 deletions
diff --git a/compiler-rt/lib/asan/asan_rtl.cc b/compiler-rt/lib/asan/asan_rtl.cc index 83528474c28..299f647e171 100644 --- a/compiler-rt/lib/asan/asan_rtl.cc +++ b/compiler-rt/lib/asan/asan_rtl.cc @@ -122,6 +122,56 @@ static void PrintBytes(const char *before, uintptr_t *a) { 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 @@ static void *asan_thread_start(void *arg) { } // ---------------------- 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 @@ static char *mmap_pages(size_t start_page, size_t n_pages, const char *mem_type, // 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 @@ void *LowLevelAllocator::Allocate(size_t size) { 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 @@ static void ASAN_OnSIGSEGV(int, siginfo_t *siginfo, void *context) { 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_OnSIGSEGV(int, siginfo_t *siginfo, void *context) { 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 @@ void __asan_init() { 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); |

