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(¤t_); 407 CHECK_EQ(*current_++, '-'); 408 *end = ParseHex(¤t_); 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(¤t_); 428 CHECK_EQ(*current_++, ' '); 429 ParseHex(¤t_); 430 CHECK_EQ(*current_++, ':'); 431 ParseHex(¤t_); 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