asan_linux.cc revision d55f5f8c413622db4bd28b5cca9bfeb4d61564e0
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> 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 381e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanynamespace __asan { 391e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 401e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanyvoid *AsanDoesNotSupportStaticLinkage() { 411e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany // This will fail to link with -static. 42efb3fa36cf421c346e8e54054cdae4fd798edab7Kostya Serebryany return &_DYNAMIC; // defined in link.h 431e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany} 441e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 459107c26bd88fc9cf44a2cd7d6967eb830ac63be3Kostya Serebryanyvoid GetPcSpBp(void *context, uintptr_t *pc, uintptr_t *sp, uintptr_t *bp) { 469107c26bd88fc9cf44a2cd7d6967eb830ac63be3Kostya Serebryany#ifdef ANDROID 479107c26bd88fc9cf44a2cd7d6967eb830ac63be3Kostya Serebryany *pc = *sp = *bp = 0; 489107c26bd88fc9cf44a2cd7d6967eb830ac63be3Kostya Serebryany#elif defined(__arm__) 499107c26bd88fc9cf44a2cd7d6967eb830ac63be3Kostya Serebryany ucontext_t *ucontext = (ucontext_t*)context; 509107c26bd88fc9cf44a2cd7d6967eb830ac63be3Kostya Serebryany *pc = ucontext->uc_mcontext.arm_pc; 519107c26bd88fc9cf44a2cd7d6967eb830ac63be3Kostya Serebryany *bp = ucontext->uc_mcontext.arm_fp; 529107c26bd88fc9cf44a2cd7d6967eb830ac63be3Kostya Serebryany *sp = ucontext->uc_mcontext.arm_sp; 539107c26bd88fc9cf44a2cd7d6967eb830ac63be3Kostya Serebryany# elif defined(__x86_64__) 549107c26bd88fc9cf44a2cd7d6967eb830ac63be3Kostya Serebryany ucontext_t *ucontext = (ucontext_t*)context; 559107c26bd88fc9cf44a2cd7d6967eb830ac63be3Kostya Serebryany *pc = ucontext->uc_mcontext.gregs[REG_RIP]; 569107c26bd88fc9cf44a2cd7d6967eb830ac63be3Kostya Serebryany *bp = ucontext->uc_mcontext.gregs[REG_RBP]; 579107c26bd88fc9cf44a2cd7d6967eb830ac63be3Kostya Serebryany *sp = ucontext->uc_mcontext.gregs[REG_RSP]; 589107c26bd88fc9cf44a2cd7d6967eb830ac63be3Kostya Serebryany# elif defined(__i386__) 599107c26bd88fc9cf44a2cd7d6967eb830ac63be3Kostya Serebryany ucontext_t *ucontext = (ucontext_t*)context; 609107c26bd88fc9cf44a2cd7d6967eb830ac63be3Kostya Serebryany *pc = ucontext->uc_mcontext.gregs[REG_EIP]; 619107c26bd88fc9cf44a2cd7d6967eb830ac63be3Kostya Serebryany *bp = ucontext->uc_mcontext.gregs[REG_EBP]; 629107c26bd88fc9cf44a2cd7d6967eb830ac63be3Kostya Serebryany *sp = ucontext->uc_mcontext.gregs[REG_ESP]; 639107c26bd88fc9cf44a2cd7d6967eb830ac63be3Kostya Serebryany#else 649107c26bd88fc9cf44a2cd7d6967eb830ac63be3Kostya Serebryany# error "Unsupported arch" 659107c26bd88fc9cf44a2cd7d6967eb830ac63be3Kostya Serebryany#endif 669107c26bd88fc9cf44a2cd7d6967eb830ac63be3Kostya Serebryany} 679107c26bd88fc9cf44a2cd7d6967eb830ac63be3Kostya Serebryany 684803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryanybool AsanInterceptsSignal(int signum) { 694803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany return signum == SIGSEGV && FLAG_handle_segv; 704803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany} 714803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany 72a874fe5b5d67152e4e737498d532eec80940bdcdKostya Serebryanystatic void *asan_mmap(void *addr, size_t length, int prot, int flags, 731e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany int fd, uint64_t offset) { 741e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany# if __WORDSIZE == 64 75de496f451bce322b6cde100456591f1f50ab3477Kostya Serebryany return (void *)syscall(__NR_mmap, addr, length, prot, flags, fd, offset); 761e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany# else 77de496f451bce322b6cde100456591f1f50ab3477Kostya Serebryany return (void *)syscall(__NR_mmap2, addr, length, prot, flags, fd, offset); 781e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany# endif 791e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany} 801e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 81de496f451bce322b6cde100456591f1f50ab3477Kostya Serebryanyvoid *AsanMmapSomewhereOrDie(size_t size, const char *mem_type) { 82de496f451bce322b6cde100456591f1f50ab3477Kostya Serebryany size = RoundUpTo(size, kPageSize); 83de496f451bce322b6cde100456591f1f50ab3477Kostya Serebryany void *res = asan_mmap(0, size, 84de496f451bce322b6cde100456591f1f50ab3477Kostya Serebryany PROT_READ | PROT_WRITE, 85de496f451bce322b6cde100456591f1f50ab3477Kostya Serebryany MAP_PRIVATE | MAP_ANON, -1, 0); 86de496f451bce322b6cde100456591f1f50ab3477Kostya Serebryany if (res == (void*)-1) { 87de496f451bce322b6cde100456591f1f50ab3477Kostya Serebryany OutOfMemoryMessageAndDie(mem_type, size); 88de496f451bce322b6cde100456591f1f50ab3477Kostya Serebryany } 89de496f451bce322b6cde100456591f1f50ab3477Kostya Serebryany return res; 90de496f451bce322b6cde100456591f1f50ab3477Kostya Serebryany} 91de496f451bce322b6cde100456591f1f50ab3477Kostya Serebryany 92a874fe5b5d67152e4e737498d532eec80940bdcdKostya Serebryanyvoid *AsanMmapFixedNoReserve(uintptr_t fixed_addr, size_t size) { 93a874fe5b5d67152e4e737498d532eec80940bdcdKostya Serebryany return asan_mmap((void*)fixed_addr, size, 94a874fe5b5d67152e4e737498d532eec80940bdcdKostya Serebryany PROT_READ | PROT_WRITE, 95a874fe5b5d67152e4e737498d532eec80940bdcdKostya Serebryany MAP_PRIVATE | MAP_ANON | MAP_FIXED | MAP_NORESERVE, 96a874fe5b5d67152e4e737498d532eec80940bdcdKostya Serebryany 0, 0); 97a874fe5b5d67152e4e737498d532eec80940bdcdKostya Serebryany} 98a874fe5b5d67152e4e737498d532eec80940bdcdKostya Serebryany 99a874fe5b5d67152e4e737498d532eec80940bdcdKostya Serebryanyvoid *AsanMmapFixedReserve(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, 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) { 127de496f451bce322b6cde100456591f1f50ab3477Kostya Serebryany return open(filename, O_RDONLY); 128de496f451bce322b6cde100456591f1f50ab3477Kostya Serebryany} 129de496f451bce322b6cde100456591f1f50ab3477Kostya Serebryany 1300ecf5eb729dd81a43f8585cb438d3cb2a35899edKostya Serebryanysize_t AsanRead(int fd, void *buf, size_t count) { 1310ecf5eb729dd81a43f8585cb438d3cb2a35899edKostya Serebryany return (size_t)syscall(__NR_read, fd, buf, count); 132de496f451bce322b6cde100456591f1f50ab3477Kostya Serebryany} 133de496f451bce322b6cde100456591f1f50ab3477Kostya Serebryany 134de496f451bce322b6cde100456591f1f50ab3477Kostya Serebryanyint AsanClose(int fd) { 135de496f451bce322b6cde100456591f1f50ab3477Kostya Serebryany return close(fd); 1361e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany} 1371e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 138df499b44de81fc757a789878f07fcaf19ebb0016Kostya SerebryanyAsanProcMaps::AsanProcMaps() { 139df499b44de81fc757a789878f07fcaf19ebb0016Kostya Serebryany proc_self_maps_buff_len_ = 140df499b44de81fc757a789878f07fcaf19ebb0016Kostya Serebryany ReadFileToBuffer("/proc/self/maps", &proc_self_maps_buff_, 141df499b44de81fc757a789878f07fcaf19ebb0016Kostya Serebryany &proc_self_maps_buff_mmaped_size_, 1 << 20); 142df499b44de81fc757a789878f07fcaf19ebb0016Kostya Serebryany CHECK(proc_self_maps_buff_len_ > 0); 143df499b44de81fc757a789878f07fcaf19ebb0016Kostya Serebryany // AsanWrite(2, proc_self_maps_buff_, proc_self_maps_buff_len_); 144df499b44de81fc757a789878f07fcaf19ebb0016Kostya Serebryany Reset(); 145df499b44de81fc757a789878f07fcaf19ebb0016Kostya Serebryany} 146df499b44de81fc757a789878f07fcaf19ebb0016Kostya Serebryany 147df499b44de81fc757a789878f07fcaf19ebb0016Kostya SerebryanyAsanProcMaps::~AsanProcMaps() { 148df499b44de81fc757a789878f07fcaf19ebb0016Kostya Serebryany AsanUnmapOrDie(proc_self_maps_buff_, proc_self_maps_buff_mmaped_size_); 149df499b44de81fc757a789878f07fcaf19ebb0016Kostya Serebryany} 150df499b44de81fc757a789878f07fcaf19ebb0016Kostya Serebryany 151df499b44de81fc757a789878f07fcaf19ebb0016Kostya Serebryanyvoid AsanProcMaps::Reset() { 152df499b44de81fc757a789878f07fcaf19ebb0016Kostya Serebryany current_ = proc_self_maps_buff_; 153df499b44de81fc757a789878f07fcaf19ebb0016Kostya Serebryany} 154df499b44de81fc757a789878f07fcaf19ebb0016Kostya Serebryany 155efb3fa36cf421c346e8e54054cdae4fd798edab7Kostya Serebryanybool AsanProcMaps::Next(uintptr_t *start, uintptr_t *end, 156efb3fa36cf421c346e8e54054cdae4fd798edab7Kostya Serebryany uintptr_t *offset, char filename[], 157df499b44de81fc757a789878f07fcaf19ebb0016Kostya Serebryany size_t filename_size) { 158df499b44de81fc757a789878f07fcaf19ebb0016Kostya Serebryany char *last = proc_self_maps_buff_ + proc_self_maps_buff_len_; 159df499b44de81fc757a789878f07fcaf19ebb0016Kostya Serebryany if (current_ >= last) return false; 160df499b44de81fc757a789878f07fcaf19ebb0016Kostya Serebryany int consumed = 0; 161df499b44de81fc757a789878f07fcaf19ebb0016Kostya Serebryany char flags[10]; 162df499b44de81fc757a789878f07fcaf19ebb0016Kostya Serebryany int major, minor; 163efb3fa36cf421c346e8e54054cdae4fd798edab7Kostya Serebryany uintptr_t inode; 164df499b44de81fc757a789878f07fcaf19ebb0016Kostya Serebryany char *next_line = (char*)internal_memchr(current_, '\n', last - current_); 165df499b44de81fc757a789878f07fcaf19ebb0016Kostya Serebryany if (next_line == NULL) 166df499b44de81fc757a789878f07fcaf19ebb0016Kostya Serebryany next_line = last; 167df499b44de81fc757a789878f07fcaf19ebb0016Kostya Serebryany if (SScanf(current_, 168efb3fa36cf421c346e8e54054cdae4fd798edab7Kostya Serebryany "%lx-%lx %4s %lx %x:%x %ld %n", 169df499b44de81fc757a789878f07fcaf19ebb0016Kostya Serebryany start, end, flags, offset, &major, &minor, 170df499b44de81fc757a789878f07fcaf19ebb0016Kostya Serebryany &inode, &consumed) != 7) 171df499b44de81fc757a789878f07fcaf19ebb0016Kostya Serebryany return false; 172df499b44de81fc757a789878f07fcaf19ebb0016Kostya Serebryany current_ += consumed; 173df499b44de81fc757a789878f07fcaf19ebb0016Kostya Serebryany // Skip spaces. 174df499b44de81fc757a789878f07fcaf19ebb0016Kostya Serebryany while (current_ < next_line && *current_ == ' ') 175df499b44de81fc757a789878f07fcaf19ebb0016Kostya Serebryany current_++; 176df499b44de81fc757a789878f07fcaf19ebb0016Kostya Serebryany // Fill in the filename. 177df499b44de81fc757a789878f07fcaf19ebb0016Kostya Serebryany size_t i = 0; 178df499b44de81fc757a789878f07fcaf19ebb0016Kostya Serebryany while (current_ < next_line) { 179df499b44de81fc757a789878f07fcaf19ebb0016Kostya Serebryany if (filename && i < filename_size - 1) 180df499b44de81fc757a789878f07fcaf19ebb0016Kostya Serebryany filename[i++] = *current_; 181df499b44de81fc757a789878f07fcaf19ebb0016Kostya Serebryany current_++; 182df499b44de81fc757a789878f07fcaf19ebb0016Kostya Serebryany } 183df499b44de81fc757a789878f07fcaf19ebb0016Kostya Serebryany if (filename && i < filename_size) 184df499b44de81fc757a789878f07fcaf19ebb0016Kostya Serebryany filename[i] = 0; 185df499b44de81fc757a789878f07fcaf19ebb0016Kostya Serebryany current_ = next_line + 1; 186df499b44de81fc757a789878f07fcaf19ebb0016Kostya Serebryany return true; 187df499b44de81fc757a789878f07fcaf19ebb0016Kostya Serebryany} 188df499b44de81fc757a789878f07fcaf19ebb0016Kostya Serebryany 189efb3fa36cf421c346e8e54054cdae4fd798edab7Kostya Serebryanystruct DlIterateData { 190efb3fa36cf421c346e8e54054cdae4fd798edab7Kostya Serebryany int count; 191efb3fa36cf421c346e8e54054cdae4fd798edab7Kostya Serebryany uintptr_t addr; 192efb3fa36cf421c346e8e54054cdae4fd798edab7Kostya Serebryany uintptr_t offset; 193efb3fa36cf421c346e8e54054cdae4fd798edab7Kostya Serebryany char *filename; 194efb3fa36cf421c346e8e54054cdae4fd798edab7Kostya Serebryany size_t filename_size; 195efb3fa36cf421c346e8e54054cdae4fd798edab7Kostya Serebryany}; 196efb3fa36cf421c346e8e54054cdae4fd798edab7Kostya Serebryany 197efb3fa36cf421c346e8e54054cdae4fd798edab7Kostya Serebryanystatic int dl_iterate_phdr_callback(struct dl_phdr_info *info, 198efb3fa36cf421c346e8e54054cdae4fd798edab7Kostya Serebryany size_t size, void *raw_data) { 199efb3fa36cf421c346e8e54054cdae4fd798edab7Kostya Serebryany DlIterateData *data = (DlIterateData*)raw_data; 200efb3fa36cf421c346e8e54054cdae4fd798edab7Kostya Serebryany int count = data->count++; 201efb3fa36cf421c346e8e54054cdae4fd798edab7Kostya Serebryany if (info->dlpi_addr > data->addr) 202efb3fa36cf421c346e8e54054cdae4fd798edab7Kostya Serebryany return 0; 203efb3fa36cf421c346e8e54054cdae4fd798edab7Kostya Serebryany if (count == 0) { 204efb3fa36cf421c346e8e54054cdae4fd798edab7Kostya Serebryany // The first item (the main executable) does not have a so name, 205efb3fa36cf421c346e8e54054cdae4fd798edab7Kostya Serebryany // but we can just read it from /proc/self/exe. 2060ecf5eb729dd81a43f8585cb438d3cb2a35899edKostya Serebryany size_t path_len = readlink("/proc/self/exe", 2070ecf5eb729dd81a43f8585cb438d3cb2a35899edKostya Serebryany data->filename, data->filename_size - 1); 208efb3fa36cf421c346e8e54054cdae4fd798edab7Kostya Serebryany data->filename[path_len] = 0; 209efb3fa36cf421c346e8e54054cdae4fd798edab7Kostya Serebryany } else { 210efb3fa36cf421c346e8e54054cdae4fd798edab7Kostya Serebryany CHECK(info->dlpi_name); 211efb3fa36cf421c346e8e54054cdae4fd798edab7Kostya Serebryany real_strncpy(data->filename, info->dlpi_name, data->filename_size); 212efb3fa36cf421c346e8e54054cdae4fd798edab7Kostya Serebryany } 213efb3fa36cf421c346e8e54054cdae4fd798edab7Kostya Serebryany data->offset = data->addr - info->dlpi_addr; 214efb3fa36cf421c346e8e54054cdae4fd798edab7Kostya Serebryany return 1; 215efb3fa36cf421c346e8e54054cdae4fd798edab7Kostya Serebryany} 216efb3fa36cf421c346e8e54054cdae4fd798edab7Kostya Serebryany 217efb3fa36cf421c346e8e54054cdae4fd798edab7Kostya Serebryany// Gets the object name and the offset using dl_iterate_phdr. 218efb3fa36cf421c346e8e54054cdae4fd798edab7Kostya Serebryanybool AsanProcMaps::GetObjectNameAndOffset(uintptr_t addr, uintptr_t *offset, 219efb3fa36cf421c346e8e54054cdae4fd798edab7Kostya Serebryany char filename[], 220efb3fa36cf421c346e8e54054cdae4fd798edab7Kostya Serebryany size_t filename_size) { 221efb3fa36cf421c346e8e54054cdae4fd798edab7Kostya Serebryany DlIterateData data; 222efb3fa36cf421c346e8e54054cdae4fd798edab7Kostya Serebryany data.count = 0; 223efb3fa36cf421c346e8e54054cdae4fd798edab7Kostya Serebryany data.addr = addr; 224efb3fa36cf421c346e8e54054cdae4fd798edab7Kostya Serebryany data.filename = filename; 225efb3fa36cf421c346e8e54054cdae4fd798edab7Kostya Serebryany data.filename_size = filename_size; 226efb3fa36cf421c346e8e54054cdae4fd798edab7Kostya Serebryany if (dl_iterate_phdr(dl_iterate_phdr_callback, &data)) { 227efb3fa36cf421c346e8e54054cdae4fd798edab7Kostya Serebryany *offset = data.offset; 228efb3fa36cf421c346e8e54054cdae4fd798edab7Kostya Serebryany return true; 229efb3fa36cf421c346e8e54054cdae4fd798edab7Kostya Serebryany } 230efb3fa36cf421c346e8e54054cdae4fd798edab7Kostya Serebryany return false; 231efb3fa36cf421c346e8e54054cdae4fd798edab7Kostya Serebryany} 232efb3fa36cf421c346e8e54054cdae4fd798edab7Kostya Serebryany 233c549dd7b5fa5fb97270f57067797224cee0429f2Kostya Serebryanyvoid AsanThread::SetThreadStackTopAndBottom() { 234c549dd7b5fa5fb97270f57067797224cee0429f2Kostya Serebryany if (tid() == 0) { 235c549dd7b5fa5fb97270f57067797224cee0429f2Kostya Serebryany // This is the main thread. Libpthread may not be initialized yet. 236c549dd7b5fa5fb97270f57067797224cee0429f2Kostya Serebryany struct rlimit rl; 237c549dd7b5fa5fb97270f57067797224cee0429f2Kostya Serebryany CHECK(getrlimit(RLIMIT_STACK, &rl) == 0); 238c549dd7b5fa5fb97270f57067797224cee0429f2Kostya Serebryany 239c549dd7b5fa5fb97270f57067797224cee0429f2Kostya Serebryany // Find the mapping that contains a stack variable. 240c549dd7b5fa5fb97270f57067797224cee0429f2Kostya Serebryany AsanProcMaps proc_maps; 241efb3fa36cf421c346e8e54054cdae4fd798edab7Kostya Serebryany uintptr_t start, end, offset; 242efb3fa36cf421c346e8e54054cdae4fd798edab7Kostya Serebryany uintptr_t prev_end = 0; 243c549dd7b5fa5fb97270f57067797224cee0429f2Kostya Serebryany while (proc_maps.Next(&start, &end, &offset, NULL, 0)) { 244c549dd7b5fa5fb97270f57067797224cee0429f2Kostya Serebryany if ((uintptr_t)&rl < end) 245c549dd7b5fa5fb97270f57067797224cee0429f2Kostya Serebryany break; 246c549dd7b5fa5fb97270f57067797224cee0429f2Kostya Serebryany prev_end = end; 247c549dd7b5fa5fb97270f57067797224cee0429f2Kostya Serebryany } 248c549dd7b5fa5fb97270f57067797224cee0429f2Kostya Serebryany CHECK((uintptr_t)&rl >= start && (uintptr_t)&rl < end); 249c549dd7b5fa5fb97270f57067797224cee0429f2Kostya Serebryany 250c549dd7b5fa5fb97270f57067797224cee0429f2Kostya Serebryany // Get stacksize from rlimit, but clip it so that it does not overlap 251c549dd7b5fa5fb97270f57067797224cee0429f2Kostya Serebryany // with other mappings. 252c549dd7b5fa5fb97270f57067797224cee0429f2Kostya Serebryany size_t stacksize = rl.rlim_cur; 253c549dd7b5fa5fb97270f57067797224cee0429f2Kostya Serebryany if (stacksize > end - prev_end) 254c549dd7b5fa5fb97270f57067797224cee0429f2Kostya Serebryany stacksize = end - prev_end; 255c549dd7b5fa5fb97270f57067797224cee0429f2Kostya Serebryany if (stacksize > kMaxThreadStackSize) 256c549dd7b5fa5fb97270f57067797224cee0429f2Kostya Serebryany stacksize = kMaxThreadStackSize; 257c549dd7b5fa5fb97270f57067797224cee0429f2Kostya Serebryany stack_top_ = end; 258c549dd7b5fa5fb97270f57067797224cee0429f2Kostya Serebryany stack_bottom_ = end - stacksize; 259c549dd7b5fa5fb97270f57067797224cee0429f2Kostya Serebryany CHECK(AddrIsInStack((uintptr_t)&rl)); 260c549dd7b5fa5fb97270f57067797224cee0429f2Kostya Serebryany return; 261c549dd7b5fa5fb97270f57067797224cee0429f2Kostya Serebryany } 262c549dd7b5fa5fb97270f57067797224cee0429f2Kostya Serebryany pthread_attr_t attr; 263c549dd7b5fa5fb97270f57067797224cee0429f2Kostya Serebryany CHECK(pthread_getattr_np(pthread_self(), &attr) == 0); 264c549dd7b5fa5fb97270f57067797224cee0429f2Kostya Serebryany size_t stacksize = 0; 265c549dd7b5fa5fb97270f57067797224cee0429f2Kostya Serebryany void *stackaddr = NULL; 266c549dd7b5fa5fb97270f57067797224cee0429f2Kostya Serebryany pthread_attr_getstack(&attr, &stackaddr, &stacksize); 267c549dd7b5fa5fb97270f57067797224cee0429f2Kostya Serebryany pthread_attr_destroy(&attr); 268c549dd7b5fa5fb97270f57067797224cee0429f2Kostya Serebryany 269c549dd7b5fa5fb97270f57067797224cee0429f2Kostya Serebryany stack_top_ = (uintptr_t)stackaddr + stacksize; 270c549dd7b5fa5fb97270f57067797224cee0429f2Kostya Serebryany stack_bottom_ = (uintptr_t)stackaddr; 271c549dd7b5fa5fb97270f57067797224cee0429f2Kostya Serebryany // When running with unlimited stack size, we still want to set some limit. 272c549dd7b5fa5fb97270f57067797224cee0429f2Kostya Serebryany // The unlimited stack size is caused by 'ulimit -s unlimited'. 273c549dd7b5fa5fb97270f57067797224cee0429f2Kostya Serebryany // Also, for some reason, GNU make spawns subrocesses with unlimited stack. 274c549dd7b5fa5fb97270f57067797224cee0429f2Kostya Serebryany if (stacksize > kMaxThreadStackSize) { 275c549dd7b5fa5fb97270f57067797224cee0429f2Kostya Serebryany stack_bottom_ = stack_top_ - kMaxThreadStackSize; 276c549dd7b5fa5fb97270f57067797224cee0429f2Kostya Serebryany } 277c549dd7b5fa5fb97270f57067797224cee0429f2Kostya Serebryany CHECK(AddrIsInStack((uintptr_t)&attr)); 278c549dd7b5fa5fb97270f57067797224cee0429f2Kostya Serebryany} 279c549dd7b5fa5fb97270f57067797224cee0429f2Kostya Serebryany 280d55f5f8c413622db4bd28b5cca9bfeb4d61564e0Kostya SerebryanyAsanLock::AsanLock(LinkerInitialized) { 281d55f5f8c413622db4bd28b5cca9bfeb4d61564e0Kostya Serebryany // We assume that pthread_mutex_t initialized to all zeroes is a valid 282d55f5f8c413622db4bd28b5cca9bfeb4d61564e0Kostya Serebryany // unlocked mutex. We can not use PTHREAD_MUTEX_INITIALIZER as it triggers 283d55f5f8c413622db4bd28b5cca9bfeb4d61564e0Kostya Serebryany // a gcc warning: 284d55f5f8c413622db4bd28b5cca9bfeb4d61564e0Kostya Serebryany // extended initializer lists only available with -std=c++0x or -std=gnu++0x 285d55f5f8c413622db4bd28b5cca9bfeb4d61564e0Kostya Serebryany} 286d55f5f8c413622db4bd28b5cca9bfeb4d61564e0Kostya Serebryany 287d55f5f8c413622db4bd28b5cca9bfeb4d61564e0Kostya Serebryanyvoid AsanLock::Lock() { 288d55f5f8c413622db4bd28b5cca9bfeb4d61564e0Kostya Serebryany CHECK(sizeof(pthread_mutex_t) <= sizeof(opaque_storage_)); 289d55f5f8c413622db4bd28b5cca9bfeb4d61564e0Kostya Serebryany pthread_mutex_lock((pthread_mutex_t*)&opaque_storage_); 290d55f5f8c413622db4bd28b5cca9bfeb4d61564e0Kostya Serebryany CHECK(!owner_); 291d55f5f8c413622db4bd28b5cca9bfeb4d61564e0Kostya Serebryany owner_ = (uintptr_t)pthread_self(); 292d55f5f8c413622db4bd28b5cca9bfeb4d61564e0Kostya Serebryany} 293d55f5f8c413622db4bd28b5cca9bfeb4d61564e0Kostya Serebryany 294d55f5f8c413622db4bd28b5cca9bfeb4d61564e0Kostya Serebryanyvoid AsanLock::Unlock() { 295d55f5f8c413622db4bd28b5cca9bfeb4d61564e0Kostya Serebryany CHECK(owner_ == (uintptr_t)pthread_self()); 296d55f5f8c413622db4bd28b5cca9bfeb4d61564e0Kostya Serebryany owner_ = 0; 297d55f5f8c413622db4bd28b5cca9bfeb4d61564e0Kostya Serebryany pthread_mutex_unlock((pthread_mutex_t*)&opaque_storage_); 298d55f5f8c413622db4bd28b5cca9bfeb4d61564e0Kostya Serebryany} 299d55f5f8c413622db4bd28b5cca9bfeb4d61564e0Kostya Serebryany 3001e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany} // namespace __asan 301d6567c5166412f6acdde851e767c26f332d51d3dKostya Serebryany 302d6567c5166412f6acdde851e767c26f332d51d3dKostya Serebryany#endif // __linux__ 303