asan_linux.cc revision c3390df6670cb166119b961eb27a033fb9073496
1//===-- asan_linux.cc -----------------------------------------------------===//
2//
3//                     The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file is a part of AddressSanitizer, an address sanity checker.
11//
12// Linux-specific details.
13//===----------------------------------------------------------------------===//
14#ifdef __linux__
15
16#include "asan_interceptors.h"
17#include "asan_internal.h"
18#include "asan_lock.h"
19#include "asan_thread.h"
20#include "sanitizer_common/sanitizer_libc.h"
21#include "sanitizer_common/sanitizer_procmaps.h"
22
23#include <sys/time.h>
24#include <sys/resource.h>
25#include <sys/mman.h>
26#include <sys/syscall.h>
27#include <sys/types.h>
28#include <fcntl.h>
29#include <pthread.h>
30#include <stdio.h>
31#include <unistd.h>
32#include <unwind.h>
33
34#if !ASAN_ANDROID
35// FIXME: where to get ucontext on Android?
36#include <sys/ucontext.h>
37#endif
38
39extern "C" void* _DYNAMIC;
40
41namespace __asan {
42
43void MaybeReexec() {
44  // No need to re-exec on Linux.
45}
46
47void *AsanDoesNotSupportStaticLinkage() {
48  // This will fail to link with -static.
49  return &_DYNAMIC;  // defined in link.h
50}
51
52void GetPcSpBp(void *context, uptr *pc, uptr *sp, uptr *bp) {
53#if ASAN_ANDROID
54  *pc = *sp = *bp = 0;
55#elif defined(__arm__)
56  ucontext_t *ucontext = (ucontext_t*)context;
57  *pc = ucontext->uc_mcontext.arm_pc;
58  *bp = ucontext->uc_mcontext.arm_fp;
59  *sp = ucontext->uc_mcontext.arm_sp;
60# elif defined(__x86_64__)
61  ucontext_t *ucontext = (ucontext_t*)context;
62  *pc = ucontext->uc_mcontext.gregs[REG_RIP];
63  *bp = ucontext->uc_mcontext.gregs[REG_RBP];
64  *sp = ucontext->uc_mcontext.gregs[REG_RSP];
65# elif defined(__i386__)
66  ucontext_t *ucontext = (ucontext_t*)context;
67  *pc = ucontext->uc_mcontext.gregs[REG_EIP];
68  *bp = ucontext->uc_mcontext.gregs[REG_EBP];
69  *sp = ucontext->uc_mcontext.gregs[REG_ESP];
70#else
71# error "Unsupported arch"
72#endif
73}
74
75bool AsanInterceptsSignal(int signum) {
76  return signum == SIGSEGV && flags()->handle_segv;
77}
78
79void AsanPlatformThreadInit() {
80  // Nothing here for now.
81}
82
83AsanLock::AsanLock(LinkerInitialized) {
84  // We assume that pthread_mutex_t initialized to all zeroes is a valid
85  // unlocked mutex. We can not use PTHREAD_MUTEX_INITIALIZER as it triggers
86  // a gcc warning:
87  // extended initializer lists only available with -std=c++0x or -std=gnu++0x
88}
89
90void AsanLock::Lock() {
91  CHECK(sizeof(pthread_mutex_t) <= sizeof(opaque_storage_));
92  pthread_mutex_lock((pthread_mutex_t*)&opaque_storage_);
93  CHECK(!owner_);
94  owner_ = (uptr)pthread_self();
95}
96
97void AsanLock::Unlock() {
98  CHECK(owner_ == (uptr)pthread_self());
99  owner_ = 0;
100  pthread_mutex_unlock((pthread_mutex_t*)&opaque_storage_);
101}
102
103#ifdef __arm__
104#define UNWIND_STOP _URC_END_OF_STACK
105#define UNWIND_CONTINUE _URC_NO_REASON
106#else
107#define UNWIND_STOP _URC_NORMAL_STOP
108#define UNWIND_CONTINUE _URC_NO_REASON
109#endif
110
111uptr Unwind_GetIP(struct _Unwind_Context *ctx) {
112#ifdef __arm__
113  uptr val;
114  _Unwind_VRS_Result res = _Unwind_VRS_Get(ctx, _UVRSC_CORE,
115      15 /* r15 = PC */, _UVRSD_UINT32, &val);
116  CHECK(res == _UVRSR_OK && "_Unwind_VRS_Get failed");
117  // Clear the Thumb bit.
118  return val & ~(uptr)1;
119#else
120  return _Unwind_GetIP(ctx);
121#endif
122}
123
124_Unwind_Reason_Code Unwind_Trace(struct _Unwind_Context *ctx,
125    void *param) {
126  StackTrace *b = (StackTrace*)param;
127  CHECK(b->size < b->max_size);
128  uptr pc = Unwind_GetIP(ctx);
129  b->trace[b->size++] = pc;
130  if (b->size == b->max_size) return UNWIND_STOP;
131  return UNWIND_CONTINUE;
132}
133
134void StackTrace::GetStackTrace(uptr max_s, uptr pc, uptr bp) {
135  size = 0;
136  trace[0] = pc;
137  if ((max_s) > 1) {
138    max_size = max_s;
139#ifdef __arm__
140    _Unwind_Backtrace(Unwind_Trace, this);
141#else
142     FastUnwindStack(pc, bp);
143#endif
144  }
145}
146
147}  // namespace __asan
148
149#endif  // __linux__
150