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