asan_linux.cc revision 9107c26bd88fc9cf44a2cd7d6967eb830ac63be3
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" 18df499b44de81fc757a789878f07fcaf19ebb0016Kostya Serebryany#include "asan_procmaps.h" 19c549dd7b5fa5fb97270f57067797224cee0429f2Kostya Serebryany#include "asan_thread.h" 201e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 21c549dd7b5fa5fb97270f57067797224cee0429f2Kostya Serebryany#include <sys/time.h> 22c549dd7b5fa5fb97270f57067797224cee0429f2Kostya Serebryany#include <sys/resource.h> 231e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany#include <sys/mman.h> 241e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany#include <sys/syscall.h> 25de496f451bce322b6cde100456591f1f50ab3477Kostya Serebryany#include <sys/types.h> 26de496f451bce322b6cde100456591f1f50ab3477Kostya Serebryany#include <fcntl.h> 27efb3fa36cf421c346e8e54054cdae4fd798edab7Kostya Serebryany#include <link.h> 28c549dd7b5fa5fb97270f57067797224cee0429f2Kostya Serebryany#include <pthread.h> 29df499b44de81fc757a789878f07fcaf19ebb0016Kostya Serebryany#include <stdio.h> 301e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany#include <unistd.h> 311e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 329107c26bd88fc9cf44a2cd7d6967eb830ac63be3Kostya Serebryany#ifndef ANDROID 339107c26bd88fc9cf44a2cd7d6967eb830ac63be3Kostya Serebryany// FIXME: where to get ucontext on Android? 349107c26bd88fc9cf44a2cd7d6967eb830ac63be3Kostya Serebryany#include <sys/ucontext.h> 359107c26bd88fc9cf44a2cd7d6967eb830ac63be3Kostya Serebryany#endif 369107c26bd88fc9cf44a2cd7d6967eb830ac63be3Kostya Serebryany 371e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanynamespace __asan { 381e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 391e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanyvoid *AsanDoesNotSupportStaticLinkage() { 401e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany // This will fail to link with -static. 41efb3fa36cf421c346e8e54054cdae4fd798edab7Kostya Serebryany return &_DYNAMIC; // defined in link.h 421e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany} 431e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 449107c26bd88fc9cf44a2cd7d6967eb830ac63be3Kostya Serebryanyvoid GetPcSpBp(void *context, uintptr_t *pc, uintptr_t *sp, uintptr_t *bp) { 459107c26bd88fc9cf44a2cd7d6967eb830ac63be3Kostya Serebryany#ifdef ANDROID 469107c26bd88fc9cf44a2cd7d6967eb830ac63be3Kostya Serebryany *pc = *sp = *bp = 0; 479107c26bd88fc9cf44a2cd7d6967eb830ac63be3Kostya Serebryany#elif defined(__arm__) 489107c26bd88fc9cf44a2cd7d6967eb830ac63be3Kostya Serebryany ucontext_t *ucontext = (ucontext_t*)context; 499107c26bd88fc9cf44a2cd7d6967eb830ac63be3Kostya Serebryany *pc = ucontext->uc_mcontext.arm_pc; 509107c26bd88fc9cf44a2cd7d6967eb830ac63be3Kostya Serebryany *bp = ucontext->uc_mcontext.arm_fp; 519107c26bd88fc9cf44a2cd7d6967eb830ac63be3Kostya Serebryany *sp = ucontext->uc_mcontext.arm_sp; 529107c26bd88fc9cf44a2cd7d6967eb830ac63be3Kostya Serebryany# elif defined(__x86_64__) 539107c26bd88fc9cf44a2cd7d6967eb830ac63be3Kostya Serebryany ucontext_t *ucontext = (ucontext_t*)context; 549107c26bd88fc9cf44a2cd7d6967eb830ac63be3Kostya Serebryany *pc = ucontext->uc_mcontext.gregs[REG_RIP]; 559107c26bd88fc9cf44a2cd7d6967eb830ac63be3Kostya Serebryany *bp = ucontext->uc_mcontext.gregs[REG_RBP]; 569107c26bd88fc9cf44a2cd7d6967eb830ac63be3Kostya Serebryany *sp = ucontext->uc_mcontext.gregs[REG_RSP]; 579107c26bd88fc9cf44a2cd7d6967eb830ac63be3Kostya Serebryany# elif defined(__i386__) 589107c26bd88fc9cf44a2cd7d6967eb830ac63be3Kostya Serebryany ucontext_t *ucontext = (ucontext_t*)context; 599107c26bd88fc9cf44a2cd7d6967eb830ac63be3Kostya Serebryany *pc = ucontext->uc_mcontext.gregs[REG_EIP]; 609107c26bd88fc9cf44a2cd7d6967eb830ac63be3Kostya Serebryany *bp = ucontext->uc_mcontext.gregs[REG_EBP]; 619107c26bd88fc9cf44a2cd7d6967eb830ac63be3Kostya Serebryany *sp = ucontext->uc_mcontext.gregs[REG_ESP]; 629107c26bd88fc9cf44a2cd7d6967eb830ac63be3Kostya Serebryany#else 639107c26bd88fc9cf44a2cd7d6967eb830ac63be3Kostya Serebryany# error "Unsupported arch" 649107c26bd88fc9cf44a2cd7d6967eb830ac63be3Kostya Serebryany#endif 659107c26bd88fc9cf44a2cd7d6967eb830ac63be3Kostya Serebryany} 669107c26bd88fc9cf44a2cd7d6967eb830ac63be3Kostya Serebryany 67a874fe5b5d67152e4e737498d532eec80940bdcdKostya Serebryanystatic void *asan_mmap(void *addr, size_t length, int prot, int flags, 681e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany int fd, uint64_t offset) { 691e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany# if __WORDSIZE == 64 70de496f451bce322b6cde100456591f1f50ab3477Kostya Serebryany return (void *)syscall(__NR_mmap, addr, length, prot, flags, fd, offset); 711e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany# else 72de496f451bce322b6cde100456591f1f50ab3477Kostya Serebryany return (void *)syscall(__NR_mmap2, addr, length, prot, flags, fd, offset); 731e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany# endif 741e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany} 751e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 76de496f451bce322b6cde100456591f1f50ab3477Kostya Serebryanyvoid *AsanMmapSomewhereOrDie(size_t size, const char *mem_type) { 77de496f451bce322b6cde100456591f1f50ab3477Kostya Serebryany size = RoundUpTo(size, kPageSize); 78de496f451bce322b6cde100456591f1f50ab3477Kostya Serebryany void *res = asan_mmap(0, size, 79de496f451bce322b6cde100456591f1f50ab3477Kostya Serebryany PROT_READ | PROT_WRITE, 80de496f451bce322b6cde100456591f1f50ab3477Kostya Serebryany MAP_PRIVATE | MAP_ANON, -1, 0); 81de496f451bce322b6cde100456591f1f50ab3477Kostya Serebryany if (res == (void*)-1) { 82de496f451bce322b6cde100456591f1f50ab3477Kostya Serebryany OutOfMemoryMessageAndDie(mem_type, size); 83de496f451bce322b6cde100456591f1f50ab3477Kostya Serebryany } 84de496f451bce322b6cde100456591f1f50ab3477Kostya Serebryany return res; 85de496f451bce322b6cde100456591f1f50ab3477Kostya Serebryany} 86de496f451bce322b6cde100456591f1f50ab3477Kostya Serebryany 87a874fe5b5d67152e4e737498d532eec80940bdcdKostya Serebryanyvoid *AsanMmapFixedNoReserve(uintptr_t fixed_addr, size_t size) { 88a874fe5b5d67152e4e737498d532eec80940bdcdKostya Serebryany return asan_mmap((void*)fixed_addr, size, 89a874fe5b5d67152e4e737498d532eec80940bdcdKostya Serebryany PROT_READ | PROT_WRITE, 90a874fe5b5d67152e4e737498d532eec80940bdcdKostya Serebryany MAP_PRIVATE | MAP_ANON | MAP_FIXED | MAP_NORESERVE, 91a874fe5b5d67152e4e737498d532eec80940bdcdKostya Serebryany 0, 0); 92a874fe5b5d67152e4e737498d532eec80940bdcdKostya Serebryany} 93a874fe5b5d67152e4e737498d532eec80940bdcdKostya Serebryany 94a874fe5b5d67152e4e737498d532eec80940bdcdKostya Serebryanyvoid *AsanMmapFixedReserve(uintptr_t fixed_addr, size_t size) { 95a874fe5b5d67152e4e737498d532eec80940bdcdKostya Serebryany return asan_mmap((void*)fixed_addr, size, 96a874fe5b5d67152e4e737498d532eec80940bdcdKostya Serebryany PROT_READ | PROT_WRITE, 97a874fe5b5d67152e4e737498d532eec80940bdcdKostya Serebryany MAP_PRIVATE | MAP_ANON | MAP_FIXED, 98a874fe5b5d67152e4e737498d532eec80940bdcdKostya Serebryany 0, 0); 99a874fe5b5d67152e4e737498d532eec80940bdcdKostya Serebryany} 100a874fe5b5d67152e4e737498d532eec80940bdcdKostya Serebryany 101a874fe5b5d67152e4e737498d532eec80940bdcdKostya Serebryanyvoid *AsanMprotect(uintptr_t fixed_addr, size_t size) { 102a874fe5b5d67152e4e737498d532eec80940bdcdKostya Serebryany return asan_mmap((void*)fixed_addr, size, 103a874fe5b5d67152e4e737498d532eec80940bdcdKostya Serebryany PROT_NONE, 104a874fe5b5d67152e4e737498d532eec80940bdcdKostya Serebryany MAP_PRIVATE | MAP_ANON | MAP_FIXED | MAP_NORESERVE, 105a874fe5b5d67152e4e737498d532eec80940bdcdKostya Serebryany 0, 0); 106a874fe5b5d67152e4e737498d532eec80940bdcdKostya Serebryany} 107a874fe5b5d67152e4e737498d532eec80940bdcdKostya Serebryany 108de496f451bce322b6cde100456591f1f50ab3477Kostya Serebryanyvoid AsanUnmapOrDie(void *addr, size_t size) { 109de496f451bce322b6cde100456591f1f50ab3477Kostya Serebryany if (!addr || !size) return; 110de496f451bce322b6cde100456591f1f50ab3477Kostya Serebryany int res = syscall(__NR_munmap, addr, size); 111de496f451bce322b6cde100456591f1f50ab3477Kostya Serebryany if (res != 0) { 112de496f451bce322b6cde100456591f1f50ab3477Kostya Serebryany Report("Failed to unmap\n"); 113de496f451bce322b6cde100456591f1f50ab3477Kostya Serebryany ASAN_DIE; 114de496f451bce322b6cde100456591f1f50ab3477Kostya Serebryany } 115de496f451bce322b6cde100456591f1f50ab3477Kostya Serebryany} 116de496f451bce322b6cde100456591f1f50ab3477Kostya Serebryany 117de496f451bce322b6cde100456591f1f50ab3477Kostya Serebryanyssize_t AsanWrite(int fd, const void *buf, size_t count) { 118de496f451bce322b6cde100456591f1f50ab3477Kostya Serebryany return (ssize_t)syscall(__NR_write, fd, buf, count); 119de496f451bce322b6cde100456591f1f50ab3477Kostya Serebryany} 120de496f451bce322b6cde100456591f1f50ab3477Kostya Serebryany 121de496f451bce322b6cde100456591f1f50ab3477Kostya Serebryanyint AsanOpenReadonly(const char* filename) { 122de496f451bce322b6cde100456591f1f50ab3477Kostya Serebryany return open(filename, O_RDONLY); 123de496f451bce322b6cde100456591f1f50ab3477Kostya Serebryany} 124de496f451bce322b6cde100456591f1f50ab3477Kostya Serebryany 125de496f451bce322b6cde100456591f1f50ab3477Kostya Serebryanyssize_t AsanRead(int fd, void *buf, size_t count) { 126de496f451bce322b6cde100456591f1f50ab3477Kostya Serebryany return (ssize_t)syscall(__NR_read, fd, buf, count); 127de496f451bce322b6cde100456591f1f50ab3477Kostya Serebryany} 128de496f451bce322b6cde100456591f1f50ab3477Kostya Serebryany 129de496f451bce322b6cde100456591f1f50ab3477Kostya Serebryanyint AsanClose(int fd) { 130de496f451bce322b6cde100456591f1f50ab3477Kostya Serebryany return close(fd); 1311e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany} 1321e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 133df499b44de81fc757a789878f07fcaf19ebb0016Kostya SerebryanyAsanProcMaps::AsanProcMaps() { 134df499b44de81fc757a789878f07fcaf19ebb0016Kostya Serebryany proc_self_maps_buff_len_ = 135df499b44de81fc757a789878f07fcaf19ebb0016Kostya Serebryany ReadFileToBuffer("/proc/self/maps", &proc_self_maps_buff_, 136df499b44de81fc757a789878f07fcaf19ebb0016Kostya Serebryany &proc_self_maps_buff_mmaped_size_, 1 << 20); 137df499b44de81fc757a789878f07fcaf19ebb0016Kostya Serebryany CHECK(proc_self_maps_buff_len_ > 0); 138df499b44de81fc757a789878f07fcaf19ebb0016Kostya Serebryany // AsanWrite(2, proc_self_maps_buff_, proc_self_maps_buff_len_); 139df499b44de81fc757a789878f07fcaf19ebb0016Kostya Serebryany Reset(); 140df499b44de81fc757a789878f07fcaf19ebb0016Kostya Serebryany} 141df499b44de81fc757a789878f07fcaf19ebb0016Kostya Serebryany 142df499b44de81fc757a789878f07fcaf19ebb0016Kostya SerebryanyAsanProcMaps::~AsanProcMaps() { 143df499b44de81fc757a789878f07fcaf19ebb0016Kostya Serebryany AsanUnmapOrDie(proc_self_maps_buff_, proc_self_maps_buff_mmaped_size_); 144df499b44de81fc757a789878f07fcaf19ebb0016Kostya Serebryany} 145df499b44de81fc757a789878f07fcaf19ebb0016Kostya Serebryany 146df499b44de81fc757a789878f07fcaf19ebb0016Kostya Serebryanyvoid AsanProcMaps::Reset() { 147df499b44de81fc757a789878f07fcaf19ebb0016Kostya Serebryany current_ = proc_self_maps_buff_; 148df499b44de81fc757a789878f07fcaf19ebb0016Kostya Serebryany} 149df499b44de81fc757a789878f07fcaf19ebb0016Kostya Serebryany 150efb3fa36cf421c346e8e54054cdae4fd798edab7Kostya Serebryanybool AsanProcMaps::Next(uintptr_t *start, uintptr_t *end, 151efb3fa36cf421c346e8e54054cdae4fd798edab7Kostya Serebryany uintptr_t *offset, char filename[], 152df499b44de81fc757a789878f07fcaf19ebb0016Kostya Serebryany size_t filename_size) { 153df499b44de81fc757a789878f07fcaf19ebb0016Kostya Serebryany char *last = proc_self_maps_buff_ + proc_self_maps_buff_len_; 154df499b44de81fc757a789878f07fcaf19ebb0016Kostya Serebryany if (current_ >= last) return false; 155df499b44de81fc757a789878f07fcaf19ebb0016Kostya Serebryany int consumed = 0; 156df499b44de81fc757a789878f07fcaf19ebb0016Kostya Serebryany char flags[10]; 157df499b44de81fc757a789878f07fcaf19ebb0016Kostya Serebryany int major, minor; 158efb3fa36cf421c346e8e54054cdae4fd798edab7Kostya Serebryany uintptr_t inode; 159df499b44de81fc757a789878f07fcaf19ebb0016Kostya Serebryany char *next_line = (char*)internal_memchr(current_, '\n', last - current_); 160df499b44de81fc757a789878f07fcaf19ebb0016Kostya Serebryany if (next_line == NULL) 161df499b44de81fc757a789878f07fcaf19ebb0016Kostya Serebryany next_line = last; 162df499b44de81fc757a789878f07fcaf19ebb0016Kostya Serebryany if (SScanf(current_, 163efb3fa36cf421c346e8e54054cdae4fd798edab7Kostya Serebryany "%lx-%lx %4s %lx %x:%x %ld %n", 164df499b44de81fc757a789878f07fcaf19ebb0016Kostya Serebryany start, end, flags, offset, &major, &minor, 165df499b44de81fc757a789878f07fcaf19ebb0016Kostya Serebryany &inode, &consumed) != 7) 166df499b44de81fc757a789878f07fcaf19ebb0016Kostya Serebryany return false; 167df499b44de81fc757a789878f07fcaf19ebb0016Kostya Serebryany current_ += consumed; 168df499b44de81fc757a789878f07fcaf19ebb0016Kostya Serebryany // Skip spaces. 169df499b44de81fc757a789878f07fcaf19ebb0016Kostya Serebryany while (current_ < next_line && *current_ == ' ') 170df499b44de81fc757a789878f07fcaf19ebb0016Kostya Serebryany current_++; 171df499b44de81fc757a789878f07fcaf19ebb0016Kostya Serebryany // Fill in the filename. 172df499b44de81fc757a789878f07fcaf19ebb0016Kostya Serebryany size_t i = 0; 173df499b44de81fc757a789878f07fcaf19ebb0016Kostya Serebryany while (current_ < next_line) { 174df499b44de81fc757a789878f07fcaf19ebb0016Kostya Serebryany if (filename && i < filename_size - 1) 175df499b44de81fc757a789878f07fcaf19ebb0016Kostya Serebryany filename[i++] = *current_; 176df499b44de81fc757a789878f07fcaf19ebb0016Kostya Serebryany current_++; 177df499b44de81fc757a789878f07fcaf19ebb0016Kostya Serebryany } 178df499b44de81fc757a789878f07fcaf19ebb0016Kostya Serebryany if (filename && i < filename_size) 179df499b44de81fc757a789878f07fcaf19ebb0016Kostya Serebryany filename[i] = 0; 180df499b44de81fc757a789878f07fcaf19ebb0016Kostya Serebryany current_ = next_line + 1; 181df499b44de81fc757a789878f07fcaf19ebb0016Kostya Serebryany return true; 182df499b44de81fc757a789878f07fcaf19ebb0016Kostya Serebryany} 183df499b44de81fc757a789878f07fcaf19ebb0016Kostya Serebryany 184efb3fa36cf421c346e8e54054cdae4fd798edab7Kostya Serebryanystruct DlIterateData { 185efb3fa36cf421c346e8e54054cdae4fd798edab7Kostya Serebryany int count; 186efb3fa36cf421c346e8e54054cdae4fd798edab7Kostya Serebryany uintptr_t addr; 187efb3fa36cf421c346e8e54054cdae4fd798edab7Kostya Serebryany uintptr_t offset; 188efb3fa36cf421c346e8e54054cdae4fd798edab7Kostya Serebryany char *filename; 189efb3fa36cf421c346e8e54054cdae4fd798edab7Kostya Serebryany size_t filename_size; 190efb3fa36cf421c346e8e54054cdae4fd798edab7Kostya Serebryany}; 191efb3fa36cf421c346e8e54054cdae4fd798edab7Kostya Serebryany 192efb3fa36cf421c346e8e54054cdae4fd798edab7Kostya Serebryanystatic int dl_iterate_phdr_callback(struct dl_phdr_info *info, 193efb3fa36cf421c346e8e54054cdae4fd798edab7Kostya Serebryany size_t size, void *raw_data) { 194efb3fa36cf421c346e8e54054cdae4fd798edab7Kostya Serebryany DlIterateData *data = (DlIterateData*)raw_data; 195efb3fa36cf421c346e8e54054cdae4fd798edab7Kostya Serebryany int count = data->count++; 196efb3fa36cf421c346e8e54054cdae4fd798edab7Kostya Serebryany if (info->dlpi_addr > data->addr) 197efb3fa36cf421c346e8e54054cdae4fd798edab7Kostya Serebryany return 0; 198efb3fa36cf421c346e8e54054cdae4fd798edab7Kostya Serebryany if (count == 0) { 199efb3fa36cf421c346e8e54054cdae4fd798edab7Kostya Serebryany // The first item (the main executable) does not have a so name, 200efb3fa36cf421c346e8e54054cdae4fd798edab7Kostya Serebryany // but we can just read it from /proc/self/exe. 201efb3fa36cf421c346e8e54054cdae4fd798edab7Kostya Serebryany ssize_t path_len = readlink("/proc/self/exe", 202efb3fa36cf421c346e8e54054cdae4fd798edab7Kostya Serebryany data->filename, data->filename_size - 1); 203efb3fa36cf421c346e8e54054cdae4fd798edab7Kostya Serebryany data->filename[path_len] = 0; 204efb3fa36cf421c346e8e54054cdae4fd798edab7Kostya Serebryany } else { 205efb3fa36cf421c346e8e54054cdae4fd798edab7Kostya Serebryany CHECK(info->dlpi_name); 206efb3fa36cf421c346e8e54054cdae4fd798edab7Kostya Serebryany real_strncpy(data->filename, info->dlpi_name, data->filename_size); 207efb3fa36cf421c346e8e54054cdae4fd798edab7Kostya Serebryany } 208efb3fa36cf421c346e8e54054cdae4fd798edab7Kostya Serebryany data->offset = data->addr - info->dlpi_addr; 209efb3fa36cf421c346e8e54054cdae4fd798edab7Kostya Serebryany return 1; 210efb3fa36cf421c346e8e54054cdae4fd798edab7Kostya Serebryany} 211efb3fa36cf421c346e8e54054cdae4fd798edab7Kostya Serebryany 212efb3fa36cf421c346e8e54054cdae4fd798edab7Kostya Serebryany// Gets the object name and the offset using dl_iterate_phdr. 213efb3fa36cf421c346e8e54054cdae4fd798edab7Kostya Serebryanybool AsanProcMaps::GetObjectNameAndOffset(uintptr_t addr, uintptr_t *offset, 214efb3fa36cf421c346e8e54054cdae4fd798edab7Kostya Serebryany char filename[], 215efb3fa36cf421c346e8e54054cdae4fd798edab7Kostya Serebryany size_t filename_size) { 216efb3fa36cf421c346e8e54054cdae4fd798edab7Kostya Serebryany DlIterateData data; 217efb3fa36cf421c346e8e54054cdae4fd798edab7Kostya Serebryany data.count = 0; 218efb3fa36cf421c346e8e54054cdae4fd798edab7Kostya Serebryany data.addr = addr; 219efb3fa36cf421c346e8e54054cdae4fd798edab7Kostya Serebryany data.filename = filename; 220efb3fa36cf421c346e8e54054cdae4fd798edab7Kostya Serebryany data.filename_size = filename_size; 221efb3fa36cf421c346e8e54054cdae4fd798edab7Kostya Serebryany if (dl_iterate_phdr(dl_iterate_phdr_callback, &data)) { 222efb3fa36cf421c346e8e54054cdae4fd798edab7Kostya Serebryany *offset = data.offset; 223efb3fa36cf421c346e8e54054cdae4fd798edab7Kostya Serebryany return true; 224efb3fa36cf421c346e8e54054cdae4fd798edab7Kostya Serebryany } 225efb3fa36cf421c346e8e54054cdae4fd798edab7Kostya Serebryany return false; 226efb3fa36cf421c346e8e54054cdae4fd798edab7Kostya Serebryany} 227efb3fa36cf421c346e8e54054cdae4fd798edab7Kostya Serebryany 228c549dd7b5fa5fb97270f57067797224cee0429f2Kostya Serebryanyvoid AsanThread::SetThreadStackTopAndBottom() { 229c549dd7b5fa5fb97270f57067797224cee0429f2Kostya Serebryany if (tid() == 0) { 230c549dd7b5fa5fb97270f57067797224cee0429f2Kostya Serebryany // This is the main thread. Libpthread may not be initialized yet. 231c549dd7b5fa5fb97270f57067797224cee0429f2Kostya Serebryany struct rlimit rl; 232c549dd7b5fa5fb97270f57067797224cee0429f2Kostya Serebryany CHECK(getrlimit(RLIMIT_STACK, &rl) == 0); 233c549dd7b5fa5fb97270f57067797224cee0429f2Kostya Serebryany 234c549dd7b5fa5fb97270f57067797224cee0429f2Kostya Serebryany // Find the mapping that contains a stack variable. 235c549dd7b5fa5fb97270f57067797224cee0429f2Kostya Serebryany AsanProcMaps proc_maps; 236efb3fa36cf421c346e8e54054cdae4fd798edab7Kostya Serebryany uintptr_t start, end, offset; 237efb3fa36cf421c346e8e54054cdae4fd798edab7Kostya Serebryany uintptr_t prev_end = 0; 238c549dd7b5fa5fb97270f57067797224cee0429f2Kostya Serebryany while (proc_maps.Next(&start, &end, &offset, NULL, 0)) { 239c549dd7b5fa5fb97270f57067797224cee0429f2Kostya Serebryany if ((uintptr_t)&rl < end) 240c549dd7b5fa5fb97270f57067797224cee0429f2Kostya Serebryany break; 241c549dd7b5fa5fb97270f57067797224cee0429f2Kostya Serebryany prev_end = end; 242c549dd7b5fa5fb97270f57067797224cee0429f2Kostya Serebryany } 243c549dd7b5fa5fb97270f57067797224cee0429f2Kostya Serebryany CHECK((uintptr_t)&rl >= start && (uintptr_t)&rl < end); 244c549dd7b5fa5fb97270f57067797224cee0429f2Kostya Serebryany 245c549dd7b5fa5fb97270f57067797224cee0429f2Kostya Serebryany // Get stacksize from rlimit, but clip it so that it does not overlap 246c549dd7b5fa5fb97270f57067797224cee0429f2Kostya Serebryany // with other mappings. 247c549dd7b5fa5fb97270f57067797224cee0429f2Kostya Serebryany size_t stacksize = rl.rlim_cur; 248c549dd7b5fa5fb97270f57067797224cee0429f2Kostya Serebryany if (stacksize > end - prev_end) 249c549dd7b5fa5fb97270f57067797224cee0429f2Kostya Serebryany stacksize = end - prev_end; 250c549dd7b5fa5fb97270f57067797224cee0429f2Kostya Serebryany if (stacksize > kMaxThreadStackSize) 251c549dd7b5fa5fb97270f57067797224cee0429f2Kostya Serebryany stacksize = kMaxThreadStackSize; 252c549dd7b5fa5fb97270f57067797224cee0429f2Kostya Serebryany stack_top_ = end; 253c549dd7b5fa5fb97270f57067797224cee0429f2Kostya Serebryany stack_bottom_ = end - stacksize; 254c549dd7b5fa5fb97270f57067797224cee0429f2Kostya Serebryany CHECK(AddrIsInStack((uintptr_t)&rl)); 255c549dd7b5fa5fb97270f57067797224cee0429f2Kostya Serebryany return; 256c549dd7b5fa5fb97270f57067797224cee0429f2Kostya Serebryany } 257c549dd7b5fa5fb97270f57067797224cee0429f2Kostya Serebryany pthread_attr_t attr; 258c549dd7b5fa5fb97270f57067797224cee0429f2Kostya Serebryany CHECK(pthread_getattr_np(pthread_self(), &attr) == 0); 259c549dd7b5fa5fb97270f57067797224cee0429f2Kostya Serebryany size_t stacksize = 0; 260c549dd7b5fa5fb97270f57067797224cee0429f2Kostya Serebryany void *stackaddr = NULL; 261c549dd7b5fa5fb97270f57067797224cee0429f2Kostya Serebryany pthread_attr_getstack(&attr, &stackaddr, &stacksize); 262c549dd7b5fa5fb97270f57067797224cee0429f2Kostya Serebryany pthread_attr_destroy(&attr); 263c549dd7b5fa5fb97270f57067797224cee0429f2Kostya Serebryany 264c549dd7b5fa5fb97270f57067797224cee0429f2Kostya Serebryany stack_top_ = (uintptr_t)stackaddr + stacksize; 265c549dd7b5fa5fb97270f57067797224cee0429f2Kostya Serebryany stack_bottom_ = (uintptr_t)stackaddr; 266c549dd7b5fa5fb97270f57067797224cee0429f2Kostya Serebryany // When running with unlimited stack size, we still want to set some limit. 267c549dd7b5fa5fb97270f57067797224cee0429f2Kostya Serebryany // The unlimited stack size is caused by 'ulimit -s unlimited'. 268c549dd7b5fa5fb97270f57067797224cee0429f2Kostya Serebryany // Also, for some reason, GNU make spawns subrocesses with unlimited stack. 269c549dd7b5fa5fb97270f57067797224cee0429f2Kostya Serebryany if (stacksize > kMaxThreadStackSize) { 270c549dd7b5fa5fb97270f57067797224cee0429f2Kostya Serebryany stack_bottom_ = stack_top_ - kMaxThreadStackSize; 271c549dd7b5fa5fb97270f57067797224cee0429f2Kostya Serebryany } 272c549dd7b5fa5fb97270f57067797224cee0429f2Kostya Serebryany CHECK(AddrIsInStack((uintptr_t)&attr)); 273c549dd7b5fa5fb97270f57067797224cee0429f2Kostya Serebryany} 274c549dd7b5fa5fb97270f57067797224cee0429f2Kostya Serebryany 275ef14ff6512d7b2e20aa3206dff820b5f90285420Kostya Serebryanyvoid AsanDisableCoreDumper() { 276ef14ff6512d7b2e20aa3206dff820b5f90285420Kostya Serebryany struct rlimit nocore; 277ef14ff6512d7b2e20aa3206dff820b5f90285420Kostya Serebryany nocore.rlim_cur = 0; 278ef14ff6512d7b2e20aa3206dff820b5f90285420Kostya Serebryany nocore.rlim_max = 0; 279ef14ff6512d7b2e20aa3206dff820b5f90285420Kostya Serebryany setrlimit(RLIMIT_CORE, &nocore); 280ef14ff6512d7b2e20aa3206dff820b5f90285420Kostya Serebryany} 281c549dd7b5fa5fb97270f57067797224cee0429f2Kostya Serebryany 2821e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany} // namespace __asan 283d6567c5166412f6acdde851e767c26f332d51d3dKostya Serebryany 284d6567c5166412f6acdde851e767c26f332d51d3dKostya Serebryany#endif // __linux__ 285