Home | History | Annotate | Download | only in asan
      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_thread.h"
     19 #include "asan_thread_registry.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 
     39 extern "C" void* _DYNAMIC;
     40 
     41 namespace __asan {
     42 
     43 void MaybeReexec() {
     44   // No need to re-exec on Linux.
     45 }
     46 
     47 void *AsanDoesNotSupportStaticLinkage() {
     48   // This will fail to link with -static.
     49   return &_DYNAMIC;  // defined in link.h
     50 }
     51 
     52 void 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 # elif defined(__powerpc__) || defined(__powerpc64__)
     71   ucontext_t *ucontext = (ucontext_t*)context;
     72   *pc = ucontext->uc_mcontext.regs->nip;
     73   *sp = ucontext->uc_mcontext.regs->gpr[PT_R1];
     74   // The powerpc{,64}-linux ABIs do not specify r31 as the frame
     75   // pointer, but GCC always uses r31 when we need a frame pointer.
     76   *bp = ucontext->uc_mcontext.regs->gpr[PT_R31];
     77 # elif defined(__sparc__)
     78   ucontext_t *ucontext = (ucontext_t*)context;
     79   uptr *stk_ptr;
     80 # if defined (__arch64__)
     81   *pc = ucontext->uc_mcontext.mc_gregs[MC_PC];
     82   *sp = ucontext->uc_mcontext.mc_gregs[MC_O6];
     83   stk_ptr = (uptr *) (*sp + 2047);
     84   *bp = stk_ptr[15];
     85 # else
     86   *pc = ucontext->uc_mcontext.gregs[REG_PC];
     87   *sp = ucontext->uc_mcontext.gregs[REG_O6];
     88   stk_ptr = (uptr *) *sp;
     89   *bp = stk_ptr[15];
     90 # endif
     91 #else
     92 # error "Unsupported arch"
     93 #endif
     94 }
     95 
     96 bool AsanInterceptsSignal(int signum) {
     97   return signum == SIGSEGV && flags()->handle_segv;
     98 }
     99 
    100 void AsanPlatformThreadInit() {
    101   // Nothing here for now.
    102 }
    103 
    104 void GetStackTrace(StackTrace *stack, uptr max_s, uptr pc, uptr bp, bool fast) {
    105 #if defined(__arm__) || \
    106     defined(__powerpc__) || defined(__powerpc64__) || \
    107     defined(__sparc__)
    108   fast = false;
    109 #endif
    110   if (!fast)
    111     return stack->SlowUnwindStack(pc, max_s);
    112   stack->size = 0;
    113   stack->trace[0] = pc;
    114   if (max_s > 1) {
    115     stack->max_size = max_s;
    116     if (!asan_inited) return;
    117     if (AsanThread *t = asanThreadRegistry().GetCurrent())
    118       stack->FastUnwindStack(pc, bp, t->stack_top(), t->stack_bottom());
    119   }
    120 }
    121 
    122 #if !ASAN_ANDROID
    123 void ReadContextStack(void *context, uptr *stack, uptr *ssize) {
    124   ucontext_t *ucp = (ucontext_t*)context;
    125   *stack = (uptr)ucp->uc_stack.ss_sp;
    126   *ssize = ucp->uc_stack.ss_size;
    127 }
    128 #else
    129 void ReadContextStack(void *context, uptr *stack, uptr *ssize) {
    130   UNIMPLEMENTED();
    131 }
    132 #endif
    133 
    134 }  // namespace __asan
    135 
    136 #endif  // __linux__
    137