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//===----------------------------------------------------------------------===//
14ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov#ifdef __linux__
15ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov
166895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov#include "sanitizer_common.h"
1794b5036ee6ba866e1702848855b6d687d1e70afaAlexey Samsonov#include "sanitizer_internal_defs.h"
18ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov#include "sanitizer_libc.h"
196fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany#include "sanitizer_linux.h"
2093da8b6a5e0ed2ca621897504c5d06449b3d7077Alexander Potapenko#include "sanitizer_mutex.h"
21a68633fb76208137ccb807914df52758ee5ca6f0Alexey Samsonov#include "sanitizer_placement_new.h"
226895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov#include "sanitizer_procmaps.h"
23a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryany#include "sanitizer_stacktrace.h"
24ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov
25b114ed83859d8d4964ac2284584733bcd2acf4f6Evgeniy Stepanov#include <dlfcn.h>
2635a7faf1fbfac678136e79d53824672dafb7d13eAlexey Samsonov#include <errno.h>
27c5d465136b911bf925f2a631e2b79f1c03e8a1b0Alexey Samsonov#include <fcntl.h>
28e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov#include <pthread.h>
290969bcf2c936126b1f6e636b978aade8fc207437Alexey Samsonov#include <sched.h>
30ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov#include <sys/mman.h>
316fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany#include <sys/ptrace.h>
32e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov#include <sys/resource.h>
33c5d465136b911bf925f2a631e2b79f1c03e8a1b0Alexey Samsonov#include <sys/stat.h>
34ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov#include <sys/syscall.h>
35e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov#include <sys/time.h>
36ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov#include <sys/types.h>
37fa5c41eddf77a3614da0f62044ebf741d86aeab7Dmitry Vyukov#include <sys/prctl.h>
38ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov#include <unistd.h>
39a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryany#include <unwind.h>
4035a7faf1fbfac678136e79d53824672dafb7d13eAlexey Samsonov
4135a7faf1fbfac678136e79d53824672dafb7d13eAlexey Samsonov#if !defined(__ANDROID__) && !defined(ANDROID)
4235a7faf1fbfac678136e79d53824672dafb7d13eAlexey Samsonov#include <sys/signal.h>
4335a7faf1fbfac678136e79d53824672dafb7d13eAlexey Samsonov#endif
44fa5c41eddf77a3614da0f62044ebf741d86aeab7Dmitry Vyukov
45fa5c41eddf77a3614da0f62044ebf741d86aeab7Dmitry Vyukov// <linux/futex.h> is broken on some linux distributions.
46fa5c41eddf77a3614da0f62044ebf741d86aeab7Dmitry Vyukovconst int FUTEX_WAIT = 0;
47fa5c41eddf77a3614da0f62044ebf741d86aeab7Dmitry Vyukovconst int FUTEX_WAKE = 1;
48ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov
499d0dbbaf33e5c2fe280f141e30be497d62b703a8Kostya Serebryany// Are we using 32-bit or 64-bit syscalls?
505af39e50366f1aacbebc284f572f08ad1ad07357Kostya Serebryany// x32 (which defines __x86_64__) has SANITIZER_WORDSIZE == 32
5108bfe4988de493dd3e61d02759b3f19c42f8fb78Kostya Serebryany// but it still needs to use 64-bit syscalls.
525af39e50366f1aacbebc284f572f08ad1ad07357Kostya Serebryany#if defined(__x86_64__) || SANITIZER_WORDSIZE == 64
539d0dbbaf33e5c2fe280f141e30be497d62b703a8Kostya Serebryany# define SANITIZER_LINUX_USES_64BIT_SYSCALLS 1
549d0dbbaf33e5c2fe280f141e30be497d62b703a8Kostya Serebryany#else
559d0dbbaf33e5c2fe280f141e30be497d62b703a8Kostya Serebryany# define SANITIZER_LINUX_USES_64BIT_SYSCALLS 0
569d0dbbaf33e5c2fe280f141e30be497d62b703a8Kostya Serebryany#endif
579d0dbbaf33e5c2fe280f141e30be497d62b703a8Kostya Serebryany
58ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonovnamespace __sanitizer {
59ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov
60e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov// --------------- sanitizer_libc.h
61ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonovvoid *internal_mmap(void *addr, uptr length, int prot, int flags,
62ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov                    int fd, u64 offset) {
639d0dbbaf33e5c2fe280f141e30be497d62b703a8Kostya Serebryany#if SANITIZER_LINUX_USES_64BIT_SYSCALLS
64ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov  return (void *)syscall(__NR_mmap, addr, length, prot, flags, fd, offset);
65ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov#else
66ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov  return (void *)syscall(__NR_mmap2, addr, length, prot, flags, fd, offset);
67ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov#endif
68ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov}
69ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov
701f11d31faa5ed89b74f7d543b1182fe8de198be5Alexey Samsonovint internal_munmap(void *addr, uptr length) {
711f11d31faa5ed89b74f7d543b1182fe8de198be5Alexey Samsonov  return syscall(__NR_munmap, addr, length);
721f11d31faa5ed89b74f7d543b1182fe8de198be5Alexey Samsonov}
731f11d31faa5ed89b74f7d543b1182fe8de198be5Alexey Samsonov
74a56aefd2e01940fcf88d1426f9de3d5e4b1ee203Alexey Samsonovint internal_close(fd_t fd) {
75a56aefd2e01940fcf88d1426f9de3d5e4b1ee203Alexey Samsonov  return syscall(__NR_close, fd);
76a56aefd2e01940fcf88d1426f9de3d5e4b1ee203Alexey Samsonov}
77a56aefd2e01940fcf88d1426f9de3d5e4b1ee203Alexey Samsonov
78ee7cc4454421a176d23442382afd9a01d36e7ad4Alexey Samsonovfd_t internal_open(const char *filename, int flags) {
79ee7cc4454421a176d23442382afd9a01d36e7ad4Alexey Samsonov  return syscall(__NR_open, filename, flags);
80ee7cc4454421a176d23442382afd9a01d36e7ad4Alexey Samsonov}
81ee7cc4454421a176d23442382afd9a01d36e7ad4Alexey Samsonov
82e85c83dcee3d35068e6670ab32545953d4330335Alexey Samsonovfd_t internal_open(const char *filename, int flags, u32 mode) {
83ee7cc4454421a176d23442382afd9a01d36e7ad4Alexey Samsonov  return syscall(__NR_open, filename, flags, mode);
84ee7cc4454421a176d23442382afd9a01d36e7ad4Alexey Samsonov}
85ee7cc4454421a176d23442382afd9a01d36e7ad4Alexey Samsonov
86ee7cc4454421a176d23442382afd9a01d36e7ad4Alexey Samsonovfd_t OpenFile(const char *filename, bool write) {
87ee7cc4454421a176d23442382afd9a01d36e7ad4Alexey Samsonov  return internal_open(filename,
889b8a9c1b1ce4659457178ff4c0838ac1b35ca9dcKostya Serebryany      write ? O_WRONLY | O_CREAT /*| O_CLOEXEC*/ : O_RDONLY, 0660);
89c5d465136b911bf925f2a631e2b79f1c03e8a1b0Alexey Samsonov}
90c5d465136b911bf925f2a631e2b79f1c03e8a1b0Alexey Samsonov
91a56aefd2e01940fcf88d1426f9de3d5e4b1ee203Alexey Samsonovuptr internal_read(fd_t fd, void *buf, uptr count) {
923334e12d33261cb8f211f2f49f28ddfa027a40c3Evgeniy Stepanov  sptr res;
933334e12d33261cb8f211f2f49f28ddfa027a40c3Evgeniy Stepanov  HANDLE_EINTR(res, (sptr)syscall(__NR_read, fd, buf, count));
943334e12d33261cb8f211f2f49f28ddfa027a40c3Evgeniy Stepanov  return res;
95a56aefd2e01940fcf88d1426f9de3d5e4b1ee203Alexey Samsonov}
96a56aefd2e01940fcf88d1426f9de3d5e4b1ee203Alexey Samsonov
97a56aefd2e01940fcf88d1426f9de3d5e4b1ee203Alexey Samsonovuptr internal_write(fd_t fd, const void *buf, uptr count) {
983334e12d33261cb8f211f2f49f28ddfa027a40c3Evgeniy Stepanov  sptr res;
993334e12d33261cb8f211f2f49f28ddfa027a40c3Evgeniy Stepanov  HANDLE_EINTR(res, (sptr)syscall(__NR_write, fd, buf, count));
1003334e12d33261cb8f211f2f49f28ddfa027a40c3Evgeniy Stepanov  return res;
101a56aefd2e01940fcf88d1426f9de3d5e4b1ee203Alexey Samsonov}
102a56aefd2e01940fcf88d1426f9de3d5e4b1ee203Alexey Samsonov
1034c9317a7b61e136f832d2ede70f557963fd46bceAlexey Samsonovint internal_stat(const char *path, void *buf) {
1044c9317a7b61e136f832d2ede70f557963fd46bceAlexey Samsonov#if SANITIZER_LINUX_USES_64BIT_SYSCALLS
1054c9317a7b61e136f832d2ede70f557963fd46bceAlexey Samsonov  return syscall(__NR_stat, path, buf);
1064c9317a7b61e136f832d2ede70f557963fd46bceAlexey Samsonov#else
1074c9317a7b61e136f832d2ede70f557963fd46bceAlexey Samsonov  return syscall(__NR_stat64, path, buf);
1084c9317a7b61e136f832d2ede70f557963fd46bceAlexey Samsonov#endif
1094c9317a7b61e136f832d2ede70f557963fd46bceAlexey Samsonov}
1104c9317a7b61e136f832d2ede70f557963fd46bceAlexey Samsonov
1114c9317a7b61e136f832d2ede70f557963fd46bceAlexey Samsonovint internal_lstat(const char *path, void *buf) {
1124c9317a7b61e136f832d2ede70f557963fd46bceAlexey Samsonov#if SANITIZER_LINUX_USES_64BIT_SYSCALLS
1134c9317a7b61e136f832d2ede70f557963fd46bceAlexey Samsonov  return syscall(__NR_lstat, path, buf);
1144c9317a7b61e136f832d2ede70f557963fd46bceAlexey Samsonov#else
1154c9317a7b61e136f832d2ede70f557963fd46bceAlexey Samsonov  return syscall(__NR_lstat64, path, buf);
1164c9317a7b61e136f832d2ede70f557963fd46bceAlexey Samsonov#endif
1174c9317a7b61e136f832d2ede70f557963fd46bceAlexey Samsonov}
1184c9317a7b61e136f832d2ede70f557963fd46bceAlexey Samsonov
1194c9317a7b61e136f832d2ede70f557963fd46bceAlexey Samsonovint internal_fstat(fd_t fd, void *buf) {
1204c9317a7b61e136f832d2ede70f557963fd46bceAlexey Samsonov#if SANITIZER_LINUX_USES_64BIT_SYSCALLS
1214c9317a7b61e136f832d2ede70f557963fd46bceAlexey Samsonov  return syscall(__NR_fstat, fd, buf);
1224c9317a7b61e136f832d2ede70f557963fd46bceAlexey Samsonov#else
1234c9317a7b61e136f832d2ede70f557963fd46bceAlexey Samsonov  return syscall(__NR_fstat64, fd, buf);
1244c9317a7b61e136f832d2ede70f557963fd46bceAlexey Samsonov#endif
1254c9317a7b61e136f832d2ede70f557963fd46bceAlexey Samsonov}
1264c9317a7b61e136f832d2ede70f557963fd46bceAlexey Samsonov
1278e820fcf7aafeb8101322182d742fcf99255d972Alexey Samsonovuptr internal_filesize(fd_t fd) {
1289d0dbbaf33e5c2fe280f141e30be497d62b703a8Kostya Serebryany#if SANITIZER_LINUX_USES_64BIT_SYSCALLS
129a68633fb76208137ccb807914df52758ee5ca6f0Alexey Samsonov  struct stat st;
130a68633fb76208137ccb807914df52758ee5ca6f0Alexey Samsonov#else
131a68633fb76208137ccb807914df52758ee5ca6f0Alexey Samsonov  struct stat64 st;
132a68633fb76208137ccb807914df52758ee5ca6f0Alexey Samsonov#endif
1334c9317a7b61e136f832d2ede70f557963fd46bceAlexey Samsonov  if (internal_fstat(fd, &st))
1344c9317a7b61e136f832d2ede70f557963fd46bceAlexey Samsonov    return -1;
1358e820fcf7aafeb8101322182d742fcf99255d972Alexey Samsonov  return (uptr)st.st_size;
1368e820fcf7aafeb8101322182d742fcf99255d972Alexey Samsonov}
1378e820fcf7aafeb8101322182d742fcf99255d972Alexey Samsonov
1388e820fcf7aafeb8101322182d742fcf99255d972Alexey Samsonovint internal_dup2(int oldfd, int newfd) {
1398e820fcf7aafeb8101322182d742fcf99255d972Alexey Samsonov  return syscall(__NR_dup2, oldfd, newfd);
1408e820fcf7aafeb8101322182d742fcf99255d972Alexey Samsonov}
1418e820fcf7aafeb8101322182d742fcf99255d972Alexey Samsonov
142d1b8f588d6b712b6ff2b3d58c73d71614f520122Alexey Samsonovuptr internal_readlink(const char *path, char *buf, uptr bufsize) {
143d1b8f588d6b712b6ff2b3d58c73d71614f520122Alexey Samsonov  return (uptr)syscall(__NR_readlink, path, buf, bufsize);
144d1b8f588d6b712b6ff2b3d58c73d71614f520122Alexey Samsonov}
145d1b8f588d6b712b6ff2b3d58c73d71614f520122Alexey Samsonov
1460969bcf2c936126b1f6e636b978aade8fc207437Alexey Samsonovint internal_sched_yield() {
1470969bcf2c936126b1f6e636b978aade8fc207437Alexey Samsonov  return syscall(__NR_sched_yield);
1480969bcf2c936126b1f6e636b978aade8fc207437Alexey Samsonov}
1490969bcf2c936126b1f6e636b978aade8fc207437Alexey Samsonov
150f882247088952deed954a19d745c2dd8871e2035Alexey Samsonovvoid internal__exit(int exitcode) {
151f882247088952deed954a19d745c2dd8871e2035Alexey Samsonov  syscall(__NR_exit_group, exitcode);
152f882247088952deed954a19d745c2dd8871e2035Alexey Samsonov  Die();  // Unreachable.
153f882247088952deed954a19d745c2dd8871e2035Alexey Samsonov}
154f882247088952deed954a19d745c2dd8871e2035Alexey Samsonov
155e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov// ----------------- sanitizer_common.h
15693b4cafd631b661b4b612ccdc0938f7f1e1c86d6Alexey Samsonovbool FileExists(const char *filename) {
1579d0dbbaf33e5c2fe280f141e30be497d62b703a8Kostya Serebryany#if SANITIZER_LINUX_USES_64BIT_SYSCALLS
15893b4cafd631b661b4b612ccdc0938f7f1e1c86d6Alexey Samsonov  struct stat st;
15993b4cafd631b661b4b612ccdc0938f7f1e1c86d6Alexey Samsonov  if (syscall(__NR_stat, filename, &st))
16093b4cafd631b661b4b612ccdc0938f7f1e1c86d6Alexey Samsonov    return false;
16193b4cafd631b661b4b612ccdc0938f7f1e1c86d6Alexey Samsonov#else
16293b4cafd631b661b4b612ccdc0938f7f1e1c86d6Alexey Samsonov  struct stat64 st;
16393b4cafd631b661b4b612ccdc0938f7f1e1c86d6Alexey Samsonov  if (syscall(__NR_stat64, filename, &st))
16493b4cafd631b661b4b612ccdc0938f7f1e1c86d6Alexey Samsonov    return false;
16593b4cafd631b661b4b612ccdc0938f7f1e1c86d6Alexey Samsonov#endif
16693b4cafd631b661b4b612ccdc0938f7f1e1c86d6Alexey Samsonov  // Sanity check: filename is a regular file.
16793b4cafd631b661b4b612ccdc0938f7f1e1c86d6Alexey Samsonov  return S_ISREG(st.st_mode);
16893b4cafd631b661b4b612ccdc0938f7f1e1c86d6Alexey Samsonov}
16993b4cafd631b661b4b612ccdc0938f7f1e1c86d6Alexey Samsonov
170e0023f74ea88efee329f68391b70f8adc6b21617Dmitry Vyukovuptr GetTid() {
171e0023f74ea88efee329f68391b70f8adc6b21617Dmitry Vyukov  return syscall(__NR_gettid);
172e0023f74ea88efee329f68391b70f8adc6b21617Dmitry Vyukov}
173e0023f74ea88efee329f68391b70f8adc6b21617Dmitry Vyukov
174ed996f79710f532bf231537e44d5c8c9c9d57e8dAlexey Samsonovvoid GetThreadStackTopAndBottom(bool at_initialization, uptr *stack_top,
175e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov                                uptr *stack_bottom) {
176e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov  static const uptr kMaxThreadStackSize = 256 * (1 << 20);  // 256M
177e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov  CHECK(stack_top);
178e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov  CHECK(stack_bottom);
179ed996f79710f532bf231537e44d5c8c9c9d57e8dAlexey Samsonov  if (at_initialization) {
180e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov    // This is the main thread. Libpthread may not be initialized yet.
181e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov    struct rlimit rl;
1826985085c4860bf945358f227ddba26511ae770e9Kostya Serebryany    CHECK_EQ(getrlimit(RLIMIT_STACK, &rl), 0);
183e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov
184e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov    // Find the mapping that contains a stack variable.
185e1f5dac9296df08ff83ae5fca51ce4da995b55cfAlexey Samsonov    MemoryMappingLayout proc_maps;
186e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov    uptr start, end, offset;
187e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov    uptr prev_end = 0;
18845717c9d5e39a434749ae10509111f9df1b2cdf4Alexey Samsonov    while (proc_maps.Next(&start, &end, &offset, 0, 0, /* protection */0)) {
189e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov      if ((uptr)&rl < end)
190e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov        break;
191e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov      prev_end = end;
192e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov    }
193e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov    CHECK((uptr)&rl >= start && (uptr)&rl < end);
194e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov
195e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov    // Get stacksize from rlimit, but clip it so that it does not overlap
196e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov    // with other mappings.
197e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov    uptr stacksize = rl.rlim_cur;
198e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov    if (stacksize > end - prev_end)
199e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov      stacksize = end - prev_end;
200e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov    // When running with unlimited stack size, we still want to set some limit.
201e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov    // The unlimited stack size is caused by 'ulimit -s unlimited'.
202e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov    // Also, for some reason, GNU make spawns subprocesses with unlimited stack.
203e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov    if (stacksize > kMaxThreadStackSize)
204e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov      stacksize = kMaxThreadStackSize;
205e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov    *stack_top = end;
206e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov    *stack_bottom = end - stacksize;
207e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov    return;
208e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov  }
209e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov  pthread_attr_t attr;
2106985085c4860bf945358f227ddba26511ae770e9Kostya Serebryany  CHECK_EQ(pthread_getattr_np(pthread_self(), &attr), 0);
211e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov  uptr stacksize = 0;
212e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov  void *stackaddr = 0;
213e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov  pthread_attr_getstack(&attr, &stackaddr, (size_t*)&stacksize);
214e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov  pthread_attr_destroy(&attr);
215e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov
216e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov  *stack_top = (uptr)stackaddr + stacksize;
217e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov  *stack_bottom = (uptr)stackaddr;
218e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov  CHECK(stacksize < kMaxThreadStackSize);  // Sanity check.
219e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov}
220e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov
2213dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov// Like getenv, but reads env directly from /proc and does not use libc.
2223dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov// This function should be called first inside __asan_init.
2233dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonovconst char *GetEnv(const char *name) {
2243dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov  static char *environ;
2253dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov  static uptr len;
2263dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov  static bool inited;
2273dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov  if (!inited) {
2283dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov    inited = true;
2293dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov    uptr environ_size;
2303dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov    len = ReadFileToBuffer("/proc/self/environ",
2313dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov                           &environ, &environ_size, 1 << 26);
2323dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov  }
2333dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov  if (!environ || len == 0) return 0;
2343dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov  uptr namelen = internal_strlen(name);
2353dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov  const char *p = environ;
2363dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov  while (*p != '\0') {  // will happen at the \0\0 that terminates the buffer
2373dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov    // proc file has the format NAME=value\0NAME=value\0NAME=value\0...
2383dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov    const char* endp =
2393dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov        (char*)internal_memchr(p, '\0', len - (p - environ));
2403dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov    if (endp == 0)  // this entry isn't NUL terminated
2413dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov      return 0;
2423dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov    else if (!internal_memcmp(p, name, namelen) && p[namelen] == '=')  // Match.
2433dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov      return p + namelen + 1;  // point after =
2443dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov    p = endp + 1;
2453dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov  }
2463dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov  return 0;  // Not found.
2473dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov}
2483dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov
249eab061185ec0046d447b298a1dff84f028202a3cEvgeniy Stepanov#ifdef __GLIBC__
250eab061185ec0046d447b298a1dff84f028202a3cEvgeniy Stepanov
251eab061185ec0046d447b298a1dff84f028202a3cEvgeniy Stepanovextern "C" {
252eab061185ec0046d447b298a1dff84f028202a3cEvgeniy Stepanov  extern void *__libc_stack_end;
253eab061185ec0046d447b298a1dff84f028202a3cEvgeniy Stepanov}
254eab061185ec0046d447b298a1dff84f028202a3cEvgeniy Stepanov
255eab061185ec0046d447b298a1dff84f028202a3cEvgeniy Stepanovstatic void GetArgsAndEnv(char ***argv, char ***envp) {
256eab061185ec0046d447b298a1dff84f028202a3cEvgeniy Stepanov  uptr *stack_end = (uptr *)__libc_stack_end;
257eab061185ec0046d447b298a1dff84f028202a3cEvgeniy Stepanov  int argc = *stack_end;
258eab061185ec0046d447b298a1dff84f028202a3cEvgeniy Stepanov  *argv = (char**)(stack_end + 1);
259eab061185ec0046d447b298a1dff84f028202a3cEvgeniy Stepanov  *envp = (char**)(stack_end + argc + 2);
260eab061185ec0046d447b298a1dff84f028202a3cEvgeniy Stepanov}
261eab061185ec0046d447b298a1dff84f028202a3cEvgeniy Stepanov
262eab061185ec0046d447b298a1dff84f028202a3cEvgeniy Stepanov#else  // __GLIBC__
263eab061185ec0046d447b298a1dff84f028202a3cEvgeniy Stepanov
26423709c9ad9ac7c45de288f5260403426bf932db7Peter Collingbournestatic void ReadNullSepFileToArray(const char *path, char ***arr,
26523709c9ad9ac7c45de288f5260403426bf932db7Peter Collingbourne                                   int arr_size) {
26623709c9ad9ac7c45de288f5260403426bf932db7Peter Collingbourne  char *buff;
267d7e5bb4043adf4756e6f8cfe0f5a3165b185474dAlexey Samsonov  uptr buff_size = 0;
26823709c9ad9ac7c45de288f5260403426bf932db7Peter Collingbourne  *arr = (char **)MmapOrDie(arr_size * sizeof(char *), "NullSepFileArray");
26923709c9ad9ac7c45de288f5260403426bf932db7Peter Collingbourne  ReadFileToBuffer(path, &buff, &buff_size, 1024 * 1024);
27023709c9ad9ac7c45de288f5260403426bf932db7Peter Collingbourne  (*arr)[0] = buff;
27123709c9ad9ac7c45de288f5260403426bf932db7Peter Collingbourne  int count, i;
27223709c9ad9ac7c45de288f5260403426bf932db7Peter Collingbourne  for (count = 1, i = 1; ; i++) {
273d7e5bb4043adf4756e6f8cfe0f5a3165b185474dAlexey Samsonov    if (buff[i] == 0) {
274d7e5bb4043adf4756e6f8cfe0f5a3165b185474dAlexey Samsonov      if (buff[i+1] == 0) break;
27523709c9ad9ac7c45de288f5260403426bf932db7Peter Collingbourne      (*arr)[count] = &buff[i+1];
27623709c9ad9ac7c45de288f5260403426bf932db7Peter Collingbourne      CHECK_LE(count, arr_size - 1);  // FIXME: make this more flexible.
27723709c9ad9ac7c45de288f5260403426bf932db7Peter Collingbourne      count++;
278d7e5bb4043adf4756e6f8cfe0f5a3165b185474dAlexey Samsonov    }
279d7e5bb4043adf4756e6f8cfe0f5a3165b185474dAlexey Samsonov  }
28023709c9ad9ac7c45de288f5260403426bf932db7Peter Collingbourne  (*arr)[count] = 0;
28123709c9ad9ac7c45de288f5260403426bf932db7Peter Collingbourne}
28223709c9ad9ac7c45de288f5260403426bf932db7Peter Collingbourne
283eab061185ec0046d447b298a1dff84f028202a3cEvgeniy Stepanovstatic void GetArgsAndEnv(char ***argv, char ***envp) {
2847b7801d0811e7091240ddbfdcff817791973ef6fEvgeniy Stepanov  static const int kMaxArgv = 2000, kMaxEnvp = 2000;
285eab061185ec0046d447b298a1dff84f028202a3cEvgeniy Stepanov  ReadNullSepFileToArray("/proc/self/cmdline", argv, kMaxArgv);
286eab061185ec0046d447b298a1dff84f028202a3cEvgeniy Stepanov  ReadNullSepFileToArray("/proc/self/environ", envp, kMaxEnvp);
287eab061185ec0046d447b298a1dff84f028202a3cEvgeniy Stepanov}
288eab061185ec0046d447b298a1dff84f028202a3cEvgeniy Stepanov
289eab061185ec0046d447b298a1dff84f028202a3cEvgeniy Stepanov#endif  // __GLIBC__
290eab061185ec0046d447b298a1dff84f028202a3cEvgeniy Stepanov
291eab061185ec0046d447b298a1dff84f028202a3cEvgeniy Stepanovvoid ReExec() {
29223709c9ad9ac7c45de288f5260403426bf932db7Peter Collingbourne  char **argv, **envp;
293eab061185ec0046d447b298a1dff84f028202a3cEvgeniy Stepanov  GetArgsAndEnv(&argv, &envp);
294f35eae83757946decb312deab3f0fe155fe5d580Evgeniy Stepanov  execve("/proc/self/exe", argv, envp);
295f35eae83757946decb312deab3f0fe155fe5d580Evgeniy Stepanov  Printf("execve failed, errno %d\n", errno);
296f35eae83757946decb312deab3f0fe155fe5d580Evgeniy Stepanov  Die();
297d7e5bb4043adf4756e6f8cfe0f5a3165b185474dAlexey Samsonov}
298d7e5bb4043adf4756e6f8cfe0f5a3165b185474dAlexey Samsonov
29925742574510cfb41b97e32f63f107fbb9b328d13Alexander Potapenkovoid PrepareForSandboxing() {
30025742574510cfb41b97e32f63f107fbb9b328d13Alexander Potapenko  // Some kinds of sandboxes may forbid filesystem access, so we won't be able
30125742574510cfb41b97e32f63f107fbb9b328d13Alexander Potapenko  // to read the file mappings from /proc/self/maps. Luckily, neither the
30225742574510cfb41b97e32f63f107fbb9b328d13Alexander Potapenko  // process will be able to load additional libraries, so it's fine to use the
30325742574510cfb41b97e32f63f107fbb9b328d13Alexander Potapenko  // cached mappings.
30425742574510cfb41b97e32f63f107fbb9b328d13Alexander Potapenko  MemoryMappingLayout::CacheMemoryMappings();
30525742574510cfb41b97e32f63f107fbb9b328d13Alexander Potapenko}
30625742574510cfb41b97e32f63f107fbb9b328d13Alexander Potapenko
307e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov// ----------------- sanitizer_procmaps.h
308286dd3f8afe6700e5dd9b0bdb7afd23121c98c12Dmitry Vyukov// Linker initialized.
309286dd3f8afe6700e5dd9b0bdb7afd23121c98c12Dmitry VyukovProcSelfMapsBuff MemoryMappingLayout::cached_proc_self_maps_;
310ad91267d45fef531c1082ab7974e4cc78aba5280Alexander PotapenkoStaticSpinMutex MemoryMappingLayout::cache_lock_;  // Linker initialized.
31193da8b6a5e0ed2ca621897504c5d06449b3d7077Alexander Potapenko
312e1f5dac9296df08ff83ae5fca51ce4da995b55cfAlexey SamsonovMemoryMappingLayout::MemoryMappingLayout() {
313ad91267d45fef531c1082ab7974e4cc78aba5280Alexander Potapenko  proc_self_maps_.len =
314ad91267d45fef531c1082ab7974e4cc78aba5280Alexander Potapenko      ReadFileToBuffer("/proc/self/maps", &proc_self_maps_.data,
315ad91267d45fef531c1082ab7974e4cc78aba5280Alexander Potapenko                       &proc_self_maps_.mmaped_size, 1 << 26);
316ad91267d45fef531c1082ab7974e4cc78aba5280Alexander Potapenko  if (proc_self_maps_.mmaped_size == 0) {
31793da8b6a5e0ed2ca621897504c5d06449b3d7077Alexander Potapenko    LoadFromCache();
318ad91267d45fef531c1082ab7974e4cc78aba5280Alexander Potapenko    CHECK_GT(proc_self_maps_.len, 0);
31993da8b6a5e0ed2ca621897504c5d06449b3d7077Alexander Potapenko  }
320ad91267d45fef531c1082ab7974e4cc78aba5280Alexander Potapenko  // internal_write(2, proc_self_maps_.data, proc_self_maps_.len);
3216895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov  Reset();
32293da8b6a5e0ed2ca621897504c5d06449b3d7077Alexander Potapenko  // FIXME: in the future we may want to cache the mappings on demand only.
32393da8b6a5e0ed2ca621897504c5d06449b3d7077Alexander Potapenko  CacheMemoryMappings();
3246895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov}
3256895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov
326e1f5dac9296df08ff83ae5fca51ce4da995b55cfAlexey SamsonovMemoryMappingLayout::~MemoryMappingLayout() {
3277385f8b8b8723064910cf9737dc929e90aeac548Alexander Potapenko  // Only unmap the buffer if it is different from the cached one. Otherwise
3287385f8b8b8723064910cf9737dc929e90aeac548Alexander Potapenko  // it will be unmapped when the cache is refreshed.
3297385f8b8b8723064910cf9737dc929e90aeac548Alexander Potapenko  if (proc_self_maps_.data != cached_proc_self_maps_.data) {
3307385f8b8b8723064910cf9737dc929e90aeac548Alexander Potapenko    UnmapOrDie(proc_self_maps_.data, proc_self_maps_.mmaped_size);
3317385f8b8b8723064910cf9737dc929e90aeac548Alexander Potapenko  }
3326895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov}
3336895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov
334e1f5dac9296df08ff83ae5fca51ce4da995b55cfAlexey Samsonovvoid MemoryMappingLayout::Reset() {
335ad91267d45fef531c1082ab7974e4cc78aba5280Alexander Potapenko  current_ = proc_self_maps_.data;
3366895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov}
3376895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov
33893da8b6a5e0ed2ca621897504c5d06449b3d7077Alexander Potapenko// static
33993da8b6a5e0ed2ca621897504c5d06449b3d7077Alexander Potapenkovoid MemoryMappingLayout::CacheMemoryMappings() {
34093da8b6a5e0ed2ca621897504c5d06449b3d7077Alexander Potapenko  SpinMutexLock l(&cache_lock_);
34193da8b6a5e0ed2ca621897504c5d06449b3d7077Alexander Potapenko  // Don't invalidate the cache if the mappings are unavailable.
342ad91267d45fef531c1082ab7974e4cc78aba5280Alexander Potapenko  ProcSelfMapsBuff old_proc_self_maps;
343ad91267d45fef531c1082ab7974e4cc78aba5280Alexander Potapenko  old_proc_self_maps = cached_proc_self_maps_;
344ad91267d45fef531c1082ab7974e4cc78aba5280Alexander Potapenko  cached_proc_self_maps_.len =
345ad91267d45fef531c1082ab7974e4cc78aba5280Alexander Potapenko      ReadFileToBuffer("/proc/self/maps", &cached_proc_self_maps_.data,
346ad91267d45fef531c1082ab7974e4cc78aba5280Alexander Potapenko                       &cached_proc_self_maps_.mmaped_size, 1 << 26);
347ad91267d45fef531c1082ab7974e4cc78aba5280Alexander Potapenko  if (cached_proc_self_maps_.mmaped_size == 0) {
348ad91267d45fef531c1082ab7974e4cc78aba5280Alexander Potapenko    cached_proc_self_maps_ = old_proc_self_maps;
34993da8b6a5e0ed2ca621897504c5d06449b3d7077Alexander Potapenko  } else {
350ad91267d45fef531c1082ab7974e4cc78aba5280Alexander Potapenko    if (old_proc_self_maps.mmaped_size) {
351ad91267d45fef531c1082ab7974e4cc78aba5280Alexander Potapenko      UnmapOrDie(old_proc_self_maps.data,
352ad91267d45fef531c1082ab7974e4cc78aba5280Alexander Potapenko                 old_proc_self_maps.mmaped_size);
35393da8b6a5e0ed2ca621897504c5d06449b3d7077Alexander Potapenko    }
35493da8b6a5e0ed2ca621897504c5d06449b3d7077Alexander Potapenko  }
35593da8b6a5e0ed2ca621897504c5d06449b3d7077Alexander Potapenko}
35693da8b6a5e0ed2ca621897504c5d06449b3d7077Alexander Potapenko
35793da8b6a5e0ed2ca621897504c5d06449b3d7077Alexander Potapenkovoid MemoryMappingLayout::LoadFromCache() {
35893da8b6a5e0ed2ca621897504c5d06449b3d7077Alexander Potapenko  SpinMutexLock l(&cache_lock_);
359ad91267d45fef531c1082ab7974e4cc78aba5280Alexander Potapenko  if (cached_proc_self_maps_.data) {
360286dd3f8afe6700e5dd9b0bdb7afd23121c98c12Dmitry Vyukov    proc_self_maps_ = cached_proc_self_maps_;
36193da8b6a5e0ed2ca621897504c5d06449b3d7077Alexander Potapenko  }
36293da8b6a5e0ed2ca621897504c5d06449b3d7077Alexander Potapenko}
36393da8b6a5e0ed2ca621897504c5d06449b3d7077Alexander Potapenko
364a4e4744778e6b3067f5cf223cf28bb586c1ecf67Kostya Serebryany// Parse a hex value in str and update str.
365a4e4744778e6b3067f5cf223cf28bb586c1ecf67Kostya Serebryanystatic uptr ParseHex(char **str) {
366a4e4744778e6b3067f5cf223cf28bb586c1ecf67Kostya Serebryany  uptr x = 0;
367a4e4744778e6b3067f5cf223cf28bb586c1ecf67Kostya Serebryany  char *s;
368a4e4744778e6b3067f5cf223cf28bb586c1ecf67Kostya Serebryany  for (s = *str; ; s++) {
369a4e4744778e6b3067f5cf223cf28bb586c1ecf67Kostya Serebryany    char c = *s;
370a4e4744778e6b3067f5cf223cf28bb586c1ecf67Kostya Serebryany    uptr v = 0;
371a4e4744778e6b3067f5cf223cf28bb586c1ecf67Kostya Serebryany    if (c >= '0' && c <= '9')
372a4e4744778e6b3067f5cf223cf28bb586c1ecf67Kostya Serebryany      v = c - '0';
373a4e4744778e6b3067f5cf223cf28bb586c1ecf67Kostya Serebryany    else if (c >= 'a' && c <= 'f')
374a4e4744778e6b3067f5cf223cf28bb586c1ecf67Kostya Serebryany      v = c - 'a' + 10;
375a4e4744778e6b3067f5cf223cf28bb586c1ecf67Kostya Serebryany    else if (c >= 'A' && c <= 'F')
376a4e4744778e6b3067f5cf223cf28bb586c1ecf67Kostya Serebryany      v = c - 'A' + 10;
377a4e4744778e6b3067f5cf223cf28bb586c1ecf67Kostya Serebryany    else
378a4e4744778e6b3067f5cf223cf28bb586c1ecf67Kostya Serebryany      break;
379a4e4744778e6b3067f5cf223cf28bb586c1ecf67Kostya Serebryany    x = x * 16 + v;
380a4e4744778e6b3067f5cf223cf28bb586c1ecf67Kostya Serebryany  }
381a4e4744778e6b3067f5cf223cf28bb586c1ecf67Kostya Serebryany  *str = s;
382a4e4744778e6b3067f5cf223cf28bb586c1ecf67Kostya Serebryany  return x;
383a4e4744778e6b3067f5cf223cf28bb586c1ecf67Kostya Serebryany}
384a4e4744778e6b3067f5cf223cf28bb586c1ecf67Kostya Serebryany
385ab11e0b10d077945a6e681766b41e12ac6aeb0f0Alexey Samsonovstatic bool IsOneOf(char c, char c1, char c2) {
386a4e4744778e6b3067f5cf223cf28bb586c1ecf67Kostya Serebryany  return c == c1 || c == c2;
387a4e4744778e6b3067f5cf223cf28bb586c1ecf67Kostya Serebryany}
388a4e4744778e6b3067f5cf223cf28bb586c1ecf67Kostya Serebryany
389a4e4744778e6b3067f5cf223cf28bb586c1ecf67Kostya Serebryanystatic bool IsDecimal(char c) {
390a4e4744778e6b3067f5cf223cf28bb586c1ecf67Kostya Serebryany  return c >= '0' && c <= '9';
391a4e4744778e6b3067f5cf223cf28bb586c1ecf67Kostya Serebryany}
392a4e4744778e6b3067f5cf223cf28bb586c1ecf67Kostya Serebryany
393e1f5dac9296df08ff83ae5fca51ce4da995b55cfAlexey Samsonovbool MemoryMappingLayout::Next(uptr *start, uptr *end, uptr *offset,
39445717c9d5e39a434749ae10509111f9df1b2cdf4Alexey Samsonov                               char filename[], uptr filename_size,
39545717c9d5e39a434749ae10509111f9df1b2cdf4Alexey Samsonov                               uptr *protection) {
396ad91267d45fef531c1082ab7974e4cc78aba5280Alexander Potapenko  char *last = proc_self_maps_.data + proc_self_maps_.len;
3976895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov  if (current_ >= last) return false;
3986895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov  uptr dummy;
3996895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov  if (!start) start = &dummy;
4006895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov  if (!end) end = &dummy;
4016895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov  if (!offset) offset = &dummy;
4026895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov  char *next_line = (char*)internal_memchr(current_, '\n', last - current_);
4036895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov  if (next_line == 0)
4046895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov    next_line = last;
405a4e4744778e6b3067f5cf223cf28bb586c1ecf67Kostya Serebryany  // Example: 08048000-08056000 r-xp 00000000 03:0c 64593   /foo/bar
406a4e4744778e6b3067f5cf223cf28bb586c1ecf67Kostya Serebryany  *start = ParseHex(&current_);
407bb8a9511bc748d6a4fd601d713bda584ef7bb772Kostya Serebryany  CHECK_EQ(*current_++, '-');
408a4e4744778e6b3067f5cf223cf28bb586c1ecf67Kostya Serebryany  *end = ParseHex(&current_);
409bb8a9511bc748d6a4fd601d713bda584ef7bb772Kostya Serebryany  CHECK_EQ(*current_++, ' ');
41045717c9d5e39a434749ae10509111f9df1b2cdf4Alexey Samsonov  uptr local_protection = 0;
411ab11e0b10d077945a6e681766b41e12ac6aeb0f0Alexey Samsonov  CHECK(IsOneOf(*current_, '-', 'r'));
41245717c9d5e39a434749ae10509111f9df1b2cdf4Alexey Samsonov  if (*current_++ == 'r')
41345717c9d5e39a434749ae10509111f9df1b2cdf4Alexey Samsonov    local_protection |= kProtectionRead;
414ab11e0b10d077945a6e681766b41e12ac6aeb0f0Alexey Samsonov  CHECK(IsOneOf(*current_, '-', 'w'));
41545717c9d5e39a434749ae10509111f9df1b2cdf4Alexey Samsonov  if (*current_++ == 'w')
41645717c9d5e39a434749ae10509111f9df1b2cdf4Alexey Samsonov    local_protection |= kProtectionWrite;
417ab11e0b10d077945a6e681766b41e12ac6aeb0f0Alexey Samsonov  CHECK(IsOneOf(*current_, '-', 'x'));
41845717c9d5e39a434749ae10509111f9df1b2cdf4Alexey Samsonov  if (*current_++ == 'x')
41945717c9d5e39a434749ae10509111f9df1b2cdf4Alexey Samsonov    local_protection |= kProtectionExecute;
420ab11e0b10d077945a6e681766b41e12ac6aeb0f0Alexey Samsonov  CHECK(IsOneOf(*current_, 's', 'p'));
42145717c9d5e39a434749ae10509111f9df1b2cdf4Alexey Samsonov  if (*current_++ == 's')
42245717c9d5e39a434749ae10509111f9df1b2cdf4Alexey Samsonov    local_protection |= kProtectionShared;
42345717c9d5e39a434749ae10509111f9df1b2cdf4Alexey Samsonov  if (protection) {
42445717c9d5e39a434749ae10509111f9df1b2cdf4Alexey Samsonov    *protection = local_protection;
42545717c9d5e39a434749ae10509111f9df1b2cdf4Alexey Samsonov  }
426bb8a9511bc748d6a4fd601d713bda584ef7bb772Kostya Serebryany  CHECK_EQ(*current_++, ' ');
427a4e4744778e6b3067f5cf223cf28bb586c1ecf67Kostya Serebryany  *offset = ParseHex(&current_);
428bb8a9511bc748d6a4fd601d713bda584ef7bb772Kostya Serebryany  CHECK_EQ(*current_++, ' ');
429a4e4744778e6b3067f5cf223cf28bb586c1ecf67Kostya Serebryany  ParseHex(&current_);
430bb8a9511bc748d6a4fd601d713bda584ef7bb772Kostya Serebryany  CHECK_EQ(*current_++, ':');
431a4e4744778e6b3067f5cf223cf28bb586c1ecf67Kostya Serebryany  ParseHex(&current_);
432bb8a9511bc748d6a4fd601d713bda584ef7bb772Kostya Serebryany  CHECK_EQ(*current_++, ' ');
433a4e4744778e6b3067f5cf223cf28bb586c1ecf67Kostya Serebryany  while (IsDecimal(*current_))
434a4e4744778e6b3067f5cf223cf28bb586c1ecf67Kostya Serebryany    current_++;
435bb8a9511bc748d6a4fd601d713bda584ef7bb772Kostya Serebryany  CHECK_EQ(*current_++, ' ');
4366895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov  // Skip spaces.
4376895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov  while (current_ < next_line && *current_ == ' ')
4386895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov    current_++;
4396895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov  // Fill in the filename.
4406895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov  uptr i = 0;
4416895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov  while (current_ < next_line) {
4426895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov    if (filename && i < filename_size - 1)
4436895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov      filename[i++] = *current_;
4446895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov    current_++;
4456895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov  }
4466895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov  if (filename && i < filename_size)
4476895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov    filename[i] = 0;
4486895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov  current_ = next_line + 1;
4496895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov  return true;
4506895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov}
4516895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov
452e1f5dac9296df08ff83ae5fca51ce4da995b55cfAlexey Samsonov// Gets the object name and the offset by walking MemoryMappingLayout.
453e1f5dac9296df08ff83ae5fca51ce4da995b55cfAlexey Samsonovbool MemoryMappingLayout::GetObjectNameAndOffset(uptr addr, uptr *offset,
454e1f5dac9296df08ff83ae5fca51ce4da995b55cfAlexey Samsonov                                                 char filename[],
45545717c9d5e39a434749ae10509111f9df1b2cdf4Alexey Samsonov                                                 uptr filename_size,
45645717c9d5e39a434749ae10509111f9df1b2cdf4Alexey Samsonov                                                 uptr *protection) {
45745717c9d5e39a434749ae10509111f9df1b2cdf4Alexey Samsonov  return IterateForObjectNameAndOffset(addr, offset, filename, filename_size,
45845717c9d5e39a434749ae10509111f9df1b2cdf4Alexey Samsonov                                       protection);
4596895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov}
4606895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov
461dddb18b7be36fe1843c8b98a8d9d7614aef5ce8dKostya Serebryanybool SanitizerSetThreadName(const char *name) {
462b10a5621daa804f3a2b18fbe75d5fed2a4aeadd3Kostya Serebryany#ifdef PR_SET_NAME
4631ec519c604021162de8bdb8d433fbad1c5033200Dmitry Vyukov  return 0 == prctl(PR_SET_NAME, (unsigned long)name, 0, 0, 0);  // NOLINT
464b10a5621daa804f3a2b18fbe75d5fed2a4aeadd3Kostya Serebryany#else
465b10a5621daa804f3a2b18fbe75d5fed2a4aeadd3Kostya Serebryany  return false;
466b10a5621daa804f3a2b18fbe75d5fed2a4aeadd3Kostya Serebryany#endif
467dddb18b7be36fe1843c8b98a8d9d7614aef5ce8dKostya Serebryany}
468dddb18b7be36fe1843c8b98a8d9d7614aef5ce8dKostya Serebryany
469dddb18b7be36fe1843c8b98a8d9d7614aef5ce8dKostya Serebryanybool SanitizerGetThreadName(char *name, int max_len) {
470b10a5621daa804f3a2b18fbe75d5fed2a4aeadd3Kostya Serebryany#ifdef PR_GET_NAME
471dddb18b7be36fe1843c8b98a8d9d7614aef5ce8dKostya Serebryany  char buff[17];
4721ec519c604021162de8bdb8d433fbad1c5033200Dmitry Vyukov  if (prctl(PR_GET_NAME, (unsigned long)buff, 0, 0, 0))  // NOLINT
473dddb18b7be36fe1843c8b98a8d9d7614aef5ce8dKostya Serebryany    return false;
474dddb18b7be36fe1843c8b98a8d9d7614aef5ce8dKostya Serebryany  internal_strncpy(name, buff, max_len);
475dddb18b7be36fe1843c8b98a8d9d7614aef5ce8dKostya Serebryany  name[max_len] = 0;
476dddb18b7be36fe1843c8b98a8d9d7614aef5ce8dKostya Serebryany  return true;
477b10a5621daa804f3a2b18fbe75d5fed2a4aeadd3Kostya Serebryany#else
478b10a5621daa804f3a2b18fbe75d5fed2a4aeadd3Kostya Serebryany  return false;
479b10a5621daa804f3a2b18fbe75d5fed2a4aeadd3Kostya Serebryany#endif
480dddb18b7be36fe1843c8b98a8d9d7614aef5ce8dKostya Serebryany}
481dddb18b7be36fe1843c8b98a8d9d7614aef5ce8dKostya Serebryany
4824fce4495502a3668cc4e99164ffcaea92e534d48Dmitry Vyukov#ifndef SANITIZER_GO
483a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryany//------------------------- SlowUnwindStack -----------------------------------
484a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryany#ifdef __arm__
485a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryany#define UNWIND_STOP _URC_END_OF_STACK
486a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryany#define UNWIND_CONTINUE _URC_NO_REASON
487a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryany#else
488a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryany#define UNWIND_STOP _URC_NORMAL_STOP
489a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryany#define UNWIND_CONTINUE _URC_NO_REASON
490a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryany#endif
491a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryany
492a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryanyuptr Unwind_GetIP(struct _Unwind_Context *ctx) {
493a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryany#ifdef __arm__
494a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryany  uptr val;
495a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryany  _Unwind_VRS_Result res = _Unwind_VRS_Get(ctx, _UVRSC_CORE,
496a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryany      15 /* r15 = PC */, _UVRSD_UINT32, &val);
497a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryany  CHECK(res == _UVRSR_OK && "_Unwind_VRS_Get failed");
498a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryany  // Clear the Thumb bit.
499a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryany  return val & ~(uptr)1;
500a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryany#else
501a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryany  return _Unwind_GetIP(ctx);
502a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryany#endif
503a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryany}
504a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryany
505a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryany_Unwind_Reason_Code Unwind_Trace(struct _Unwind_Context *ctx, void *param) {
506a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryany  StackTrace *b = (StackTrace*)param;
507a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryany  CHECK(b->size < b->max_size);
508a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryany  uptr pc = Unwind_GetIP(ctx);
509a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryany  b->trace[b->size++] = pc;
510a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryany  if (b->size == b->max_size) return UNWIND_STOP;
511a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryany  return UNWIND_CONTINUE;
512a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryany}
513a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryany
51449d616ec42ab420ce3ebcbe846b21e3729adf5acKostya Serebryanystatic bool MatchPc(uptr cur_pc, uptr trace_pc) {
5155e10443518154a9d68d299ef65a0a99ed42193b7Kostya Serebryany  return cur_pc - trace_pc <= 64 || trace_pc - cur_pc <= 64;
51649d616ec42ab420ce3ebcbe846b21e3729adf5acKostya Serebryany}
51749d616ec42ab420ce3ebcbe846b21e3729adf5acKostya Serebryany
51849d616ec42ab420ce3ebcbe846b21e3729adf5acKostya Serebryanyvoid StackTrace::SlowUnwindStack(uptr pc, uptr max_depth) {
519a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryany  this->size = 0;
520a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryany  this->max_size = max_depth;
521a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryany  if (max_depth > 1) {
522a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryany    _Unwind_Backtrace(Unwind_Trace, this);
5235e10443518154a9d68d299ef65a0a99ed42193b7Kostya Serebryany    // We need to pop a few frames so that pc is on top.
5245e10443518154a9d68d299ef65a0a99ed42193b7Kostya Serebryany    // trace[0] belongs to the current function so we always pop it.
52549d616ec42ab420ce3ebcbe846b21e3729adf5acKostya Serebryany    int to_pop = 1;
5265e10443518154a9d68d299ef65a0a99ed42193b7Kostya Serebryany    /**/ if (size > 1 && MatchPc(pc, trace[1])) to_pop = 1;
5275e10443518154a9d68d299ef65a0a99ed42193b7Kostya Serebryany    else if (size > 2 && MatchPc(pc, trace[2])) to_pop = 2;
5285e10443518154a9d68d299ef65a0a99ed42193b7Kostya Serebryany    else if (size > 3 && MatchPc(pc, trace[3])) to_pop = 3;
5295e10443518154a9d68d299ef65a0a99ed42193b7Kostya Serebryany    else if (size > 4 && MatchPc(pc, trace[4])) to_pop = 4;
5305e10443518154a9d68d299ef65a0a99ed42193b7Kostya Serebryany    else if (size > 5 && MatchPc(pc, trace[5])) to_pop = 5;
53149d616ec42ab420ce3ebcbe846b21e3729adf5acKostya Serebryany    this->PopStackFrames(to_pop);
532a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryany  }
53349d616ec42ab420ce3ebcbe846b21e3729adf5acKostya Serebryany  this->trace[0] = pc;
534a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryany}
535a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryany
5364fce4495502a3668cc4e99164ffcaea92e534d48Dmitry Vyukov#endif  // #ifndef SANITIZER_GO
5374fce4495502a3668cc4e99164ffcaea92e534d48Dmitry Vyukov
538f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukovenum MutexState {
539f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov  MtxUnlocked = 0,
540f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov  MtxLocked = 1,
541f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov  MtxSleeping = 2
542f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov};
543f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov
544f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry VyukovBlockingMutex::BlockingMutex(LinkerInitialized) {
545d164ed175a61529589938b3db3cab076a19acf67Dmitry Vyukov  CHECK_EQ(owner_, 0);
546f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov}
547f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov
54893af5948d3e0c5bdc396f432dd0ae782f499c449Alexey SamsonovBlockingMutex::BlockingMutex() {
54993af5948d3e0c5bdc396f432dd0ae782f499c449Alexey Samsonov  internal_memset(this, 0, sizeof(*this));
55093af5948d3e0c5bdc396f432dd0ae782f499c449Alexey Samsonov}
55193af5948d3e0c5bdc396f432dd0ae782f499c449Alexey Samsonov
552f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukovvoid BlockingMutex::Lock() {
553f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov  atomic_uint32_t *m = reinterpret_cast<atomic_uint32_t *>(&opaque_storage_);
554f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov  if (atomic_exchange(m, MtxLocked, memory_order_acquire) == MtxUnlocked)
555f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov    return;
556f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov  while (atomic_exchange(m, MtxSleeping, memory_order_acquire) != MtxUnlocked)
557c0dbb80bf0eac2771da6faefa5c22155ed4fd33bDmitry Vyukov    syscall(__NR_futex, m, FUTEX_WAIT, MtxSleeping, 0, 0, 0);
558f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov}
559f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov
560f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukovvoid BlockingMutex::Unlock() {
561f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov  atomic_uint32_t *m = reinterpret_cast<atomic_uint32_t *>(&opaque_storage_);
562f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov  u32 v = atomic_exchange(m, MtxUnlocked, memory_order_relaxed);
56348526014de78e21f7ed027a60670016bc7f5d292Dmitry Vyukov  CHECK_NE(v, MtxUnlocked);
564f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov  if (v == MtxSleeping)
565c0dbb80bf0eac2771da6faefa5c22155ed4fd33bDmitry Vyukov    syscall(__NR_futex, m, FUTEX_WAKE, 1, 0, 0, 0);
566f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov}
567f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov
568ce700979f644c790c2d9d80f5cc2a1ada0380284Alexey Samsonovvoid BlockingMutex::CheckLocked() {
569ce700979f644c790c2d9d80f5cc2a1ada0380284Alexey Samsonov  atomic_uint32_t *m = reinterpret_cast<atomic_uint32_t *>(&opaque_storage_);
570ce700979f644c790c2d9d80f5cc2a1ada0380284Alexey Samsonov  CHECK_NE(MtxUnlocked, atomic_load(m, memory_order_relaxed));
571ce700979f644c790c2d9d80f5cc2a1ada0380284Alexey Samsonov}
572ce700979f644c790c2d9d80f5cc2a1ada0380284Alexey Samsonov
5736fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany// ----------------- sanitizer_linux.h
5746fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany// The actual size of this structure is specified by d_reclen.
5756fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany// Note that getdents64 uses a different structure format. We only provide the
5766fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany// 32-bit syscall here.
5776fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryanystruct linux_dirent {
5786fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany  unsigned long      d_ino;
5796fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany  unsigned long      d_off;
5806fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany  unsigned short     d_reclen;
5816fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany  char               d_name[256];
5826fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany};
5836fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany
5846fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany// Syscall wrappers.
5856fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryanylong internal_ptrace(int request, int pid, void *addr, void *data) {
5866fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany  return syscall(__NR_ptrace, request, pid, addr, data);
5876fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany}
5886fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany
5896fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryanyint internal_waitpid(int pid, int *status, int options) {
5906fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany  return syscall(__NR_wait4, pid, status, options, NULL /* rusage */);
5916fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany}
5926fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany
5936fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryanyint internal_getppid() {
5946fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany  return syscall(__NR_getppid);
5956fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany}
5966fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany
5976fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryanyint internal_getdents(fd_t fd, struct linux_dirent *dirp, unsigned int count) {
5986fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany  return syscall(__NR_getdents, fd, dirp, count);
5996fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany}
6006fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany
6016fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya SerebryanyOFF_T internal_lseek(fd_t fd, OFF_T offset, int whence) {
6026fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany  return syscall(__NR_lseek, fd, offset, whence);
6036fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany}
6046fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany
6056fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryanyint internal_prctl(int option, uptr arg2, uptr arg3, uptr arg4, uptr arg5) {
6066fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany  return syscall(__NR_prctl, option, arg2, arg3, arg4, arg5);
6076fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany}
6086fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany
6096fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryanyint internal_sigaltstack(const struct sigaltstack *ss,
6106fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany                         struct sigaltstack *oss) {
6116fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany  return syscall(__NR_sigaltstack, ss, oss);
6126fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany}
6136fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany
6146fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany
6156fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany// ThreadLister implementation.
6166fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya SerebryanyThreadLister::ThreadLister(int pid)
6176fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany  : pid_(pid),
6186fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany    descriptor_(-1),
6196fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany    error_(true),
6206fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany    entry_((linux_dirent *)buffer_),
6216fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany    bytes_read_(0) {
6226fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany  char task_directory_path[80];
6236fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany  internal_snprintf(task_directory_path, sizeof(task_directory_path),
6246fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany                    "/proc/%d/task/", pid);
6256fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany  descriptor_ = internal_open(task_directory_path, O_RDONLY | O_DIRECTORY);
6266fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany  if (descriptor_ < 0) {
6276fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany    error_ = true;
6286fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany    Report("Can't open /proc/%d/task for reading.\n", pid);
6296fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany  } else {
6306fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany    error_ = false;
6316fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany  }
6326fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany}
6336fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany
6346fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryanyint ThreadLister::GetNextTID() {
6356fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany  int tid = -1;
6366fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany  do {
6376fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany    if (error_)
6386fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany      return -1;
6396fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany    if ((char *)entry_ >= &buffer_[bytes_read_] && !GetDirectoryEntries())
6406fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany      return -1;
6416fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany    if (entry_->d_ino != 0 && entry_->d_name[0] >= '0' &&
6426fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany        entry_->d_name[0] <= '9') {
6436fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany      // Found a valid tid.
6446fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany      tid = (int)internal_atoll(entry_->d_name);
6456fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany    }
6466fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany    entry_ = (struct linux_dirent *)(((char *)entry_) + entry_->d_reclen);
6476fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany  } while (tid < 0);
6486fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany  return tid;
6496fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany}
6506fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany
6516fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryanyvoid ThreadLister::Reset() {
6526fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany  if (error_ || descriptor_ < 0)
6536fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany    return;
6546fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany  internal_lseek(descriptor_, 0, SEEK_SET);
6556fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany}
6566fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany
6576fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya SerebryanyThreadLister::~ThreadLister() {
6586fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany  if (descriptor_ >= 0)
6596fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany    internal_close(descriptor_);
6606fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany}
6616fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany
6626fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryanybool ThreadLister::error() { return error_; }
6636fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany
6646fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryanybool ThreadLister::GetDirectoryEntries() {
6656fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany  CHECK_GE(descriptor_, 0);
6666fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany  CHECK_NE(error_, true);
6676fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany  bytes_read_ = internal_getdents(descriptor_,
6686fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany                                  (struct linux_dirent *)buffer_,
6696fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany                                  sizeof(buffer_));
6706fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany  if (bytes_read_ < 0) {
6716fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany    Report("Can't read directory entries from /proc/%d/task.\n", pid_);
6726fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany    error_ = true;
6736fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany    return false;
6746fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany  } else if (bytes_read_ == 0) {
6756fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany    return false;
6766fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany  }
6776fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany  entry_ = (struct linux_dirent *)buffer_;
6786fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany  return true;
6796fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany}
6806fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany
681b114ed83859d8d4964ac2284584733bcd2acf4f6Evgeniy Stepanovstatic uptr g_tls_size;
682b114ed83859d8d4964ac2284584733bcd2acf4f6Evgeniy Stepanov
683b114ed83859d8d4964ac2284584733bcd2acf4f6Evgeniy Stepanov#ifdef __i386__
684b114ed83859d8d4964ac2284584733bcd2acf4f6Evgeniy Stepanov# define DL_INTERNAL_FUNCTION __attribute__((regparm(3), stdcall))
685b114ed83859d8d4964ac2284584733bcd2acf4f6Evgeniy Stepanov#else
686b114ed83859d8d4964ac2284584733bcd2acf4f6Evgeniy Stepanov# define DL_INTERNAL_FUNCTION
687b114ed83859d8d4964ac2284584733bcd2acf4f6Evgeniy Stepanov#endif
688b114ed83859d8d4964ac2284584733bcd2acf4f6Evgeniy Stepanov
689b114ed83859d8d4964ac2284584733bcd2acf4f6Evgeniy Stepanovvoid InitTlsSize() {
690b114ed83859d8d4964ac2284584733bcd2acf4f6Evgeniy Stepanov#ifndef SANITIZER_GO
691b114ed83859d8d4964ac2284584733bcd2acf4f6Evgeniy Stepanov  typedef void (*get_tls_func)(size_t*, size_t*) DL_INTERNAL_FUNCTION;
692b114ed83859d8d4964ac2284584733bcd2acf4f6Evgeniy Stepanov  get_tls_func get_tls;
693b114ed83859d8d4964ac2284584733bcd2acf4f6Evgeniy Stepanov  void *get_tls_static_info_ptr = dlsym(RTLD_NEXT, "_dl_get_tls_static_info");
694b114ed83859d8d4964ac2284584733bcd2acf4f6Evgeniy Stepanov  CHECK_EQ(sizeof(get_tls), sizeof(get_tls_static_info_ptr));
695b114ed83859d8d4964ac2284584733bcd2acf4f6Evgeniy Stepanov  internal_memcpy(&get_tls, &get_tls_static_info_ptr,
696b114ed83859d8d4964ac2284584733bcd2acf4f6Evgeniy Stepanov                  sizeof(get_tls_static_info_ptr));
697b114ed83859d8d4964ac2284584733bcd2acf4f6Evgeniy Stepanov  CHECK_NE(get_tls, 0);
698b114ed83859d8d4964ac2284584733bcd2acf4f6Evgeniy Stepanov  size_t tls_size = 0;
699b114ed83859d8d4964ac2284584733bcd2acf4f6Evgeniy Stepanov  size_t tls_align = 0;
700b114ed83859d8d4964ac2284584733bcd2acf4f6Evgeniy Stepanov  get_tls(&tls_size, &tls_align);
701b114ed83859d8d4964ac2284584733bcd2acf4f6Evgeniy Stepanov  g_tls_size = tls_size;
702b114ed83859d8d4964ac2284584733bcd2acf4f6Evgeniy Stepanov#endif
703b114ed83859d8d4964ac2284584733bcd2acf4f6Evgeniy Stepanov}
704b114ed83859d8d4964ac2284584733bcd2acf4f6Evgeniy Stepanov
705b114ed83859d8d4964ac2284584733bcd2acf4f6Evgeniy Stepanovuptr GetTlsSize() {
706b114ed83859d8d4964ac2284584733bcd2acf4f6Evgeniy Stepanov  return g_tls_size;
707b114ed83859d8d4964ac2284584733bcd2acf4f6Evgeniy Stepanov}
708b114ed83859d8d4964ac2284584733bcd2acf4f6Evgeniy Stepanov
709ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov}  // namespace __sanitizer
710ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov
711ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov#endif  // __linux__
712