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