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