asan_linux.cc revision e5931fd7d2a74fd7fb60bd8d7f644cca51a24364
1e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson//===-- asan_linux.cc -----------------------------------------------------===//
2e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson//
3e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson//                     The LLVM Compiler Infrastructure
4e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson//
5e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson// This file is distributed under the University of Illinois Open Source
6e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson// License. See LICENSE.TXT for details.
7e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson//
8e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson//===----------------------------------------------------------------------===//
9e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson//
10e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson// This file is a part of AddressSanitizer, an address sanity checker.
11e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson//
12e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson// Linux-specific details.
13e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson//===----------------------------------------------------------------------===//
14e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson#ifdef __linux__
15e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson
16e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson#include "asan_interceptors.h"
17e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson#include "asan_internal.h"
18e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson#include "asan_lock.h"
19e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson#include "asan_procmaps.h"
20e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson#include "asan_thread.h"
21e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson#include "sanitizer_common/sanitizer_libc.h"
22e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson#include "sanitizer_common/sanitizer_procmaps.h"
23e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson
24e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson#include <sys/time.h>
25e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson#include <sys/resource.h>
26e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson#include <sys/mman.h>
27e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson#include <sys/syscall.h>
28e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson#include <sys/types.h>
29e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson#include <fcntl.h>
30#include <pthread.h>
31#include <stdio.h>
32#include <unistd.h>
33#include <unwind.h>
34
35#ifndef ANDROID
36// FIXME: where to get ucontext on Android?
37#include <sys/ucontext.h>
38#endif
39
40extern "C" void* _DYNAMIC;
41
42namespace __asan {
43
44const uptr kMaxThreadStackSize = 256 * (1 << 20);  // 256M
45
46void *AsanDoesNotSupportStaticLinkage() {
47  // This will fail to link with -static.
48  return &_DYNAMIC;  // defined in link.h
49}
50
51void GetPcSpBp(void *context, uptr *pc, uptr *sp, uptr *bp) {
52#ifdef ANDROID
53  *pc = *sp = *bp = 0;
54#elif defined(__arm__)
55  ucontext_t *ucontext = (ucontext_t*)context;
56  *pc = ucontext->uc_mcontext.arm_pc;
57  *bp = ucontext->uc_mcontext.arm_fp;
58  *sp = ucontext->uc_mcontext.arm_sp;
59# elif defined(__x86_64__)
60  ucontext_t *ucontext = (ucontext_t*)context;
61  *pc = ucontext->uc_mcontext.gregs[REG_RIP];
62  *bp = ucontext->uc_mcontext.gregs[REG_RBP];
63  *sp = ucontext->uc_mcontext.gregs[REG_RSP];
64# elif defined(__i386__)
65  ucontext_t *ucontext = (ucontext_t*)context;
66  *pc = ucontext->uc_mcontext.gregs[REG_EIP];
67  *bp = ucontext->uc_mcontext.gregs[REG_EBP];
68  *sp = ucontext->uc_mcontext.gregs[REG_ESP];
69#else
70# error "Unsupported arch"
71#endif
72}
73
74bool AsanInterceptsSignal(int signum) {
75  return signum == SIGSEGV && FLAG_handle_segv;
76}
77
78void *AsanMmapFixedNoReserve(uptr fixed_addr, uptr size) {
79  return internal_mmap((void*)fixed_addr, size,
80                      PROT_READ | PROT_WRITE,
81                      MAP_PRIVATE | MAP_ANON | MAP_FIXED | MAP_NORESERVE,
82                      0, 0);
83}
84
85void *AsanMprotect(uptr fixed_addr, uptr size) {
86  return internal_mmap((void*)fixed_addr, size,
87                       PROT_NONE,
88                       MAP_PRIVATE | MAP_ANON | MAP_FIXED | MAP_NORESERVE,
89                       0, 0);
90}
91
92// Like getenv, but reads env directly from /proc and does not use libc.
93// This function should be called first inside __asan_init.
94const char* AsanGetEnv(const char* name) {
95  static char *environ;
96  static uptr len;
97  static bool inited;
98  if (!inited) {
99    inited = true;
100    uptr environ_size;
101    len = ReadFileToBuffer("/proc/self/environ",
102                           &environ, &environ_size, 1 << 26);
103  }
104  if (!environ || len == 0) return 0;
105  uptr namelen = internal_strlen(name);
106  const char *p = environ;
107  while (*p != '\0') {  // will happen at the \0\0 that terminates the buffer
108    // proc file has the format NAME=value\0NAME=value\0NAME=value\0...
109    const char* endp =
110        (char*)internal_memchr(p, '\0', len - (p - environ));
111    if (endp == 0)  // this entry isn't NUL terminated
112      return 0;
113    else if (!internal_memcmp(p, name, namelen) && p[namelen] == '=')  // Match.
114      return p + namelen + 1;  // point after =
115    p = endp + 1;
116  }
117  return 0;  // Not found.
118}
119
120AsanLock::AsanLock(LinkerInitialized) {
121  // We assume that pthread_mutex_t initialized to all zeroes is a valid
122  // unlocked mutex. We can not use PTHREAD_MUTEX_INITIALIZER as it triggers
123  // a gcc warning:
124  // extended initializer lists only available with -std=c++0x or -std=gnu++0x
125}
126
127void AsanLock::Lock() {
128  CHECK(sizeof(pthread_mutex_t) <= sizeof(opaque_storage_));
129  pthread_mutex_lock((pthread_mutex_t*)&opaque_storage_);
130  CHECK(!owner_);
131  owner_ = (uptr)pthread_self();
132}
133
134void AsanLock::Unlock() {
135  CHECK(owner_ == (uptr)pthread_self());
136  owner_ = 0;
137  pthread_mutex_unlock((pthread_mutex_t*)&opaque_storage_);
138}
139
140#ifdef __arm__
141#define UNWIND_STOP _URC_END_OF_STACK
142#define UNWIND_CONTINUE _URC_NO_REASON
143#else
144#define UNWIND_STOP _URC_NORMAL_STOP
145#define UNWIND_CONTINUE _URC_NO_REASON
146#endif
147
148uptr Unwind_GetIP(struct _Unwind_Context *ctx) {
149#ifdef __arm__
150  uptr val;
151  _Unwind_VRS_Result res = _Unwind_VRS_Get(ctx, _UVRSC_CORE,
152      15 /* r15 = PC */, _UVRSD_UINT32, &val);
153  CHECK(res == _UVRSR_OK && "_Unwind_VRS_Get failed");
154  // Clear the Thumb bit.
155  return val & ~(uptr)1;
156#else
157  return _Unwind_GetIP(ctx);
158#endif
159}
160
161_Unwind_Reason_Code Unwind_Trace(struct _Unwind_Context *ctx,
162    void *param) {
163  AsanStackTrace *b = (AsanStackTrace*)param;
164  CHECK(b->size < b->max_size);
165  uptr pc = Unwind_GetIP(ctx);
166  b->trace[b->size++] = pc;
167  if (b->size == b->max_size) return UNWIND_STOP;
168  return UNWIND_CONTINUE;
169}
170
171void AsanStackTrace::GetStackTrace(uptr max_s, uptr pc, uptr bp) {
172  size = 0;
173  trace[0] = pc;
174  if ((max_s) > 1) {
175    max_size = max_s;
176#ifdef __arm__
177    _Unwind_Backtrace(Unwind_Trace, this);
178#else
179     FastUnwindStack(pc, bp);
180#endif
181  }
182}
183
184}  // namespace __asan
185
186#endif  // __linux__
187