Home | History | Annotate | Download | only in sanitizer_common
      1 //===-- sanitizer_linux_libcdep.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 shared between AddressSanitizer and ThreadSanitizer
     11 // run-time libraries and implements linux-specific functions from
     12 // sanitizer_libc.h.
     13 //===----------------------------------------------------------------------===//
     14 
     15 #include "sanitizer_platform.h"
     16 #if SANITIZER_LINUX
     17 
     18 #include "sanitizer_common.h"
     19 #include "sanitizer_procmaps.h"
     20 #include "sanitizer_stacktrace.h"
     21 
     22 #include <dlfcn.h>
     23 #include <pthread.h>
     24 #include <sys/prctl.h>
     25 #include <sys/resource.h>
     26 #include <unwind.h>
     27 
     28 namespace __sanitizer {
     29 
     30 void GetThreadStackTopAndBottom(bool at_initialization, uptr *stack_top,
     31                                 uptr *stack_bottom) {
     32   static const uptr kMaxThreadStackSize = 1 << 30;  // 1Gb
     33   CHECK(stack_top);
     34   CHECK(stack_bottom);
     35   if (at_initialization) {
     36     // This is the main thread. Libpthread may not be initialized yet.
     37     struct rlimit rl;
     38     CHECK_EQ(getrlimit(RLIMIT_STACK, &rl), 0);
     39 
     40     // Find the mapping that contains a stack variable.
     41     MemoryMappingLayout proc_maps(/*cache_enabled*/true);
     42     uptr start, end, offset;
     43     uptr prev_end = 0;
     44     while (proc_maps.Next(&start, &end, &offset, 0, 0, /* protection */0)) {
     45       if ((uptr)&rl < end)
     46         break;
     47       prev_end = end;
     48     }
     49     CHECK((uptr)&rl >= start && (uptr)&rl < end);
     50 
     51     // Get stacksize from rlimit, but clip it so that it does not overlap
     52     // with other mappings.
     53     uptr stacksize = rl.rlim_cur;
     54     if (stacksize > end - prev_end)
     55       stacksize = end - prev_end;
     56     // When running with unlimited stack size, we still want to set some limit.
     57     // The unlimited stack size is caused by 'ulimit -s unlimited'.
     58     // Also, for some reason, GNU make spawns subprocesses with unlimited stack.
     59     if (stacksize > kMaxThreadStackSize)
     60       stacksize = kMaxThreadStackSize;
     61     *stack_top = end;
     62     *stack_bottom = end - stacksize;
     63     return;
     64   }
     65   pthread_attr_t attr;
     66   pthread_attr_init(&attr);
     67   CHECK_EQ(pthread_getattr_np(pthread_self(), &attr), 0);
     68   uptr stacksize = 0;
     69   void *stackaddr = 0;
     70   pthread_attr_getstack(&attr, &stackaddr, (size_t*)&stacksize);
     71   pthread_attr_destroy(&attr);
     72 
     73   CHECK_LE(stacksize, kMaxThreadStackSize);  // Sanity check.
     74   *stack_top = (uptr)stackaddr + stacksize;
     75   *stack_bottom = (uptr)stackaddr;
     76 }
     77 
     78 // Does not compile for Go because dlsym() requires -ldl
     79 #ifndef SANITIZER_GO
     80 bool SetEnv(const char *name, const char *value) {
     81   void *f = dlsym(RTLD_NEXT, "setenv");
     82   if (f == 0)
     83     return false;
     84   typedef int(*setenv_ft)(const char *name, const char *value, int overwrite);
     85   setenv_ft setenv_f;
     86   CHECK_EQ(sizeof(setenv_f), sizeof(f));
     87   internal_memcpy(&setenv_f, &f, sizeof(f));
     88   return setenv_f(name, value, 1) == 0;
     89 }
     90 #endif
     91 
     92 bool SanitizerSetThreadName(const char *name) {
     93 #ifdef PR_SET_NAME
     94   return 0 == prctl(PR_SET_NAME, (unsigned long)name, 0, 0, 0);  // NOLINT
     95 #else
     96   return false;
     97 #endif
     98 }
     99 
    100 bool SanitizerGetThreadName(char *name, int max_len) {
    101 #ifdef PR_GET_NAME
    102   char buff[17];
    103   if (prctl(PR_GET_NAME, (unsigned long)buff, 0, 0, 0))  // NOLINT
    104     return false;
    105   internal_strncpy(name, buff, max_len);
    106   name[max_len] = 0;
    107   return true;
    108 #else
    109   return false;
    110 #endif
    111 }
    112 
    113 #ifndef SANITIZER_GO
    114 //------------------------- SlowUnwindStack -----------------------------------
    115 #ifdef __arm__
    116 #define UNWIND_STOP _URC_END_OF_STACK
    117 #define UNWIND_CONTINUE _URC_NO_REASON
    118 #else
    119 #define UNWIND_STOP _URC_NORMAL_STOP
    120 #define UNWIND_CONTINUE _URC_NO_REASON
    121 #endif
    122 
    123 uptr Unwind_GetIP(struct _Unwind_Context *ctx) {
    124 #ifdef __arm__
    125   uptr val;
    126   _Unwind_VRS_Result res = _Unwind_VRS_Get(ctx, _UVRSC_CORE,
    127       15 /* r15 = PC */, _UVRSD_UINT32, &val);
    128   CHECK(res == _UVRSR_OK && "_Unwind_VRS_Get failed");
    129   // Clear the Thumb bit.
    130   return val & ~(uptr)1;
    131 #else
    132   return _Unwind_GetIP(ctx);
    133 #endif
    134 }
    135 
    136 _Unwind_Reason_Code Unwind_Trace(struct _Unwind_Context *ctx, void *param) {
    137   StackTrace *b = (StackTrace*)param;
    138   CHECK(b->size < b->max_size);
    139   uptr pc = Unwind_GetIP(ctx);
    140   b->trace[b->size++] = pc;
    141   if (b->size == b->max_size) return UNWIND_STOP;
    142   return UNWIND_CONTINUE;
    143 }
    144 
    145 static bool MatchPc(uptr cur_pc, uptr trace_pc) {
    146   return cur_pc - trace_pc <= 64 || trace_pc - cur_pc <= 64;
    147 }
    148 
    149 void StackTrace::SlowUnwindStack(uptr pc, uptr max_depth) {
    150   this->size = 0;
    151   this->max_size = max_depth;
    152   if (max_depth > 1) {
    153     _Unwind_Backtrace(Unwind_Trace, this);
    154     // We need to pop a few frames so that pc is on top.
    155     // trace[0] belongs to the current function so we always pop it.
    156     int to_pop = 1;
    157     /**/ if (size > 1 && MatchPc(pc, trace[1])) to_pop = 1;
    158     else if (size > 2 && MatchPc(pc, trace[2])) to_pop = 2;
    159     else if (size > 3 && MatchPc(pc, trace[3])) to_pop = 3;
    160     else if (size > 4 && MatchPc(pc, trace[4])) to_pop = 4;
    161     else if (size > 5 && MatchPc(pc, trace[5])) to_pop = 5;
    162     this->PopStackFrames(to_pop);
    163   }
    164   this->trace[0] = pc;
    165 }
    166 
    167 #endif  // !SANITIZER_GO
    168 
    169 static uptr g_tls_size;
    170 
    171 #ifdef __i386__
    172 # define DL_INTERNAL_FUNCTION __attribute__((regparm(3), stdcall))
    173 #else
    174 # define DL_INTERNAL_FUNCTION
    175 #endif
    176 
    177 void InitTlsSize() {
    178 #if !defined(SANITIZER_GO) && !SANITIZER_ANDROID
    179   typedef void (*get_tls_func)(size_t*, size_t*) DL_INTERNAL_FUNCTION;
    180   get_tls_func get_tls;
    181   void *get_tls_static_info_ptr = dlsym(RTLD_NEXT, "_dl_get_tls_static_info");
    182   CHECK_EQ(sizeof(get_tls), sizeof(get_tls_static_info_ptr));
    183   internal_memcpy(&get_tls, &get_tls_static_info_ptr,
    184                   sizeof(get_tls_static_info_ptr));
    185   CHECK_NE(get_tls, 0);
    186   size_t tls_size = 0;
    187   size_t tls_align = 0;
    188   get_tls(&tls_size, &tls_align);
    189   g_tls_size = tls_size;
    190 #endif
    191 }
    192 
    193 uptr GetTlsSize() {
    194   return g_tls_size;
    195 }
    196 
    197 #if defined(__x86_64__) || defined(__i386__)
    198 // sizeof(struct thread) from glibc.
    199 // There has been a report of this being different on glibc 2.11. We don't know
    200 // when this change happened, so 2.12 is a conservative estimate.
    201 #if __GLIBC_PREREQ(2, 12)
    202 const uptr kThreadDescriptorSize = FIRST_32_SECOND_64(1216, 2304);
    203 #else
    204 const uptr kThreadDescriptorSize = FIRST_32_SECOND_64(1168, 2304);
    205 #endif
    206 
    207 uptr ThreadDescriptorSize() {
    208   return kThreadDescriptorSize;
    209 }
    210 
    211 // The offset at which pointer to self is located in the thread descriptor.
    212 const uptr kThreadSelfOffset = FIRST_32_SECOND_64(8, 16);
    213 
    214 uptr ThreadSelfOffset() {
    215   return kThreadSelfOffset;
    216 }
    217 
    218 uptr ThreadSelf() {
    219   uptr descr_addr;
    220 #ifdef __i386__
    221   asm("mov %%gs:%c1,%0" : "=r"(descr_addr) : "i"(kThreadSelfOffset));
    222 #else
    223   asm("mov %%fs:%c1,%0" : "=r"(descr_addr) : "i"(kThreadSelfOffset));
    224 #endif
    225   return descr_addr;
    226 }
    227 #endif  // defined(__x86_64__) || defined(__i386__)
    228 
    229 void GetThreadStackAndTls(bool main, uptr *stk_addr, uptr *stk_size,
    230                           uptr *tls_addr, uptr *tls_size) {
    231 #ifndef SANITIZER_GO
    232 #if defined(__x86_64__) || defined(__i386__)
    233   *tls_addr = ThreadSelf();
    234   *tls_size = GetTlsSize();
    235   *tls_addr -= *tls_size;
    236   *tls_addr += kThreadDescriptorSize;
    237 #else
    238   *tls_addr = 0;
    239   *tls_size = 0;
    240 #endif
    241 
    242   uptr stack_top, stack_bottom;
    243   GetThreadStackTopAndBottom(main, &stack_top, &stack_bottom);
    244   *stk_addr = stack_bottom;
    245   *stk_size = stack_top - stack_bottom;
    246 
    247   if (!main) {
    248     // If stack and tls intersect, make them non-intersecting.
    249     if (*tls_addr > *stk_addr && *tls_addr < *stk_addr + *stk_size) {
    250       CHECK_GT(*tls_addr + *tls_size, *stk_addr);
    251       CHECK_LE(*tls_addr + *tls_size, *stk_addr + *stk_size);
    252       *stk_size -= *tls_size;
    253       *tls_addr = *stk_addr + *stk_size;
    254     }
    255   }
    256 #else  // SANITIZER_GO
    257   *stk_addr = 0;
    258   *stk_size = 0;
    259   *tls_addr = 0;
    260   *tls_size = 0;
    261 #endif  // SANITIZER_GO
    262 }
    263 
    264 void AdjustStackSizeLinux(void *attr_, int verbosity) {
    265   pthread_attr_t *attr = (pthread_attr_t *)attr_;
    266   uptr stackaddr = 0;
    267   size_t stacksize = 0;
    268   pthread_attr_getstack(attr, (void**)&stackaddr, &stacksize);
    269   // GLibC will return (0 - stacksize) as the stack address in the case when
    270   // stacksize is set, but stackaddr is not.
    271   bool stack_set = (stackaddr != 0) && (stackaddr + stacksize != 0);
    272   // We place a lot of tool data into TLS, account for that.
    273   const uptr minstacksize = GetTlsSize() + 128*1024;
    274   if (stacksize < minstacksize) {
    275     if (!stack_set) {
    276       if (verbosity && stacksize != 0)
    277         Printf("Sanitizer: increasing stacksize %zu->%zu\n", stacksize,
    278                minstacksize);
    279       pthread_attr_setstacksize(attr, minstacksize);
    280     } else {
    281       Printf("Sanitizer: pre-allocated stack size is insufficient: "
    282              "%zu < %zu\n", stacksize, minstacksize);
    283       Printf("Sanitizer: pthread_create is likely to fail.\n");
    284     }
    285   }
    286 }
    287 
    288 }  // namespace __sanitizer
    289 
    290 #endif  // SANITIZER_LINUX
    291