sanitizer_linux.cc revision 9578a3ecfc35a264ede1135033398e2a77a6cad6
1ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov//===-- sanitizer_linux.cc ------------------------------------------------===//
2ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov//
3ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov//                     The LLVM Compiler Infrastructure
4ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov//
5ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov// This file is distributed under the University of Illinois Open Source
6ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov// License. See LICENSE.TXT for details.
7ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov//
8ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov//===----------------------------------------------------------------------===//
9ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov//
10ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov// This file is shared between AddressSanitizer and ThreadSanitizer
11ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov// run-time libraries and implements linux-specific functions from
12ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov// sanitizer_libc.h.
13ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov//===----------------------------------------------------------------------===//
1424e13723f8477d8c42ab8b2a7f4f69fc089842f1Evgeniy Stepanov
1524e13723f8477d8c42ab8b2a7f4f69fc089842f1Evgeniy Stepanov#include "sanitizer_platform.h"
1624e13723f8477d8c42ab8b2a7f4f69fc089842f1Evgeniy Stepanov#if SANITIZER_LINUX
17ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov
186895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov#include "sanitizer_common.h"
1994b5036ee6ba866e1702848855b6d687d1e70afaAlexey Samsonov#include "sanitizer_internal_defs.h"
20ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov#include "sanitizer_libc.h"
216fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany#include "sanitizer_linux.h"
2293da8b6a5e0ed2ca621897504c5d06449b3d7077Alexander Potapenko#include "sanitizer_mutex.h"
23a68633fb76208137ccb807914df52758ee5ca6f0Alexey Samsonov#include "sanitizer_placement_new.h"
246895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov#include "sanitizer_procmaps.h"
25a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryany#include "sanitizer_stacktrace.h"
26ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov
2735f1c1f7d4f18097c9eca2ce5f6c34a686707829Sergey Matveev#ifdef __x86_64__
2824323de08fa8850712d56621bff29dbbbd0285a9Sergey Matveev#include <asm/prctl.h>
2935f1c1f7d4f18097c9eca2ce5f6c34a686707829Sergey Matveev#endif
30b114ed83859d8d4964ac2284584733bcd2acf4f6Evgeniy Stepanov#include <dlfcn.h>
3135a7faf1fbfac678136e79d53824672dafb7d13eAlexey Samsonov#include <errno.h>
32c5d465136b911bf925f2a631e2b79f1c03e8a1b0Alexey Samsonov#include <fcntl.h>
33e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov#include <pthread.h>
340969bcf2c936126b1f6e636b978aade8fc207437Alexey Samsonov#include <sched.h>
35ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov#include <sys/mman.h>
366fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany#include <sys/ptrace.h>
37e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov#include <sys/resource.h>
38c5d465136b911bf925f2a631e2b79f1c03e8a1b0Alexey Samsonov#include <sys/stat.h>
39ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov#include <sys/syscall.h>
40e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov#include <sys/time.h>
41ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov#include <sys/types.h>
42fa5c41eddf77a3614da0f62044ebf741d86aeab7Dmitry Vyukov#include <sys/prctl.h>
43ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov#include <unistd.h>
44a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryany#include <unwind.h>
4535a7faf1fbfac678136e79d53824672dafb7d13eAlexey Samsonov
4624e13723f8477d8c42ab8b2a7f4f69fc089842f1Evgeniy Stepanov#if !SANITIZER_ANDROID
4735a7faf1fbfac678136e79d53824672dafb7d13eAlexey Samsonov#include <sys/signal.h>
4835a7faf1fbfac678136e79d53824672dafb7d13eAlexey Samsonov#endif
49fa5c41eddf77a3614da0f62044ebf741d86aeab7Dmitry Vyukov
504bebe7bab966c82f0a8952f797ed3d490624dc62Dmitry Vyukov// <linux/time.h>
514bebe7bab966c82f0a8952f797ed3d490624dc62Dmitry Vyukovstruct kernel_timeval {
524bebe7bab966c82f0a8952f797ed3d490624dc62Dmitry Vyukov  long tv_sec;
534bebe7bab966c82f0a8952f797ed3d490624dc62Dmitry Vyukov  long tv_usec;
544bebe7bab966c82f0a8952f797ed3d490624dc62Dmitry Vyukov};
554bebe7bab966c82f0a8952f797ed3d490624dc62Dmitry Vyukov
56fa5c41eddf77a3614da0f62044ebf741d86aeab7Dmitry Vyukov// <linux/futex.h> is broken on some linux distributions.
57fa5c41eddf77a3614da0f62044ebf741d86aeab7Dmitry Vyukovconst int FUTEX_WAIT = 0;
58fa5c41eddf77a3614da0f62044ebf741d86aeab7Dmitry Vyukovconst int FUTEX_WAKE = 1;
59ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov
609d0dbbaf33e5c2fe280f141e30be497d62b703a8Kostya Serebryany// Are we using 32-bit or 64-bit syscalls?
615af39e50366f1aacbebc284f572f08ad1ad07357Kostya Serebryany// x32 (which defines __x86_64__) has SANITIZER_WORDSIZE == 32
6208bfe4988de493dd3e61d02759b3f19c42f8fb78Kostya Serebryany// but it still needs to use 64-bit syscalls.
635af39e50366f1aacbebc284f572f08ad1ad07357Kostya Serebryany#if defined(__x86_64__) || SANITIZER_WORDSIZE == 64
649d0dbbaf33e5c2fe280f141e30be497d62b703a8Kostya Serebryany# define SANITIZER_LINUX_USES_64BIT_SYSCALLS 1
659d0dbbaf33e5c2fe280f141e30be497d62b703a8Kostya Serebryany#else
669d0dbbaf33e5c2fe280f141e30be497d62b703a8Kostya Serebryany# define SANITIZER_LINUX_USES_64BIT_SYSCALLS 0
679d0dbbaf33e5c2fe280f141e30be497d62b703a8Kostya Serebryany#endif
689d0dbbaf33e5c2fe280f141e30be497d62b703a8Kostya Serebryany
6935f1c1f7d4f18097c9eca2ce5f6c34a686707829Sergey Matveev#ifdef __x86_64__
7024323de08fa8850712d56621bff29dbbbd0285a9Sergey Matveevextern "C" int arch_prctl(int code, __sanitizer::uptr *addr);
7135f1c1f7d4f18097c9eca2ce5f6c34a686707829Sergey Matveev#endif
7224323de08fa8850712d56621bff29dbbbd0285a9Sergey Matveev
73ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonovnamespace __sanitizer {
74ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov
759578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne#ifdef __x86_64__
769578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne#include "sanitizer_syscall_linux_x86_64.inc"
779578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne#else
789578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne#include "sanitizer_syscall_generic.inc"
799578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne#endif
809578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne
81e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov// --------------- sanitizer_libc.h
829578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourneuptr internal_mmap(void *addr, uptr length, int prot, int flags,
83ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov                    int fd, u64 offset) {
849d0dbbaf33e5c2fe280f141e30be497d62b703a8Kostya Serebryany#if SANITIZER_LINUX_USES_64BIT_SYSCALLS
859578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne  return internal_syscall(__NR_mmap, addr, length, prot, flags, fd, offset);
86ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov#else
879578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne  return internal_syscall(__NR_mmap2, addr, length, prot, flags, fd, offset);
88ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov#endif
89ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov}
90ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov
919578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourneuptr internal_munmap(void *addr, uptr length) {
929578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne  return internal_syscall(__NR_munmap, addr, length);
931f11d31faa5ed89b74f7d543b1182fe8de198be5Alexey Samsonov}
941f11d31faa5ed89b74f7d543b1182fe8de198be5Alexey Samsonov
959578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourneuptr internal_close(fd_t fd) {
969578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne  return internal_syscall(__NR_close, fd);
97a56aefd2e01940fcf88d1426f9de3d5e4b1ee203Alexey Samsonov}
98a56aefd2e01940fcf88d1426f9de3d5e4b1ee203Alexey Samsonov
999578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourneuptr internal_open(const char *filename, int flags) {
1009578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne  return internal_syscall(__NR_open, filename, flags);
101ee7cc4454421a176d23442382afd9a01d36e7ad4Alexey Samsonov}
102ee7cc4454421a176d23442382afd9a01d36e7ad4Alexey Samsonov
1039578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourneuptr internal_open(const char *filename, int flags, u32 mode) {
1049578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne  return internal_syscall(__NR_open, filename, flags, mode);
105ee7cc4454421a176d23442382afd9a01d36e7ad4Alexey Samsonov}
106ee7cc4454421a176d23442382afd9a01d36e7ad4Alexey Samsonov
1079578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourneuptr OpenFile(const char *filename, bool write) {
108ee7cc4454421a176d23442382afd9a01d36e7ad4Alexey Samsonov  return internal_open(filename,
1099b8a9c1b1ce4659457178ff4c0838ac1b35ca9dcKostya Serebryany      write ? O_WRONLY | O_CREAT /*| O_CLOEXEC*/ : O_RDONLY, 0660);
110c5d465136b911bf925f2a631e2b79f1c03e8a1b0Alexey Samsonov}
111c5d465136b911bf925f2a631e2b79f1c03e8a1b0Alexey Samsonov
112a56aefd2e01940fcf88d1426f9de3d5e4b1ee203Alexey Samsonovuptr internal_read(fd_t fd, void *buf, uptr count) {
1133334e12d33261cb8f211f2f49f28ddfa027a40c3Evgeniy Stepanov  sptr res;
1149578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne  HANDLE_EINTR(res, (sptr)internal_syscall(__NR_read, fd, buf, count));
1153334e12d33261cb8f211f2f49f28ddfa027a40c3Evgeniy Stepanov  return res;
116a56aefd2e01940fcf88d1426f9de3d5e4b1ee203Alexey Samsonov}
117a56aefd2e01940fcf88d1426f9de3d5e4b1ee203Alexey Samsonov
118a56aefd2e01940fcf88d1426f9de3d5e4b1ee203Alexey Samsonovuptr internal_write(fd_t fd, const void *buf, uptr count) {
1193334e12d33261cb8f211f2f49f28ddfa027a40c3Evgeniy Stepanov  sptr res;
1209578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne  HANDLE_EINTR(res, (sptr)internal_syscall(__NR_write, fd, buf, count));
1213334e12d33261cb8f211f2f49f28ddfa027a40c3Evgeniy Stepanov  return res;
122a56aefd2e01940fcf88d1426f9de3d5e4b1ee203Alexey Samsonov}
123a56aefd2e01940fcf88d1426f9de3d5e4b1ee203Alexey Samsonov
1242be3a283939d4fc14ad86f6cd8be34b1468f22baEvgeniy Stepanov#if !SANITIZER_LINUX_USES_64BIT_SYSCALLS
1252be3a283939d4fc14ad86f6cd8be34b1468f22baEvgeniy Stepanovstatic void stat64_to_stat(struct stat64 *in, struct stat *out) {
1262be3a283939d4fc14ad86f6cd8be34b1468f22baEvgeniy Stepanov  internal_memset(out, 0, sizeof(*out));
1272be3a283939d4fc14ad86f6cd8be34b1468f22baEvgeniy Stepanov  out->st_dev = in->st_dev;
1282be3a283939d4fc14ad86f6cd8be34b1468f22baEvgeniy Stepanov  out->st_ino = in->st_ino;
1292be3a283939d4fc14ad86f6cd8be34b1468f22baEvgeniy Stepanov  out->st_mode = in->st_mode;
1302be3a283939d4fc14ad86f6cd8be34b1468f22baEvgeniy Stepanov  out->st_nlink = in->st_nlink;
1312be3a283939d4fc14ad86f6cd8be34b1468f22baEvgeniy Stepanov  out->st_uid = in->st_uid;
1322be3a283939d4fc14ad86f6cd8be34b1468f22baEvgeniy Stepanov  out->st_gid = in->st_gid;
1332be3a283939d4fc14ad86f6cd8be34b1468f22baEvgeniy Stepanov  out->st_rdev = in->st_rdev;
1342be3a283939d4fc14ad86f6cd8be34b1468f22baEvgeniy Stepanov  out->st_size = in->st_size;
1352be3a283939d4fc14ad86f6cd8be34b1468f22baEvgeniy Stepanov  out->st_blksize = in->st_blksize;
1362be3a283939d4fc14ad86f6cd8be34b1468f22baEvgeniy Stepanov  out->st_blocks = in->st_blocks;
1372be3a283939d4fc14ad86f6cd8be34b1468f22baEvgeniy Stepanov  out->st_atime = in->st_atime;
1382be3a283939d4fc14ad86f6cd8be34b1468f22baEvgeniy Stepanov  out->st_mtime = in->st_mtime;
1392be3a283939d4fc14ad86f6cd8be34b1468f22baEvgeniy Stepanov  out->st_ctime = in->st_ctime;
1402be3a283939d4fc14ad86f6cd8be34b1468f22baEvgeniy Stepanov  out->st_ino = in->st_ino;
1412be3a283939d4fc14ad86f6cd8be34b1468f22baEvgeniy Stepanov}
1422be3a283939d4fc14ad86f6cd8be34b1468f22baEvgeniy Stepanov#endif
1432be3a283939d4fc14ad86f6cd8be34b1468f22baEvgeniy Stepanov
1449578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourneuptr internal_stat(const char *path, void *buf) {
1454c9317a7b61e136f832d2ede70f557963fd46bceAlexey Samsonov#if SANITIZER_LINUX_USES_64BIT_SYSCALLS
1469578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne  return internal_syscall(__NR_stat, path, buf);
1474c9317a7b61e136f832d2ede70f557963fd46bceAlexey Samsonov#else
1482be3a283939d4fc14ad86f6cd8be34b1468f22baEvgeniy Stepanov  struct stat64 buf64;
1499578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne  int res = internal_syscall(__NR_stat64, path, &buf64);
1502be3a283939d4fc14ad86f6cd8be34b1468f22baEvgeniy Stepanov  stat64_to_stat(&buf64, (struct stat *)buf);
1512be3a283939d4fc14ad86f6cd8be34b1468f22baEvgeniy Stepanov  return res;
1524c9317a7b61e136f832d2ede70f557963fd46bceAlexey Samsonov#endif
1534c9317a7b61e136f832d2ede70f557963fd46bceAlexey Samsonov}
1544c9317a7b61e136f832d2ede70f557963fd46bceAlexey Samsonov
1559578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourneuptr internal_lstat(const char *path, void *buf) {
1564c9317a7b61e136f832d2ede70f557963fd46bceAlexey Samsonov#if SANITIZER_LINUX_USES_64BIT_SYSCALLS
1579578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne  return internal_syscall(__NR_lstat, path, buf);
1584c9317a7b61e136f832d2ede70f557963fd46bceAlexey Samsonov#else
1592be3a283939d4fc14ad86f6cd8be34b1468f22baEvgeniy Stepanov  struct stat64 buf64;
1609578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne  int res = internal_syscall(__NR_lstat64, path, &buf64);
1612be3a283939d4fc14ad86f6cd8be34b1468f22baEvgeniy Stepanov  stat64_to_stat(&buf64, (struct stat *)buf);
1622be3a283939d4fc14ad86f6cd8be34b1468f22baEvgeniy Stepanov  return res;
1634c9317a7b61e136f832d2ede70f557963fd46bceAlexey Samsonov#endif
1644c9317a7b61e136f832d2ede70f557963fd46bceAlexey Samsonov}
1654c9317a7b61e136f832d2ede70f557963fd46bceAlexey Samsonov
1669578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourneuptr internal_fstat(fd_t fd, void *buf) {
1674c9317a7b61e136f832d2ede70f557963fd46bceAlexey Samsonov#if SANITIZER_LINUX_USES_64BIT_SYSCALLS
1689578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne  return internal_syscall(__NR_fstat, fd, buf);
1694c9317a7b61e136f832d2ede70f557963fd46bceAlexey Samsonov#else
1702be3a283939d4fc14ad86f6cd8be34b1468f22baEvgeniy Stepanov  struct stat64 buf64;
1719578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne  int res = internal_syscall(__NR_fstat64, fd, &buf64);
1722be3a283939d4fc14ad86f6cd8be34b1468f22baEvgeniy Stepanov  stat64_to_stat(&buf64, (struct stat *)buf);
1732be3a283939d4fc14ad86f6cd8be34b1468f22baEvgeniy Stepanov  return res;
1744c9317a7b61e136f832d2ede70f557963fd46bceAlexey Samsonov#endif
1754c9317a7b61e136f832d2ede70f557963fd46bceAlexey Samsonov}
1764c9317a7b61e136f832d2ede70f557963fd46bceAlexey Samsonov
1778e820fcf7aafeb8101322182d742fcf99255d972Alexey Samsonovuptr internal_filesize(fd_t fd) {
178a68633fb76208137ccb807914df52758ee5ca6f0Alexey Samsonov  struct stat st;
1794c9317a7b61e136f832d2ede70f557963fd46bceAlexey Samsonov  if (internal_fstat(fd, &st))
1804c9317a7b61e136f832d2ede70f557963fd46bceAlexey Samsonov    return -1;
1818e820fcf7aafeb8101322182d742fcf99255d972Alexey Samsonov  return (uptr)st.st_size;
1828e820fcf7aafeb8101322182d742fcf99255d972Alexey Samsonov}
1838e820fcf7aafeb8101322182d742fcf99255d972Alexey Samsonov
1849578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourneuptr internal_dup2(int oldfd, int newfd) {
1859578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne  return internal_syscall(__NR_dup2, oldfd, newfd);
1868e820fcf7aafeb8101322182d742fcf99255d972Alexey Samsonov}
1878e820fcf7aafeb8101322182d742fcf99255d972Alexey Samsonov
188d1b8f588d6b712b6ff2b3d58c73d71614f520122Alexey Samsonovuptr internal_readlink(const char *path, char *buf, uptr bufsize) {
1899578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne  return internal_syscall(__NR_readlink, path, buf, bufsize);
190d1b8f588d6b712b6ff2b3d58c73d71614f520122Alexey Samsonov}
191d1b8f588d6b712b6ff2b3d58c73d71614f520122Alexey Samsonov
1929578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourneuptr internal_unlink(const char *path) {
1939578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne  return internal_syscall(__NR_unlink, path);
1946d6ab9eeea4a99370d7ab18ce80eb96091e2cf3fDmitry Vyukov}
1956d6ab9eeea4a99370d7ab18ce80eb96091e2cf3fDmitry Vyukov
1969578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourneuptr internal_sched_yield() {
1979578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne  return internal_syscall(__NR_sched_yield);
1980969bcf2c936126b1f6e636b978aade8fc207437Alexey Samsonov}
1990969bcf2c936126b1f6e636b978aade8fc207437Alexey Samsonov
200f882247088952deed954a19d745c2dd8871e2035Alexey Samsonovvoid internal__exit(int exitcode) {
2019578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne  internal_syscall(__NR_exit_group, exitcode);
202f882247088952deed954a19d745c2dd8871e2035Alexey Samsonov  Die();  // Unreachable.
203f882247088952deed954a19d745c2dd8871e2035Alexey Samsonov}
204f882247088952deed954a19d745c2dd8871e2035Alexey Samsonov
2059578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourneuptr internal_execve(const char *filename, char *const argv[],
2069578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne                     char *const envp[]) {
2079578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne  return internal_syscall(__NR_execve, filename, argv, envp);
2089578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne}
2099578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne
210e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov// ----------------- sanitizer_common.h
21193b4cafd631b661b4b612ccdc0938f7f1e1c86d6Alexey Samsonovbool FileExists(const char *filename) {
21293b4cafd631b661b4b612ccdc0938f7f1e1c86d6Alexey Samsonov  struct stat st;
2132be3a283939d4fc14ad86f6cd8be34b1468f22baEvgeniy Stepanov  if (internal_stat(filename, &st))
21493b4cafd631b661b4b612ccdc0938f7f1e1c86d6Alexey Samsonov    return false;
21593b4cafd631b661b4b612ccdc0938f7f1e1c86d6Alexey Samsonov  // Sanity check: filename is a regular file.
21693b4cafd631b661b4b612ccdc0938f7f1e1c86d6Alexey Samsonov  return S_ISREG(st.st_mode);
21793b4cafd631b661b4b612ccdc0938f7f1e1c86d6Alexey Samsonov}
21893b4cafd631b661b4b612ccdc0938f7f1e1c86d6Alexey Samsonov
219e0023f74ea88efee329f68391b70f8adc6b21617Dmitry Vyukovuptr GetTid() {
2209578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne  return internal_syscall(__NR_gettid);
221e0023f74ea88efee329f68391b70f8adc6b21617Dmitry Vyukov}
222e0023f74ea88efee329f68391b70f8adc6b21617Dmitry Vyukov
2234bebe7bab966c82f0a8952f797ed3d490624dc62Dmitry Vyukovu64 NanoTime() {
2244bebe7bab966c82f0a8952f797ed3d490624dc62Dmitry Vyukov  kernel_timeval tv;
2259578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne  internal_syscall(__NR_gettimeofday, &tv, 0);
2264bebe7bab966c82f0a8952f797ed3d490624dc62Dmitry Vyukov  return (u64)tv.tv_sec * 1000*1000*1000 + tv.tv_usec * 1000;
2274bebe7bab966c82f0a8952f797ed3d490624dc62Dmitry Vyukov}
2284bebe7bab966c82f0a8952f797ed3d490624dc62Dmitry Vyukov
229ed996f79710f532bf231537e44d5c8c9c9d57e8dAlexey Samsonovvoid GetThreadStackTopAndBottom(bool at_initialization, uptr *stack_top,
230e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov                                uptr *stack_bottom) {
231e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov  static const uptr kMaxThreadStackSize = 256 * (1 << 20);  // 256M
232e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov  CHECK(stack_top);
233e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov  CHECK(stack_bottom);
234ed996f79710f532bf231537e44d5c8c9c9d57e8dAlexey Samsonov  if (at_initialization) {
235e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov    // This is the main thread. Libpthread may not be initialized yet.
236e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov    struct rlimit rl;
2376985085c4860bf945358f227ddba26511ae770e9Kostya Serebryany    CHECK_EQ(getrlimit(RLIMIT_STACK, &rl), 0);
238e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov
239e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov    // Find the mapping that contains a stack variable.
2409ae2883d88dd28b9c5dc862107e6e6d12a35926eAlexander Potapenko    MemoryMappingLayout proc_maps(/*cache_enabled*/true);
241e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov    uptr start, end, offset;
242e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov    uptr prev_end = 0;
24345717c9d5e39a434749ae10509111f9df1b2cdf4Alexey Samsonov    while (proc_maps.Next(&start, &end, &offset, 0, 0, /* protection */0)) {
244e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov      if ((uptr)&rl < end)
245e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov        break;
246e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov      prev_end = end;
247e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov    }
248e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov    CHECK((uptr)&rl >= start && (uptr)&rl < end);
249e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov
250e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov    // Get stacksize from rlimit, but clip it so that it does not overlap
251e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov    // with other mappings.
252e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov    uptr stacksize = rl.rlim_cur;
253e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov    if (stacksize > end - prev_end)
254e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov      stacksize = end - prev_end;
255e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov    // When running with unlimited stack size, we still want to set some limit.
256e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov    // The unlimited stack size is caused by 'ulimit -s unlimited'.
257e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov    // Also, for some reason, GNU make spawns subprocesses with unlimited stack.
258e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov    if (stacksize > kMaxThreadStackSize)
259e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov      stacksize = kMaxThreadStackSize;
260e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov    *stack_top = end;
261e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov    *stack_bottom = end - stacksize;
262e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov    return;
263e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov  }
264e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov  pthread_attr_t attr;
2656985085c4860bf945358f227ddba26511ae770e9Kostya Serebryany  CHECK_EQ(pthread_getattr_np(pthread_self(), &attr), 0);
266e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov  uptr stacksize = 0;
267e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov  void *stackaddr = 0;
268e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov  pthread_attr_getstack(&attr, &stackaddr, (size_t*)&stacksize);
269e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov  pthread_attr_destroy(&attr);
270e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov
271e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov  *stack_top = (uptr)stackaddr + stacksize;
272e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov  *stack_bottom = (uptr)stackaddr;
273e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov  CHECK(stacksize < kMaxThreadStackSize);  // Sanity check.
274e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov}
275e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov
2763dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov// Like getenv, but reads env directly from /proc and does not use libc.
2773dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov// This function should be called first inside __asan_init.
2783dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonovconst char *GetEnv(const char *name) {
2793dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov  static char *environ;
2803dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov  static uptr len;
2813dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov  static bool inited;
2823dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov  if (!inited) {
2833dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov    inited = true;
2843dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov    uptr environ_size;
2853dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov    len = ReadFileToBuffer("/proc/self/environ",
2863dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov                           &environ, &environ_size, 1 << 26);
2873dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov  }
2883dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov  if (!environ || len == 0) return 0;
2893dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov  uptr namelen = internal_strlen(name);
2903dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov  const char *p = environ;
2913dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov  while (*p != '\0') {  // will happen at the \0\0 that terminates the buffer
2923dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov    // proc file has the format NAME=value\0NAME=value\0NAME=value\0...
2933dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov    const char* endp =
2943dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov        (char*)internal_memchr(p, '\0', len - (p - environ));
2953dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov    if (endp == 0)  // this entry isn't NUL terminated
2963dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov      return 0;
2973dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov    else if (!internal_memcmp(p, name, namelen) && p[namelen] == '=')  // Match.
2983dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov      return p + namelen + 1;  // point after =
2993dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov    p = endp + 1;
3003dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov  }
3013dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov  return 0;  // Not found.
3023dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov}
3033dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov
304ff7c14f911463db91b574533f62eb847a2e08b1cAlexey Samsonov// Does not compile for Go because dlsym() requires -ldl
305ff7c14f911463db91b574533f62eb847a2e08b1cAlexey Samsonov#ifndef SANITIZER_GO
306ff7c14f911463db91b574533f62eb847a2e08b1cAlexey Samsonovbool SetEnv(const char *name, const char *value) {
307ff7c14f911463db91b574533f62eb847a2e08b1cAlexey Samsonov  void *f = dlsym(RTLD_NEXT, "setenv");
308ff7c14f911463db91b574533f62eb847a2e08b1cAlexey Samsonov  if (f == 0)
309ff7c14f911463db91b574533f62eb847a2e08b1cAlexey Samsonov    return false;
310ff7c14f911463db91b574533f62eb847a2e08b1cAlexey Samsonov  typedef int(*setenv_ft)(const char *name, const char *value, int overwrite);
311ff7c14f911463db91b574533f62eb847a2e08b1cAlexey Samsonov  setenv_ft setenv_f;
312ff7c14f911463db91b574533f62eb847a2e08b1cAlexey Samsonov  CHECK_EQ(sizeof(setenv_f), sizeof(f));
313ff7c14f911463db91b574533f62eb847a2e08b1cAlexey Samsonov  internal_memcpy(&setenv_f, &f, sizeof(f));
314ff7c14f911463db91b574533f62eb847a2e08b1cAlexey Samsonov  return setenv_f(name, value, 1) == 0;
315ff7c14f911463db91b574533f62eb847a2e08b1cAlexey Samsonov}
316ff7c14f911463db91b574533f62eb847a2e08b1cAlexey Samsonov#endif
317ff7c14f911463db91b574533f62eb847a2e08b1cAlexey Samsonov
318eab061185ec0046d447b298a1dff84f028202a3cEvgeniy Stepanov#ifdef __GLIBC__
319eab061185ec0046d447b298a1dff84f028202a3cEvgeniy Stepanov
320eab061185ec0046d447b298a1dff84f028202a3cEvgeniy Stepanovextern "C" {
321eab061185ec0046d447b298a1dff84f028202a3cEvgeniy Stepanov  extern void *__libc_stack_end;
322eab061185ec0046d447b298a1dff84f028202a3cEvgeniy Stepanov}
323eab061185ec0046d447b298a1dff84f028202a3cEvgeniy Stepanov
324eab061185ec0046d447b298a1dff84f028202a3cEvgeniy Stepanovstatic void GetArgsAndEnv(char ***argv, char ***envp) {
325eab061185ec0046d447b298a1dff84f028202a3cEvgeniy Stepanov  uptr *stack_end = (uptr *)__libc_stack_end;
326eab061185ec0046d447b298a1dff84f028202a3cEvgeniy Stepanov  int argc = *stack_end;
327eab061185ec0046d447b298a1dff84f028202a3cEvgeniy Stepanov  *argv = (char**)(stack_end + 1);
328eab061185ec0046d447b298a1dff84f028202a3cEvgeniy Stepanov  *envp = (char**)(stack_end + argc + 2);
329eab061185ec0046d447b298a1dff84f028202a3cEvgeniy Stepanov}
330eab061185ec0046d447b298a1dff84f028202a3cEvgeniy Stepanov
331eab061185ec0046d447b298a1dff84f028202a3cEvgeniy Stepanov#else  // __GLIBC__
332eab061185ec0046d447b298a1dff84f028202a3cEvgeniy Stepanov
33323709c9ad9ac7c45de288f5260403426bf932db7Peter Collingbournestatic void ReadNullSepFileToArray(const char *path, char ***arr,
33423709c9ad9ac7c45de288f5260403426bf932db7Peter Collingbourne                                   int arr_size) {
33523709c9ad9ac7c45de288f5260403426bf932db7Peter Collingbourne  char *buff;
336d7e5bb4043adf4756e6f8cfe0f5a3165b185474dAlexey Samsonov  uptr buff_size = 0;
33723709c9ad9ac7c45de288f5260403426bf932db7Peter Collingbourne  *arr = (char **)MmapOrDie(arr_size * sizeof(char *), "NullSepFileArray");
33823709c9ad9ac7c45de288f5260403426bf932db7Peter Collingbourne  ReadFileToBuffer(path, &buff, &buff_size, 1024 * 1024);
33923709c9ad9ac7c45de288f5260403426bf932db7Peter Collingbourne  (*arr)[0] = buff;
34023709c9ad9ac7c45de288f5260403426bf932db7Peter Collingbourne  int count, i;
34123709c9ad9ac7c45de288f5260403426bf932db7Peter Collingbourne  for (count = 1, i = 1; ; i++) {
342d7e5bb4043adf4756e6f8cfe0f5a3165b185474dAlexey Samsonov    if (buff[i] == 0) {
343d7e5bb4043adf4756e6f8cfe0f5a3165b185474dAlexey Samsonov      if (buff[i+1] == 0) break;
34423709c9ad9ac7c45de288f5260403426bf932db7Peter Collingbourne      (*arr)[count] = &buff[i+1];
34523709c9ad9ac7c45de288f5260403426bf932db7Peter Collingbourne      CHECK_LE(count, arr_size - 1);  // FIXME: make this more flexible.
34623709c9ad9ac7c45de288f5260403426bf932db7Peter Collingbourne      count++;
347d7e5bb4043adf4756e6f8cfe0f5a3165b185474dAlexey Samsonov    }
348d7e5bb4043adf4756e6f8cfe0f5a3165b185474dAlexey Samsonov  }
34923709c9ad9ac7c45de288f5260403426bf932db7Peter Collingbourne  (*arr)[count] = 0;
35023709c9ad9ac7c45de288f5260403426bf932db7Peter Collingbourne}
35123709c9ad9ac7c45de288f5260403426bf932db7Peter Collingbourne
352eab061185ec0046d447b298a1dff84f028202a3cEvgeniy Stepanovstatic void GetArgsAndEnv(char ***argv, char ***envp) {
3537b7801d0811e7091240ddbfdcff817791973ef6fEvgeniy Stepanov  static const int kMaxArgv = 2000, kMaxEnvp = 2000;
354eab061185ec0046d447b298a1dff84f028202a3cEvgeniy Stepanov  ReadNullSepFileToArray("/proc/self/cmdline", argv, kMaxArgv);
355eab061185ec0046d447b298a1dff84f028202a3cEvgeniy Stepanov  ReadNullSepFileToArray("/proc/self/environ", envp, kMaxEnvp);
356eab061185ec0046d447b298a1dff84f028202a3cEvgeniy Stepanov}
357eab061185ec0046d447b298a1dff84f028202a3cEvgeniy Stepanov
358eab061185ec0046d447b298a1dff84f028202a3cEvgeniy Stepanov#endif  // __GLIBC__
359eab061185ec0046d447b298a1dff84f028202a3cEvgeniy Stepanov
360eab061185ec0046d447b298a1dff84f028202a3cEvgeniy Stepanovvoid ReExec() {
36123709c9ad9ac7c45de288f5260403426bf932db7Peter Collingbourne  char **argv, **envp;
362eab061185ec0046d447b298a1dff84f028202a3cEvgeniy Stepanov  GetArgsAndEnv(&argv, &envp);
3639578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne  uptr rv = internal_execve("/proc/self/exe", argv, envp);
3649578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne  int rverrno;
3659578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne  CHECK_EQ(internal_iserror(rv, &rverrno), true);
3669578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne  Printf("execve failed, errno %d\n", rverrno);
367f35eae83757946decb312deab3f0fe155fe5d580Evgeniy Stepanov  Die();
368d7e5bb4043adf4756e6f8cfe0f5a3165b185474dAlexey Samsonov}
369d7e5bb4043adf4756e6f8cfe0f5a3165b185474dAlexey Samsonov
37025742574510cfb41b97e32f63f107fbb9b328d13Alexander Potapenkovoid PrepareForSandboxing() {
37125742574510cfb41b97e32f63f107fbb9b328d13Alexander Potapenko  // Some kinds of sandboxes may forbid filesystem access, so we won't be able
37225742574510cfb41b97e32f63f107fbb9b328d13Alexander Potapenko  // to read the file mappings from /proc/self/maps. Luckily, neither the
37325742574510cfb41b97e32f63f107fbb9b328d13Alexander Potapenko  // process will be able to load additional libraries, so it's fine to use the
37425742574510cfb41b97e32f63f107fbb9b328d13Alexander Potapenko  // cached mappings.
37525742574510cfb41b97e32f63f107fbb9b328d13Alexander Potapenko  MemoryMappingLayout::CacheMemoryMappings();
37625742574510cfb41b97e32f63f107fbb9b328d13Alexander Potapenko}
37725742574510cfb41b97e32f63f107fbb9b328d13Alexander Potapenko
378e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov// ----------------- sanitizer_procmaps.h
379286dd3f8afe6700e5dd9b0bdb7afd23121c98c12Dmitry Vyukov// Linker initialized.
380286dd3f8afe6700e5dd9b0bdb7afd23121c98c12Dmitry VyukovProcSelfMapsBuff MemoryMappingLayout::cached_proc_self_maps_;
381ad91267d45fef531c1082ab7974e4cc78aba5280Alexander PotapenkoStaticSpinMutex MemoryMappingLayout::cache_lock_;  // Linker initialized.
38293da8b6a5e0ed2ca621897504c5d06449b3d7077Alexander Potapenko
3839ae2883d88dd28b9c5dc862107e6e6d12a35926eAlexander PotapenkoMemoryMappingLayout::MemoryMappingLayout(bool cache_enabled) {
384ad91267d45fef531c1082ab7974e4cc78aba5280Alexander Potapenko  proc_self_maps_.len =
385ad91267d45fef531c1082ab7974e4cc78aba5280Alexander Potapenko      ReadFileToBuffer("/proc/self/maps", &proc_self_maps_.data,
386ad91267d45fef531c1082ab7974e4cc78aba5280Alexander Potapenko                       &proc_self_maps_.mmaped_size, 1 << 26);
3879ae2883d88dd28b9c5dc862107e6e6d12a35926eAlexander Potapenko  if (cache_enabled) {
3889ae2883d88dd28b9c5dc862107e6e6d12a35926eAlexander Potapenko    if (proc_self_maps_.mmaped_size == 0) {
3899ae2883d88dd28b9c5dc862107e6e6d12a35926eAlexander Potapenko      LoadFromCache();
3909ae2883d88dd28b9c5dc862107e6e6d12a35926eAlexander Potapenko      CHECK_GT(proc_self_maps_.len, 0);
3919ae2883d88dd28b9c5dc862107e6e6d12a35926eAlexander Potapenko    }
3929ae2883d88dd28b9c5dc862107e6e6d12a35926eAlexander Potapenko  } else {
3939ae2883d88dd28b9c5dc862107e6e6d12a35926eAlexander Potapenko    CHECK_GT(proc_self_maps_.mmaped_size, 0);
39493da8b6a5e0ed2ca621897504c5d06449b3d7077Alexander Potapenko  }
3956895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov  Reset();
39693da8b6a5e0ed2ca621897504c5d06449b3d7077Alexander Potapenko  // FIXME: in the future we may want to cache the mappings on demand only.
3979ae2883d88dd28b9c5dc862107e6e6d12a35926eAlexander Potapenko  if (cache_enabled)
3989ae2883d88dd28b9c5dc862107e6e6d12a35926eAlexander Potapenko    CacheMemoryMappings();
3996895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov}
4006895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov
401e1f5dac9296df08ff83ae5fca51ce4da995b55cfAlexey SamsonovMemoryMappingLayout::~MemoryMappingLayout() {
4027385f8b8b8723064910cf9737dc929e90aeac548Alexander Potapenko  // Only unmap the buffer if it is different from the cached one. Otherwise
4037385f8b8b8723064910cf9737dc929e90aeac548Alexander Potapenko  // it will be unmapped when the cache is refreshed.
4047385f8b8b8723064910cf9737dc929e90aeac548Alexander Potapenko  if (proc_self_maps_.data != cached_proc_self_maps_.data) {
4057385f8b8b8723064910cf9737dc929e90aeac548Alexander Potapenko    UnmapOrDie(proc_self_maps_.data, proc_self_maps_.mmaped_size);
4067385f8b8b8723064910cf9737dc929e90aeac548Alexander Potapenko  }
4076895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov}
4086895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov
409e1f5dac9296df08ff83ae5fca51ce4da995b55cfAlexey Samsonovvoid MemoryMappingLayout::Reset() {
410ad91267d45fef531c1082ab7974e4cc78aba5280Alexander Potapenko  current_ = proc_self_maps_.data;
4116895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov}
4126895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov
41393da8b6a5e0ed2ca621897504c5d06449b3d7077Alexander Potapenko// static
41493da8b6a5e0ed2ca621897504c5d06449b3d7077Alexander Potapenkovoid MemoryMappingLayout::CacheMemoryMappings() {
41593da8b6a5e0ed2ca621897504c5d06449b3d7077Alexander Potapenko  SpinMutexLock l(&cache_lock_);
41693da8b6a5e0ed2ca621897504c5d06449b3d7077Alexander Potapenko  // Don't invalidate the cache if the mappings are unavailable.
417ad91267d45fef531c1082ab7974e4cc78aba5280Alexander Potapenko  ProcSelfMapsBuff old_proc_self_maps;
418ad91267d45fef531c1082ab7974e4cc78aba5280Alexander Potapenko  old_proc_self_maps = cached_proc_self_maps_;
419ad91267d45fef531c1082ab7974e4cc78aba5280Alexander Potapenko  cached_proc_self_maps_.len =
420ad91267d45fef531c1082ab7974e4cc78aba5280Alexander Potapenko      ReadFileToBuffer("/proc/self/maps", &cached_proc_self_maps_.data,
421ad91267d45fef531c1082ab7974e4cc78aba5280Alexander Potapenko                       &cached_proc_self_maps_.mmaped_size, 1 << 26);
422ad91267d45fef531c1082ab7974e4cc78aba5280Alexander Potapenko  if (cached_proc_self_maps_.mmaped_size == 0) {
423ad91267d45fef531c1082ab7974e4cc78aba5280Alexander Potapenko    cached_proc_self_maps_ = old_proc_self_maps;
42493da8b6a5e0ed2ca621897504c5d06449b3d7077Alexander Potapenko  } else {
425ad91267d45fef531c1082ab7974e4cc78aba5280Alexander Potapenko    if (old_proc_self_maps.mmaped_size) {
426ad91267d45fef531c1082ab7974e4cc78aba5280Alexander Potapenko      UnmapOrDie(old_proc_self_maps.data,
427ad91267d45fef531c1082ab7974e4cc78aba5280Alexander Potapenko                 old_proc_self_maps.mmaped_size);
42893da8b6a5e0ed2ca621897504c5d06449b3d7077Alexander Potapenko    }
42993da8b6a5e0ed2ca621897504c5d06449b3d7077Alexander Potapenko  }
43093da8b6a5e0ed2ca621897504c5d06449b3d7077Alexander Potapenko}
43193da8b6a5e0ed2ca621897504c5d06449b3d7077Alexander Potapenko
43293da8b6a5e0ed2ca621897504c5d06449b3d7077Alexander Potapenkovoid MemoryMappingLayout::LoadFromCache() {
43393da8b6a5e0ed2ca621897504c5d06449b3d7077Alexander Potapenko  SpinMutexLock l(&cache_lock_);
434ad91267d45fef531c1082ab7974e4cc78aba5280Alexander Potapenko  if (cached_proc_self_maps_.data) {
435286dd3f8afe6700e5dd9b0bdb7afd23121c98c12Dmitry Vyukov    proc_self_maps_ = cached_proc_self_maps_;
43693da8b6a5e0ed2ca621897504c5d06449b3d7077Alexander Potapenko  }
43793da8b6a5e0ed2ca621897504c5d06449b3d7077Alexander Potapenko}
43893da8b6a5e0ed2ca621897504c5d06449b3d7077Alexander Potapenko
439a4e4744778e6b3067f5cf223cf28bb586c1ecf67Kostya Serebryany// Parse a hex value in str and update str.
440a4e4744778e6b3067f5cf223cf28bb586c1ecf67Kostya Serebryanystatic uptr ParseHex(char **str) {
441a4e4744778e6b3067f5cf223cf28bb586c1ecf67Kostya Serebryany  uptr x = 0;
442a4e4744778e6b3067f5cf223cf28bb586c1ecf67Kostya Serebryany  char *s;
443a4e4744778e6b3067f5cf223cf28bb586c1ecf67Kostya Serebryany  for (s = *str; ; s++) {
444a4e4744778e6b3067f5cf223cf28bb586c1ecf67Kostya Serebryany    char c = *s;
445a4e4744778e6b3067f5cf223cf28bb586c1ecf67Kostya Serebryany    uptr v = 0;
446a4e4744778e6b3067f5cf223cf28bb586c1ecf67Kostya Serebryany    if (c >= '0' && c <= '9')
447a4e4744778e6b3067f5cf223cf28bb586c1ecf67Kostya Serebryany      v = c - '0';
448a4e4744778e6b3067f5cf223cf28bb586c1ecf67Kostya Serebryany    else if (c >= 'a' && c <= 'f')
449a4e4744778e6b3067f5cf223cf28bb586c1ecf67Kostya Serebryany      v = c - 'a' + 10;
450a4e4744778e6b3067f5cf223cf28bb586c1ecf67Kostya Serebryany    else if (c >= 'A' && c <= 'F')
451a4e4744778e6b3067f5cf223cf28bb586c1ecf67Kostya Serebryany      v = c - 'A' + 10;
452a4e4744778e6b3067f5cf223cf28bb586c1ecf67Kostya Serebryany    else
453a4e4744778e6b3067f5cf223cf28bb586c1ecf67Kostya Serebryany      break;
454a4e4744778e6b3067f5cf223cf28bb586c1ecf67Kostya Serebryany    x = x * 16 + v;
455a4e4744778e6b3067f5cf223cf28bb586c1ecf67Kostya Serebryany  }
456a4e4744778e6b3067f5cf223cf28bb586c1ecf67Kostya Serebryany  *str = s;
457a4e4744778e6b3067f5cf223cf28bb586c1ecf67Kostya Serebryany  return x;
458a4e4744778e6b3067f5cf223cf28bb586c1ecf67Kostya Serebryany}
459a4e4744778e6b3067f5cf223cf28bb586c1ecf67Kostya Serebryany
460ab11e0b10d077945a6e681766b41e12ac6aeb0f0Alexey Samsonovstatic bool IsOneOf(char c, char c1, char c2) {
461a4e4744778e6b3067f5cf223cf28bb586c1ecf67Kostya Serebryany  return c == c1 || c == c2;
462a4e4744778e6b3067f5cf223cf28bb586c1ecf67Kostya Serebryany}
463a4e4744778e6b3067f5cf223cf28bb586c1ecf67Kostya Serebryany
464a4e4744778e6b3067f5cf223cf28bb586c1ecf67Kostya Serebryanystatic bool IsDecimal(char c) {
465a4e4744778e6b3067f5cf223cf28bb586c1ecf67Kostya Serebryany  return c >= '0' && c <= '9';
466a4e4744778e6b3067f5cf223cf28bb586c1ecf67Kostya Serebryany}
467a4e4744778e6b3067f5cf223cf28bb586c1ecf67Kostya Serebryany
468e1f5dac9296df08ff83ae5fca51ce4da995b55cfAlexey Samsonovbool MemoryMappingLayout::Next(uptr *start, uptr *end, uptr *offset,
46945717c9d5e39a434749ae10509111f9df1b2cdf4Alexey Samsonov                               char filename[], uptr filename_size,
47045717c9d5e39a434749ae10509111f9df1b2cdf4Alexey Samsonov                               uptr *protection) {
471ad91267d45fef531c1082ab7974e4cc78aba5280Alexander Potapenko  char *last = proc_self_maps_.data + proc_self_maps_.len;
4726895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov  if (current_ >= last) return false;
4736895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov  uptr dummy;
4746895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov  if (!start) start = &dummy;
4756895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov  if (!end) end = &dummy;
4766895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov  if (!offset) offset = &dummy;
4776895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov  char *next_line = (char*)internal_memchr(current_, '\n', last - current_);
4786895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov  if (next_line == 0)
4796895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov    next_line = last;
480a4e4744778e6b3067f5cf223cf28bb586c1ecf67Kostya Serebryany  // Example: 08048000-08056000 r-xp 00000000 03:0c 64593   /foo/bar
481a4e4744778e6b3067f5cf223cf28bb586c1ecf67Kostya Serebryany  *start = ParseHex(&current_);
482bb8a9511bc748d6a4fd601d713bda584ef7bb772Kostya Serebryany  CHECK_EQ(*current_++, '-');
483a4e4744778e6b3067f5cf223cf28bb586c1ecf67Kostya Serebryany  *end = ParseHex(&current_);
484bb8a9511bc748d6a4fd601d713bda584ef7bb772Kostya Serebryany  CHECK_EQ(*current_++, ' ');
48545717c9d5e39a434749ae10509111f9df1b2cdf4Alexey Samsonov  uptr local_protection = 0;
486ab11e0b10d077945a6e681766b41e12ac6aeb0f0Alexey Samsonov  CHECK(IsOneOf(*current_, '-', 'r'));
48745717c9d5e39a434749ae10509111f9df1b2cdf4Alexey Samsonov  if (*current_++ == 'r')
48845717c9d5e39a434749ae10509111f9df1b2cdf4Alexey Samsonov    local_protection |= kProtectionRead;
489ab11e0b10d077945a6e681766b41e12ac6aeb0f0Alexey Samsonov  CHECK(IsOneOf(*current_, '-', 'w'));
49045717c9d5e39a434749ae10509111f9df1b2cdf4Alexey Samsonov  if (*current_++ == 'w')
49145717c9d5e39a434749ae10509111f9df1b2cdf4Alexey Samsonov    local_protection |= kProtectionWrite;
492ab11e0b10d077945a6e681766b41e12ac6aeb0f0Alexey Samsonov  CHECK(IsOneOf(*current_, '-', 'x'));
49345717c9d5e39a434749ae10509111f9df1b2cdf4Alexey Samsonov  if (*current_++ == 'x')
49445717c9d5e39a434749ae10509111f9df1b2cdf4Alexey Samsonov    local_protection |= kProtectionExecute;
495ab11e0b10d077945a6e681766b41e12ac6aeb0f0Alexey Samsonov  CHECK(IsOneOf(*current_, 's', 'p'));
49645717c9d5e39a434749ae10509111f9df1b2cdf4Alexey Samsonov  if (*current_++ == 's')
49745717c9d5e39a434749ae10509111f9df1b2cdf4Alexey Samsonov    local_protection |= kProtectionShared;
49845717c9d5e39a434749ae10509111f9df1b2cdf4Alexey Samsonov  if (protection) {
49945717c9d5e39a434749ae10509111f9df1b2cdf4Alexey Samsonov    *protection = local_protection;
50045717c9d5e39a434749ae10509111f9df1b2cdf4Alexey Samsonov  }
501bb8a9511bc748d6a4fd601d713bda584ef7bb772Kostya Serebryany  CHECK_EQ(*current_++, ' ');
502a4e4744778e6b3067f5cf223cf28bb586c1ecf67Kostya Serebryany  *offset = ParseHex(&current_);
503bb8a9511bc748d6a4fd601d713bda584ef7bb772Kostya Serebryany  CHECK_EQ(*current_++, ' ');
504a4e4744778e6b3067f5cf223cf28bb586c1ecf67Kostya Serebryany  ParseHex(&current_);
505bb8a9511bc748d6a4fd601d713bda584ef7bb772Kostya Serebryany  CHECK_EQ(*current_++, ':');
506a4e4744778e6b3067f5cf223cf28bb586c1ecf67Kostya Serebryany  ParseHex(&current_);
507bb8a9511bc748d6a4fd601d713bda584ef7bb772Kostya Serebryany  CHECK_EQ(*current_++, ' ');
508a4e4744778e6b3067f5cf223cf28bb586c1ecf67Kostya Serebryany  while (IsDecimal(*current_))
509a4e4744778e6b3067f5cf223cf28bb586c1ecf67Kostya Serebryany    current_++;
510bb8a9511bc748d6a4fd601d713bda584ef7bb772Kostya Serebryany  CHECK_EQ(*current_++, ' ');
5116895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov  // Skip spaces.
5126895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov  while (current_ < next_line && *current_ == ' ')
5136895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov    current_++;
5146895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov  // Fill in the filename.
5156895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov  uptr i = 0;
5166895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov  while (current_ < next_line) {
5176895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov    if (filename && i < filename_size - 1)
5186895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov      filename[i++] = *current_;
5196895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov    current_++;
5206895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov  }
5216895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov  if (filename && i < filename_size)
5226895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov    filename[i] = 0;
5236895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov  current_ = next_line + 1;
5246895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov  return true;
5256895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov}
5266895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov
527e1f5dac9296df08ff83ae5fca51ce4da995b55cfAlexey Samsonov// Gets the object name and the offset by walking MemoryMappingLayout.
528e1f5dac9296df08ff83ae5fca51ce4da995b55cfAlexey Samsonovbool MemoryMappingLayout::GetObjectNameAndOffset(uptr addr, uptr *offset,
529e1f5dac9296df08ff83ae5fca51ce4da995b55cfAlexey Samsonov                                                 char filename[],
53045717c9d5e39a434749ae10509111f9df1b2cdf4Alexey Samsonov                                                 uptr filename_size,
53145717c9d5e39a434749ae10509111f9df1b2cdf4Alexey Samsonov                                                 uptr *protection) {
53245717c9d5e39a434749ae10509111f9df1b2cdf4Alexey Samsonov  return IterateForObjectNameAndOffset(addr, offset, filename, filename_size,
53345717c9d5e39a434749ae10509111f9df1b2cdf4Alexey Samsonov                                       protection);
5346895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov}
5356895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov
536dddb18b7be36fe1843c8b98a8d9d7614aef5ce8dKostya Serebryanybool SanitizerSetThreadName(const char *name) {
537b10a5621daa804f3a2b18fbe75d5fed2a4aeadd3Kostya Serebryany#ifdef PR_SET_NAME
5381ec519c604021162de8bdb8d433fbad1c5033200Dmitry Vyukov  return 0 == prctl(PR_SET_NAME, (unsigned long)name, 0, 0, 0);  // NOLINT
539b10a5621daa804f3a2b18fbe75d5fed2a4aeadd3Kostya Serebryany#else
540b10a5621daa804f3a2b18fbe75d5fed2a4aeadd3Kostya Serebryany  return false;
541b10a5621daa804f3a2b18fbe75d5fed2a4aeadd3Kostya Serebryany#endif
542dddb18b7be36fe1843c8b98a8d9d7614aef5ce8dKostya Serebryany}
543dddb18b7be36fe1843c8b98a8d9d7614aef5ce8dKostya Serebryany
544dddb18b7be36fe1843c8b98a8d9d7614aef5ce8dKostya Serebryanybool SanitizerGetThreadName(char *name, int max_len) {
545b10a5621daa804f3a2b18fbe75d5fed2a4aeadd3Kostya Serebryany#ifdef PR_GET_NAME
546dddb18b7be36fe1843c8b98a8d9d7614aef5ce8dKostya Serebryany  char buff[17];
5471ec519c604021162de8bdb8d433fbad1c5033200Dmitry Vyukov  if (prctl(PR_GET_NAME, (unsigned long)buff, 0, 0, 0))  // NOLINT
548dddb18b7be36fe1843c8b98a8d9d7614aef5ce8dKostya Serebryany    return false;
549dddb18b7be36fe1843c8b98a8d9d7614aef5ce8dKostya Serebryany  internal_strncpy(name, buff, max_len);
550dddb18b7be36fe1843c8b98a8d9d7614aef5ce8dKostya Serebryany  name[max_len] = 0;
551dddb18b7be36fe1843c8b98a8d9d7614aef5ce8dKostya Serebryany  return true;
552b10a5621daa804f3a2b18fbe75d5fed2a4aeadd3Kostya Serebryany#else
553b10a5621daa804f3a2b18fbe75d5fed2a4aeadd3Kostya Serebryany  return false;
554b10a5621daa804f3a2b18fbe75d5fed2a4aeadd3Kostya Serebryany#endif
555dddb18b7be36fe1843c8b98a8d9d7614aef5ce8dKostya Serebryany}
556dddb18b7be36fe1843c8b98a8d9d7614aef5ce8dKostya Serebryany
5574fce4495502a3668cc4e99164ffcaea92e534d48Dmitry Vyukov#ifndef SANITIZER_GO
558a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryany//------------------------- SlowUnwindStack -----------------------------------
559a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryany#ifdef __arm__
560a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryany#define UNWIND_STOP _URC_END_OF_STACK
561a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryany#define UNWIND_CONTINUE _URC_NO_REASON
562a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryany#else
563a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryany#define UNWIND_STOP _URC_NORMAL_STOP
564a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryany#define UNWIND_CONTINUE _URC_NO_REASON
565a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryany#endif
566a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryany
567a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryanyuptr Unwind_GetIP(struct _Unwind_Context *ctx) {
568a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryany#ifdef __arm__
569a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryany  uptr val;
570a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryany  _Unwind_VRS_Result res = _Unwind_VRS_Get(ctx, _UVRSC_CORE,
571a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryany      15 /* r15 = PC */, _UVRSD_UINT32, &val);
572a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryany  CHECK(res == _UVRSR_OK && "_Unwind_VRS_Get failed");
573a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryany  // Clear the Thumb bit.
574a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryany  return val & ~(uptr)1;
575a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryany#else
576a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryany  return _Unwind_GetIP(ctx);
577a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryany#endif
578a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryany}
579a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryany
580a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryany_Unwind_Reason_Code Unwind_Trace(struct _Unwind_Context *ctx, void *param) {
581a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryany  StackTrace *b = (StackTrace*)param;
582a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryany  CHECK(b->size < b->max_size);
583a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryany  uptr pc = Unwind_GetIP(ctx);
584a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryany  b->trace[b->size++] = pc;
585a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryany  if (b->size == b->max_size) return UNWIND_STOP;
586a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryany  return UNWIND_CONTINUE;
587a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryany}
588a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryany
58949d616ec42ab420ce3ebcbe846b21e3729adf5acKostya Serebryanystatic bool MatchPc(uptr cur_pc, uptr trace_pc) {
5905e10443518154a9d68d299ef65a0a99ed42193b7Kostya Serebryany  return cur_pc - trace_pc <= 64 || trace_pc - cur_pc <= 64;
59149d616ec42ab420ce3ebcbe846b21e3729adf5acKostya Serebryany}
59249d616ec42ab420ce3ebcbe846b21e3729adf5acKostya Serebryany
59349d616ec42ab420ce3ebcbe846b21e3729adf5acKostya Serebryanyvoid StackTrace::SlowUnwindStack(uptr pc, uptr max_depth) {
594a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryany  this->size = 0;
595a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryany  this->max_size = max_depth;
596a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryany  if (max_depth > 1) {
597a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryany    _Unwind_Backtrace(Unwind_Trace, this);
5985e10443518154a9d68d299ef65a0a99ed42193b7Kostya Serebryany    // We need to pop a few frames so that pc is on top.
5995e10443518154a9d68d299ef65a0a99ed42193b7Kostya Serebryany    // trace[0] belongs to the current function so we always pop it.
60049d616ec42ab420ce3ebcbe846b21e3729adf5acKostya Serebryany    int to_pop = 1;
6015e10443518154a9d68d299ef65a0a99ed42193b7Kostya Serebryany    /**/ if (size > 1 && MatchPc(pc, trace[1])) to_pop = 1;
6025e10443518154a9d68d299ef65a0a99ed42193b7Kostya Serebryany    else if (size > 2 && MatchPc(pc, trace[2])) to_pop = 2;
6035e10443518154a9d68d299ef65a0a99ed42193b7Kostya Serebryany    else if (size > 3 && MatchPc(pc, trace[3])) to_pop = 3;
6045e10443518154a9d68d299ef65a0a99ed42193b7Kostya Serebryany    else if (size > 4 && MatchPc(pc, trace[4])) to_pop = 4;
6055e10443518154a9d68d299ef65a0a99ed42193b7Kostya Serebryany    else if (size > 5 && MatchPc(pc, trace[5])) to_pop = 5;
60649d616ec42ab420ce3ebcbe846b21e3729adf5acKostya Serebryany    this->PopStackFrames(to_pop);
607a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryany  }
60849d616ec42ab420ce3ebcbe846b21e3729adf5acKostya Serebryany  this->trace[0] = pc;
609a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryany}
610a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryany
6114fce4495502a3668cc4e99164ffcaea92e534d48Dmitry Vyukov#endif  // #ifndef SANITIZER_GO
6124fce4495502a3668cc4e99164ffcaea92e534d48Dmitry Vyukov
613f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukovenum MutexState {
614f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov  MtxUnlocked = 0,
615f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov  MtxLocked = 1,
616f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov  MtxSleeping = 2
617f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov};
618f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov
619f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry VyukovBlockingMutex::BlockingMutex(LinkerInitialized) {
620d164ed175a61529589938b3db3cab076a19acf67Dmitry Vyukov  CHECK_EQ(owner_, 0);
621f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov}
622f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov
62393af5948d3e0c5bdc396f432dd0ae782f499c449Alexey SamsonovBlockingMutex::BlockingMutex() {
62493af5948d3e0c5bdc396f432dd0ae782f499c449Alexey Samsonov  internal_memset(this, 0, sizeof(*this));
62593af5948d3e0c5bdc396f432dd0ae782f499c449Alexey Samsonov}
62693af5948d3e0c5bdc396f432dd0ae782f499c449Alexey Samsonov
627f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukovvoid BlockingMutex::Lock() {
628f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov  atomic_uint32_t *m = reinterpret_cast<atomic_uint32_t *>(&opaque_storage_);
629f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov  if (atomic_exchange(m, MtxLocked, memory_order_acquire) == MtxUnlocked)
630f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov    return;
631f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov  while (atomic_exchange(m, MtxSleeping, memory_order_acquire) != MtxUnlocked)
6329578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne    internal_syscall(__NR_futex, m, FUTEX_WAIT, MtxSleeping, 0, 0, 0);
633f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov}
634f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov
635f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukovvoid BlockingMutex::Unlock() {
636f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov  atomic_uint32_t *m = reinterpret_cast<atomic_uint32_t *>(&opaque_storage_);
637f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov  u32 v = atomic_exchange(m, MtxUnlocked, memory_order_relaxed);
63848526014de78e21f7ed027a60670016bc7f5d292Dmitry Vyukov  CHECK_NE(v, MtxUnlocked);
639f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov  if (v == MtxSleeping)
6409578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne    internal_syscall(__NR_futex, m, FUTEX_WAKE, 1, 0, 0, 0);
641f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov}
642f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov
643ce700979f644c790c2d9d80f5cc2a1ada0380284Alexey Samsonovvoid BlockingMutex::CheckLocked() {
644ce700979f644c790c2d9d80f5cc2a1ada0380284Alexey Samsonov  atomic_uint32_t *m = reinterpret_cast<atomic_uint32_t *>(&opaque_storage_);
645ce700979f644c790c2d9d80f5cc2a1ada0380284Alexey Samsonov  CHECK_NE(MtxUnlocked, atomic_load(m, memory_order_relaxed));
646ce700979f644c790c2d9d80f5cc2a1ada0380284Alexey Samsonov}
647ce700979f644c790c2d9d80f5cc2a1ada0380284Alexey Samsonov
6486fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany// ----------------- sanitizer_linux.h
6496fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany// The actual size of this structure is specified by d_reclen.
6506fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany// Note that getdents64 uses a different structure format. We only provide the
6516fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany// 32-bit syscall here.
6526fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryanystruct linux_dirent {
6536fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany  unsigned long      d_ino;
6546fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany  unsigned long      d_off;
6556fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany  unsigned short     d_reclen;
6566fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany  char               d_name[256];
6576fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany};
6586fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany
6596fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany// Syscall wrappers.
6609578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourneuptr internal_ptrace(int request, int pid, void *addr, void *data) {
6619578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne  return internal_syscall(__NR_ptrace, request, pid, addr, data);
6629578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne}
6639578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne
6649578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourneuptr internal_waitpid(int pid, int *status, int options) {
6659578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne  return internal_syscall(__NR_wait4, pid, status, options, 0 /* rusage */);
6666fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany}
6676fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany
6689578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourneuptr internal_getpid() {
6699578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne  return internal_syscall(__NR_getpid);
6706fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany}
6716fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany
6729578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourneuptr internal_getppid() {
6739578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne  return internal_syscall(__NR_getppid);
6746fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany}
6756fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany
6769578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourneuptr internal_getdents(fd_t fd, struct linux_dirent *dirp, unsigned int count) {
6779578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne  return internal_syscall(__NR_getdents, fd, dirp, count);
6786fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany}
6796fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany
6809578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourneuptr internal_lseek(fd_t fd, OFF_T offset, int whence) {
6819578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne  return internal_syscall(__NR_lseek, fd, offset, whence);
6826fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany}
6836fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany
6849578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourneuptr internal_prctl(int option, uptr arg2, uptr arg3, uptr arg4, uptr arg5) {
6859578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne  return internal_syscall(__NR_prctl, option, arg2, arg3, arg4, arg5);
6866fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany}
6876fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany
6889578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourneuptr internal_sigaltstack(const struct sigaltstack *ss,
6896fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany                         struct sigaltstack *oss) {
6909578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne  return internal_syscall(__NR_sigaltstack, ss, oss);
6916fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany}
6926fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany
6936fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany// ThreadLister implementation.
6946fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya SerebryanyThreadLister::ThreadLister(int pid)
6956fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany  : pid_(pid),
6966fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany    descriptor_(-1),
69710f3ab775088bec69dd9e7b611f9b4e152f629bcAlexey Samsonov    buffer_(4096),
6986fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany    error_(true),
69910f3ab775088bec69dd9e7b611f9b4e152f629bcAlexey Samsonov    entry_((struct linux_dirent *)buffer_.data()),
7006fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany    bytes_read_(0) {
7016fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany  char task_directory_path[80];
7026fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany  internal_snprintf(task_directory_path, sizeof(task_directory_path),
7036fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany                    "/proc/%d/task/", pid);
7049578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne  uptr openrv = internal_open(task_directory_path, O_RDONLY | O_DIRECTORY);
7059578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne  if (internal_iserror(openrv)) {
7066fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany    error_ = true;
7076fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany    Report("Can't open /proc/%d/task for reading.\n", pid);
7086fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany  } else {
7096fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany    error_ = false;
7109578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne    descriptor_ = openrv;
7116fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany  }
7126fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany}
7136fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany
7146fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryanyint ThreadLister::GetNextTID() {
7156fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany  int tid = -1;
7166fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany  do {
7176fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany    if (error_)
7186fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany      return -1;
7196fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany    if ((char *)entry_ >= &buffer_[bytes_read_] && !GetDirectoryEntries())
7206fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany      return -1;
7216fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany    if (entry_->d_ino != 0 && entry_->d_name[0] >= '0' &&
7226fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany        entry_->d_name[0] <= '9') {
7236fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany      // Found a valid tid.
7246fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany      tid = (int)internal_atoll(entry_->d_name);
7256fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany    }
7266fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany    entry_ = (struct linux_dirent *)(((char *)entry_) + entry_->d_reclen);
7276fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany  } while (tid < 0);
7286fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany  return tid;
7296fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany}
7306fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany
7316fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryanyvoid ThreadLister::Reset() {
7326fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany  if (error_ || descriptor_ < 0)
7336fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany    return;
7346fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany  internal_lseek(descriptor_, 0, SEEK_SET);
7356fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany}
7366fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany
7376fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya SerebryanyThreadLister::~ThreadLister() {
7386fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany  if (descriptor_ >= 0)
7396fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany    internal_close(descriptor_);
7406fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany}
7416fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany
7426fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryanybool ThreadLister::error() { return error_; }
7436fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany
7446fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryanybool ThreadLister::GetDirectoryEntries() {
7456fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany  CHECK_GE(descriptor_, 0);
7466fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany  CHECK_NE(error_, true);
7476fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany  bytes_read_ = internal_getdents(descriptor_,
74810f3ab775088bec69dd9e7b611f9b4e152f629bcAlexey Samsonov                                  (struct linux_dirent *)buffer_.data(),
74910f3ab775088bec69dd9e7b611f9b4e152f629bcAlexey Samsonov                                  buffer_.size());
7509578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne  if (internal_iserror(bytes_read_)) {
7516fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany    Report("Can't read directory entries from /proc/%d/task.\n", pid_);
7526fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany    error_ = true;
7536fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany    return false;
7546fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany  } else if (bytes_read_ == 0) {
7556fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany    return false;
7566fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany  }
75710f3ab775088bec69dd9e7b611f9b4e152f629bcAlexey Samsonov  entry_ = (struct linux_dirent *)buffer_.data();
7586fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany  return true;
7596fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany}
7606fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany
761b114ed83859d8d4964ac2284584733bcd2acf4f6Evgeniy Stepanovstatic uptr g_tls_size;
762b114ed83859d8d4964ac2284584733bcd2acf4f6Evgeniy Stepanov
763b114ed83859d8d4964ac2284584733bcd2acf4f6Evgeniy Stepanov#ifdef __i386__
764b114ed83859d8d4964ac2284584733bcd2acf4f6Evgeniy Stepanov# define DL_INTERNAL_FUNCTION __attribute__((regparm(3), stdcall))
765b114ed83859d8d4964ac2284584733bcd2acf4f6Evgeniy Stepanov#else
766b114ed83859d8d4964ac2284584733bcd2acf4f6Evgeniy Stepanov# define DL_INTERNAL_FUNCTION
767b114ed83859d8d4964ac2284584733bcd2acf4f6Evgeniy Stepanov#endif
768b114ed83859d8d4964ac2284584733bcd2acf4f6Evgeniy Stepanov
769b114ed83859d8d4964ac2284584733bcd2acf4f6Evgeniy Stepanovvoid InitTlsSize() {
770f310654ee19b6887677a09f09e522e36e81eb9daSergey Matveev#if !defined(SANITIZER_GO) && !SANITIZER_ANDROID
771b114ed83859d8d4964ac2284584733bcd2acf4f6Evgeniy Stepanov  typedef void (*get_tls_func)(size_t*, size_t*) DL_INTERNAL_FUNCTION;
772b114ed83859d8d4964ac2284584733bcd2acf4f6Evgeniy Stepanov  get_tls_func get_tls;
773b114ed83859d8d4964ac2284584733bcd2acf4f6Evgeniy Stepanov  void *get_tls_static_info_ptr = dlsym(RTLD_NEXT, "_dl_get_tls_static_info");
774b114ed83859d8d4964ac2284584733bcd2acf4f6Evgeniy Stepanov  CHECK_EQ(sizeof(get_tls), sizeof(get_tls_static_info_ptr));
775b114ed83859d8d4964ac2284584733bcd2acf4f6Evgeniy Stepanov  internal_memcpy(&get_tls, &get_tls_static_info_ptr,
776b114ed83859d8d4964ac2284584733bcd2acf4f6Evgeniy Stepanov                  sizeof(get_tls_static_info_ptr));
777b114ed83859d8d4964ac2284584733bcd2acf4f6Evgeniy Stepanov  CHECK_NE(get_tls, 0);
778b114ed83859d8d4964ac2284584733bcd2acf4f6Evgeniy Stepanov  size_t tls_size = 0;
779b114ed83859d8d4964ac2284584733bcd2acf4f6Evgeniy Stepanov  size_t tls_align = 0;
780b114ed83859d8d4964ac2284584733bcd2acf4f6Evgeniy Stepanov  get_tls(&tls_size, &tls_align);
781b114ed83859d8d4964ac2284584733bcd2acf4f6Evgeniy Stepanov  g_tls_size = tls_size;
782b114ed83859d8d4964ac2284584733bcd2acf4f6Evgeniy Stepanov#endif
783b114ed83859d8d4964ac2284584733bcd2acf4f6Evgeniy Stepanov}
784b114ed83859d8d4964ac2284584733bcd2acf4f6Evgeniy Stepanov
785b114ed83859d8d4964ac2284584733bcd2acf4f6Evgeniy Stepanovuptr GetTlsSize() {
786b114ed83859d8d4964ac2284584733bcd2acf4f6Evgeniy Stepanov  return g_tls_size;
787b114ed83859d8d4964ac2284584733bcd2acf4f6Evgeniy Stepanov}
788b114ed83859d8d4964ac2284584733bcd2acf4f6Evgeniy Stepanov
78924323de08fa8850712d56621bff29dbbbd0285a9Sergey Matveev// sizeof(struct thread) from glibc.
79024323de08fa8850712d56621bff29dbbbd0285a9Sergey Matveev#ifdef __x86_64__
79124323de08fa8850712d56621bff29dbbbd0285a9Sergey Matveevconst uptr kThreadDescriptorSize = 2304;
79224323de08fa8850712d56621bff29dbbbd0285a9Sergey Matveev
79324323de08fa8850712d56621bff29dbbbd0285a9Sergey Matveevuptr ThreadDescriptorSize() {
79424323de08fa8850712d56621bff29dbbbd0285a9Sergey Matveev  return kThreadDescriptorSize;
79524323de08fa8850712d56621bff29dbbbd0285a9Sergey Matveev}
79624323de08fa8850712d56621bff29dbbbd0285a9Sergey Matveev#endif
79724323de08fa8850712d56621bff29dbbbd0285a9Sergey Matveev
79824323de08fa8850712d56621bff29dbbbd0285a9Sergey Matveevvoid GetThreadStackAndTls(bool main, uptr *stk_addr, uptr *stk_size,
79924323de08fa8850712d56621bff29dbbbd0285a9Sergey Matveev                          uptr *tls_addr, uptr *tls_size) {
80024323de08fa8850712d56621bff29dbbbd0285a9Sergey Matveev#ifndef SANITIZER_GO
80124323de08fa8850712d56621bff29dbbbd0285a9Sergey Matveev#ifdef __x86_64__
80224323de08fa8850712d56621bff29dbbbd0285a9Sergey Matveev  arch_prctl(ARCH_GET_FS, tls_addr);
80324323de08fa8850712d56621bff29dbbbd0285a9Sergey Matveev  *tls_size = GetTlsSize();
80424323de08fa8850712d56621bff29dbbbd0285a9Sergey Matveev  *tls_addr -= *tls_size;
80524323de08fa8850712d56621bff29dbbbd0285a9Sergey Matveev  *tls_addr += kThreadDescriptorSize;
80624323de08fa8850712d56621bff29dbbbd0285a9Sergey Matveev#else
80724323de08fa8850712d56621bff29dbbbd0285a9Sergey Matveev  *tls_addr = 0;
80824323de08fa8850712d56621bff29dbbbd0285a9Sergey Matveev  *tls_size = 0;
80924323de08fa8850712d56621bff29dbbbd0285a9Sergey Matveev#endif
81024323de08fa8850712d56621bff29dbbbd0285a9Sergey Matveev
81124323de08fa8850712d56621bff29dbbbd0285a9Sergey Matveev  uptr stack_top, stack_bottom;
81224323de08fa8850712d56621bff29dbbbd0285a9Sergey Matveev  GetThreadStackTopAndBottom(main, &stack_top, &stack_bottom);
81324323de08fa8850712d56621bff29dbbbd0285a9Sergey Matveev  *stk_addr = stack_bottom;
81424323de08fa8850712d56621bff29dbbbd0285a9Sergey Matveev  *stk_size = stack_top - stack_bottom;
81524323de08fa8850712d56621bff29dbbbd0285a9Sergey Matveev
81624323de08fa8850712d56621bff29dbbbd0285a9Sergey Matveev  if (!main) {
81724323de08fa8850712d56621bff29dbbbd0285a9Sergey Matveev    // If stack and tls intersect, make them non-intersecting.
81824323de08fa8850712d56621bff29dbbbd0285a9Sergey Matveev    if (*tls_addr > *stk_addr && *tls_addr < *stk_addr + *stk_size) {
81924323de08fa8850712d56621bff29dbbbd0285a9Sergey Matveev      CHECK_GT(*tls_addr + *tls_size, *stk_addr);
82024323de08fa8850712d56621bff29dbbbd0285a9Sergey Matveev      CHECK_LE(*tls_addr + *tls_size, *stk_addr + *stk_size);
82124323de08fa8850712d56621bff29dbbbd0285a9Sergey Matveev      *stk_size -= *tls_size;
82224323de08fa8850712d56621bff29dbbbd0285a9Sergey Matveev      *tls_addr = *stk_addr + *stk_size;
82324323de08fa8850712d56621bff29dbbbd0285a9Sergey Matveev    }
82424323de08fa8850712d56621bff29dbbbd0285a9Sergey Matveev  }
82524323de08fa8850712d56621bff29dbbbd0285a9Sergey Matveev#else  // SANITIZER_GO
82624323de08fa8850712d56621bff29dbbbd0285a9Sergey Matveev  *stk_addr = 0;
82724323de08fa8850712d56621bff29dbbbd0285a9Sergey Matveev  *stk_size = 0;
82824323de08fa8850712d56621bff29dbbbd0285a9Sergey Matveev  *tls_addr = 0;
82924323de08fa8850712d56621bff29dbbbd0285a9Sergey Matveev  *tls_size = 0;
83024323de08fa8850712d56621bff29dbbbd0285a9Sergey Matveev#endif  // SANITIZER_GO
83124323de08fa8850712d56621bff29dbbbd0285a9Sergey Matveev}
83224323de08fa8850712d56621bff29dbbbd0285a9Sergey Matveev
833b9bf700ae7fe59e25976e0abe9636150f3a39cd2Evgeniy Stepanovvoid AdjustStackSizeLinux(void *attr_, int verbosity) {
834b9bf700ae7fe59e25976e0abe9636150f3a39cd2Evgeniy Stepanov  pthread_attr_t *attr = (pthread_attr_t *)attr_;
835609a02ad07f09147e2fe7beaa257b8c607aca033Evgeniy Stepanov  uptr stackaddr = 0;
836b9bf700ae7fe59e25976e0abe9636150f3a39cd2Evgeniy Stepanov  size_t stacksize = 0;
837b9bf700ae7fe59e25976e0abe9636150f3a39cd2Evgeniy Stepanov  pthread_attr_getstack(attr, (void**)&stackaddr, &stacksize);
838b9bf700ae7fe59e25976e0abe9636150f3a39cd2Evgeniy Stepanov  // GLibC will return (0 - stacksize) as the stack address in the case when
839b9bf700ae7fe59e25976e0abe9636150f3a39cd2Evgeniy Stepanov  // stacksize is set, but stackaddr is not.
840b9bf700ae7fe59e25976e0abe9636150f3a39cd2Evgeniy Stepanov  bool stack_set = (stackaddr != 0) && (stackaddr + stacksize != 0);
841b9bf700ae7fe59e25976e0abe9636150f3a39cd2Evgeniy Stepanov  // We place a lot of tool data into TLS, account for that.
842b9bf700ae7fe59e25976e0abe9636150f3a39cd2Evgeniy Stepanov  const uptr minstacksize = GetTlsSize() + 128*1024;
843b9bf700ae7fe59e25976e0abe9636150f3a39cd2Evgeniy Stepanov  if (stacksize < minstacksize) {
844b9bf700ae7fe59e25976e0abe9636150f3a39cd2Evgeniy Stepanov    if (!stack_set) {
845b9bf700ae7fe59e25976e0abe9636150f3a39cd2Evgeniy Stepanov      if (verbosity && stacksize != 0)
846b9bf700ae7fe59e25976e0abe9636150f3a39cd2Evgeniy Stepanov        Printf("Sanitizer: increasing stacksize %zu->%zu\n", stacksize,
847b9bf700ae7fe59e25976e0abe9636150f3a39cd2Evgeniy Stepanov               minstacksize);
848b9bf700ae7fe59e25976e0abe9636150f3a39cd2Evgeniy Stepanov      pthread_attr_setstacksize(attr, minstacksize);
849b9bf700ae7fe59e25976e0abe9636150f3a39cd2Evgeniy Stepanov    } else {
850b9bf700ae7fe59e25976e0abe9636150f3a39cd2Evgeniy Stepanov      Printf("Sanitizer: pre-allocated stack size is insufficient: "
851b9bf700ae7fe59e25976e0abe9636150f3a39cd2Evgeniy Stepanov             "%zu < %zu\n", stacksize, minstacksize);
852b9bf700ae7fe59e25976e0abe9636150f3a39cd2Evgeniy Stepanov      Printf("Sanitizer: pthread_create is likely to fail.\n");
853b9bf700ae7fe59e25976e0abe9636150f3a39cd2Evgeniy Stepanov    }
854b9bf700ae7fe59e25976e0abe9636150f3a39cd2Evgeniy Stepanov  }
855b9bf700ae7fe59e25976e0abe9636150f3a39cd2Evgeniy Stepanov}
856b9bf700ae7fe59e25976e0abe9636150f3a39cd2Evgeniy Stepanov
857ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov}  // namespace __sanitizer
858ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov
85946f9395baf65e17f1a3f7a3a1deee72a1560ac53Alexey Samsonov#endif  // SANITIZER_LINUX
860