Home | History | Annotate | Download | only in sanitizer_common
      1 //===-- sanitizer_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 shared between AddressSanitizer and ThreadSanitizer
     11 // run-time libraries and implements linux-specific functions from
     12 // sanitizer_libc.h.
     13 //===----------------------------------------------------------------------===//
     14 #ifdef __linux__
     15 
     16 #include "sanitizer_common.h"
     17 #include "sanitizer_internal_defs.h"
     18 #include "sanitizer_libc.h"
     19 #include "sanitizer_linux.h"
     20 #include "sanitizer_mutex.h"
     21 #include "sanitizer_placement_new.h"
     22 #include "sanitizer_procmaps.h"
     23 #include "sanitizer_stacktrace.h"
     24 
     25 #include <dlfcn.h>
     26 #include <errno.h>
     27 #include <fcntl.h>
     28 #include <pthread.h>
     29 #include <sched.h>
     30 #include <sys/mman.h>
     31 #include <sys/ptrace.h>
     32 #include <sys/resource.h>
     33 #include <sys/stat.h>
     34 #include <sys/syscall.h>
     35 #include <sys/time.h>
     36 #include <sys/types.h>
     37 #include <sys/prctl.h>
     38 #include <unistd.h>
     39 #include <unwind.h>
     40 
     41 #if !defined(__ANDROID__) && !defined(ANDROID)
     42 #include <sys/signal.h>
     43 #endif
     44 
     45 // <linux/futex.h> is broken on some linux distributions.
     46 const int FUTEX_WAIT = 0;
     47 const int FUTEX_WAKE = 1;
     48 
     49 // Are we using 32-bit or 64-bit syscalls?
     50 // x32 (which defines __x86_64__) has SANITIZER_WORDSIZE == 32
     51 // but it still needs to use 64-bit syscalls.
     52 #if defined(__x86_64__) || SANITIZER_WORDSIZE == 64
     53 # define SANITIZER_LINUX_USES_64BIT_SYSCALLS 1
     54 #else
     55 # define SANITIZER_LINUX_USES_64BIT_SYSCALLS 0
     56 #endif
     57 
     58 namespace __sanitizer {
     59 
     60 // --------------- sanitizer_libc.h
     61 void *internal_mmap(void *addr, uptr length, int prot, int flags,
     62                     int fd, u64 offset) {
     63 #if SANITIZER_LINUX_USES_64BIT_SYSCALLS
     64   return (void *)syscall(__NR_mmap, addr, length, prot, flags, fd, offset);
     65 #else
     66   return (void *)syscall(__NR_mmap2, addr, length, prot, flags, fd, offset);
     67 #endif
     68 }
     69 
     70 int internal_munmap(void *addr, uptr length) {
     71   return syscall(__NR_munmap, addr, length);
     72 }
     73 
     74 int internal_close(fd_t fd) {
     75   return syscall(__NR_close, fd);
     76 }
     77 
     78 fd_t internal_open(const char *filename, int flags) {
     79   return syscall(__NR_open, filename, flags);
     80 }
     81 
     82 fd_t internal_open(const char *filename, int flags, u32 mode) {
     83   return syscall(__NR_open, filename, flags, mode);
     84 }
     85 
     86 fd_t OpenFile(const char *filename, bool write) {
     87   return internal_open(filename,
     88       write ? O_WRONLY | O_CREAT /*| O_CLOEXEC*/ : O_RDONLY, 0660);
     89 }
     90 
     91 uptr internal_read(fd_t fd, void *buf, uptr count) {
     92   sptr res;
     93   HANDLE_EINTR(res, (sptr)syscall(__NR_read, fd, buf, count));
     94   return res;
     95 }
     96 
     97 uptr internal_write(fd_t fd, const void *buf, uptr count) {
     98   sptr res;
     99   HANDLE_EINTR(res, (sptr)syscall(__NR_write, fd, buf, count));
    100   return res;
    101 }
    102 
    103 int internal_stat(const char *path, void *buf) {
    104 #if SANITIZER_LINUX_USES_64BIT_SYSCALLS
    105   return syscall(__NR_stat, path, buf);
    106 #else
    107   return syscall(__NR_stat64, path, buf);
    108 #endif
    109 }
    110 
    111 int internal_lstat(const char *path, void *buf) {
    112 #if SANITIZER_LINUX_USES_64BIT_SYSCALLS
    113   return syscall(__NR_lstat, path, buf);
    114 #else
    115   return syscall(__NR_lstat64, path, buf);
    116 #endif
    117 }
    118 
    119 int internal_fstat(fd_t fd, void *buf) {
    120 #if SANITIZER_LINUX_USES_64BIT_SYSCALLS
    121   return syscall(__NR_fstat, fd, buf);
    122 #else
    123   return syscall(__NR_fstat64, fd, buf);
    124 #endif
    125 }
    126 
    127 uptr internal_filesize(fd_t fd) {
    128 #if SANITIZER_LINUX_USES_64BIT_SYSCALLS
    129   struct stat st;
    130 #else
    131   struct stat64 st;
    132 #endif
    133   if (internal_fstat(fd, &st))
    134     return -1;
    135   return (uptr)st.st_size;
    136 }
    137 
    138 int internal_dup2(int oldfd, int newfd) {
    139   return syscall(__NR_dup2, oldfd, newfd);
    140 }
    141 
    142 uptr internal_readlink(const char *path, char *buf, uptr bufsize) {
    143   return (uptr)syscall(__NR_readlink, path, buf, bufsize);
    144 }
    145 
    146 int internal_sched_yield() {
    147   return syscall(__NR_sched_yield);
    148 }
    149 
    150 void internal__exit(int exitcode) {
    151   syscall(__NR_exit_group, exitcode);
    152   Die();  // Unreachable.
    153 }
    154 
    155 // ----------------- sanitizer_common.h
    156 bool FileExists(const char *filename) {
    157 #if SANITIZER_LINUX_USES_64BIT_SYSCALLS
    158   struct stat st;
    159   if (syscall(__NR_stat, filename, &st))
    160     return false;
    161 #else
    162   struct stat64 st;
    163   if (syscall(__NR_stat64, filename, &st))
    164     return false;
    165 #endif
    166   // Sanity check: filename is a regular file.
    167   return S_ISREG(st.st_mode);
    168 }
    169 
    170 uptr GetTid() {
    171   return syscall(__NR_gettid);
    172 }
    173 
    174 void GetThreadStackTopAndBottom(bool at_initialization, uptr *stack_top,
    175                                 uptr *stack_bottom) {
    176   static const uptr kMaxThreadStackSize = 256 * (1 << 20);  // 256M
    177   CHECK(stack_top);
    178   CHECK(stack_bottom);
    179   if (at_initialization) {
    180     // This is the main thread. Libpthread may not be initialized yet.
    181     struct rlimit rl;
    182     CHECK_EQ(getrlimit(RLIMIT_STACK, &rl), 0);
    183 
    184     // Find the mapping that contains a stack variable.
    185     MemoryMappingLayout proc_maps;
    186     uptr start, end, offset;
    187     uptr prev_end = 0;
    188     while (proc_maps.Next(&start, &end, &offset, 0, 0, /* protection */0)) {
    189       if ((uptr)&rl < end)
    190         break;
    191       prev_end = end;
    192     }
    193     CHECK((uptr)&rl >= start && (uptr)&rl < end);
    194 
    195     // Get stacksize from rlimit, but clip it so that it does not overlap
    196     // with other mappings.
    197     uptr stacksize = rl.rlim_cur;
    198     if (stacksize > end - prev_end)
    199       stacksize = end - prev_end;
    200     // When running with unlimited stack size, we still want to set some limit.
    201     // The unlimited stack size is caused by 'ulimit -s unlimited'.
    202     // Also, for some reason, GNU make spawns subprocesses with unlimited stack.
    203     if (stacksize > kMaxThreadStackSize)
    204       stacksize = kMaxThreadStackSize;
    205     *stack_top = end;
    206     *stack_bottom = end - stacksize;
    207     return;
    208   }
    209   pthread_attr_t attr;
    210   CHECK_EQ(pthread_getattr_np(pthread_self(), &attr), 0);
    211   uptr stacksize = 0;
    212   void *stackaddr = 0;
    213   pthread_attr_getstack(&attr, &stackaddr, (size_t*)&stacksize);
    214   pthread_attr_destroy(&attr);
    215 
    216   *stack_top = (uptr)stackaddr + stacksize;
    217   *stack_bottom = (uptr)stackaddr;
    218   CHECK(stacksize < kMaxThreadStackSize);  // Sanity check.
    219 }
    220 
    221 // Like getenv, but reads env directly from /proc and does not use libc.
    222 // This function should be called first inside __asan_init.
    223 const char *GetEnv(const char *name) {
    224   static char *environ;
    225   static uptr len;
    226   static bool inited;
    227   if (!inited) {
    228     inited = true;
    229     uptr environ_size;
    230     len = ReadFileToBuffer("/proc/self/environ",
    231                            &environ, &environ_size, 1 << 26);
    232   }
    233   if (!environ || len == 0) return 0;
    234   uptr namelen = internal_strlen(name);
    235   const char *p = environ;
    236   while (*p != '\0') {  // will happen at the \0\0 that terminates the buffer
    237     // proc file has the format NAME=value\0NAME=value\0NAME=value\0...
    238     const char* endp =
    239         (char*)internal_memchr(p, '\0', len - (p - environ));
    240     if (endp == 0)  // this entry isn't NUL terminated
    241       return 0;
    242     else if (!internal_memcmp(p, name, namelen) && p[namelen] == '=')  // Match.
    243       return p + namelen + 1;  // point after =
    244     p = endp + 1;
    245   }
    246   return 0;  // Not found.
    247 }
    248 
    249 #ifdef __GLIBC__
    250 
    251 extern "C" {
    252   extern void *__libc_stack_end;
    253 }
    254 
    255 static void GetArgsAndEnv(char ***argv, char ***envp) {
    256   uptr *stack_end = (uptr *)__libc_stack_end;
    257   int argc = *stack_end;
    258   *argv = (char**)(stack_end + 1);
    259   *envp = (char**)(stack_end + argc + 2);
    260 }
    261 
    262 #else  // __GLIBC__
    263 
    264 static void ReadNullSepFileToArray(const char *path, char ***arr,
    265                                    int arr_size) {
    266   char *buff;
    267   uptr buff_size = 0;
    268   *arr = (char **)MmapOrDie(arr_size * sizeof(char *), "NullSepFileArray");
    269   ReadFileToBuffer(path, &buff, &buff_size, 1024 * 1024);
    270   (*arr)[0] = buff;
    271   int count, i;
    272   for (count = 1, i = 1; ; i++) {
    273     if (buff[i] == 0) {
    274       if (buff[i+1] == 0) break;
    275       (*arr)[count] = &buff[i+1];
    276       CHECK_LE(count, arr_size - 1);  // FIXME: make this more flexible.
    277       count++;
    278     }
    279   }
    280   (*arr)[count] = 0;
    281 }
    282 
    283 static void GetArgsAndEnv(char ***argv, char ***envp) {
    284   static const int kMaxArgv = 2000, kMaxEnvp = 2000;
    285   ReadNullSepFileToArray("/proc/self/cmdline", argv, kMaxArgv);
    286   ReadNullSepFileToArray("/proc/self/environ", envp, kMaxEnvp);
    287 }
    288 
    289 #endif  // __GLIBC__
    290 
    291 void ReExec() {
    292   char **argv, **envp;
    293   GetArgsAndEnv(&argv, &envp);
    294   execve("/proc/self/exe", argv, envp);
    295   Printf("execve failed, errno %d\n", errno);
    296   Die();
    297 }
    298 
    299 void PrepareForSandboxing() {
    300   // Some kinds of sandboxes may forbid filesystem access, so we won't be able
    301   // to read the file mappings from /proc/self/maps. Luckily, neither the
    302   // process will be able to load additional libraries, so it's fine to use the
    303   // cached mappings.
    304   MemoryMappingLayout::CacheMemoryMappings();
    305 }
    306 
    307 // ----------------- sanitizer_procmaps.h
    308 // Linker initialized.
    309 ProcSelfMapsBuff MemoryMappingLayout::cached_proc_self_maps_;
    310 StaticSpinMutex MemoryMappingLayout::cache_lock_;  // Linker initialized.
    311 
    312 MemoryMappingLayout::MemoryMappingLayout() {
    313   proc_self_maps_.len =
    314       ReadFileToBuffer("/proc/self/maps", &proc_self_maps_.data,
    315                        &proc_self_maps_.mmaped_size, 1 << 26);
    316   if (proc_self_maps_.mmaped_size == 0) {
    317     LoadFromCache();
    318     CHECK_GT(proc_self_maps_.len, 0);
    319   }
    320   // internal_write(2, proc_self_maps_.data, proc_self_maps_.len);
    321   Reset();
    322   // FIXME: in the future we may want to cache the mappings on demand only.
    323   CacheMemoryMappings();
    324 }
    325 
    326 MemoryMappingLayout::~MemoryMappingLayout() {
    327   // Only unmap the buffer if it is different from the cached one. Otherwise
    328   // it will be unmapped when the cache is refreshed.
    329   if (proc_self_maps_.data != cached_proc_self_maps_.data) {
    330     UnmapOrDie(proc_self_maps_.data, proc_self_maps_.mmaped_size);
    331   }
    332 }
    333 
    334 void MemoryMappingLayout::Reset() {
    335   current_ = proc_self_maps_.data;
    336 }
    337 
    338 // static
    339 void MemoryMappingLayout::CacheMemoryMappings() {
    340   SpinMutexLock l(&cache_lock_);
    341   // Don't invalidate the cache if the mappings are unavailable.
    342   ProcSelfMapsBuff old_proc_self_maps;
    343   old_proc_self_maps = cached_proc_self_maps_;
    344   cached_proc_self_maps_.len =
    345       ReadFileToBuffer("/proc/self/maps", &cached_proc_self_maps_.data,
    346                        &cached_proc_self_maps_.mmaped_size, 1 << 26);
    347   if (cached_proc_self_maps_.mmaped_size == 0) {
    348     cached_proc_self_maps_ = old_proc_self_maps;
    349   } else {
    350     if (old_proc_self_maps.mmaped_size) {
    351       UnmapOrDie(old_proc_self_maps.data,
    352                  old_proc_self_maps.mmaped_size);
    353     }
    354   }
    355 }
    356 
    357 void MemoryMappingLayout::LoadFromCache() {
    358   SpinMutexLock l(&cache_lock_);
    359   if (cached_proc_self_maps_.data) {
    360     proc_self_maps_ = cached_proc_self_maps_;
    361   }
    362 }
    363 
    364 // Parse a hex value in str and update str.
    365 static uptr ParseHex(char **str) {
    366   uptr x = 0;
    367   char *s;
    368   for (s = *str; ; s++) {
    369     char c = *s;
    370     uptr v = 0;
    371     if (c >= '0' && c <= '9')
    372       v = c - '0';
    373     else if (c >= 'a' && c <= 'f')
    374       v = c - 'a' + 10;
    375     else if (c >= 'A' && c <= 'F')
    376       v = c - 'A' + 10;
    377     else
    378       break;
    379     x = x * 16 + v;
    380   }
    381   *str = s;
    382   return x;
    383 }
    384 
    385 static bool IsOneOf(char c, char c1, char c2) {
    386   return c == c1 || c == c2;
    387 }
    388 
    389 static bool IsDecimal(char c) {
    390   return c >= '0' && c <= '9';
    391 }
    392 
    393 bool MemoryMappingLayout::Next(uptr *start, uptr *end, uptr *offset,
    394                                char filename[], uptr filename_size,
    395                                uptr *protection) {
    396   char *last = proc_self_maps_.data + proc_self_maps_.len;
    397   if (current_ >= last) return false;
    398   uptr dummy;
    399   if (!start) start = &dummy;
    400   if (!end) end = &dummy;
    401   if (!offset) offset = &dummy;
    402   char *next_line = (char*)internal_memchr(current_, '\n', last - current_);
    403   if (next_line == 0)
    404     next_line = last;
    405   // Example: 08048000-08056000 r-xp 00000000 03:0c 64593   /foo/bar
    406   *start = ParseHex(&current_);
    407   CHECK_EQ(*current_++, '-');
    408   *end = ParseHex(&current_);
    409   CHECK_EQ(*current_++, ' ');
    410   uptr local_protection = 0;
    411   CHECK(IsOneOf(*current_, '-', 'r'));
    412   if (*current_++ == 'r')
    413     local_protection |= kProtectionRead;
    414   CHECK(IsOneOf(*current_, '-', 'w'));
    415   if (*current_++ == 'w')
    416     local_protection |= kProtectionWrite;
    417   CHECK(IsOneOf(*current_, '-', 'x'));
    418   if (*current_++ == 'x')
    419     local_protection |= kProtectionExecute;
    420   CHECK(IsOneOf(*current_, 's', 'p'));
    421   if (*current_++ == 's')
    422     local_protection |= kProtectionShared;
    423   if (protection) {
    424     *protection = local_protection;
    425   }
    426   CHECK_EQ(*current_++, ' ');
    427   *offset = ParseHex(&current_);
    428   CHECK_EQ(*current_++, ' ');
    429   ParseHex(&current_);
    430   CHECK_EQ(*current_++, ':');
    431   ParseHex(&current_);
    432   CHECK_EQ(*current_++, ' ');
    433   while (IsDecimal(*current_))
    434     current_++;
    435   CHECK_EQ(*current_++, ' ');
    436   // Skip spaces.
    437   while (current_ < next_line && *current_ == ' ')
    438     current_++;
    439   // Fill in the filename.
    440   uptr i = 0;
    441   while (current_ < next_line) {
    442     if (filename && i < filename_size - 1)
    443       filename[i++] = *current_;
    444     current_++;
    445   }
    446   if (filename && i < filename_size)
    447     filename[i] = 0;
    448   current_ = next_line + 1;
    449   return true;
    450 }
    451 
    452 // Gets the object name and the offset by walking MemoryMappingLayout.
    453 bool MemoryMappingLayout::GetObjectNameAndOffset(uptr addr, uptr *offset,
    454                                                  char filename[],
    455                                                  uptr filename_size,
    456                                                  uptr *protection) {
    457   return IterateForObjectNameAndOffset(addr, offset, filename, filename_size,
    458                                        protection);
    459 }
    460 
    461 bool SanitizerSetThreadName(const char *name) {
    462 #ifdef PR_SET_NAME
    463   return 0 == prctl(PR_SET_NAME, (unsigned long)name, 0, 0, 0);  // NOLINT
    464 #else
    465   return false;
    466 #endif
    467 }
    468 
    469 bool SanitizerGetThreadName(char *name, int max_len) {
    470 #ifdef PR_GET_NAME
    471   char buff[17];
    472   if (prctl(PR_GET_NAME, (unsigned long)buff, 0, 0, 0))  // NOLINT
    473     return false;
    474   internal_strncpy(name, buff, max_len);
    475   name[max_len] = 0;
    476   return true;
    477 #else
    478   return false;
    479 #endif
    480 }
    481 
    482 #ifndef SANITIZER_GO
    483 //------------------------- SlowUnwindStack -----------------------------------
    484 #ifdef __arm__
    485 #define UNWIND_STOP _URC_END_OF_STACK
    486 #define UNWIND_CONTINUE _URC_NO_REASON
    487 #else
    488 #define UNWIND_STOP _URC_NORMAL_STOP
    489 #define UNWIND_CONTINUE _URC_NO_REASON
    490 #endif
    491 
    492 uptr Unwind_GetIP(struct _Unwind_Context *ctx) {
    493 #ifdef __arm__
    494   uptr val;
    495   _Unwind_VRS_Result res = _Unwind_VRS_Get(ctx, _UVRSC_CORE,
    496       15 /* r15 = PC */, _UVRSD_UINT32, &val);
    497   CHECK(res == _UVRSR_OK && "_Unwind_VRS_Get failed");
    498   // Clear the Thumb bit.
    499   return val & ~(uptr)1;
    500 #else
    501   return _Unwind_GetIP(ctx);
    502 #endif
    503 }
    504 
    505 _Unwind_Reason_Code Unwind_Trace(struct _Unwind_Context *ctx, void *param) {
    506   StackTrace *b = (StackTrace*)param;
    507   CHECK(b->size < b->max_size);
    508   uptr pc = Unwind_GetIP(ctx);
    509   b->trace[b->size++] = pc;
    510   if (b->size == b->max_size) return UNWIND_STOP;
    511   return UNWIND_CONTINUE;
    512 }
    513 
    514 static bool MatchPc(uptr cur_pc, uptr trace_pc) {
    515   return cur_pc - trace_pc <= 64 || trace_pc - cur_pc <= 64;
    516 }
    517 
    518 void StackTrace::SlowUnwindStack(uptr pc, uptr max_depth) {
    519   this->size = 0;
    520   this->max_size = max_depth;
    521   if (max_depth > 1) {
    522     _Unwind_Backtrace(Unwind_Trace, this);
    523     // We need to pop a few frames so that pc is on top.
    524     // trace[0] belongs to the current function so we always pop it.
    525     int to_pop = 1;
    526     /**/ if (size > 1 && MatchPc(pc, trace[1])) to_pop = 1;
    527     else if (size > 2 && MatchPc(pc, trace[2])) to_pop = 2;
    528     else if (size > 3 && MatchPc(pc, trace[3])) to_pop = 3;
    529     else if (size > 4 && MatchPc(pc, trace[4])) to_pop = 4;
    530     else if (size > 5 && MatchPc(pc, trace[5])) to_pop = 5;
    531     this->PopStackFrames(to_pop);
    532   }
    533   this->trace[0] = pc;
    534 }
    535 
    536 #endif  // #ifndef SANITIZER_GO
    537 
    538 enum MutexState {
    539   MtxUnlocked = 0,
    540   MtxLocked = 1,
    541   MtxSleeping = 2
    542 };
    543 
    544 BlockingMutex::BlockingMutex(LinkerInitialized) {
    545   CHECK_EQ(owner_, 0);
    546 }
    547 
    548 BlockingMutex::BlockingMutex() {
    549   internal_memset(this, 0, sizeof(*this));
    550 }
    551 
    552 void BlockingMutex::Lock() {
    553   atomic_uint32_t *m = reinterpret_cast<atomic_uint32_t *>(&opaque_storage_);
    554   if (atomic_exchange(m, MtxLocked, memory_order_acquire) == MtxUnlocked)
    555     return;
    556   while (atomic_exchange(m, MtxSleeping, memory_order_acquire) != MtxUnlocked)
    557     syscall(__NR_futex, m, FUTEX_WAIT, MtxSleeping, 0, 0, 0);
    558 }
    559 
    560 void BlockingMutex::Unlock() {
    561   atomic_uint32_t *m = reinterpret_cast<atomic_uint32_t *>(&opaque_storage_);
    562   u32 v = atomic_exchange(m, MtxUnlocked, memory_order_relaxed);
    563   CHECK_NE(v, MtxUnlocked);
    564   if (v == MtxSleeping)
    565     syscall(__NR_futex, m, FUTEX_WAKE, 1, 0, 0, 0);
    566 }
    567 
    568 void BlockingMutex::CheckLocked() {
    569   atomic_uint32_t *m = reinterpret_cast<atomic_uint32_t *>(&opaque_storage_);
    570   CHECK_NE(MtxUnlocked, atomic_load(m, memory_order_relaxed));
    571 }
    572 
    573 // ----------------- sanitizer_linux.h
    574 // The actual size of this structure is specified by d_reclen.
    575 // Note that getdents64 uses a different structure format. We only provide the
    576 // 32-bit syscall here.
    577 struct linux_dirent {
    578   unsigned long      d_ino;
    579   unsigned long      d_off;
    580   unsigned short     d_reclen;
    581   char               d_name[256];
    582 };
    583 
    584 // Syscall wrappers.
    585 long internal_ptrace(int request, int pid, void *addr, void *data) {
    586   return syscall(__NR_ptrace, request, pid, addr, data);
    587 }
    588 
    589 int internal_waitpid(int pid, int *status, int options) {
    590   return syscall(__NR_wait4, pid, status, options, NULL /* rusage */);
    591 }
    592 
    593 int internal_getppid() {
    594   return syscall(__NR_getppid);
    595 }
    596 
    597 int internal_getdents(fd_t fd, struct linux_dirent *dirp, unsigned int count) {
    598   return syscall(__NR_getdents, fd, dirp, count);
    599 }
    600 
    601 OFF_T internal_lseek(fd_t fd, OFF_T offset, int whence) {
    602   return syscall(__NR_lseek, fd, offset, whence);
    603 }
    604 
    605 int internal_prctl(int option, uptr arg2, uptr arg3, uptr arg4, uptr arg5) {
    606   return syscall(__NR_prctl, option, arg2, arg3, arg4, arg5);
    607 }
    608 
    609 int internal_sigaltstack(const struct sigaltstack *ss,
    610                          struct sigaltstack *oss) {
    611   return syscall(__NR_sigaltstack, ss, oss);
    612 }
    613 
    614 
    615 // ThreadLister implementation.
    616 ThreadLister::ThreadLister(int pid)
    617   : pid_(pid),
    618     descriptor_(-1),
    619     error_(true),
    620     entry_((linux_dirent *)buffer_),
    621     bytes_read_(0) {
    622   char task_directory_path[80];
    623   internal_snprintf(task_directory_path, sizeof(task_directory_path),
    624                     "/proc/%d/task/", pid);
    625   descriptor_ = internal_open(task_directory_path, O_RDONLY | O_DIRECTORY);
    626   if (descriptor_ < 0) {
    627     error_ = true;
    628     Report("Can't open /proc/%d/task for reading.\n", pid);
    629   } else {
    630     error_ = false;
    631   }
    632 }
    633 
    634 int ThreadLister::GetNextTID() {
    635   int tid = -1;
    636   do {
    637     if (error_)
    638       return -1;
    639     if ((char *)entry_ >= &buffer_[bytes_read_] && !GetDirectoryEntries())
    640       return -1;
    641     if (entry_->d_ino != 0 && entry_->d_name[0] >= '0' &&
    642         entry_->d_name[0] <= '9') {
    643       // Found a valid tid.
    644       tid = (int)internal_atoll(entry_->d_name);
    645     }
    646     entry_ = (struct linux_dirent *)(((char *)entry_) + entry_->d_reclen);
    647   } while (tid < 0);
    648   return tid;
    649 }
    650 
    651 void ThreadLister::Reset() {
    652   if (error_ || descriptor_ < 0)
    653     return;
    654   internal_lseek(descriptor_, 0, SEEK_SET);
    655 }
    656 
    657 ThreadLister::~ThreadLister() {
    658   if (descriptor_ >= 0)
    659     internal_close(descriptor_);
    660 }
    661 
    662 bool ThreadLister::error() { return error_; }
    663 
    664 bool ThreadLister::GetDirectoryEntries() {
    665   CHECK_GE(descriptor_, 0);
    666   CHECK_NE(error_, true);
    667   bytes_read_ = internal_getdents(descriptor_,
    668                                   (struct linux_dirent *)buffer_,
    669                                   sizeof(buffer_));
    670   if (bytes_read_ < 0) {
    671     Report("Can't read directory entries from /proc/%d/task.\n", pid_);
    672     error_ = true;
    673     return false;
    674   } else if (bytes_read_ == 0) {
    675     return false;
    676   }
    677   entry_ = (struct linux_dirent *)buffer_;
    678   return true;
    679 }
    680 
    681 static uptr g_tls_size;
    682 
    683 #ifdef __i386__
    684 # define DL_INTERNAL_FUNCTION __attribute__((regparm(3), stdcall))
    685 #else
    686 # define DL_INTERNAL_FUNCTION
    687 #endif
    688 
    689 void InitTlsSize() {
    690 #ifndef SANITIZER_GO
    691   typedef void (*get_tls_func)(size_t*, size_t*) DL_INTERNAL_FUNCTION;
    692   get_tls_func get_tls;
    693   void *get_tls_static_info_ptr = dlsym(RTLD_NEXT, "_dl_get_tls_static_info");
    694   CHECK_EQ(sizeof(get_tls), sizeof(get_tls_static_info_ptr));
    695   internal_memcpy(&get_tls, &get_tls_static_info_ptr,
    696                   sizeof(get_tls_static_info_ptr));
    697   CHECK_NE(get_tls, 0);
    698   size_t tls_size = 0;
    699   size_t tls_align = 0;
    700   get_tls(&tls_size, &tls_align);
    701   g_tls_size = tls_size;
    702 #endif
    703 }
    704 
    705 uptr GetTlsSize() {
    706   return g_tls_size;
    707 }
    708 
    709 }  // namespace __sanitizer
    710 
    711 #endif  // __linux__
    712