asan_linux.cc revision aa33a50c9d0f3e3f22c8b21fa7309ec91f9d939a
11e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany//===-- asan_linux.cc -----------------------------------------------------===// 21e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// 31e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// The LLVM Compiler Infrastructure 41e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// 51e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// This file is distributed under the University of Illinois Open Source 61e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// License. See LICENSE.TXT for details. 71e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// 81e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany//===----------------------------------------------------------------------===// 91e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// 101e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// This file is a part of AddressSanitizer, an address sanity checker. 111e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// 121e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// Linux-specific details. 131e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany//===----------------------------------------------------------------------===// 14d6567c5166412f6acdde851e767c26f332d51d3dKostya Serebryany#ifdef __linux__ 151e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 16df499b44de81fc757a789878f07fcaf19ebb0016Kostya Serebryany#include "asan_interceptors.h" 171e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany#include "asan_internal.h" 18d55f5f8c413622db4bd28b5cca9bfeb4d61564e0Kostya Serebryany#include "asan_lock.h" 19df499b44de81fc757a789878f07fcaf19ebb0016Kostya Serebryany#include "asan_procmaps.h" 20c549dd7b5fa5fb97270f57067797224cee0429f2Kostya Serebryany#include "asan_thread.h" 211e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 22c549dd7b5fa5fb97270f57067797224cee0429f2Kostya Serebryany#include <sys/time.h> 23c549dd7b5fa5fb97270f57067797224cee0429f2Kostya Serebryany#include <sys/resource.h> 241e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany#include <sys/mman.h> 251e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany#include <sys/syscall.h> 26de496f451bce322b6cde100456591f1f50ab3477Kostya Serebryany#include <sys/types.h> 27de496f451bce322b6cde100456591f1f50ab3477Kostya Serebryany#include <fcntl.h> 28c549dd7b5fa5fb97270f57067797224cee0429f2Kostya Serebryany#include <pthread.h> 29df499b44de81fc757a789878f07fcaf19ebb0016Kostya Serebryany#include <stdio.h> 301e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany#include <unistd.h> 319cfa194cc62026fc7c6e82f7303eee8ad4d10cf4Evgeniy Stepanov#include <unwind.h> 321e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 339107c26bd88fc9cf44a2cd7d6967eb830ac63be3Kostya Serebryany#ifndef ANDROID 349107c26bd88fc9cf44a2cd7d6967eb830ac63be3Kostya Serebryany// FIXME: where to get ucontext on Android? 359107c26bd88fc9cf44a2cd7d6967eb830ac63be3Kostya Serebryany#include <sys/ucontext.h> 369107c26bd88fc9cf44a2cd7d6967eb830ac63be3Kostya Serebryany#endif 379107c26bd88fc9cf44a2cd7d6967eb830ac63be3Kostya Serebryany 38aa33a50c9d0f3e3f22c8b21fa7309ec91f9d939aEvgeniy Stepanovextern "C" void* _DYNAMIC; 39aa33a50c9d0f3e3f22c8b21fa7309ec91f9d939aEvgeniy Stepanov 401e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanynamespace __asan { 411e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 421e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanyvoid *AsanDoesNotSupportStaticLinkage() { 431e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany // This will fail to link with -static. 44efb3fa36cf421c346e8e54054cdae4fd798edab7Kostya Serebryany return &_DYNAMIC; // defined in link.h 451e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany} 461e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 47f73a6a3f81573ba85a5e29955980818b18b0a58aAlexander Potapenkobool AsanShadowRangeIsAvailable() { 48f73a6a3f81573ba85a5e29955980818b18b0a58aAlexander Potapenko // FIXME: shall we need anything here on Linux? 49f73a6a3f81573ba85a5e29955980818b18b0a58aAlexander Potapenko return true; 50f73a6a3f81573ba85a5e29955980818b18b0a58aAlexander Potapenko} 51f73a6a3f81573ba85a5e29955980818b18b0a58aAlexander Potapenko 529107c26bd88fc9cf44a2cd7d6967eb830ac63be3Kostya Serebryanyvoid GetPcSpBp(void *context, uintptr_t *pc, uintptr_t *sp, uintptr_t *bp) { 539107c26bd88fc9cf44a2cd7d6967eb830ac63be3Kostya Serebryany#ifdef ANDROID 549107c26bd88fc9cf44a2cd7d6967eb830ac63be3Kostya Serebryany *pc = *sp = *bp = 0; 559107c26bd88fc9cf44a2cd7d6967eb830ac63be3Kostya Serebryany#elif defined(__arm__) 569107c26bd88fc9cf44a2cd7d6967eb830ac63be3Kostya Serebryany ucontext_t *ucontext = (ucontext_t*)context; 579107c26bd88fc9cf44a2cd7d6967eb830ac63be3Kostya Serebryany *pc = ucontext->uc_mcontext.arm_pc; 589107c26bd88fc9cf44a2cd7d6967eb830ac63be3Kostya Serebryany *bp = ucontext->uc_mcontext.arm_fp; 599107c26bd88fc9cf44a2cd7d6967eb830ac63be3Kostya Serebryany *sp = ucontext->uc_mcontext.arm_sp; 609107c26bd88fc9cf44a2cd7d6967eb830ac63be3Kostya Serebryany# elif defined(__x86_64__) 619107c26bd88fc9cf44a2cd7d6967eb830ac63be3Kostya Serebryany ucontext_t *ucontext = (ucontext_t*)context; 629107c26bd88fc9cf44a2cd7d6967eb830ac63be3Kostya Serebryany *pc = ucontext->uc_mcontext.gregs[REG_RIP]; 639107c26bd88fc9cf44a2cd7d6967eb830ac63be3Kostya Serebryany *bp = ucontext->uc_mcontext.gregs[REG_RBP]; 649107c26bd88fc9cf44a2cd7d6967eb830ac63be3Kostya Serebryany *sp = ucontext->uc_mcontext.gregs[REG_RSP]; 659107c26bd88fc9cf44a2cd7d6967eb830ac63be3Kostya Serebryany# elif defined(__i386__) 669107c26bd88fc9cf44a2cd7d6967eb830ac63be3Kostya Serebryany ucontext_t *ucontext = (ucontext_t*)context; 679107c26bd88fc9cf44a2cd7d6967eb830ac63be3Kostya Serebryany *pc = ucontext->uc_mcontext.gregs[REG_EIP]; 689107c26bd88fc9cf44a2cd7d6967eb830ac63be3Kostya Serebryany *bp = ucontext->uc_mcontext.gregs[REG_EBP]; 699107c26bd88fc9cf44a2cd7d6967eb830ac63be3Kostya Serebryany *sp = ucontext->uc_mcontext.gregs[REG_ESP]; 709107c26bd88fc9cf44a2cd7d6967eb830ac63be3Kostya Serebryany#else 719107c26bd88fc9cf44a2cd7d6967eb830ac63be3Kostya Serebryany# error "Unsupported arch" 729107c26bd88fc9cf44a2cd7d6967eb830ac63be3Kostya Serebryany#endif 739107c26bd88fc9cf44a2cd7d6967eb830ac63be3Kostya Serebryany} 749107c26bd88fc9cf44a2cd7d6967eb830ac63be3Kostya Serebryany 754803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryanybool AsanInterceptsSignal(int signum) { 764803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany return signum == SIGSEGV && FLAG_handle_segv; 774803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany} 784803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany 79a874fe5b5d67152e4e737498d532eec80940bdcdKostya Serebryanystatic void *asan_mmap(void *addr, size_t length, int prot, int flags, 801e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany int fd, uint64_t offset) { 811e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany# if __WORDSIZE == 64 82de496f451bce322b6cde100456591f1f50ab3477Kostya Serebryany return (void *)syscall(__NR_mmap, addr, length, prot, flags, fd, offset); 831e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany# else 84de496f451bce322b6cde100456591f1f50ab3477Kostya Serebryany return (void *)syscall(__NR_mmap2, addr, length, prot, flags, fd, offset); 851e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany# endif 861e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany} 871e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 88de496f451bce322b6cde100456591f1f50ab3477Kostya Serebryanyvoid *AsanMmapSomewhereOrDie(size_t size, const char *mem_type) { 89de496f451bce322b6cde100456591f1f50ab3477Kostya Serebryany size = RoundUpTo(size, kPageSize); 90de496f451bce322b6cde100456591f1f50ab3477Kostya Serebryany void *res = asan_mmap(0, size, 91de496f451bce322b6cde100456591f1f50ab3477Kostya Serebryany PROT_READ | PROT_WRITE, 92de496f451bce322b6cde100456591f1f50ab3477Kostya Serebryany MAP_PRIVATE | MAP_ANON, -1, 0); 93de496f451bce322b6cde100456591f1f50ab3477Kostya Serebryany if (res == (void*)-1) { 94de496f451bce322b6cde100456591f1f50ab3477Kostya Serebryany OutOfMemoryMessageAndDie(mem_type, size); 95de496f451bce322b6cde100456591f1f50ab3477Kostya Serebryany } 96de496f451bce322b6cde100456591f1f50ab3477Kostya Serebryany return res; 97de496f451bce322b6cde100456591f1f50ab3477Kostya Serebryany} 98de496f451bce322b6cde100456591f1f50ab3477Kostya Serebryany 99a874fe5b5d67152e4e737498d532eec80940bdcdKostya Serebryanyvoid *AsanMmapFixedNoReserve(uintptr_t fixed_addr, size_t size) { 100a874fe5b5d67152e4e737498d532eec80940bdcdKostya Serebryany return asan_mmap((void*)fixed_addr, size, 101a874fe5b5d67152e4e737498d532eec80940bdcdKostya Serebryany PROT_READ | PROT_WRITE, 102a874fe5b5d67152e4e737498d532eec80940bdcdKostya Serebryany MAP_PRIVATE | MAP_ANON | MAP_FIXED | MAP_NORESERVE, 103a874fe5b5d67152e4e737498d532eec80940bdcdKostya Serebryany 0, 0); 104a874fe5b5d67152e4e737498d532eec80940bdcdKostya Serebryany} 105a874fe5b5d67152e4e737498d532eec80940bdcdKostya Serebryany 106a874fe5b5d67152e4e737498d532eec80940bdcdKostya Serebryanyvoid *AsanMprotect(uintptr_t fixed_addr, size_t size) { 107a874fe5b5d67152e4e737498d532eec80940bdcdKostya Serebryany return asan_mmap((void*)fixed_addr, size, 108a874fe5b5d67152e4e737498d532eec80940bdcdKostya Serebryany PROT_NONE, 109a874fe5b5d67152e4e737498d532eec80940bdcdKostya Serebryany MAP_PRIVATE | MAP_ANON | MAP_FIXED | MAP_NORESERVE, 110a874fe5b5d67152e4e737498d532eec80940bdcdKostya Serebryany 0, 0); 111a874fe5b5d67152e4e737498d532eec80940bdcdKostya Serebryany} 112a874fe5b5d67152e4e737498d532eec80940bdcdKostya Serebryany 113de496f451bce322b6cde100456591f1f50ab3477Kostya Serebryanyvoid AsanUnmapOrDie(void *addr, size_t size) { 114de496f451bce322b6cde100456591f1f50ab3477Kostya Serebryany if (!addr || !size) return; 115de496f451bce322b6cde100456591f1f50ab3477Kostya Serebryany int res = syscall(__NR_munmap, addr, size); 116de496f451bce322b6cde100456591f1f50ab3477Kostya Serebryany if (res != 0) { 117de496f451bce322b6cde100456591f1f50ab3477Kostya Serebryany Report("Failed to unmap\n"); 1180ecf5eb729dd81a43f8585cb438d3cb2a35899edKostya Serebryany AsanDie(); 119de496f451bce322b6cde100456591f1f50ab3477Kostya Serebryany } 120de496f451bce322b6cde100456591f1f50ab3477Kostya Serebryany} 121de496f451bce322b6cde100456591f1f50ab3477Kostya Serebryany 1220ecf5eb729dd81a43f8585cb438d3cb2a35899edKostya Serebryanysize_t AsanWrite(int fd, const void *buf, size_t count) { 1230ecf5eb729dd81a43f8585cb438d3cb2a35899edKostya Serebryany return (size_t)syscall(__NR_write, fd, buf, count); 124de496f451bce322b6cde100456591f1f50ab3477Kostya Serebryany} 125de496f451bce322b6cde100456591f1f50ab3477Kostya Serebryany 126de496f451bce322b6cde100456591f1f50ab3477Kostya Serebryanyint AsanOpenReadonly(const char* filename) { 1275ea4a76f88675993cd0c1cf73b1b5924ae7f6599Kostya Serebryany return syscall(__NR_open, filename, O_RDONLY); 128de496f451bce322b6cde100456591f1f50ab3477Kostya Serebryany} 129de496f451bce322b6cde100456591f1f50ab3477Kostya Serebryany 1301e316d7f488a75312539629e9d937e156280eeb6Alexander Potapenko// Like getenv, but reads env directly from /proc and does not use libc. 1311e316d7f488a75312539629e9d937e156280eeb6Alexander Potapenko// This function should be called first inside __asan_init. 1321e316d7f488a75312539629e9d937e156280eeb6Alexander Potapenkoconst char* AsanGetEnv(const char* name) { 1331e316d7f488a75312539629e9d937e156280eeb6Alexander Potapenko static char *environ; 1341e316d7f488a75312539629e9d937e156280eeb6Alexander Potapenko static size_t len; 1351e316d7f488a75312539629e9d937e156280eeb6Alexander Potapenko static bool inited; 1361e316d7f488a75312539629e9d937e156280eeb6Alexander Potapenko if (!inited) { 1371e316d7f488a75312539629e9d937e156280eeb6Alexander Potapenko inited = true; 1381e316d7f488a75312539629e9d937e156280eeb6Alexander Potapenko size_t environ_size; 1391e316d7f488a75312539629e9d937e156280eeb6Alexander Potapenko len = ReadFileToBuffer("/proc/self/environ", 140160cc4aa34e2418ba91035bb49648e751476f0d9Kostya Serebryany &environ, &environ_size, 1 << 26); 1411e316d7f488a75312539629e9d937e156280eeb6Alexander Potapenko } 1421e316d7f488a75312539629e9d937e156280eeb6Alexander Potapenko if (!environ || len == 0) return NULL; 1431e316d7f488a75312539629e9d937e156280eeb6Alexander Potapenko size_t namelen = internal_strlen(name); 1441e316d7f488a75312539629e9d937e156280eeb6Alexander Potapenko const char *p = environ; 1451e316d7f488a75312539629e9d937e156280eeb6Alexander Potapenko while (*p != '\0') { // will happen at the \0\0 that terminates the buffer 1461e316d7f488a75312539629e9d937e156280eeb6Alexander Potapenko // proc file has the format NAME=value\0NAME=value\0NAME=value\0... 1471e316d7f488a75312539629e9d937e156280eeb6Alexander Potapenko const char* endp = 1481e316d7f488a75312539629e9d937e156280eeb6Alexander Potapenko (char*)internal_memchr(p, '\0', len - (p - environ)); 1491e316d7f488a75312539629e9d937e156280eeb6Alexander Potapenko if (endp == NULL) // this entry isn't NUL terminated 1501e316d7f488a75312539629e9d937e156280eeb6Alexander Potapenko return NULL; 1511e316d7f488a75312539629e9d937e156280eeb6Alexander Potapenko else if (!internal_memcmp(p, name, namelen) && p[namelen] == '=') // Match. 1521e316d7f488a75312539629e9d937e156280eeb6Alexander Potapenko return p + namelen + 1; // point after = 1531e316d7f488a75312539629e9d937e156280eeb6Alexander Potapenko p = endp + 1; 1541e316d7f488a75312539629e9d937e156280eeb6Alexander Potapenko } 1551e316d7f488a75312539629e9d937e156280eeb6Alexander Potapenko return NULL; // Not found. 1561e316d7f488a75312539629e9d937e156280eeb6Alexander Potapenko} 1571e316d7f488a75312539629e9d937e156280eeb6Alexander Potapenko 1580ecf5eb729dd81a43f8585cb438d3cb2a35899edKostya Serebryanysize_t AsanRead(int fd, void *buf, size_t count) { 1590ecf5eb729dd81a43f8585cb438d3cb2a35899edKostya Serebryany return (size_t)syscall(__NR_read, fd, buf, count); 160de496f451bce322b6cde100456591f1f50ab3477Kostya Serebryany} 161de496f451bce322b6cde100456591f1f50ab3477Kostya Serebryany 162de496f451bce322b6cde100456591f1f50ab3477Kostya Serebryanyint AsanClose(int fd) { 1635ea4a76f88675993cd0c1cf73b1b5924ae7f6599Kostya Serebryany return syscall(__NR_close, fd); 1641e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany} 1651e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 166df499b44de81fc757a789878f07fcaf19ebb0016Kostya SerebryanyAsanProcMaps::AsanProcMaps() { 167df499b44de81fc757a789878f07fcaf19ebb0016Kostya Serebryany proc_self_maps_buff_len_ = 168df499b44de81fc757a789878f07fcaf19ebb0016Kostya Serebryany ReadFileToBuffer("/proc/self/maps", &proc_self_maps_buff_, 169160cc4aa34e2418ba91035bb49648e751476f0d9Kostya Serebryany &proc_self_maps_buff_mmaped_size_, 1 << 26); 170df499b44de81fc757a789878f07fcaf19ebb0016Kostya Serebryany CHECK(proc_self_maps_buff_len_ > 0); 171df499b44de81fc757a789878f07fcaf19ebb0016Kostya Serebryany // AsanWrite(2, proc_self_maps_buff_, proc_self_maps_buff_len_); 172df499b44de81fc757a789878f07fcaf19ebb0016Kostya Serebryany Reset(); 173df499b44de81fc757a789878f07fcaf19ebb0016Kostya Serebryany} 174df499b44de81fc757a789878f07fcaf19ebb0016Kostya Serebryany 175df499b44de81fc757a789878f07fcaf19ebb0016Kostya SerebryanyAsanProcMaps::~AsanProcMaps() { 176df499b44de81fc757a789878f07fcaf19ebb0016Kostya Serebryany AsanUnmapOrDie(proc_self_maps_buff_, proc_self_maps_buff_mmaped_size_); 177df499b44de81fc757a789878f07fcaf19ebb0016Kostya Serebryany} 178df499b44de81fc757a789878f07fcaf19ebb0016Kostya Serebryany 179df499b44de81fc757a789878f07fcaf19ebb0016Kostya Serebryanyvoid AsanProcMaps::Reset() { 180df499b44de81fc757a789878f07fcaf19ebb0016Kostya Serebryany current_ = proc_self_maps_buff_; 181df499b44de81fc757a789878f07fcaf19ebb0016Kostya Serebryany} 182df499b44de81fc757a789878f07fcaf19ebb0016Kostya Serebryany 183efb3fa36cf421c346e8e54054cdae4fd798edab7Kostya Serebryanybool AsanProcMaps::Next(uintptr_t *start, uintptr_t *end, 184efb3fa36cf421c346e8e54054cdae4fd798edab7Kostya Serebryany uintptr_t *offset, char filename[], 185df499b44de81fc757a789878f07fcaf19ebb0016Kostya Serebryany size_t filename_size) { 186df499b44de81fc757a789878f07fcaf19ebb0016Kostya Serebryany char *last = proc_self_maps_buff_ + proc_self_maps_buff_len_; 187df499b44de81fc757a789878f07fcaf19ebb0016Kostya Serebryany if (current_ >= last) return false; 188df499b44de81fc757a789878f07fcaf19ebb0016Kostya Serebryany int consumed = 0; 189df499b44de81fc757a789878f07fcaf19ebb0016Kostya Serebryany char flags[10]; 190df499b44de81fc757a789878f07fcaf19ebb0016Kostya Serebryany int major, minor; 191efb3fa36cf421c346e8e54054cdae4fd798edab7Kostya Serebryany uintptr_t inode; 192df499b44de81fc757a789878f07fcaf19ebb0016Kostya Serebryany char *next_line = (char*)internal_memchr(current_, '\n', last - current_); 193df499b44de81fc757a789878f07fcaf19ebb0016Kostya Serebryany if (next_line == NULL) 194df499b44de81fc757a789878f07fcaf19ebb0016Kostya Serebryany next_line = last; 195df499b44de81fc757a789878f07fcaf19ebb0016Kostya Serebryany if (SScanf(current_, 196efb3fa36cf421c346e8e54054cdae4fd798edab7Kostya Serebryany "%lx-%lx %4s %lx %x:%x %ld %n", 197df499b44de81fc757a789878f07fcaf19ebb0016Kostya Serebryany start, end, flags, offset, &major, &minor, 198df499b44de81fc757a789878f07fcaf19ebb0016Kostya Serebryany &inode, &consumed) != 7) 199df499b44de81fc757a789878f07fcaf19ebb0016Kostya Serebryany return false; 200df499b44de81fc757a789878f07fcaf19ebb0016Kostya Serebryany current_ += consumed; 201df499b44de81fc757a789878f07fcaf19ebb0016Kostya Serebryany // Skip spaces. 202df499b44de81fc757a789878f07fcaf19ebb0016Kostya Serebryany while (current_ < next_line && *current_ == ' ') 203df499b44de81fc757a789878f07fcaf19ebb0016Kostya Serebryany current_++; 204df499b44de81fc757a789878f07fcaf19ebb0016Kostya Serebryany // Fill in the filename. 205df499b44de81fc757a789878f07fcaf19ebb0016Kostya Serebryany size_t i = 0; 206df499b44de81fc757a789878f07fcaf19ebb0016Kostya Serebryany while (current_ < next_line) { 207df499b44de81fc757a789878f07fcaf19ebb0016Kostya Serebryany if (filename && i < filename_size - 1) 208df499b44de81fc757a789878f07fcaf19ebb0016Kostya Serebryany filename[i++] = *current_; 209df499b44de81fc757a789878f07fcaf19ebb0016Kostya Serebryany current_++; 210df499b44de81fc757a789878f07fcaf19ebb0016Kostya Serebryany } 211df499b44de81fc757a789878f07fcaf19ebb0016Kostya Serebryany if (filename && i < filename_size) 212df499b44de81fc757a789878f07fcaf19ebb0016Kostya Serebryany filename[i] = 0; 213df499b44de81fc757a789878f07fcaf19ebb0016Kostya Serebryany current_ = next_line + 1; 214df499b44de81fc757a789878f07fcaf19ebb0016Kostya Serebryany return true; 215df499b44de81fc757a789878f07fcaf19ebb0016Kostya Serebryany} 216df499b44de81fc757a789878f07fcaf19ebb0016Kostya Serebryany 21750f9b8f8d1d9ac33d4bfca9fb2315f1265d957d3Kostya Serebryany#if 1 21892bda94d7bd042ee2f3e1a9ccc0e0fec7797a200Evgeniy Stepanov 21992bda94d7bd042ee2f3e1a9ccc0e0fec7797a200Evgeniy Stepanov// Gets the object name and the offset by walking AsanProcMaps. 22092bda94d7bd042ee2f3e1a9ccc0e0fec7797a200Evgeniy Stepanovbool AsanProcMaps::GetObjectNameAndOffset(uintptr_t addr, uintptr_t *offset, 22192bda94d7bd042ee2f3e1a9ccc0e0fec7797a200Evgeniy Stepanov char filename[], 22292bda94d7bd042ee2f3e1a9ccc0e0fec7797a200Evgeniy Stepanov size_t filename_size) { 2238a34d384255f9bf4c2a9b03a4df81b9af57124d8Alexander Potapenko return IterateForObjectNameAndOffset(addr, offset, filename, filename_size); 22492bda94d7bd042ee2f3e1a9ccc0e0fec7797a200Evgeniy Stepanov} 22592bda94d7bd042ee2f3e1a9ccc0e0fec7797a200Evgeniy Stepanov 22650f9b8f8d1d9ac33d4bfca9fb2315f1265d957d3Kostya Serebryany#else 22750f9b8f8d1d9ac33d4bfca9fb2315f1265d957d3Kostya Serebryany// dl_iterate_phdr machinery is not working well for us. 22850f9b8f8d1d9ac33d4bfca9fb2315f1265d957d3Kostya Serebryany// We either need to fix it or get rid of it. 229efb3fa36cf421c346e8e54054cdae4fd798edab7Kostya Serebryanystruct DlIterateData { 230efb3fa36cf421c346e8e54054cdae4fd798edab7Kostya Serebryany int count; 231efb3fa36cf421c346e8e54054cdae4fd798edab7Kostya Serebryany uintptr_t addr; 232efb3fa36cf421c346e8e54054cdae4fd798edab7Kostya Serebryany uintptr_t offset; 233efb3fa36cf421c346e8e54054cdae4fd798edab7Kostya Serebryany char *filename; 234efb3fa36cf421c346e8e54054cdae4fd798edab7Kostya Serebryany size_t filename_size; 235efb3fa36cf421c346e8e54054cdae4fd798edab7Kostya Serebryany}; 236efb3fa36cf421c346e8e54054cdae4fd798edab7Kostya Serebryany 237efb3fa36cf421c346e8e54054cdae4fd798edab7Kostya Serebryanystatic int dl_iterate_phdr_callback(struct dl_phdr_info *info, 238efb3fa36cf421c346e8e54054cdae4fd798edab7Kostya Serebryany size_t size, void *raw_data) { 239efb3fa36cf421c346e8e54054cdae4fd798edab7Kostya Serebryany DlIterateData *data = (DlIterateData*)raw_data; 240efb3fa36cf421c346e8e54054cdae4fd798edab7Kostya Serebryany int count = data->count++; 241efb3fa36cf421c346e8e54054cdae4fd798edab7Kostya Serebryany if (info->dlpi_addr > data->addr) 242efb3fa36cf421c346e8e54054cdae4fd798edab7Kostya Serebryany return 0; 243efb3fa36cf421c346e8e54054cdae4fd798edab7Kostya Serebryany if (count == 0) { 244efb3fa36cf421c346e8e54054cdae4fd798edab7Kostya Serebryany // The first item (the main executable) does not have a so name, 245efb3fa36cf421c346e8e54054cdae4fd798edab7Kostya Serebryany // but we can just read it from /proc/self/exe. 2460ecf5eb729dd81a43f8585cb438d3cb2a35899edKostya Serebryany size_t path_len = readlink("/proc/self/exe", 2470ecf5eb729dd81a43f8585cb438d3cb2a35899edKostya Serebryany data->filename, data->filename_size - 1); 248efb3fa36cf421c346e8e54054cdae4fd798edab7Kostya Serebryany data->filename[path_len] = 0; 249efb3fa36cf421c346e8e54054cdae4fd798edab7Kostya Serebryany } else { 250efb3fa36cf421c346e8e54054cdae4fd798edab7Kostya Serebryany CHECK(info->dlpi_name); 25109672caefb5694f1981a1712fdefa44840a95e67Alexey Samsonov REAL(strncpy)(data->filename, info->dlpi_name, data->filename_size); 252efb3fa36cf421c346e8e54054cdae4fd798edab7Kostya Serebryany } 253efb3fa36cf421c346e8e54054cdae4fd798edab7Kostya Serebryany data->offset = data->addr - info->dlpi_addr; 254efb3fa36cf421c346e8e54054cdae4fd798edab7Kostya Serebryany return 1; 255efb3fa36cf421c346e8e54054cdae4fd798edab7Kostya Serebryany} 256efb3fa36cf421c346e8e54054cdae4fd798edab7Kostya Serebryany 257efb3fa36cf421c346e8e54054cdae4fd798edab7Kostya Serebryany// Gets the object name and the offset using dl_iterate_phdr. 258efb3fa36cf421c346e8e54054cdae4fd798edab7Kostya Serebryanybool AsanProcMaps::GetObjectNameAndOffset(uintptr_t addr, uintptr_t *offset, 259efb3fa36cf421c346e8e54054cdae4fd798edab7Kostya Serebryany char filename[], 260efb3fa36cf421c346e8e54054cdae4fd798edab7Kostya Serebryany size_t filename_size) { 261efb3fa36cf421c346e8e54054cdae4fd798edab7Kostya Serebryany DlIterateData data; 262efb3fa36cf421c346e8e54054cdae4fd798edab7Kostya Serebryany data.count = 0; 263efb3fa36cf421c346e8e54054cdae4fd798edab7Kostya Serebryany data.addr = addr; 264efb3fa36cf421c346e8e54054cdae4fd798edab7Kostya Serebryany data.filename = filename; 265efb3fa36cf421c346e8e54054cdae4fd798edab7Kostya Serebryany data.filename_size = filename_size; 266efb3fa36cf421c346e8e54054cdae4fd798edab7Kostya Serebryany if (dl_iterate_phdr(dl_iterate_phdr_callback, &data)) { 267efb3fa36cf421c346e8e54054cdae4fd798edab7Kostya Serebryany *offset = data.offset; 268efb3fa36cf421c346e8e54054cdae4fd798edab7Kostya Serebryany return true; 269efb3fa36cf421c346e8e54054cdae4fd798edab7Kostya Serebryany } 270efb3fa36cf421c346e8e54054cdae4fd798edab7Kostya Serebryany return false; 271efb3fa36cf421c346e8e54054cdae4fd798edab7Kostya Serebryany} 272efb3fa36cf421c346e8e54054cdae4fd798edab7Kostya Serebryany 2734fd95f141f78906570c15a8a3b4cf0a7b50a201dAlexey Samsonov#endif // __arm__ 27492bda94d7bd042ee2f3e1a9ccc0e0fec7797a200Evgeniy Stepanov 275c549dd7b5fa5fb97270f57067797224cee0429f2Kostya Serebryanyvoid AsanThread::SetThreadStackTopAndBottom() { 276c549dd7b5fa5fb97270f57067797224cee0429f2Kostya Serebryany if (tid() == 0) { 277c549dd7b5fa5fb97270f57067797224cee0429f2Kostya Serebryany // This is the main thread. Libpthread may not be initialized yet. 278c549dd7b5fa5fb97270f57067797224cee0429f2Kostya Serebryany struct rlimit rl; 279c549dd7b5fa5fb97270f57067797224cee0429f2Kostya Serebryany CHECK(getrlimit(RLIMIT_STACK, &rl) == 0); 280c549dd7b5fa5fb97270f57067797224cee0429f2Kostya Serebryany 281c549dd7b5fa5fb97270f57067797224cee0429f2Kostya Serebryany // Find the mapping that contains a stack variable. 282c549dd7b5fa5fb97270f57067797224cee0429f2Kostya Serebryany AsanProcMaps proc_maps; 283efb3fa36cf421c346e8e54054cdae4fd798edab7Kostya Serebryany uintptr_t start, end, offset; 284efb3fa36cf421c346e8e54054cdae4fd798edab7Kostya Serebryany uintptr_t prev_end = 0; 285c549dd7b5fa5fb97270f57067797224cee0429f2Kostya Serebryany while (proc_maps.Next(&start, &end, &offset, NULL, 0)) { 286c549dd7b5fa5fb97270f57067797224cee0429f2Kostya Serebryany if ((uintptr_t)&rl < end) 287c549dd7b5fa5fb97270f57067797224cee0429f2Kostya Serebryany break; 288c549dd7b5fa5fb97270f57067797224cee0429f2Kostya Serebryany prev_end = end; 289c549dd7b5fa5fb97270f57067797224cee0429f2Kostya Serebryany } 290c549dd7b5fa5fb97270f57067797224cee0429f2Kostya Serebryany CHECK((uintptr_t)&rl >= start && (uintptr_t)&rl < end); 291c549dd7b5fa5fb97270f57067797224cee0429f2Kostya Serebryany 292c549dd7b5fa5fb97270f57067797224cee0429f2Kostya Serebryany // Get stacksize from rlimit, but clip it so that it does not overlap 293c549dd7b5fa5fb97270f57067797224cee0429f2Kostya Serebryany // with other mappings. 294c549dd7b5fa5fb97270f57067797224cee0429f2Kostya Serebryany size_t stacksize = rl.rlim_cur; 295c549dd7b5fa5fb97270f57067797224cee0429f2Kostya Serebryany if (stacksize > end - prev_end) 296c549dd7b5fa5fb97270f57067797224cee0429f2Kostya Serebryany stacksize = end - prev_end; 297c549dd7b5fa5fb97270f57067797224cee0429f2Kostya Serebryany if (stacksize > kMaxThreadStackSize) 298c549dd7b5fa5fb97270f57067797224cee0429f2Kostya Serebryany stacksize = kMaxThreadStackSize; 299c549dd7b5fa5fb97270f57067797224cee0429f2Kostya Serebryany stack_top_ = end; 300c549dd7b5fa5fb97270f57067797224cee0429f2Kostya Serebryany stack_bottom_ = end - stacksize; 301c549dd7b5fa5fb97270f57067797224cee0429f2Kostya Serebryany CHECK(AddrIsInStack((uintptr_t)&rl)); 302c549dd7b5fa5fb97270f57067797224cee0429f2Kostya Serebryany return; 303c549dd7b5fa5fb97270f57067797224cee0429f2Kostya Serebryany } 304c549dd7b5fa5fb97270f57067797224cee0429f2Kostya Serebryany pthread_attr_t attr; 305c549dd7b5fa5fb97270f57067797224cee0429f2Kostya Serebryany CHECK(pthread_getattr_np(pthread_self(), &attr) == 0); 306c549dd7b5fa5fb97270f57067797224cee0429f2Kostya Serebryany size_t stacksize = 0; 307c549dd7b5fa5fb97270f57067797224cee0429f2Kostya Serebryany void *stackaddr = NULL; 308c549dd7b5fa5fb97270f57067797224cee0429f2Kostya Serebryany pthread_attr_getstack(&attr, &stackaddr, &stacksize); 309c549dd7b5fa5fb97270f57067797224cee0429f2Kostya Serebryany pthread_attr_destroy(&attr); 310c549dd7b5fa5fb97270f57067797224cee0429f2Kostya Serebryany 311c549dd7b5fa5fb97270f57067797224cee0429f2Kostya Serebryany stack_top_ = (uintptr_t)stackaddr + stacksize; 312c549dd7b5fa5fb97270f57067797224cee0429f2Kostya Serebryany stack_bottom_ = (uintptr_t)stackaddr; 313c549dd7b5fa5fb97270f57067797224cee0429f2Kostya Serebryany // When running with unlimited stack size, we still want to set some limit. 314c549dd7b5fa5fb97270f57067797224cee0429f2Kostya Serebryany // The unlimited stack size is caused by 'ulimit -s unlimited'. 315c549dd7b5fa5fb97270f57067797224cee0429f2Kostya Serebryany // Also, for some reason, GNU make spawns subrocesses with unlimited stack. 316c549dd7b5fa5fb97270f57067797224cee0429f2Kostya Serebryany if (stacksize > kMaxThreadStackSize) { 317c549dd7b5fa5fb97270f57067797224cee0429f2Kostya Serebryany stack_bottom_ = stack_top_ - kMaxThreadStackSize; 318c549dd7b5fa5fb97270f57067797224cee0429f2Kostya Serebryany } 319c549dd7b5fa5fb97270f57067797224cee0429f2Kostya Serebryany CHECK(AddrIsInStack((uintptr_t)&attr)); 320c549dd7b5fa5fb97270f57067797224cee0429f2Kostya Serebryany} 321c549dd7b5fa5fb97270f57067797224cee0429f2Kostya Serebryany 322d55f5f8c413622db4bd28b5cca9bfeb4d61564e0Kostya SerebryanyAsanLock::AsanLock(LinkerInitialized) { 323d55f5f8c413622db4bd28b5cca9bfeb4d61564e0Kostya Serebryany // We assume that pthread_mutex_t initialized to all zeroes is a valid 324d55f5f8c413622db4bd28b5cca9bfeb4d61564e0Kostya Serebryany // unlocked mutex. We can not use PTHREAD_MUTEX_INITIALIZER as it triggers 325d55f5f8c413622db4bd28b5cca9bfeb4d61564e0Kostya Serebryany // a gcc warning: 326d55f5f8c413622db4bd28b5cca9bfeb4d61564e0Kostya Serebryany // extended initializer lists only available with -std=c++0x or -std=gnu++0x 327d55f5f8c413622db4bd28b5cca9bfeb4d61564e0Kostya Serebryany} 328d55f5f8c413622db4bd28b5cca9bfeb4d61564e0Kostya Serebryany 329d55f5f8c413622db4bd28b5cca9bfeb4d61564e0Kostya Serebryanyvoid AsanLock::Lock() { 330d55f5f8c413622db4bd28b5cca9bfeb4d61564e0Kostya Serebryany CHECK(sizeof(pthread_mutex_t) <= sizeof(opaque_storage_)); 331d55f5f8c413622db4bd28b5cca9bfeb4d61564e0Kostya Serebryany pthread_mutex_lock((pthread_mutex_t*)&opaque_storage_); 332d55f5f8c413622db4bd28b5cca9bfeb4d61564e0Kostya Serebryany CHECK(!owner_); 333d55f5f8c413622db4bd28b5cca9bfeb4d61564e0Kostya Serebryany owner_ = (uintptr_t)pthread_self(); 334d55f5f8c413622db4bd28b5cca9bfeb4d61564e0Kostya Serebryany} 335d55f5f8c413622db4bd28b5cca9bfeb4d61564e0Kostya Serebryany 336d55f5f8c413622db4bd28b5cca9bfeb4d61564e0Kostya Serebryanyvoid AsanLock::Unlock() { 337d55f5f8c413622db4bd28b5cca9bfeb4d61564e0Kostya Serebryany CHECK(owner_ == (uintptr_t)pthread_self()); 338d55f5f8c413622db4bd28b5cca9bfeb4d61564e0Kostya Serebryany owner_ = 0; 339d55f5f8c413622db4bd28b5cca9bfeb4d61564e0Kostya Serebryany pthread_mutex_unlock((pthread_mutex_t*)&opaque_storage_); 340d55f5f8c413622db4bd28b5cca9bfeb4d61564e0Kostya Serebryany} 341d55f5f8c413622db4bd28b5cca9bfeb4d61564e0Kostya Serebryany 3429cfa194cc62026fc7c6e82f7303eee8ad4d10cf4Evgeniy Stepanov#ifdef __arm__ 3439cfa194cc62026fc7c6e82f7303eee8ad4d10cf4Evgeniy Stepanov#define UNWIND_STOP _URC_END_OF_STACK 3449cfa194cc62026fc7c6e82f7303eee8ad4d10cf4Evgeniy Stepanov#define UNWIND_CONTINUE _URC_NO_REASON 3459cfa194cc62026fc7c6e82f7303eee8ad4d10cf4Evgeniy Stepanov#else 3469cfa194cc62026fc7c6e82f7303eee8ad4d10cf4Evgeniy Stepanov#define UNWIND_STOP _URC_NORMAL_STOP 3479cfa194cc62026fc7c6e82f7303eee8ad4d10cf4Evgeniy Stepanov#define UNWIND_CONTINUE _URC_NO_REASON 3489cfa194cc62026fc7c6e82f7303eee8ad4d10cf4Evgeniy Stepanov#endif 3499cfa194cc62026fc7c6e82f7303eee8ad4d10cf4Evgeniy Stepanov 3509cfa194cc62026fc7c6e82f7303eee8ad4d10cf4Evgeniy Stepanovuintptr_t Unwind_GetIP(struct _Unwind_Context *ctx) { 3519cfa194cc62026fc7c6e82f7303eee8ad4d10cf4Evgeniy Stepanov#ifdef __arm__ 3529cfa194cc62026fc7c6e82f7303eee8ad4d10cf4Evgeniy Stepanov uintptr_t val; 3539cfa194cc62026fc7c6e82f7303eee8ad4d10cf4Evgeniy Stepanov _Unwind_VRS_Result res = _Unwind_VRS_Get(ctx, _UVRSC_CORE, 3549cfa194cc62026fc7c6e82f7303eee8ad4d10cf4Evgeniy Stepanov 15 /* r15 = PC */, _UVRSD_UINT32, &val); 3559cfa194cc62026fc7c6e82f7303eee8ad4d10cf4Evgeniy Stepanov CHECK(res == _UVRSR_OK && "_Unwind_VRS_Get failed"); 3569cfa194cc62026fc7c6e82f7303eee8ad4d10cf4Evgeniy Stepanov // Clear the Thumb bit. 3579cfa194cc62026fc7c6e82f7303eee8ad4d10cf4Evgeniy Stepanov return val & ~(uintptr_t)1; 3589cfa194cc62026fc7c6e82f7303eee8ad4d10cf4Evgeniy Stepanov#else 3599cfa194cc62026fc7c6e82f7303eee8ad4d10cf4Evgeniy Stepanov return _Unwind_GetIP(ctx); 3609cfa194cc62026fc7c6e82f7303eee8ad4d10cf4Evgeniy Stepanov#endif 3619cfa194cc62026fc7c6e82f7303eee8ad4d10cf4Evgeniy Stepanov} 3629cfa194cc62026fc7c6e82f7303eee8ad4d10cf4Evgeniy Stepanov 3639cfa194cc62026fc7c6e82f7303eee8ad4d10cf4Evgeniy Stepanov_Unwind_Reason_Code Unwind_Trace(struct _Unwind_Context *ctx, 3649cfa194cc62026fc7c6e82f7303eee8ad4d10cf4Evgeniy Stepanov void *param) { 3659cfa194cc62026fc7c6e82f7303eee8ad4d10cf4Evgeniy Stepanov AsanStackTrace *b = (AsanStackTrace*)param; 3669cfa194cc62026fc7c6e82f7303eee8ad4d10cf4Evgeniy Stepanov CHECK(b->size < b->max_size); 3679cfa194cc62026fc7c6e82f7303eee8ad4d10cf4Evgeniy Stepanov uintptr_t pc = Unwind_GetIP(ctx); 3689cfa194cc62026fc7c6e82f7303eee8ad4d10cf4Evgeniy Stepanov b->trace[b->size++] = pc; 3699cfa194cc62026fc7c6e82f7303eee8ad4d10cf4Evgeniy Stepanov if (b->size == b->max_size) return UNWIND_STOP; 3709cfa194cc62026fc7c6e82f7303eee8ad4d10cf4Evgeniy Stepanov return UNWIND_CONTINUE; 3719cfa194cc62026fc7c6e82f7303eee8ad4d10cf4Evgeniy Stepanov} 3729cfa194cc62026fc7c6e82f7303eee8ad4d10cf4Evgeniy Stepanov 3739cfa194cc62026fc7c6e82f7303eee8ad4d10cf4Evgeniy Stepanovvoid AsanStackTrace::GetStackTrace(size_t max_s, uintptr_t pc, uintptr_t bp) { 3749cfa194cc62026fc7c6e82f7303eee8ad4d10cf4Evgeniy Stepanov size = 0; 3759cfa194cc62026fc7c6e82f7303eee8ad4d10cf4Evgeniy Stepanov trace[0] = pc; 3769cfa194cc62026fc7c6e82f7303eee8ad4d10cf4Evgeniy Stepanov if ((max_s) > 1) { 3779cfa194cc62026fc7c6e82f7303eee8ad4d10cf4Evgeniy Stepanov max_size = max_s; 3789cfa194cc62026fc7c6e82f7303eee8ad4d10cf4Evgeniy Stepanov#ifdef __arm__ 3799cfa194cc62026fc7c6e82f7303eee8ad4d10cf4Evgeniy Stepanov _Unwind_Backtrace(Unwind_Trace, this); 3809cfa194cc62026fc7c6e82f7303eee8ad4d10cf4Evgeniy Stepanov#else 3819cfa194cc62026fc7c6e82f7303eee8ad4d10cf4Evgeniy Stepanov FastUnwindStack(pc, bp); 3829cfa194cc62026fc7c6e82f7303eee8ad4d10cf4Evgeniy Stepanov#endif 3839cfa194cc62026fc7c6e82f7303eee8ad4d10cf4Evgeniy Stepanov } 3849cfa194cc62026fc7c6e82f7303eee8ad4d10cf4Evgeniy Stepanov} 3859cfa194cc62026fc7c6e82f7303eee8ad4d10cf4Evgeniy Stepanov 3861e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany} // namespace __asan 387d6567c5166412f6acdde851e767c26f332d51d3dKostya Serebryany 388d6567c5166412f6acdde851e767c26f332d51d3dKostya Serebryany#endif // __linux__ 389