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