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"
162d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#if SANITIZER_FREEBSD || SANITIZER_LINUX
17ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov
186895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov#include "sanitizer_common.h"
192d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#include "sanitizer_flags.h"
2094b5036ee6ba866e1702848855b6d687d1e70afaAlexey Samsonov#include "sanitizer_internal_defs.h"
21ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov#include "sanitizer_libc.h"
226fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany#include "sanitizer_linux.h"
2393da8b6a5e0ed2ca621897504c5d06449b3d7077Alexander Potapenko#include "sanitizer_mutex.h"
24a68633fb76208137ccb807914df52758ee5ca6f0Alexey Samsonov#include "sanitizer_placement_new.h"
256895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov#include "sanitizer_procmaps.h"
26a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryany#include "sanitizer_stacktrace.h"
275ce93fc96ab5e2defd85890da63b51cc4c57a2afAlexander Potapenko#include "sanitizer_symbolizer.h"
28ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov
292d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#if !SANITIZER_FREEBSD
30088ea2b46f97172bd0b0663a629e11cf826b84f7Peter Collingbourne#include <asm/param.h>
312d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#endif
322d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
33b114ed83859d8d4964ac2284584733bcd2acf4f6Evgeniy Stepanov#include <dlfcn.h>
3435a7faf1fbfac678136e79d53824672dafb7d13eAlexey Samsonov#include <errno.h>
35c5d465136b911bf925f2a631e2b79f1c03e8a1b0Alexey Samsonov#include <fcntl.h>
366d40a0a2ffa6735e45bd1d62c94ff725fd3e8b71Peter Collingbourne#if !SANITIZER_ANDROID
372e75ac983cb233daa1abfa35fb33d2bafffe2ab1Peter Collingbourne#include <link.h>
386d40a0a2ffa6735e45bd1d62c94ff725fd3e8b71Peter Collingbourne#endif
39e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov#include <pthread.h>
400969bcf2c936126b1f6e636b978aade8fc207437Alexey Samsonov#include <sched.h>
41ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov#include <sys/mman.h>
426fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany#include <sys/ptrace.h>
43e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov#include <sys/resource.h>
44c5d465136b911bf925f2a631e2b79f1c03e8a1b0Alexey Samsonov#include <sys/stat.h>
45ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov#include <sys/syscall.h>
46e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov#include <sys/time.h>
47ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov#include <sys/types.h>
48ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov#include <unistd.h>
4935a7faf1fbfac678136e79d53824672dafb7d13eAlexey Samsonov
502d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#if SANITIZER_FREEBSD
515d71de26cedae3dafc17449fe0182045c0bd20e8Stephen Hines#include <sys/sysctl.h>
522d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#include <machine/atomic.h>
532d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesextern "C" {
542d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines// <sys/umtx.h> must be included after <errno.h> and <sys/types.h> on
552d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines// FreeBSD 9.2 and 10.0.
562d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#include <sys/umtx.h>
572d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines}
585d71de26cedae3dafc17449fe0182045c0bd20e8Stephen Hinesextern char **environ;  // provided by crt1
592d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#endif  // SANITIZER_FREEBSD
602d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
6124e13723f8477d8c42ab8b2a7f4f69fc089842f1Evgeniy Stepanov#if !SANITIZER_ANDROID
6235a7faf1fbfac678136e79d53824672dafb7d13eAlexey Samsonov#include <sys/signal.h>
6335a7faf1fbfac678136e79d53824672dafb7d13eAlexey Samsonov#endif
64fa5c41eddf77a3614da0f62044ebf741d86aeab7Dmitry Vyukov
652d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#if SANITIZER_ANDROID
662d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#include <android/log.h>
672d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#include <sys/system_properties.h>
682d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#endif
692d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
702d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#if SANITIZER_LINUX
714bebe7bab966c82f0a8952f797ed3d490624dc62Dmitry Vyukov// <linux/time.h>
724bebe7bab966c82f0a8952f797ed3d490624dc62Dmitry Vyukovstruct kernel_timeval {
734bebe7bab966c82f0a8952f797ed3d490624dc62Dmitry Vyukov  long tv_sec;
744bebe7bab966c82f0a8952f797ed3d490624dc62Dmitry Vyukov  long tv_usec;
754bebe7bab966c82f0a8952f797ed3d490624dc62Dmitry Vyukov};
764bebe7bab966c82f0a8952f797ed3d490624dc62Dmitry Vyukov
77fa5c41eddf77a3614da0f62044ebf741d86aeab7Dmitry Vyukov// <linux/futex.h> is broken on some linux distributions.
78fa5c41eddf77a3614da0f62044ebf741d86aeab7Dmitry Vyukovconst int FUTEX_WAIT = 0;
79fa5c41eddf77a3614da0f62044ebf741d86aeab7Dmitry Vyukovconst int FUTEX_WAKE = 1;
802d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#endif  // SANITIZER_LINUX
81ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov
822d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines// Are we using 32-bit or 64-bit Linux syscalls?
835af39e50366f1aacbebc284f572f08ad1ad07357Kostya Serebryany// x32 (which defines __x86_64__) has SANITIZER_WORDSIZE == 32
8408bfe4988de493dd3e61d02759b3f19c42f8fb78Kostya Serebryany// but it still needs to use 64-bit syscalls.
852d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#if SANITIZER_LINUX && (defined(__x86_64__) || SANITIZER_WORDSIZE == 64)
869d0dbbaf33e5c2fe280f141e30be497d62b703a8Kostya Serebryany# define SANITIZER_LINUX_USES_64BIT_SYSCALLS 1
879d0dbbaf33e5c2fe280f141e30be497d62b703a8Kostya Serebryany#else
889d0dbbaf33e5c2fe280f141e30be497d62b703a8Kostya Serebryany# define SANITIZER_LINUX_USES_64BIT_SYSCALLS 0
899d0dbbaf33e5c2fe280f141e30be497d62b703a8Kostya Serebryany#endif
909d0dbbaf33e5c2fe280f141e30be497d62b703a8Kostya Serebryany
91ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonovnamespace __sanitizer {
92ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov
932d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#if SANITIZER_LINUX && defined(__x86_64__)
949578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne#include "sanitizer_syscall_linux_x86_64.inc"
959578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne#else
969578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne#include "sanitizer_syscall_generic.inc"
979578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne#endif
989578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne
99e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov// --------------- sanitizer_libc.h
1009578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourneuptr internal_mmap(void *addr, uptr length, int prot, int flags,
101ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov                    int fd, u64 offset) {
1022d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#if SANITIZER_FREEBSD || SANITIZER_LINUX_USES_64BIT_SYSCALLS
1032d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  return internal_syscall(SYSCALL(mmap), (uptr)addr, length, prot, flags, fd,
104e041c6024b3ebf1365c0f99732fc69c607577571Kostya Serebryany                          offset);
105ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov#else
1062d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  return internal_syscall(SYSCALL(mmap2), addr, length, prot, flags, fd,
1072d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines                          offset);
108ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov#endif
109ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov}
110ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov
1119578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourneuptr internal_munmap(void *addr, uptr length) {
1122d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  return internal_syscall(SYSCALL(munmap), (uptr)addr, length);
1131f11d31faa5ed89b74f7d543b1182fe8de198be5Alexey Samsonov}
1141f11d31faa5ed89b74f7d543b1182fe8de198be5Alexey Samsonov
1159578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourneuptr internal_close(fd_t fd) {
1162d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  return internal_syscall(SYSCALL(close), fd);
117a56aefd2e01940fcf88d1426f9de3d5e4b1ee203Alexey Samsonov}
118a56aefd2e01940fcf88d1426f9de3d5e4b1ee203Alexey Samsonov
1199578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourneuptr internal_open(const char *filename, int flags) {
1202d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#if SANITIZER_USES_CANONICAL_LINUX_SYSCALLS
1212d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  return internal_syscall(SYSCALL(openat), AT_FDCWD, (uptr)filename, flags);
1222d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#else
1232d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  return internal_syscall(SYSCALL(open), (uptr)filename, flags);
1242d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#endif
125ee7cc4454421a176d23442382afd9a01d36e7ad4Alexey Samsonov}
126ee7cc4454421a176d23442382afd9a01d36e7ad4Alexey Samsonov
1279578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourneuptr internal_open(const char *filename, int flags, u32 mode) {
1282d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#if SANITIZER_USES_CANONICAL_LINUX_SYSCALLS
1292d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  return internal_syscall(SYSCALL(openat), AT_FDCWD, (uptr)filename, flags,
1302d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines                          mode);
1312d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#else
1322d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  return internal_syscall(SYSCALL(open), (uptr)filename, flags, mode);
1332d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#endif
134ee7cc4454421a176d23442382afd9a01d36e7ad4Alexey Samsonov}
135ee7cc4454421a176d23442382afd9a01d36e7ad4Alexey Samsonov
1369578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourneuptr OpenFile(const char *filename, bool write) {
137ee7cc4454421a176d23442382afd9a01d36e7ad4Alexey Samsonov  return internal_open(filename,
1382d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines      write ? O_RDWR | O_CREAT /*| O_CLOEXEC*/ : O_RDONLY, 0660);
139c5d465136b911bf925f2a631e2b79f1c03e8a1b0Alexey Samsonov}
140c5d465136b911bf925f2a631e2b79f1c03e8a1b0Alexey Samsonov
141a56aefd2e01940fcf88d1426f9de3d5e4b1ee203Alexey Samsonovuptr internal_read(fd_t fd, void *buf, uptr count) {
1423334e12d33261cb8f211f2f49f28ddfa027a40c3Evgeniy Stepanov  sptr res;
1432d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  HANDLE_EINTR(res, (sptr)internal_syscall(SYSCALL(read), fd, (uptr)buf,
1442d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines               count));
1453334e12d33261cb8f211f2f49f28ddfa027a40c3Evgeniy Stepanov  return res;
146a56aefd2e01940fcf88d1426f9de3d5e4b1ee203Alexey Samsonov}
147a56aefd2e01940fcf88d1426f9de3d5e4b1ee203Alexey Samsonov
148a56aefd2e01940fcf88d1426f9de3d5e4b1ee203Alexey Samsonovuptr internal_write(fd_t fd, const void *buf, uptr count) {
1493334e12d33261cb8f211f2f49f28ddfa027a40c3Evgeniy Stepanov  sptr res;
1502d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  HANDLE_EINTR(res, (sptr)internal_syscall(SYSCALL(write), fd, (uptr)buf,
1512d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines               count));
1523334e12d33261cb8f211f2f49f28ddfa027a40c3Evgeniy Stepanov  return res;
153a56aefd2e01940fcf88d1426f9de3d5e4b1ee203Alexey Samsonov}
154a56aefd2e01940fcf88d1426f9de3d5e4b1ee203Alexey Samsonov
1552d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesuptr internal_ftruncate(fd_t fd, uptr size) {
1562d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  sptr res;
1572d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  HANDLE_EINTR(res, (sptr)internal_syscall(SYSCALL(ftruncate), fd, size));
1582d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  return res;
1592d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines}
1602d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
1612d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#if !SANITIZER_LINUX_USES_64BIT_SYSCALLS && !SANITIZER_FREEBSD
1622be3a283939d4fc14ad86f6cd8be34b1468f22baEvgeniy Stepanovstatic void stat64_to_stat(struct stat64 *in, struct stat *out) {
1632be3a283939d4fc14ad86f6cd8be34b1468f22baEvgeniy Stepanov  internal_memset(out, 0, sizeof(*out));
1642be3a283939d4fc14ad86f6cd8be34b1468f22baEvgeniy Stepanov  out->st_dev = in->st_dev;
1652be3a283939d4fc14ad86f6cd8be34b1468f22baEvgeniy Stepanov  out->st_ino = in->st_ino;
1662be3a283939d4fc14ad86f6cd8be34b1468f22baEvgeniy Stepanov  out->st_mode = in->st_mode;
1672be3a283939d4fc14ad86f6cd8be34b1468f22baEvgeniy Stepanov  out->st_nlink = in->st_nlink;
1682be3a283939d4fc14ad86f6cd8be34b1468f22baEvgeniy Stepanov  out->st_uid = in->st_uid;
1692be3a283939d4fc14ad86f6cd8be34b1468f22baEvgeniy Stepanov  out->st_gid = in->st_gid;
1702be3a283939d4fc14ad86f6cd8be34b1468f22baEvgeniy Stepanov  out->st_rdev = in->st_rdev;
1712be3a283939d4fc14ad86f6cd8be34b1468f22baEvgeniy Stepanov  out->st_size = in->st_size;
1722be3a283939d4fc14ad86f6cd8be34b1468f22baEvgeniy Stepanov  out->st_blksize = in->st_blksize;
1732be3a283939d4fc14ad86f6cd8be34b1468f22baEvgeniy Stepanov  out->st_blocks = in->st_blocks;
1742be3a283939d4fc14ad86f6cd8be34b1468f22baEvgeniy Stepanov  out->st_atime = in->st_atime;
1752be3a283939d4fc14ad86f6cd8be34b1468f22baEvgeniy Stepanov  out->st_mtime = in->st_mtime;
1762be3a283939d4fc14ad86f6cd8be34b1468f22baEvgeniy Stepanov  out->st_ctime = in->st_ctime;
1772be3a283939d4fc14ad86f6cd8be34b1468f22baEvgeniy Stepanov  out->st_ino = in->st_ino;
1782be3a283939d4fc14ad86f6cd8be34b1468f22baEvgeniy Stepanov}
1792be3a283939d4fc14ad86f6cd8be34b1468f22baEvgeniy Stepanov#endif
1802be3a283939d4fc14ad86f6cd8be34b1468f22baEvgeniy Stepanov
1819578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourneuptr internal_stat(const char *path, void *buf) {
1822d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#if SANITIZER_FREEBSD
1832d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  return internal_syscall(SYSCALL(stat), path, buf);
1842d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#elif SANITIZER_USES_CANONICAL_LINUX_SYSCALLS
1852d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  return internal_syscall(SYSCALL(newfstatat), AT_FDCWD, (uptr)path,
1862d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines                          (uptr)buf, 0);
1872d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#elif SANITIZER_LINUX_USES_64BIT_SYSCALLS
1882d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  return internal_syscall(SYSCALL(stat), (uptr)path, (uptr)buf);
1894c9317a7b61e136f832d2ede70f557963fd46bceAlexey Samsonov#else
1902be3a283939d4fc14ad86f6cd8be34b1468f22baEvgeniy Stepanov  struct stat64 buf64;
1912d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  int res = internal_syscall(SYSCALL(stat64), path, &buf64);
1922be3a283939d4fc14ad86f6cd8be34b1468f22baEvgeniy Stepanov  stat64_to_stat(&buf64, (struct stat *)buf);
1932be3a283939d4fc14ad86f6cd8be34b1468f22baEvgeniy Stepanov  return res;
1944c9317a7b61e136f832d2ede70f557963fd46bceAlexey Samsonov#endif
1954c9317a7b61e136f832d2ede70f557963fd46bceAlexey Samsonov}
1964c9317a7b61e136f832d2ede70f557963fd46bceAlexey Samsonov
1979578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourneuptr internal_lstat(const char *path, void *buf) {
1982d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#if SANITIZER_FREEBSD
1992d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  return internal_syscall(SYSCALL(lstat), path, buf);
2002d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#elif SANITIZER_USES_CANONICAL_LINUX_SYSCALLS
2012d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  return internal_syscall(SYSCALL(newfstatat), AT_FDCWD, (uptr)path,
2022d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines                         (uptr)buf, AT_SYMLINK_NOFOLLOW);
2032d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#elif SANITIZER_LINUX_USES_64BIT_SYSCALLS
2042d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  return internal_syscall(SYSCALL(lstat), (uptr)path, (uptr)buf);
2054c9317a7b61e136f832d2ede70f557963fd46bceAlexey Samsonov#else
2062be3a283939d4fc14ad86f6cd8be34b1468f22baEvgeniy Stepanov  struct stat64 buf64;
2072d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  int res = internal_syscall(SYSCALL(lstat64), path, &buf64);
2082be3a283939d4fc14ad86f6cd8be34b1468f22baEvgeniy Stepanov  stat64_to_stat(&buf64, (struct stat *)buf);
2092be3a283939d4fc14ad86f6cd8be34b1468f22baEvgeniy Stepanov  return res;
2104c9317a7b61e136f832d2ede70f557963fd46bceAlexey Samsonov#endif
2114c9317a7b61e136f832d2ede70f557963fd46bceAlexey Samsonov}
2124c9317a7b61e136f832d2ede70f557963fd46bceAlexey Samsonov
2139578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourneuptr internal_fstat(fd_t fd, void *buf) {
2142d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#if SANITIZER_FREEBSD || SANITIZER_LINUX_USES_64BIT_SYSCALLS
2152d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  return internal_syscall(SYSCALL(fstat), fd, (uptr)buf);
2164c9317a7b61e136f832d2ede70f557963fd46bceAlexey Samsonov#else
2172be3a283939d4fc14ad86f6cd8be34b1468f22baEvgeniy Stepanov  struct stat64 buf64;
2182d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  int res = internal_syscall(SYSCALL(fstat64), fd, &buf64);
2192be3a283939d4fc14ad86f6cd8be34b1468f22baEvgeniy Stepanov  stat64_to_stat(&buf64, (struct stat *)buf);
2202be3a283939d4fc14ad86f6cd8be34b1468f22baEvgeniy Stepanov  return res;
2214c9317a7b61e136f832d2ede70f557963fd46bceAlexey Samsonov#endif
2224c9317a7b61e136f832d2ede70f557963fd46bceAlexey Samsonov}
2234c9317a7b61e136f832d2ede70f557963fd46bceAlexey Samsonov
2248e820fcf7aafeb8101322182d742fcf99255d972Alexey Samsonovuptr internal_filesize(fd_t fd) {
225a68633fb76208137ccb807914df52758ee5ca6f0Alexey Samsonov  struct stat st;
2264c9317a7b61e136f832d2ede70f557963fd46bceAlexey Samsonov  if (internal_fstat(fd, &st))
2274c9317a7b61e136f832d2ede70f557963fd46bceAlexey Samsonov    return -1;
2288e820fcf7aafeb8101322182d742fcf99255d972Alexey Samsonov  return (uptr)st.st_size;
2298e820fcf7aafeb8101322182d742fcf99255d972Alexey Samsonov}
2308e820fcf7aafeb8101322182d742fcf99255d972Alexey Samsonov
2319578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourneuptr internal_dup2(int oldfd, int newfd) {
2322d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#if SANITIZER_USES_CANONICAL_LINUX_SYSCALLS
2332d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  return internal_syscall(SYSCALL(dup3), oldfd, newfd, 0);
2342d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#else
2352d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  return internal_syscall(SYSCALL(dup2), oldfd, newfd);
2362d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#endif
2378e820fcf7aafeb8101322182d742fcf99255d972Alexey Samsonov}
2388e820fcf7aafeb8101322182d742fcf99255d972Alexey Samsonov
239d1b8f588d6b712b6ff2b3d58c73d71614f520122Alexey Samsonovuptr internal_readlink(const char *path, char *buf, uptr bufsize) {
2402d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#if SANITIZER_USES_CANONICAL_LINUX_SYSCALLS
2412d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  return internal_syscall(SYSCALL(readlinkat), AT_FDCWD,
2422d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines                          (uptr)path, (uptr)buf, bufsize);
2432d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#else
2442d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  return internal_syscall(SYSCALL(readlink), (uptr)path, (uptr)buf, bufsize);
2452d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#endif
246d1b8f588d6b712b6ff2b3d58c73d71614f520122Alexey Samsonov}
247d1b8f588d6b712b6ff2b3d58c73d71614f520122Alexey Samsonov
2489578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourneuptr internal_unlink(const char *path) {
2492d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#if SANITIZER_USES_CANONICAL_LINUX_SYSCALLS
2502d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  return internal_syscall(SYSCALL(unlinkat), AT_FDCWD, (uptr)path, 0);
2512d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#else
2522d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  return internal_syscall(SYSCALL(unlink), (uptr)path);
2532d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#endif
2542d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines}
2552d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
2562d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesuptr internal_rename(const char *oldpath, const char *newpath) {
2572d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#if SANITIZER_USES_CANONICAL_LINUX_SYSCALLS
2582d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  return internal_syscall(SYSCALL(renameat), AT_FDCWD, (uptr)oldpath, AT_FDCWD,
2592d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines                          (uptr)newpath);
2602d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#else
2612d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  return internal_syscall(SYSCALL(rename), (uptr)oldpath, (uptr)newpath);
2622d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#endif
2636d6ab9eeea4a99370d7ab18ce80eb96091e2cf3fDmitry Vyukov}
2646d6ab9eeea4a99370d7ab18ce80eb96091e2cf3fDmitry Vyukov
2659578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourneuptr internal_sched_yield() {
2662d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  return internal_syscall(SYSCALL(sched_yield));
2670969bcf2c936126b1f6e636b978aade8fc207437Alexey Samsonov}
2680969bcf2c936126b1f6e636b978aade8fc207437Alexey Samsonov
269f882247088952deed954a19d745c2dd8871e2035Alexey Samsonovvoid internal__exit(int exitcode) {
2702d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#if SANITIZER_FREEBSD
2712d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  internal_syscall(SYSCALL(exit), exitcode);
2722d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#else
2732d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  internal_syscall(SYSCALL(exit_group), exitcode);
2742d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#endif
275f882247088952deed954a19d745c2dd8871e2035Alexey Samsonov  Die();  // Unreachable.
276f882247088952deed954a19d745c2dd8871e2035Alexey Samsonov}
277f882247088952deed954a19d745c2dd8871e2035Alexey Samsonov
2789578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourneuptr internal_execve(const char *filename, char *const argv[],
2799578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne                     char *const envp[]) {
2802d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  return internal_syscall(SYSCALL(execve), (uptr)filename, (uptr)argv,
2812d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines                          (uptr)envp);
2829578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne}
2839578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne
284e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov// ----------------- sanitizer_common.h
28593b4cafd631b661b4b612ccdc0938f7f1e1c86d6Alexey Samsonovbool FileExists(const char *filename) {
2862d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#if SANITIZER_USES_CANONICAL_LINUX_SYSCALLS
2872d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  struct stat st;
2882d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  if (internal_syscall(SYSCALL(newfstatat), AT_FDCWD, filename, &st, 0))
2892d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    return false;
2902d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#else
29193b4cafd631b661b4b612ccdc0938f7f1e1c86d6Alexey Samsonov  struct stat st;
2922be3a283939d4fc14ad86f6cd8be34b1468f22baEvgeniy Stepanov  if (internal_stat(filename, &st))
29393b4cafd631b661b4b612ccdc0938f7f1e1c86d6Alexey Samsonov    return false;
29493b4cafd631b661b4b612ccdc0938f7f1e1c86d6Alexey Samsonov  // Sanity check: filename is a regular file.
29593b4cafd631b661b4b612ccdc0938f7f1e1c86d6Alexey Samsonov  return S_ISREG(st.st_mode);
2962d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#endif
29793b4cafd631b661b4b612ccdc0938f7f1e1c86d6Alexey Samsonov}
29893b4cafd631b661b4b612ccdc0938f7f1e1c86d6Alexey Samsonov
299e0023f74ea88efee329f68391b70f8adc6b21617Dmitry Vyukovuptr GetTid() {
3002d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#if SANITIZER_FREEBSD
3012d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  return (uptr)pthread_self();
3022d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#else
3032d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  return internal_syscall(SYSCALL(gettid));
3042d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#endif
305e0023f74ea88efee329f68391b70f8adc6b21617Dmitry Vyukov}
306e0023f74ea88efee329f68391b70f8adc6b21617Dmitry Vyukov
3074bebe7bab966c82f0a8952f797ed3d490624dc62Dmitry Vyukovu64 NanoTime() {
3082d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#if SANITIZER_FREEBSD
3092d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  timeval tv;
3102d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#else
3115e7ba22755b994e4f6aaf8cc00773c4d1b8dbf07Peter Collingbourne  kernel_timeval tv;
3122d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#endif
3135e7ba22755b994e4f6aaf8cc00773c4d1b8dbf07Peter Collingbourne  internal_memset(&tv, 0, sizeof(tv));
3142d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  internal_syscall(SYSCALL(gettimeofday), (uptr)&tv, 0);
3154bebe7bab966c82f0a8952f797ed3d490624dc62Dmitry Vyukov  return (u64)tv.tv_sec * 1000*1000*1000 + tv.tv_usec * 1000;
3164bebe7bab966c82f0a8952f797ed3d490624dc62Dmitry Vyukov}
3174bebe7bab966c82f0a8952f797ed3d490624dc62Dmitry Vyukov
3185d71de26cedae3dafc17449fe0182045c0bd20e8Stephen Hines// Like getenv, but reads env directly from /proc (on Linux) or parses the
3195d71de26cedae3dafc17449fe0182045c0bd20e8Stephen Hines// 'environ' array (on FreeBSD) and does not use libc. This function should be
3205d71de26cedae3dafc17449fe0182045c0bd20e8Stephen Hines// called first inside __asan_init.
3213dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonovconst char *GetEnv(const char *name) {
3225d71de26cedae3dafc17449fe0182045c0bd20e8Stephen Hines#if SANITIZER_FREEBSD
3235d71de26cedae3dafc17449fe0182045c0bd20e8Stephen Hines  if (::environ != 0) {
3245d71de26cedae3dafc17449fe0182045c0bd20e8Stephen Hines    uptr NameLen = internal_strlen(name);
3255d71de26cedae3dafc17449fe0182045c0bd20e8Stephen Hines    for (char **Env = ::environ; *Env != 0; Env++) {
3265d71de26cedae3dafc17449fe0182045c0bd20e8Stephen Hines      if (internal_strncmp(*Env, name, NameLen) == 0 && (*Env)[NameLen] == '=')
3275d71de26cedae3dafc17449fe0182045c0bd20e8Stephen Hines        return (*Env) + NameLen + 1;
3285d71de26cedae3dafc17449fe0182045c0bd20e8Stephen Hines    }
3295d71de26cedae3dafc17449fe0182045c0bd20e8Stephen Hines  }
3305d71de26cedae3dafc17449fe0182045c0bd20e8Stephen Hines  return 0;  // Not found.
3315d71de26cedae3dafc17449fe0182045c0bd20e8Stephen Hines#elif SANITIZER_LINUX
3323dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov  static char *environ;
3333dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov  static uptr len;
3343dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov  static bool inited;
3353dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov  if (!inited) {
3363dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov    inited = true;
3373dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov    uptr environ_size;
3383dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov    len = ReadFileToBuffer("/proc/self/environ",
3393dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov                           &environ, &environ_size, 1 << 26);
3403dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov  }
3413dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov  if (!environ || len == 0) return 0;
3423dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov  uptr namelen = internal_strlen(name);
3433dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov  const char *p = environ;
3443dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov  while (*p != '\0') {  // will happen at the \0\0 that terminates the buffer
3453dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov    // proc file has the format NAME=value\0NAME=value\0NAME=value\0...
3463dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov    const char* endp =
3473dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov        (char*)internal_memchr(p, '\0', len - (p - environ));
3483dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov    if (endp == 0)  // this entry isn't NUL terminated
3493dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov      return 0;
3503dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov    else if (!internal_memcmp(p, name, namelen) && p[namelen] == '=')  // Match.
3513dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov      return p + namelen + 1;  // point after =
3523dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov    p = endp + 1;
3533dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov  }
3543dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov  return 0;  // Not found.
3555d71de26cedae3dafc17449fe0182045c0bd20e8Stephen Hines#else
3565d71de26cedae3dafc17449fe0182045c0bd20e8Stephen Hines#error "Unsupported platform"
3575d71de26cedae3dafc17449fe0182045c0bd20e8Stephen Hines#endif
3583dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov}
3593dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov
360eab061185ec0046d447b298a1dff84f028202a3cEvgeniy Stepanovextern "C" {
3613c80c6c574850106481f82b9e23d1c728458d4a9Timur Iskhodzhanov  SANITIZER_WEAK_ATTRIBUTE extern void *__libc_stack_end;
362eab061185ec0046d447b298a1dff84f028202a3cEvgeniy Stepanov}
363eab061185ec0046d447b298a1dff84f028202a3cEvgeniy Stepanov
36426337b60b1d551c4744454edd8e5ef3c479e3467Peter Collingbourne#if !SANITIZER_GO
36523709c9ad9ac7c45de288f5260403426bf932db7Peter Collingbournestatic void ReadNullSepFileToArray(const char *path, char ***arr,
36623709c9ad9ac7c45de288f5260403426bf932db7Peter Collingbourne                                   int arr_size) {
36723709c9ad9ac7c45de288f5260403426bf932db7Peter Collingbourne  char *buff;
368d7e5bb4043adf4756e6f8cfe0f5a3165b185474dAlexey Samsonov  uptr buff_size = 0;
36923709c9ad9ac7c45de288f5260403426bf932db7Peter Collingbourne  *arr = (char **)MmapOrDie(arr_size * sizeof(char *), "NullSepFileArray");
37023709c9ad9ac7c45de288f5260403426bf932db7Peter Collingbourne  ReadFileToBuffer(path, &buff, &buff_size, 1024 * 1024);
37123709c9ad9ac7c45de288f5260403426bf932db7Peter Collingbourne  (*arr)[0] = buff;
37223709c9ad9ac7c45de288f5260403426bf932db7Peter Collingbourne  int count, i;
37323709c9ad9ac7c45de288f5260403426bf932db7Peter Collingbourne  for (count = 1, i = 1; ; i++) {
374d7e5bb4043adf4756e6f8cfe0f5a3165b185474dAlexey Samsonov    if (buff[i] == 0) {
375d7e5bb4043adf4756e6f8cfe0f5a3165b185474dAlexey Samsonov      if (buff[i+1] == 0) break;
37623709c9ad9ac7c45de288f5260403426bf932db7Peter Collingbourne      (*arr)[count] = &buff[i+1];
37723709c9ad9ac7c45de288f5260403426bf932db7Peter Collingbourne      CHECK_LE(count, arr_size - 1);  // FIXME: make this more flexible.
37823709c9ad9ac7c45de288f5260403426bf932db7Peter Collingbourne      count++;
379d7e5bb4043adf4756e6f8cfe0f5a3165b185474dAlexey Samsonov    }
380d7e5bb4043adf4756e6f8cfe0f5a3165b185474dAlexey Samsonov  }
38123709c9ad9ac7c45de288f5260403426bf932db7Peter Collingbourne  (*arr)[count] = 0;
38223709c9ad9ac7c45de288f5260403426bf932db7Peter Collingbourne}
38326337b60b1d551c4744454edd8e5ef3c479e3467Peter Collingbourne#endif
38423709c9ad9ac7c45de288f5260403426bf932db7Peter Collingbourne
38526337b60b1d551c4744454edd8e5ef3c479e3467Peter Collingbournestatic void GetArgsAndEnv(char*** argv, char*** envp) {
38626337b60b1d551c4744454edd8e5ef3c479e3467Peter Collingbourne#if !SANITIZER_GO
38726337b60b1d551c4744454edd8e5ef3c479e3467Peter Collingbourne  if (&__libc_stack_end) {
38826337b60b1d551c4744454edd8e5ef3c479e3467Peter Collingbourne#endif
38926337b60b1d551c4744454edd8e5ef3c479e3467Peter Collingbourne    uptr* stack_end = (uptr*)__libc_stack_end;
39026337b60b1d551c4744454edd8e5ef3c479e3467Peter Collingbourne    int argc = *stack_end;
39126337b60b1d551c4744454edd8e5ef3c479e3467Peter Collingbourne    *argv = (char**)(stack_end + 1);
39226337b60b1d551c4744454edd8e5ef3c479e3467Peter Collingbourne    *envp = (char**)(stack_end + argc + 2);
39326337b60b1d551c4744454edd8e5ef3c479e3467Peter Collingbourne#if !SANITIZER_GO
39426337b60b1d551c4744454edd8e5ef3c479e3467Peter Collingbourne  } else {
39526337b60b1d551c4744454edd8e5ef3c479e3467Peter Collingbourne    static const int kMaxArgv = 2000, kMaxEnvp = 2000;
39626337b60b1d551c4744454edd8e5ef3c479e3467Peter Collingbourne    ReadNullSepFileToArray("/proc/self/cmdline", argv, kMaxArgv);
39726337b60b1d551c4744454edd8e5ef3c479e3467Peter Collingbourne    ReadNullSepFileToArray("/proc/self/environ", envp, kMaxEnvp);
39826337b60b1d551c4744454edd8e5ef3c479e3467Peter Collingbourne  }
39926337b60b1d551c4744454edd8e5ef3c479e3467Peter Collingbourne#endif
400eab061185ec0046d447b298a1dff84f028202a3cEvgeniy Stepanov}
401eab061185ec0046d447b298a1dff84f028202a3cEvgeniy Stepanov
402eab061185ec0046d447b298a1dff84f028202a3cEvgeniy Stepanovvoid ReExec() {
40323709c9ad9ac7c45de288f5260403426bf932db7Peter Collingbourne  char **argv, **envp;
404eab061185ec0046d447b298a1dff84f028202a3cEvgeniy Stepanov  GetArgsAndEnv(&argv, &envp);
4059578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne  uptr rv = internal_execve("/proc/self/exe", argv, envp);
4069578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne  int rverrno;
4079578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne  CHECK_EQ(internal_iserror(rv, &rverrno), true);
4089578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne  Printf("execve failed, errno %d\n", rverrno);
409f35eae83757946decb312deab3f0fe155fe5d580Evgeniy Stepanov  Die();
410d7e5bb4043adf4756e6f8cfe0f5a3165b185474dAlexey Samsonov}
411d7e5bb4043adf4756e6f8cfe0f5a3165b185474dAlexey Samsonov
4122d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines// Stub implementation of GetThreadStackAndTls for Go.
4132d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#if SANITIZER_GO
4142d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesvoid GetThreadStackAndTls(bool main, uptr *stk_addr, uptr *stk_size,
4152d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines                          uptr *tls_addr, uptr *tls_size) {
4162d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  *stk_addr = 0;
4172d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  *stk_size = 0;
4182d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  *tls_addr = 0;
4192d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  *tls_size = 0;
4202e13ca86c9ce926e6fefd528892592326478ac6cAlexander Potapenko}
4212d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#endif  // SANITIZER_GO
4222e13ca86c9ce926e6fefd528892592326478ac6cAlexander Potapenko
423f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukovenum MutexState {
424f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov  MtxUnlocked = 0,
425f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov  MtxLocked = 1,
426f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov  MtxSleeping = 2
427f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov};
428f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov
429f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry VyukovBlockingMutex::BlockingMutex(LinkerInitialized) {
430d164ed175a61529589938b3db3cab076a19acf67Dmitry Vyukov  CHECK_EQ(owner_, 0);
431f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov}
432f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov
43393af5948d3e0c5bdc396f432dd0ae782f499c449Alexey SamsonovBlockingMutex::BlockingMutex() {
43493af5948d3e0c5bdc396f432dd0ae782f499c449Alexey Samsonov  internal_memset(this, 0, sizeof(*this));
43593af5948d3e0c5bdc396f432dd0ae782f499c449Alexey Samsonov}
43693af5948d3e0c5bdc396f432dd0ae782f499c449Alexey Samsonov
437f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukovvoid BlockingMutex::Lock() {
438f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov  atomic_uint32_t *m = reinterpret_cast<atomic_uint32_t *>(&opaque_storage_);
439f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov  if (atomic_exchange(m, MtxLocked, memory_order_acquire) == MtxUnlocked)
440f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov    return;
4412d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  while (atomic_exchange(m, MtxSleeping, memory_order_acquire) != MtxUnlocked) {
4422d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#if SANITIZER_FREEBSD
4432d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    _umtx_op(m, UMTX_OP_WAIT_UINT, MtxSleeping, 0, 0);
4442d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#else
4452d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    internal_syscall(SYSCALL(futex), (uptr)m, FUTEX_WAIT, MtxSleeping, 0, 0, 0);
4462d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#endif
4472d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  }
448f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov}
449f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov
450f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukovvoid BlockingMutex::Unlock() {
451f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov  atomic_uint32_t *m = reinterpret_cast<atomic_uint32_t *>(&opaque_storage_);
452f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov  u32 v = atomic_exchange(m, MtxUnlocked, memory_order_relaxed);
45348526014de78e21f7ed027a60670016bc7f5d292Dmitry Vyukov  CHECK_NE(v, MtxUnlocked);
4542d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  if (v == MtxSleeping) {
4552d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#if SANITIZER_FREEBSD
4562d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    _umtx_op(m, UMTX_OP_WAKE, 1, 0, 0);
4572d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#else
4582d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    internal_syscall(SYSCALL(futex), (uptr)m, FUTEX_WAKE, 1, 0, 0, 0);
4592d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#endif
4602d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  }
461f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov}
462f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov
463ce700979f644c790c2d9d80f5cc2a1ada0380284Alexey Samsonovvoid BlockingMutex::CheckLocked() {
464ce700979f644c790c2d9d80f5cc2a1ada0380284Alexey Samsonov  atomic_uint32_t *m = reinterpret_cast<atomic_uint32_t *>(&opaque_storage_);
465ce700979f644c790c2d9d80f5cc2a1ada0380284Alexey Samsonov  CHECK_NE(MtxUnlocked, atomic_load(m, memory_order_relaxed));
466ce700979f644c790c2d9d80f5cc2a1ada0380284Alexey Samsonov}
467ce700979f644c790c2d9d80f5cc2a1ada0380284Alexey Samsonov
4686fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany// ----------------- sanitizer_linux.h
4696fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany// The actual size of this structure is specified by d_reclen.
4706fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany// Note that getdents64 uses a different structure format. We only provide the
4716fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany// 32-bit syscall here.
4726fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryanystruct linux_dirent {
4732d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#if SANITIZER_X32
4742d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  u64 d_ino;
4752d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  u64 d_off;
4762d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#else
4776fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany  unsigned long      d_ino;
4786fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany  unsigned long      d_off;
4792d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#endif
4806fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany  unsigned short     d_reclen;
4816fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany  char               d_name[256];
4826fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany};
4836fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany
4846fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany// Syscall wrappers.
4859578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourneuptr internal_ptrace(int request, int pid, void *addr, void *data) {
4862d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  return internal_syscall(SYSCALL(ptrace), request, pid, (uptr)addr,
4872d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines                          (uptr)data);
4889578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne}
4899578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne
4909578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourneuptr internal_waitpid(int pid, int *status, int options) {
4912d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  return internal_syscall(SYSCALL(wait4), pid, (uptr)status, options,
492e041c6024b3ebf1365c0f99732fc69c607577571Kostya Serebryany                          0 /* rusage */);
4936fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany}
4946fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany
4959578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourneuptr internal_getpid() {
4962d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  return internal_syscall(SYSCALL(getpid));
4976fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany}
4986fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany
4999578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourneuptr internal_getppid() {
5002d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  return internal_syscall(SYSCALL(getppid));
5016fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany}
5026fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany
5039578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourneuptr internal_getdents(fd_t fd, struct linux_dirent *dirp, unsigned int count) {
5042d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#if SANITIZER_USES_CANONICAL_LINUX_SYSCALLS
5052d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  return internal_syscall(SYSCALL(getdents64), fd, (uptr)dirp, count);
5062d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#else
5072d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  return internal_syscall(SYSCALL(getdents), fd, (uptr)dirp, count);
5082d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#endif
5096fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany}
5106fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany
5119578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourneuptr internal_lseek(fd_t fd, OFF_T offset, int whence) {
5122d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  return internal_syscall(SYSCALL(lseek), fd, offset, whence);
5136fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany}
5146fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany
5152d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#if SANITIZER_LINUX
5169578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourneuptr internal_prctl(int option, uptr arg2, uptr arg3, uptr arg4, uptr arg5) {
5172d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  return internal_syscall(SYSCALL(prctl), option, arg2, arg3, arg4, arg5);
5186fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany}
5192d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#endif
5206fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany
5219578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourneuptr internal_sigaltstack(const struct sigaltstack *ss,
5226fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany                         struct sigaltstack *oss) {
5232d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  return internal_syscall(SYSCALL(sigaltstack), (uptr)ss, (uptr)oss);
5242d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines}
5252d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
5262d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesint internal_fork() {
5272d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#if SANITIZER_USES_CANONICAL_LINUX_SYSCALLS
5282d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  return internal_syscall(SYSCALL(clone), SIGCHLD, 0);
5292d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#else
5302d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  return internal_syscall(SYSCALL(fork));
5312d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#endif
5326fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany}
5336fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany
5342d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#if SANITIZER_LINUX
5352d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines// Doesn't set sa_restorer, use with caution (see below).
5362d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesint internal_sigaction_norestorer(int signum, const void *act, void *oldact) {
5372d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  __sanitizer_kernel_sigaction_t k_act, k_oldact;
5382d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  internal_memset(&k_act, 0, sizeof(__sanitizer_kernel_sigaction_t));
5392d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  internal_memset(&k_oldact, 0, sizeof(__sanitizer_kernel_sigaction_t));
5402d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  const __sanitizer_sigaction *u_act = (__sanitizer_sigaction *)act;
5412d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  __sanitizer_sigaction *u_oldact = (__sanitizer_sigaction *)oldact;
5422d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  if (u_act) {
5432d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    k_act.handler = u_act->handler;
5442d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    k_act.sigaction = u_act->sigaction;
5452d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    internal_memcpy(&k_act.sa_mask, &u_act->sa_mask,
5462d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines                    sizeof(__sanitizer_kernel_sigset_t));
5472d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    k_act.sa_flags = u_act->sa_flags;
5482d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    // FIXME: most often sa_restorer is unset, however the kernel requires it
5492d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    // to point to a valid signal restorer that calls the rt_sigreturn syscall.
5502d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    // If sa_restorer passed to the kernel is NULL, the program may crash upon
5512d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    // signal delivery or fail to unwind the stack in the signal handler.
5522d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    // libc implementation of sigaction() passes its own restorer to
5532d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    // rt_sigaction, so we need to do the same (we'll need to reimplement the
5542d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    // restorers; for x86_64 the restorer address can be obtained from
5552d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    // oldact->sa_restorer upon a call to sigaction(xxx, NULL, oldact).
5562d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    k_act.sa_restorer = u_act->sa_restorer;
5572d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  }
5582d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
5592d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  uptr result = internal_syscall(SYSCALL(rt_sigaction), (uptr)signum,
5602d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines      (uptr)(u_act ? &k_act : NULL),
5612d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines      (uptr)(u_oldact ? &k_oldact : NULL),
5622d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines      (uptr)sizeof(__sanitizer_kernel_sigset_t));
5632d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
5642d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  if ((result == 0) && u_oldact) {
5652d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    u_oldact->handler = k_oldact.handler;
5662d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    u_oldact->sigaction = k_oldact.sigaction;
5672d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    internal_memcpy(&u_oldact->sa_mask, &k_oldact.sa_mask,
5682d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines                    sizeof(__sanitizer_kernel_sigset_t));
5692d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    u_oldact->sa_flags = k_oldact.sa_flags;
5702d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    u_oldact->sa_restorer = k_oldact.sa_restorer;
5712d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  }
5722d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  return result;
5730f7a2acb3326a5900d1a1339ebf959b14b372e0dDmitry Vyukov}
5742d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#endif  // SANITIZER_LINUX
5750f7a2acb3326a5900d1a1339ebf959b14b372e0dDmitry Vyukov
5762d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesuptr internal_sigprocmask(int how, __sanitizer_sigset_t *set,
5772d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    __sanitizer_sigset_t *oldset) {
5782d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#if SANITIZER_FREEBSD
5792d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  return internal_syscall(SYSCALL(sigprocmask), how, set, oldset);
5802d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#else
5812d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  __sanitizer_kernel_sigset_t *k_set = (__sanitizer_kernel_sigset_t *)set;
5822d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  __sanitizer_kernel_sigset_t *k_oldset = (__sanitizer_kernel_sigset_t *)oldset;
5832d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  return internal_syscall(SYSCALL(rt_sigprocmask), (uptr)how,
5842d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines                          (uptr)&k_set->sig[0], (uptr)&k_oldset->sig[0],
5852d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines                          sizeof(__sanitizer_kernel_sigset_t));
5862d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#endif
5870f7a2acb3326a5900d1a1339ebf959b14b372e0dDmitry Vyukov}
5880f7a2acb3326a5900d1a1339ebf959b14b372e0dDmitry Vyukov
5892d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesvoid internal_sigfillset(__sanitizer_sigset_t *set) {
5900f7a2acb3326a5900d1a1339ebf959b14b372e0dDmitry Vyukov  internal_memset(set, 0xff, sizeof(*set));
5910f7a2acb3326a5900d1a1339ebf959b14b372e0dDmitry Vyukov}
5920f7a2acb3326a5900d1a1339ebf959b14b372e0dDmitry Vyukov
5932d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#if SANITIZER_LINUX
5942d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesvoid internal_sigdelset(__sanitizer_sigset_t *set, int signum) {
5950f7a2acb3326a5900d1a1339ebf959b14b372e0dDmitry Vyukov  signum -= 1;
5960f7a2acb3326a5900d1a1339ebf959b14b372e0dDmitry Vyukov  CHECK_GE(signum, 0);
5970f7a2acb3326a5900d1a1339ebf959b14b372e0dDmitry Vyukov  CHECK_LT(signum, sizeof(*set) * 8);
5982d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  __sanitizer_kernel_sigset_t *k_set = (__sanitizer_kernel_sigset_t *)set;
5992d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  const uptr idx = signum / (sizeof(k_set->sig[0]) * 8);
6002d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  const uptr bit = signum % (sizeof(k_set->sig[0]) * 8);
6012d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  k_set->sig[idx] &= ~(1 << bit);
6020f7a2acb3326a5900d1a1339ebf959b14b372e0dDmitry Vyukov}
6032d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#endif  // SANITIZER_LINUX
6040f7a2acb3326a5900d1a1339ebf959b14b372e0dDmitry Vyukov
6056fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany// ThreadLister implementation.
6066fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya SerebryanyThreadLister::ThreadLister(int pid)
6076fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany  : pid_(pid),
6086fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany    descriptor_(-1),
60910f3ab775088bec69dd9e7b611f9b4e152f629bcAlexey Samsonov    buffer_(4096),
6106fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany    error_(true),
61110f3ab775088bec69dd9e7b611f9b4e152f629bcAlexey Samsonov    entry_((struct linux_dirent *)buffer_.data()),
6126fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany    bytes_read_(0) {
6136fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany  char task_directory_path[80];
6146fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany  internal_snprintf(task_directory_path, sizeof(task_directory_path),
6156fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany                    "/proc/%d/task/", pid);
6169578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne  uptr openrv = internal_open(task_directory_path, O_RDONLY | O_DIRECTORY);
6179578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne  if (internal_iserror(openrv)) {
6186fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany    error_ = true;
6196fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany    Report("Can't open /proc/%d/task for reading.\n", pid);
6206fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany  } else {
6216fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany    error_ = false;
6229578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne    descriptor_ = openrv;
6236fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany  }
6246fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany}
6256fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany
6266fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryanyint ThreadLister::GetNextTID() {
6276fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany  int tid = -1;
6286fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany  do {
6296fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany    if (error_)
6306fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany      return -1;
6316fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany    if ((char *)entry_ >= &buffer_[bytes_read_] && !GetDirectoryEntries())
6326fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany      return -1;
6336fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany    if (entry_->d_ino != 0 && entry_->d_name[0] >= '0' &&
6346fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany        entry_->d_name[0] <= '9') {
6356fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany      // Found a valid tid.
6366fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany      tid = (int)internal_atoll(entry_->d_name);
6376fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany    }
6386fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany    entry_ = (struct linux_dirent *)(((char *)entry_) + entry_->d_reclen);
6396fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany  } while (tid < 0);
6406fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany  return tid;
6416fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany}
6426fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany
6436fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryanyvoid ThreadLister::Reset() {
6446fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany  if (error_ || descriptor_ < 0)
6456fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany    return;
6466fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany  internal_lseek(descriptor_, 0, SEEK_SET);
6476fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany}
6486fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany
6496fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya SerebryanyThreadLister::~ThreadLister() {
6506fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany  if (descriptor_ >= 0)
6516fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany    internal_close(descriptor_);
6526fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany}
6536fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany
6546fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryanybool ThreadLister::error() { return error_; }
6556fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany
6566fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryanybool ThreadLister::GetDirectoryEntries() {
6576fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany  CHECK_GE(descriptor_, 0);
6586fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany  CHECK_NE(error_, true);
6596fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany  bytes_read_ = internal_getdents(descriptor_,
66010f3ab775088bec69dd9e7b611f9b4e152f629bcAlexey Samsonov                                  (struct linux_dirent *)buffer_.data(),
66110f3ab775088bec69dd9e7b611f9b4e152f629bcAlexey Samsonov                                  buffer_.size());
6629578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne  if (internal_iserror(bytes_read_)) {
6636fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany    Report("Can't read directory entries from /proc/%d/task.\n", pid_);
6646fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany    error_ = true;
6656fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany    return false;
6666fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany  } else if (bytes_read_ == 0) {
6676fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany    return false;
6686fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany  }
66910f3ab775088bec69dd9e7b611f9b4e152f629bcAlexey Samsonov  entry_ = (struct linux_dirent *)buffer_.data();
6706fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany  return true;
6716fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany}
6726fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany
6734df343a31cf57c309cf102b9aef870458318f579Peter Collingbourneuptr GetPageSize() {
6742d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#if SANITIZER_LINUX && (defined(__x86_64__) || defined(__i386__))
6754df343a31cf57c309cf102b9aef870458318f579Peter Collingbourne  return EXEC_PAGESIZE;
676a8bc34e420d27c47560b0742cec295e40b0f430eKostya Serebryany#else
677a8bc34e420d27c47560b0742cec295e40b0f430eKostya Serebryany  return sysconf(_SC_PAGESIZE);  // EXEC_PAGESIZE may not be trustworthy.
678a8bc34e420d27c47560b0742cec295e40b0f430eKostya Serebryany#endif
6794df343a31cf57c309cf102b9aef870458318f579Peter Collingbourne}
6804df343a31cf57c309cf102b9aef870458318f579Peter Collingbourne
6817847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonovstatic char proc_self_exe_cache_str[kMaxPathLength];
6827847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonovstatic uptr proc_self_exe_cache_len = 0;
6837847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov
6847847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonovuptr ReadBinaryName(/*out*/char *buf, uptr buf_len) {
6855d71de26cedae3dafc17449fe0182045c0bd20e8Stephen Hines  if (proc_self_exe_cache_len > 0) {
6865d71de26cedae3dafc17449fe0182045c0bd20e8Stephen Hines    // If available, use the cached module name.
6875d71de26cedae3dafc17449fe0182045c0bd20e8Stephen Hines    uptr module_name_len =
6885d71de26cedae3dafc17449fe0182045c0bd20e8Stephen Hines        internal_snprintf(buf, buf_len, "%s", proc_self_exe_cache_str);
6895d71de26cedae3dafc17449fe0182045c0bd20e8Stephen Hines    CHECK_LT(module_name_len, buf_len);
6905d71de26cedae3dafc17449fe0182045c0bd20e8Stephen Hines    return module_name_len;
6915d71de26cedae3dafc17449fe0182045c0bd20e8Stephen Hines  }
6925d71de26cedae3dafc17449fe0182045c0bd20e8Stephen Hines#if SANITIZER_FREEBSD
6935d71de26cedae3dafc17449fe0182045c0bd20e8Stephen Hines  const int Mib[4] = { CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, -1 };
6945d71de26cedae3dafc17449fe0182045c0bd20e8Stephen Hines  size_t Size = buf_len;
6955d71de26cedae3dafc17449fe0182045c0bd20e8Stephen Hines  bool IsErr = (sysctl(Mib, 4, buf, &Size, NULL, 0) != 0);
6965d71de26cedae3dafc17449fe0182045c0bd20e8Stephen Hines  int readlink_error = IsErr ? errno : 0;
6975d71de26cedae3dafc17449fe0182045c0bd20e8Stephen Hines  uptr module_name_len = Size;
6985d71de26cedae3dafc17449fe0182045c0bd20e8Stephen Hines#else
6997847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov  uptr module_name_len = internal_readlink(
7007847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov      "/proc/self/exe", buf, buf_len);
7017847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov  int readlink_error;
7025d71de26cedae3dafc17449fe0182045c0bd20e8Stephen Hines  bool IsErr = internal_iserror(module_name_len, &readlink_error);
7035d71de26cedae3dafc17449fe0182045c0bd20e8Stephen Hines#endif
7045d71de26cedae3dafc17449fe0182045c0bd20e8Stephen Hines  if (IsErr) {
7055d71de26cedae3dafc17449fe0182045c0bd20e8Stephen Hines    // We can't read /proc/self/exe for some reason, assume the name of the
7065d71de26cedae3dafc17449fe0182045c0bd20e8Stephen Hines    // binary is unknown.
7075d71de26cedae3dafc17449fe0182045c0bd20e8Stephen Hines    Report("WARNING: readlink(\"/proc/self/exe\") failed with errno %d, "
7085d71de26cedae3dafc17449fe0182045c0bd20e8Stephen Hines           "some stack frames may not be symbolized\n", readlink_error);
7095d71de26cedae3dafc17449fe0182045c0bd20e8Stephen Hines    module_name_len = internal_snprintf(buf, buf_len, "/proc/self/exe");
7107847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov    CHECK_LT(module_name_len, buf_len);
7117847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov  }
7127847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov  return module_name_len;
7137847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov}
7147847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov
7157847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonovvoid CacheBinaryName() {
7167847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov  if (!proc_self_exe_cache_len) {
7177847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov    proc_self_exe_cache_len =
7187847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov        ReadBinaryName(proc_self_exe_cache_str, kMaxPathLength);
7197847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov  }
7207847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov}
7217847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov
7223de0086409d143a612a54a7a0ed809e286656188Sergey Matveev// Match full names of the form /path/to/base_name{-,.}*
7233de0086409d143a612a54a7a0ed809e286656188Sergey Matveevbool LibraryNameIs(const char *full_name, const char *base_name) {
7243de0086409d143a612a54a7a0ed809e286656188Sergey Matveev  const char *name = full_name;
7253de0086409d143a612a54a7a0ed809e286656188Sergey Matveev  // Strip path.
7263de0086409d143a612a54a7a0ed809e286656188Sergey Matveev  while (*name != '\0') name++;
7273de0086409d143a612a54a7a0ed809e286656188Sergey Matveev  while (name > full_name && *name != '/') name--;
7283de0086409d143a612a54a7a0ed809e286656188Sergey Matveev  if (*name == '/') name++;
7293de0086409d143a612a54a7a0ed809e286656188Sergey Matveev  uptr base_name_length = internal_strlen(base_name);
7303de0086409d143a612a54a7a0ed809e286656188Sergey Matveev  if (internal_strncmp(name, base_name, base_name_length)) return false;
7313de0086409d143a612a54a7a0ed809e286656188Sergey Matveev  return (name[base_name_length] == '-' || name[base_name_length] == '.');
7323de0086409d143a612a54a7a0ed809e286656188Sergey Matveev}
7333de0086409d143a612a54a7a0ed809e286656188Sergey Matveev
734d054abef27369471e154ec5693949538c2fdffd9Evgeniy Stepanov#if !SANITIZER_ANDROID
7352e75ac983cb233daa1abfa35fb33d2bafffe2ab1Peter Collingbourne// Call cb for each region mapped by map.
7362e75ac983cb233daa1abfa35fb33d2bafffe2ab1Peter Collingbournevoid ForEachMappedRegion(link_map *map, void (*cb)(const void *, uptr)) {
7372d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#if !SANITIZER_FREEBSD
7382e75ac983cb233daa1abfa35fb33d2bafffe2ab1Peter Collingbourne  typedef ElfW(Phdr) Elf_Phdr;
7392e75ac983cb233daa1abfa35fb33d2bafffe2ab1Peter Collingbourne  typedef ElfW(Ehdr) Elf_Ehdr;
7402d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#endif  // !SANITIZER_FREEBSD
7412e75ac983cb233daa1abfa35fb33d2bafffe2ab1Peter Collingbourne  char *base = (char *)map->l_addr;
7422e75ac983cb233daa1abfa35fb33d2bafffe2ab1Peter Collingbourne  Elf_Ehdr *ehdr = (Elf_Ehdr *)base;
7432e75ac983cb233daa1abfa35fb33d2bafffe2ab1Peter Collingbourne  char *phdrs = base + ehdr->e_phoff;
7442e75ac983cb233daa1abfa35fb33d2bafffe2ab1Peter Collingbourne  char *phdrs_end = phdrs + ehdr->e_phnum * ehdr->e_phentsize;
7452e75ac983cb233daa1abfa35fb33d2bafffe2ab1Peter Collingbourne
7462e75ac983cb233daa1abfa35fb33d2bafffe2ab1Peter Collingbourne  // Find the segment with the minimum base so we can "relocate" the p_vaddr
7472e75ac983cb233daa1abfa35fb33d2bafffe2ab1Peter Collingbourne  // fields.  Typically ET_DYN objects (DSOs) have base of zero and ET_EXEC
7482e75ac983cb233daa1abfa35fb33d2bafffe2ab1Peter Collingbourne  // objects have a non-zero base.
749f50b0fc601aea71d9fb22f01a11c7e206c666edcPeter Collingbourne  uptr preferred_base = (uptr)-1;
7502e75ac983cb233daa1abfa35fb33d2bafffe2ab1Peter Collingbourne  for (char *iter = phdrs; iter != phdrs_end; iter += ehdr->e_phentsize) {
7512e75ac983cb233daa1abfa35fb33d2bafffe2ab1Peter Collingbourne    Elf_Phdr *phdr = (Elf_Phdr *)iter;
7522e75ac983cb233daa1abfa35fb33d2bafffe2ab1Peter Collingbourne    if (phdr->p_type == PT_LOAD && preferred_base > (uptr)phdr->p_vaddr)
7532e75ac983cb233daa1abfa35fb33d2bafffe2ab1Peter Collingbourne      preferred_base = (uptr)phdr->p_vaddr;
7542e75ac983cb233daa1abfa35fb33d2bafffe2ab1Peter Collingbourne  }
7552e75ac983cb233daa1abfa35fb33d2bafffe2ab1Peter Collingbourne
7562e75ac983cb233daa1abfa35fb33d2bafffe2ab1Peter Collingbourne  // Compute the delta from the real base to get a relocation delta.
7572e75ac983cb233daa1abfa35fb33d2bafffe2ab1Peter Collingbourne  sptr delta = (uptr)base - preferred_base;
7582e75ac983cb233daa1abfa35fb33d2bafffe2ab1Peter Collingbourne  // Now we can figure out what the loader really mapped.
7592e75ac983cb233daa1abfa35fb33d2bafffe2ab1Peter Collingbourne  for (char *iter = phdrs; iter != phdrs_end; iter += ehdr->e_phentsize) {
7602e75ac983cb233daa1abfa35fb33d2bafffe2ab1Peter Collingbourne    Elf_Phdr *phdr = (Elf_Phdr *)iter;
7612e75ac983cb233daa1abfa35fb33d2bafffe2ab1Peter Collingbourne    if (phdr->p_type == PT_LOAD) {
7622e75ac983cb233daa1abfa35fb33d2bafffe2ab1Peter Collingbourne      uptr seg_start = phdr->p_vaddr + delta;
7632e75ac983cb233daa1abfa35fb33d2bafffe2ab1Peter Collingbourne      uptr seg_end = seg_start + phdr->p_memsz;
7642e75ac983cb233daa1abfa35fb33d2bafffe2ab1Peter Collingbourne      // None of these values are aligned.  We consider the ragged edges of the
7652e75ac983cb233daa1abfa35fb33d2bafffe2ab1Peter Collingbourne      // load command as defined, since they are mapped from the file.
7662e75ac983cb233daa1abfa35fb33d2bafffe2ab1Peter Collingbourne      seg_start = RoundDownTo(seg_start, GetPageSizeCached());
7672e75ac983cb233daa1abfa35fb33d2bafffe2ab1Peter Collingbourne      seg_end = RoundUpTo(seg_end, GetPageSizeCached());
7682e75ac983cb233daa1abfa35fb33d2bafffe2ab1Peter Collingbourne      cb((void *)seg_start, seg_end - seg_start);
7692e75ac983cb233daa1abfa35fb33d2bafffe2ab1Peter Collingbourne    }
7702e75ac983cb233daa1abfa35fb33d2bafffe2ab1Peter Collingbourne  }
7712e75ac983cb233daa1abfa35fb33d2bafffe2ab1Peter Collingbourne}
772d054abef27369471e154ec5693949538c2fdffd9Evgeniy Stepanov#endif
7732e75ac983cb233daa1abfa35fb33d2bafffe2ab1Peter Collingbourne
7742d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#if defined(__x86_64__) && SANITIZER_LINUX
775cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev// We cannot use glibc's clone wrapper, because it messes with the child
776cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev// task's TLS. It writes the PID and TID of the child task to its thread
777cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev// descriptor, but in our case the child task shares the thread descriptor with
778cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev// the parent (because we don't know how to allocate a new thread
779cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev// descriptor to keep glibc happy). So the stock version of clone(), when
780cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev// used with CLONE_VM, would end up corrupting the parent's thread descriptor.
781cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveevuptr internal_clone(int (*fn)(void *), void *child_stack, int flags, void *arg,
782cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev                    int *parent_tidptr, void *newtls, int *child_tidptr) {
783cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev  long long res;
784cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev  if (!fn || !child_stack)
785cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev    return -EINVAL;
786cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev  CHECK_EQ(0, (uptr)child_stack % 16);
787e041c6024b3ebf1365c0f99732fc69c607577571Kostya Serebryany  child_stack = (char *)child_stack - 2 * sizeof(unsigned long long);
788e041c6024b3ebf1365c0f99732fc69c607577571Kostya Serebryany  ((unsigned long long *)child_stack)[0] = (uptr)fn;
789e041c6024b3ebf1365c0f99732fc69c607577571Kostya Serebryany  ((unsigned long long *)child_stack)[1] = (uptr)arg;
790e041c6024b3ebf1365c0f99732fc69c607577571Kostya Serebryany  register void *r8 __asm__("r8") = newtls;
791e041c6024b3ebf1365c0f99732fc69c607577571Kostya Serebryany  register int *r10 __asm__("r10") = child_tidptr;
792cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev  __asm__ __volatile__(
7932d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines                       /* %rax = syscall(%rax = SYSCALL(clone),
794cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev                        *                %rdi = flags,
795cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev                        *                %rsi = child_stack,
796cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev                        *                %rdx = parent_tidptr,
797cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev                        *                %r8  = new_tls,
798cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev                        *                %r10 = child_tidptr)
799cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev                        */
800cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev                       "syscall\n"
801cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev
802cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev                       /* if (%rax != 0)
803cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev                        *   return;
804cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev                        */
805cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev                       "testq  %%rax,%%rax\n"
806cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev                       "jnz    1f\n"
807cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev
808cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev                       /* In the child. Terminate unwind chain. */
809497ae56316cd05a0d539e0d6e065bbaee254aca3Sergey Matveev                       // XXX: We should also terminate the CFI unwind chain
810497ae56316cd05a0d539e0d6e065bbaee254aca3Sergey Matveev                       // here. Unfortunately clang 3.2 doesn't support the
811497ae56316cd05a0d539e0d6e065bbaee254aca3Sergey Matveev                       // necessary CFI directives, so we skip that part.
812cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev                       "xorq   %%rbp,%%rbp\n"
813cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev
814cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev                       /* Call "fn(arg)". */
815cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev                       "popq   %%rax\n"
816cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev                       "popq   %%rdi\n"
817cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev                       "call   *%%rax\n"
818cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev
819cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev                       /* Call _exit(%rax). */
820cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev                       "movq   %%rax,%%rdi\n"
821cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev                       "movq   %2,%%rax\n"
822cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev                       "syscall\n"
823cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev
824cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev                       /* Return to parent. */
825cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev                     "1:\n"
826cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev                       : "=a" (res)
8272d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines                       : "a"(SYSCALL(clone)), "i"(SYSCALL(exit)),
828cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev                         "S"(child_stack),
829cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev                         "D"(flags),
830cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev                         "d"(parent_tidptr),
831e041c6024b3ebf1365c0f99732fc69c607577571Kostya Serebryany                         "r"(r8),
832e041c6024b3ebf1365c0f99732fc69c607577571Kostya Serebryany                         "r"(r10)
833e041c6024b3ebf1365c0f99732fc69c607577571Kostya Serebryany                       : "rsp", "memory", "r11", "rcx");
834cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev  return res;
835cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev}
8362d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#endif  // defined(__x86_64__) && SANITIZER_LINUX
8372d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
8382d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#if SANITIZER_ANDROID
8392d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines// This thing is not, strictly speaking, async signal safe, but it does not seem
8402d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines// to cause any issues. Alternative is writing to log devices directly, but
8412d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines// their location and message format might change in the future, so we'd really
8422d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines// like to avoid that.
8432d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesvoid AndroidLogWrite(const char *buffer) {
8442d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  char *copy = internal_strdup(buffer);
8452d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  char *p = copy;
8462d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  char *q;
8472d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  // __android_log_write has an implicit message length limit.
8482d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  // Print one line at a time.
8492d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  do {
8502d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    q = internal_strchr(p, '\n');
8512d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    if (q) *q = '\0';
8522d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    __android_log_write(ANDROID_LOG_INFO, NULL, p);
8532d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    if (q) p = q + 1;
8542d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  } while (q);
8552d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  InternalFree(copy);
8562d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines}
8572d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
8582d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesvoid GetExtraActivationFlags(char *buf, uptr size) {
8592d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  CHECK(size > PROP_VALUE_MAX);
8602d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  __system_property_get("asan.options", buf);
8612d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines}
8622d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#endif
8632d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
8642d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesbool IsDeadlySignal(int signum) {
8652d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  return (signum == SIGSEGV) && common_flags()->handle_segv;
8662d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines}
8672d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
868ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov}  // namespace __sanitizer
869ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov
8702d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#endif  // SANITIZER_FREEBSD || SANITIZER_LINUX
871