asan_linux.cc revision 24e13723f8477d8c42ab8b2a7f4f69fc089842f1
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
15#include "sanitizer_common/sanitizer_platform.h"
16#if SANITIZER_LINUX
17
18#include "asan_interceptors.h"
19#include "asan_internal.h"
20#include "asan_thread.h"
21#include "asan_thread_registry.h"
22#include "sanitizer_common/sanitizer_libc.h"
23#include "sanitizer_common/sanitizer_procmaps.h"
24
25#include <sys/time.h>
26#include <sys/resource.h>
27#include <sys/mman.h>
28#include <sys/syscall.h>
29#include <sys/types.h>
30#include <fcntl.h>
31#include <pthread.h>
32#include <stdio.h>
33#include <unistd.h>
34#include <unwind.h>
35
36#if !SANITIZER_ANDROID
37// FIXME: where to get ucontext on Android?
38#include <sys/ucontext.h>
39#endif
40
41extern "C" void* _DYNAMIC;
42
43namespace __asan {
44
45void MaybeReexec() {
46  // No need to re-exec on Linux.
47}
48
49void *AsanDoesNotSupportStaticLinkage() {
50  // This will fail to link with -static.
51  return &_DYNAMIC;  // defined in link.h
52}
53
54void GetPcSpBp(void *context, uptr *pc, uptr *sp, uptr *bp) {
55#if SANITIZER_ANDROID
56  *pc = *sp = *bp = 0;
57#elif defined(__arm__)
58  ucontext_t *ucontext = (ucontext_t*)context;
59  *pc = ucontext->uc_mcontext.arm_pc;
60  *bp = ucontext->uc_mcontext.arm_fp;
61  *sp = ucontext->uc_mcontext.arm_sp;
62# elif defined(__x86_64__)
63  ucontext_t *ucontext = (ucontext_t*)context;
64  *pc = ucontext->uc_mcontext.gregs[REG_RIP];
65  *bp = ucontext->uc_mcontext.gregs[REG_RBP];
66  *sp = ucontext->uc_mcontext.gregs[REG_RSP];
67# elif defined(__i386__)
68  ucontext_t *ucontext = (ucontext_t*)context;
69  *pc = ucontext->uc_mcontext.gregs[REG_EIP];
70  *bp = ucontext->uc_mcontext.gregs[REG_EBP];
71  *sp = ucontext->uc_mcontext.gregs[REG_ESP];
72# elif defined(__powerpc__) || defined(__powerpc64__)
73  ucontext_t *ucontext = (ucontext_t*)context;
74  *pc = ucontext->uc_mcontext.regs->nip;
75  *sp = ucontext->uc_mcontext.regs->gpr[PT_R1];
76  // The powerpc{,64}-linux ABIs do not specify r31 as the frame
77  // pointer, but GCC always uses r31 when we need a frame pointer.
78  *bp = ucontext->uc_mcontext.regs->gpr[PT_R31];
79# elif defined(__sparc__)
80  ucontext_t *ucontext = (ucontext_t*)context;
81  uptr *stk_ptr;
82# if defined (__arch64__)
83  *pc = ucontext->uc_mcontext.mc_gregs[MC_PC];
84  *sp = ucontext->uc_mcontext.mc_gregs[MC_O6];
85  stk_ptr = (uptr *) (*sp + 2047);
86  *bp = stk_ptr[15];
87# else
88  *pc = ucontext->uc_mcontext.gregs[REG_PC];
89  *sp = ucontext->uc_mcontext.gregs[REG_O6];
90  stk_ptr = (uptr *) *sp;
91  *bp = stk_ptr[15];
92# endif
93#else
94# error "Unsupported arch"
95#endif
96}
97
98bool AsanInterceptsSignal(int signum) {
99  return signum == SIGSEGV && flags()->handle_segv;
100}
101
102void AsanPlatformThreadInit() {
103  // Nothing here for now.
104}
105
106void GetStackTrace(StackTrace *stack, uptr max_s, uptr pc, uptr bp, bool fast) {
107#if defined(__arm__) || \
108    defined(__powerpc__) || defined(__powerpc64__) || \
109    defined(__sparc__)
110  fast = false;
111#endif
112  if (!fast)
113    return stack->SlowUnwindStack(pc, max_s);
114  stack->size = 0;
115  stack->trace[0] = pc;
116  if (max_s > 1) {
117    stack->max_size = max_s;
118    if (!asan_inited) return;
119    if (AsanThread *t = asanThreadRegistry().GetCurrent())
120      stack->FastUnwindStack(pc, bp, t->stack_top(), t->stack_bottom());
121  }
122}
123
124#if !SANITIZER_ANDROID
125void ReadContextStack(void *context, uptr *stack, uptr *ssize) {
126  ucontext_t *ucp = (ucontext_t*)context;
127  *stack = (uptr)ucp->uc_stack.ss_sp;
128  *ssize = ucp->uc_stack.ss_size;
129}
130#else
131void ReadContextStack(void *context, uptr *stack, uptr *ssize) {
132  UNIMPLEMENTED();
133}
134#endif
135
136}  // namespace __asan
137
138#endif  // __linux__
139