sanitizer_linux.cc revision cdce50bda3603770cc4ef80cbb613c78b8e47a17
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
1886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines#include "sanitizer_allocator_internal.h"
196895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov#include "sanitizer_common.h"
202d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#include "sanitizer_flags.h"
2194b5036ee6ba866e1702848855b6d687d1e70afaAlexey Samsonov#include "sanitizer_internal_defs.h"
22ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov#include "sanitizer_libc.h"
236fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany#include "sanitizer_linux.h"
2493da8b6a5e0ed2ca621897504c5d06449b3d7077Alexander Potapenko#include "sanitizer_mutex.h"
25a68633fb76208137ccb807914df52758ee5ca6f0Alexey Samsonov#include "sanitizer_placement_new.h"
266895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov#include "sanitizer_procmaps.h"
27a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryany#include "sanitizer_stacktrace.h"
285ce93fc96ab5e2defd85890da63b51cc4c57a2afAlexander Potapenko#include "sanitizer_symbolizer.h"
29ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov
302d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#if !SANITIZER_FREEBSD
31088ea2b46f97172bd0b0663a629e11cf826b84f7Peter Collingbourne#include <asm/param.h>
322d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#endif
332d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
3486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines// For mips64, syscall(__NR_stat) fills the buffer in the 'struct kernel_stat'
3586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines// format. Struct kernel_stat is defined as 'struct stat' in asm/stat.h. To
3686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines// access stat from asm/stat.h, without conflicting with definition in
3786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines// sys/stat.h, we use this trick.
3886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines#if defined(__mips64)
39cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar#include <asm/unistd.h>
4086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines#include <sys/types.h>
4186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines#define stat kernel_stat
4286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines#include <asm/stat.h>
4386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines#undef stat
4486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines#endif
4586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines
46b114ed83859d8d4964ac2284584733bcd2acf4f6Evgeniy Stepanov#include <dlfcn.h>
4735a7faf1fbfac678136e79d53824672dafb7d13eAlexey Samsonov#include <errno.h>
48c5d465136b911bf925f2a631e2b79f1c03e8a1b0Alexey Samsonov#include <fcntl.h>
492e75ac983cb233daa1abfa35fb33d2bafffe2ab1Peter Collingbourne#include <link.h>
50e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov#include <pthread.h>
510969bcf2c936126b1f6e636b978aade8fc207437Alexey Samsonov#include <sched.h>
52ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov#include <sys/mman.h>
536fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany#include <sys/ptrace.h>
54e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov#include <sys/resource.h>
55c5d465136b911bf925f2a631e2b79f1c03e8a1b0Alexey Samsonov#include <sys/stat.h>
56ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov#include <sys/syscall.h>
57e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov#include <sys/time.h>
58ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov#include <sys/types.h>
597c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar#include <ucontext.h>
60ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov#include <unistd.h>
6135a7faf1fbfac678136e79d53824672dafb7d13eAlexey Samsonov
622d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#if SANITIZER_FREEBSD
636a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines#include <sys/sysctl.h>
642d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#include <machine/atomic.h>
652d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesextern "C" {
662d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines// <sys/umtx.h> must be included after <errno.h> and <sys/types.h> on
672d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines// FreeBSD 9.2 and 10.0.
682d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#include <sys/umtx.h>
692d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines}
706a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hinesextern char **environ;  // provided by crt1
712d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#endif  // SANITIZER_FREEBSD
722d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
7324e13723f8477d8c42ab8b2a7f4f69fc089842f1Evgeniy Stepanov#if !SANITIZER_ANDROID
7435a7faf1fbfac678136e79d53824672dafb7d13eAlexey Samsonov#include <sys/signal.h>
7535a7faf1fbfac678136e79d53824672dafb7d13eAlexey Samsonov#endif
76fa5c41eddf77a3614da0f62044ebf741d86aeab7Dmitry Vyukov
772d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#if SANITIZER_ANDROID
782d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#include <android/log.h>
792d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#include <sys/system_properties.h>
802d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#endif
812d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
822d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#if SANITIZER_LINUX
834bebe7bab966c82f0a8952f797ed3d490624dc62Dmitry Vyukov// <linux/time.h>
844bebe7bab966c82f0a8952f797ed3d490624dc62Dmitry Vyukovstruct kernel_timeval {
854bebe7bab966c82f0a8952f797ed3d490624dc62Dmitry Vyukov  long tv_sec;
864bebe7bab966c82f0a8952f797ed3d490624dc62Dmitry Vyukov  long tv_usec;
874bebe7bab966c82f0a8952f797ed3d490624dc62Dmitry Vyukov};
884bebe7bab966c82f0a8952f797ed3d490624dc62Dmitry Vyukov
89fa5c41eddf77a3614da0f62044ebf741d86aeab7Dmitry Vyukov// <linux/futex.h> is broken on some linux distributions.
90fa5c41eddf77a3614da0f62044ebf741d86aeab7Dmitry Vyukovconst int FUTEX_WAIT = 0;
91fa5c41eddf77a3614da0f62044ebf741d86aeab7Dmitry Vyukovconst int FUTEX_WAKE = 1;
922d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#endif  // SANITIZER_LINUX
93ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov
942d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines// Are we using 32-bit or 64-bit Linux syscalls?
955af39e50366f1aacbebc284f572f08ad1ad07357Kostya Serebryany// x32 (which defines __x86_64__) has SANITIZER_WORDSIZE == 32
9608bfe4988de493dd3e61d02759b3f19c42f8fb78Kostya Serebryany// but it still needs to use 64-bit syscalls.
972d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#if SANITIZER_LINUX && (defined(__x86_64__) || SANITIZER_WORDSIZE == 64)
989d0dbbaf33e5c2fe280f141e30be497d62b703a8Kostya Serebryany# define SANITIZER_LINUX_USES_64BIT_SYSCALLS 1
999d0dbbaf33e5c2fe280f141e30be497d62b703a8Kostya Serebryany#else
1009d0dbbaf33e5c2fe280f141e30be497d62b703a8Kostya Serebryany# define SANITIZER_LINUX_USES_64BIT_SYSCALLS 0
1019d0dbbaf33e5c2fe280f141e30be497d62b703a8Kostya Serebryany#endif
1029d0dbbaf33e5c2fe280f141e30be497d62b703a8Kostya Serebryany
103ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonovnamespace __sanitizer {
104ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov
1052d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#if SANITIZER_LINUX && defined(__x86_64__)
1069578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne#include "sanitizer_syscall_linux_x86_64.inc"
1079578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne#else
1089578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne#include "sanitizer_syscall_generic.inc"
1099578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne#endif
1109578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne
111e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov// --------------- sanitizer_libc.h
11286277eb844c4983c81de62d7c050e92fe7155788Stephen Hinesuptr internal_mmap(void *addr, uptr length, int prot, int flags, int fd,
11386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines                   u64 offset) {
1142d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#if SANITIZER_FREEBSD || SANITIZER_LINUX_USES_64BIT_SYSCALLS
1152d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  return internal_syscall(SYSCALL(mmap), (uptr)addr, length, prot, flags, fd,
116e041c6024b3ebf1365c0f99732fc69c607577571Kostya Serebryany                          offset);
117ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov#else
11886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  // mmap2 specifies file offset in 4096-byte units.
11986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  CHECK(IsAligned(offset, 4096));
1202d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  return internal_syscall(SYSCALL(mmap2), addr, length, prot, flags, fd,
12186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines                          offset / 4096);
122ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov#endif
123ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov}
124ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov
1259578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourneuptr internal_munmap(void *addr, uptr length) {
1262d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  return internal_syscall(SYSCALL(munmap), (uptr)addr, length);
1271f11d31faa5ed89b74f7d543b1182fe8de198be5Alexey Samsonov}
1281f11d31faa5ed89b74f7d543b1182fe8de198be5Alexey Samsonov
129259f7063e3e4c4b94dded1e90ab0a943d0fa737bPirama Arumuga Nainarint internal_mprotect(void *addr, uptr length, int prot) {
130259f7063e3e4c4b94dded1e90ab0a943d0fa737bPirama Arumuga Nainar  return internal_syscall(SYSCALL(mprotect), (uptr)addr, length, prot);
131259f7063e3e4c4b94dded1e90ab0a943d0fa737bPirama Arumuga Nainar}
132259f7063e3e4c4b94dded1e90ab0a943d0fa737bPirama Arumuga Nainar
1339578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourneuptr internal_close(fd_t fd) {
1342d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  return internal_syscall(SYSCALL(close), fd);
135a56aefd2e01940fcf88d1426f9de3d5e4b1ee203Alexey Samsonov}
136a56aefd2e01940fcf88d1426f9de3d5e4b1ee203Alexey Samsonov
1379578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourneuptr internal_open(const char *filename, int flags) {
1382d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#if SANITIZER_USES_CANONICAL_LINUX_SYSCALLS
1392d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  return internal_syscall(SYSCALL(openat), AT_FDCWD, (uptr)filename, flags);
1402d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#else
1412d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  return internal_syscall(SYSCALL(open), (uptr)filename, flags);
1422d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#endif
143ee7cc4454421a176d23442382afd9a01d36e7ad4Alexey Samsonov}
144ee7cc4454421a176d23442382afd9a01d36e7ad4Alexey Samsonov
1459578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourneuptr internal_open(const char *filename, int flags, u32 mode) {
1462d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#if SANITIZER_USES_CANONICAL_LINUX_SYSCALLS
1472d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  return internal_syscall(SYSCALL(openat), AT_FDCWD, (uptr)filename, flags,
1482d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines                          mode);
1492d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#else
1502d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  return internal_syscall(SYSCALL(open), (uptr)filename, flags, mode);
1512d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#endif
152ee7cc4454421a176d23442382afd9a01d36e7ad4Alexey Samsonov}
153ee7cc4454421a176d23442382afd9a01d36e7ad4Alexey Samsonov
154a56aefd2e01940fcf88d1426f9de3d5e4b1ee203Alexey Samsonovuptr internal_read(fd_t fd, void *buf, uptr count) {
1553334e12d33261cb8f211f2f49f28ddfa027a40c3Evgeniy Stepanov  sptr res;
1562d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  HANDLE_EINTR(res, (sptr)internal_syscall(SYSCALL(read), fd, (uptr)buf,
1572d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines               count));
1583334e12d33261cb8f211f2f49f28ddfa027a40c3Evgeniy Stepanov  return res;
159a56aefd2e01940fcf88d1426f9de3d5e4b1ee203Alexey Samsonov}
160a56aefd2e01940fcf88d1426f9de3d5e4b1ee203Alexey Samsonov
161a56aefd2e01940fcf88d1426f9de3d5e4b1ee203Alexey Samsonovuptr internal_write(fd_t fd, const void *buf, uptr count) {
1623334e12d33261cb8f211f2f49f28ddfa027a40c3Evgeniy Stepanov  sptr res;
1632d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  HANDLE_EINTR(res, (sptr)internal_syscall(SYSCALL(write), fd, (uptr)buf,
1642d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines               count));
1653334e12d33261cb8f211f2f49f28ddfa027a40c3Evgeniy Stepanov  return res;
166a56aefd2e01940fcf88d1426f9de3d5e4b1ee203Alexey Samsonov}
167a56aefd2e01940fcf88d1426f9de3d5e4b1ee203Alexey Samsonov
1682d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesuptr internal_ftruncate(fd_t fd, uptr size) {
1692d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  sptr res;
1707c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar  HANDLE_EINTR(res, (sptr)internal_syscall(SYSCALL(ftruncate), fd,
1717c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar               (OFF_T)size));
1722d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  return res;
1732d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines}
1742d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
1752d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#if !SANITIZER_LINUX_USES_64BIT_SYSCALLS && !SANITIZER_FREEBSD
1762be3a283939d4fc14ad86f6cd8be34b1468f22baEvgeniy Stepanovstatic void stat64_to_stat(struct stat64 *in, struct stat *out) {
1772be3a283939d4fc14ad86f6cd8be34b1468f22baEvgeniy Stepanov  internal_memset(out, 0, sizeof(*out));
1782be3a283939d4fc14ad86f6cd8be34b1468f22baEvgeniy Stepanov  out->st_dev = in->st_dev;
1792be3a283939d4fc14ad86f6cd8be34b1468f22baEvgeniy Stepanov  out->st_ino = in->st_ino;
1802be3a283939d4fc14ad86f6cd8be34b1468f22baEvgeniy Stepanov  out->st_mode = in->st_mode;
1812be3a283939d4fc14ad86f6cd8be34b1468f22baEvgeniy Stepanov  out->st_nlink = in->st_nlink;
1822be3a283939d4fc14ad86f6cd8be34b1468f22baEvgeniy Stepanov  out->st_uid = in->st_uid;
1832be3a283939d4fc14ad86f6cd8be34b1468f22baEvgeniy Stepanov  out->st_gid = in->st_gid;
1842be3a283939d4fc14ad86f6cd8be34b1468f22baEvgeniy Stepanov  out->st_rdev = in->st_rdev;
1852be3a283939d4fc14ad86f6cd8be34b1468f22baEvgeniy Stepanov  out->st_size = in->st_size;
1862be3a283939d4fc14ad86f6cd8be34b1468f22baEvgeniy Stepanov  out->st_blksize = in->st_blksize;
1872be3a283939d4fc14ad86f6cd8be34b1468f22baEvgeniy Stepanov  out->st_blocks = in->st_blocks;
1882be3a283939d4fc14ad86f6cd8be34b1468f22baEvgeniy Stepanov  out->st_atime = in->st_atime;
1892be3a283939d4fc14ad86f6cd8be34b1468f22baEvgeniy Stepanov  out->st_mtime = in->st_mtime;
1902be3a283939d4fc14ad86f6cd8be34b1468f22baEvgeniy Stepanov  out->st_ctime = in->st_ctime;
1912be3a283939d4fc14ad86f6cd8be34b1468f22baEvgeniy Stepanov  out->st_ino = in->st_ino;
1922be3a283939d4fc14ad86f6cd8be34b1468f22baEvgeniy Stepanov}
1932be3a283939d4fc14ad86f6cd8be34b1468f22baEvgeniy Stepanov#endif
1942be3a283939d4fc14ad86f6cd8be34b1468f22baEvgeniy Stepanov
19586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines#if defined(__mips64)
19686277eb844c4983c81de62d7c050e92fe7155788Stephen Hinesstatic void kernel_stat_to_stat(struct kernel_stat *in, struct stat *out) {
19786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  internal_memset(out, 0, sizeof(*out));
19886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  out->st_dev = in->st_dev;
19986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  out->st_ino = in->st_ino;
20086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  out->st_mode = in->st_mode;
20186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  out->st_nlink = in->st_nlink;
20286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  out->st_uid = in->st_uid;
20386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  out->st_gid = in->st_gid;
20486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  out->st_rdev = in->st_rdev;
20586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  out->st_size = in->st_size;
20686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  out->st_blksize = in->st_blksize;
20786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  out->st_blocks = in->st_blocks;
20886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  out->st_atime = in->st_atime_nsec;
20986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  out->st_mtime = in->st_mtime_nsec;
21086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  out->st_ctime = in->st_ctime_nsec;
21186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  out->st_ino = in->st_ino;
21286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines}
21386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines#endif
21486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines
2159578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourneuptr internal_stat(const char *path, void *buf) {
2162d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#if SANITIZER_FREEBSD
2172d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  return internal_syscall(SYSCALL(stat), path, buf);
2182d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#elif SANITIZER_USES_CANONICAL_LINUX_SYSCALLS
2192d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  return internal_syscall(SYSCALL(newfstatat), AT_FDCWD, (uptr)path,
2202d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines                          (uptr)buf, 0);
2212d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#elif SANITIZER_LINUX_USES_64BIT_SYSCALLS
22286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines# if defined(__mips64)
22386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  // For mips64, stat syscall fills buffer in the format of kernel_stat
22486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  struct kernel_stat kbuf;
22586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  int res = internal_syscall(SYSCALL(stat), path, &kbuf);
22686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  kernel_stat_to_stat(&kbuf, (struct stat *)buf);
22786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  return res;
22886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines# else
2292d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  return internal_syscall(SYSCALL(stat), (uptr)path, (uptr)buf);
23086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines# endif
2314c9317a7b61e136f832d2ede70f557963fd46bceAlexey Samsonov#else
2322be3a283939d4fc14ad86f6cd8be34b1468f22baEvgeniy Stepanov  struct stat64 buf64;
2332d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  int res = internal_syscall(SYSCALL(stat64), path, &buf64);
2342be3a283939d4fc14ad86f6cd8be34b1468f22baEvgeniy Stepanov  stat64_to_stat(&buf64, (struct stat *)buf);
2352be3a283939d4fc14ad86f6cd8be34b1468f22baEvgeniy Stepanov  return res;
2364c9317a7b61e136f832d2ede70f557963fd46bceAlexey Samsonov#endif
2374c9317a7b61e136f832d2ede70f557963fd46bceAlexey Samsonov}
2384c9317a7b61e136f832d2ede70f557963fd46bceAlexey Samsonov
2399578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourneuptr internal_lstat(const char *path, void *buf) {
2402d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#if SANITIZER_FREEBSD
2412d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  return internal_syscall(SYSCALL(lstat), path, buf);
2422d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#elif SANITIZER_USES_CANONICAL_LINUX_SYSCALLS
2432d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  return internal_syscall(SYSCALL(newfstatat), AT_FDCWD, (uptr)path,
2442d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines                         (uptr)buf, AT_SYMLINK_NOFOLLOW);
2452d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#elif SANITIZER_LINUX_USES_64BIT_SYSCALLS
2462d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  return internal_syscall(SYSCALL(lstat), (uptr)path, (uptr)buf);
2474c9317a7b61e136f832d2ede70f557963fd46bceAlexey Samsonov#else
2482be3a283939d4fc14ad86f6cd8be34b1468f22baEvgeniy Stepanov  struct stat64 buf64;
2492d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  int res = internal_syscall(SYSCALL(lstat64), path, &buf64);
2502be3a283939d4fc14ad86f6cd8be34b1468f22baEvgeniy Stepanov  stat64_to_stat(&buf64, (struct stat *)buf);
2512be3a283939d4fc14ad86f6cd8be34b1468f22baEvgeniy Stepanov  return res;
2524c9317a7b61e136f832d2ede70f557963fd46bceAlexey Samsonov#endif
2534c9317a7b61e136f832d2ede70f557963fd46bceAlexey Samsonov}
2544c9317a7b61e136f832d2ede70f557963fd46bceAlexey Samsonov
2559578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourneuptr internal_fstat(fd_t fd, void *buf) {
2562d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#if SANITIZER_FREEBSD || SANITIZER_LINUX_USES_64BIT_SYSCALLS
2572d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  return internal_syscall(SYSCALL(fstat), fd, (uptr)buf);
2584c9317a7b61e136f832d2ede70f557963fd46bceAlexey Samsonov#else
2592be3a283939d4fc14ad86f6cd8be34b1468f22baEvgeniy Stepanov  struct stat64 buf64;
2602d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  int res = internal_syscall(SYSCALL(fstat64), fd, &buf64);
2612be3a283939d4fc14ad86f6cd8be34b1468f22baEvgeniy Stepanov  stat64_to_stat(&buf64, (struct stat *)buf);
2622be3a283939d4fc14ad86f6cd8be34b1468f22baEvgeniy Stepanov  return res;
2634c9317a7b61e136f832d2ede70f557963fd46bceAlexey Samsonov#endif
2644c9317a7b61e136f832d2ede70f557963fd46bceAlexey Samsonov}
2654c9317a7b61e136f832d2ede70f557963fd46bceAlexey Samsonov
2668e820fcf7aafeb8101322182d742fcf99255d972Alexey Samsonovuptr internal_filesize(fd_t fd) {
267a68633fb76208137ccb807914df52758ee5ca6f0Alexey Samsonov  struct stat st;
2684c9317a7b61e136f832d2ede70f557963fd46bceAlexey Samsonov  if (internal_fstat(fd, &st))
2694c9317a7b61e136f832d2ede70f557963fd46bceAlexey Samsonov    return -1;
2708e820fcf7aafeb8101322182d742fcf99255d972Alexey Samsonov  return (uptr)st.st_size;
2718e820fcf7aafeb8101322182d742fcf99255d972Alexey Samsonov}
2728e820fcf7aafeb8101322182d742fcf99255d972Alexey Samsonov
2739578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourneuptr internal_dup2(int oldfd, int newfd) {
2742d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#if SANITIZER_USES_CANONICAL_LINUX_SYSCALLS
2752d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  return internal_syscall(SYSCALL(dup3), oldfd, newfd, 0);
2762d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#else
2772d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  return internal_syscall(SYSCALL(dup2), oldfd, newfd);
2782d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#endif
2798e820fcf7aafeb8101322182d742fcf99255d972Alexey Samsonov}
2808e820fcf7aafeb8101322182d742fcf99255d972Alexey Samsonov
281d1b8f588d6b712b6ff2b3d58c73d71614f520122Alexey Samsonovuptr internal_readlink(const char *path, char *buf, uptr bufsize) {
2822d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#if SANITIZER_USES_CANONICAL_LINUX_SYSCALLS
2832d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  return internal_syscall(SYSCALL(readlinkat), AT_FDCWD,
2842d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines                          (uptr)path, (uptr)buf, bufsize);
2852d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#else
2862d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  return internal_syscall(SYSCALL(readlink), (uptr)path, (uptr)buf, bufsize);
2872d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#endif
288d1b8f588d6b712b6ff2b3d58c73d71614f520122Alexey Samsonov}
289d1b8f588d6b712b6ff2b3d58c73d71614f520122Alexey Samsonov
2909578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourneuptr internal_unlink(const char *path) {
2912d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#if SANITIZER_USES_CANONICAL_LINUX_SYSCALLS
2922d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  return internal_syscall(SYSCALL(unlinkat), AT_FDCWD, (uptr)path, 0);
2932d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#else
2942d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  return internal_syscall(SYSCALL(unlink), (uptr)path);
2952d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#endif
2962d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines}
2972d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
2982d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesuptr internal_rename(const char *oldpath, const char *newpath) {
2992d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#if SANITIZER_USES_CANONICAL_LINUX_SYSCALLS
3002d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  return internal_syscall(SYSCALL(renameat), AT_FDCWD, (uptr)oldpath, AT_FDCWD,
3012d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines                          (uptr)newpath);
3022d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#else
3032d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  return internal_syscall(SYSCALL(rename), (uptr)oldpath, (uptr)newpath);
3042d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#endif
3056d6ab9eeea4a99370d7ab18ce80eb96091e2cf3fDmitry Vyukov}
3066d6ab9eeea4a99370d7ab18ce80eb96091e2cf3fDmitry Vyukov
3079578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourneuptr internal_sched_yield() {
3082d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  return internal_syscall(SYSCALL(sched_yield));
3090969bcf2c936126b1f6e636b978aade8fc207437Alexey Samsonov}
3100969bcf2c936126b1f6e636b978aade8fc207437Alexey Samsonov
311f882247088952deed954a19d745c2dd8871e2035Alexey Samsonovvoid internal__exit(int exitcode) {
3122d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#if SANITIZER_FREEBSD
3132d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  internal_syscall(SYSCALL(exit), exitcode);
3142d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#else
3152d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  internal_syscall(SYSCALL(exit_group), exitcode);
3162d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#endif
317f882247088952deed954a19d745c2dd8871e2035Alexey Samsonov  Die();  // Unreachable.
318f882247088952deed954a19d745c2dd8871e2035Alexey Samsonov}
319f882247088952deed954a19d745c2dd8871e2035Alexey Samsonov
3209578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourneuptr internal_execve(const char *filename, char *const argv[],
3219578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne                     char *const envp[]) {
3222d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  return internal_syscall(SYSCALL(execve), (uptr)filename, (uptr)argv,
3232d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines                          (uptr)envp);
3249578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne}
3259578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne
326e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov// ----------------- sanitizer_common.h
32793b4cafd631b661b4b612ccdc0938f7f1e1c86d6Alexey Samsonovbool FileExists(const char *filename) {
3282d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  struct stat st;
32986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines#if SANITIZER_USES_CANONICAL_LINUX_SYSCALLS
3302d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  if (internal_syscall(SYSCALL(newfstatat), AT_FDCWD, filename, &st, 0))
3312d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#else
3322be3a283939d4fc14ad86f6cd8be34b1468f22baEvgeniy Stepanov  if (internal_stat(filename, &st))
33386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines#endif
33493b4cafd631b661b4b612ccdc0938f7f1e1c86d6Alexey Samsonov    return false;
33593b4cafd631b661b4b612ccdc0938f7f1e1c86d6Alexey Samsonov  // Sanity check: filename is a regular file.
33693b4cafd631b661b4b612ccdc0938f7f1e1c86d6Alexey Samsonov  return S_ISREG(st.st_mode);
33793b4cafd631b661b4b612ccdc0938f7f1e1c86d6Alexey Samsonov}
33893b4cafd631b661b4b612ccdc0938f7f1e1c86d6Alexey Samsonov
339e0023f74ea88efee329f68391b70f8adc6b21617Dmitry Vyukovuptr GetTid() {
3402d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#if SANITIZER_FREEBSD
3412d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  return (uptr)pthread_self();
3422d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#else
3432d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  return internal_syscall(SYSCALL(gettid));
3442d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#endif
345e0023f74ea88efee329f68391b70f8adc6b21617Dmitry Vyukov}
346e0023f74ea88efee329f68391b70f8adc6b21617Dmitry Vyukov
3474bebe7bab966c82f0a8952f797ed3d490624dc62Dmitry Vyukovu64 NanoTime() {
3482d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#if SANITIZER_FREEBSD
3492d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  timeval tv;
3502d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#else
3515e7ba22755b994e4f6aaf8cc00773c4d1b8dbf07Peter Collingbourne  kernel_timeval tv;
3522d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#endif
3535e7ba22755b994e4f6aaf8cc00773c4d1b8dbf07Peter Collingbourne  internal_memset(&tv, 0, sizeof(tv));
3542d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  internal_syscall(SYSCALL(gettimeofday), (uptr)&tv, 0);
3554bebe7bab966c82f0a8952f797ed3d490624dc62Dmitry Vyukov  return (u64)tv.tv_sec * 1000*1000*1000 + tv.tv_usec * 1000;
3564bebe7bab966c82f0a8952f797ed3d490624dc62Dmitry Vyukov}
3574bebe7bab966c82f0a8952f797ed3d490624dc62Dmitry Vyukov
3586a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines// Like getenv, but reads env directly from /proc (on Linux) or parses the
3596a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines// 'environ' array (on FreeBSD) and does not use libc. This function should be
3606a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines// called first inside __asan_init.
3613dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonovconst char *GetEnv(const char *name) {
3626a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines#if SANITIZER_FREEBSD
3636a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines  if (::environ != 0) {
3646a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines    uptr NameLen = internal_strlen(name);
3656a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines    for (char **Env = ::environ; *Env != 0; Env++) {
3666a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines      if (internal_strncmp(*Env, name, NameLen) == 0 && (*Env)[NameLen] == '=')
3676a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines        return (*Env) + NameLen + 1;
3686a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines    }
3696a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines  }
3706a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines  return 0;  // Not found.
3716a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines#elif SANITIZER_LINUX
3723dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov  static char *environ;
3733dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov  static uptr len;
3743dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov  static bool inited;
3753dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov  if (!inited) {
3763dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov    inited = true;
3773dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov    uptr environ_size;
3783dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov    len = ReadFileToBuffer("/proc/self/environ",
3793dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov                           &environ, &environ_size, 1 << 26);
3803dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov  }
3813dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov  if (!environ || len == 0) return 0;
3823dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov  uptr namelen = internal_strlen(name);
3833dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov  const char *p = environ;
3843dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov  while (*p != '\0') {  // will happen at the \0\0 that terminates the buffer
3853dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov    // proc file has the format NAME=value\0NAME=value\0NAME=value\0...
3863dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov    const char* endp =
3873dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov        (char*)internal_memchr(p, '\0', len - (p - environ));
3883dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov    if (endp == 0)  // this entry isn't NUL terminated
3893dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov      return 0;
3903dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov    else if (!internal_memcmp(p, name, namelen) && p[namelen] == '=')  // Match.
3913dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov      return p + namelen + 1;  // point after =
3923dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov    p = endp + 1;
3933dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov  }
3943dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov  return 0;  // Not found.
3956a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines#else
3966a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines#error "Unsupported platform"
3976a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines#endif
3983dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov}
3993dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov
400eab061185ec0046d447b298a1dff84f028202a3cEvgeniy Stepanovextern "C" {
4013c80c6c574850106481f82b9e23d1c728458d4a9Timur Iskhodzhanov  SANITIZER_WEAK_ATTRIBUTE extern void *__libc_stack_end;
402eab061185ec0046d447b298a1dff84f028202a3cEvgeniy Stepanov}
403eab061185ec0046d447b298a1dff84f028202a3cEvgeniy Stepanov
40426337b60b1d551c4744454edd8e5ef3c479e3467Peter Collingbourne#if !SANITIZER_GO
40523709c9ad9ac7c45de288f5260403426bf932db7Peter Collingbournestatic void ReadNullSepFileToArray(const char *path, char ***arr,
40623709c9ad9ac7c45de288f5260403426bf932db7Peter Collingbourne                                   int arr_size) {
40723709c9ad9ac7c45de288f5260403426bf932db7Peter Collingbourne  char *buff;
408d7e5bb4043adf4756e6f8cfe0f5a3165b185474dAlexey Samsonov  uptr buff_size = 0;
40923709c9ad9ac7c45de288f5260403426bf932db7Peter Collingbourne  *arr = (char **)MmapOrDie(arr_size * sizeof(char *), "NullSepFileArray");
41023709c9ad9ac7c45de288f5260403426bf932db7Peter Collingbourne  ReadFileToBuffer(path, &buff, &buff_size, 1024 * 1024);
41123709c9ad9ac7c45de288f5260403426bf932db7Peter Collingbourne  (*arr)[0] = buff;
41223709c9ad9ac7c45de288f5260403426bf932db7Peter Collingbourne  int count, i;
41323709c9ad9ac7c45de288f5260403426bf932db7Peter Collingbourne  for (count = 1, i = 1; ; i++) {
414d7e5bb4043adf4756e6f8cfe0f5a3165b185474dAlexey Samsonov    if (buff[i] == 0) {
415d7e5bb4043adf4756e6f8cfe0f5a3165b185474dAlexey Samsonov      if (buff[i+1] == 0) break;
41623709c9ad9ac7c45de288f5260403426bf932db7Peter Collingbourne      (*arr)[count] = &buff[i+1];
41723709c9ad9ac7c45de288f5260403426bf932db7Peter Collingbourne      CHECK_LE(count, arr_size - 1);  // FIXME: make this more flexible.
41823709c9ad9ac7c45de288f5260403426bf932db7Peter Collingbourne      count++;
419d7e5bb4043adf4756e6f8cfe0f5a3165b185474dAlexey Samsonov    }
420d7e5bb4043adf4756e6f8cfe0f5a3165b185474dAlexey Samsonov  }
42123709c9ad9ac7c45de288f5260403426bf932db7Peter Collingbourne  (*arr)[count] = 0;
42223709c9ad9ac7c45de288f5260403426bf932db7Peter Collingbourne}
42326337b60b1d551c4744454edd8e5ef3c479e3467Peter Collingbourne#endif
42423709c9ad9ac7c45de288f5260403426bf932db7Peter Collingbourne
42526337b60b1d551c4744454edd8e5ef3c479e3467Peter Collingbournestatic void GetArgsAndEnv(char*** argv, char*** envp) {
42626337b60b1d551c4744454edd8e5ef3c479e3467Peter Collingbourne#if !SANITIZER_GO
42726337b60b1d551c4744454edd8e5ef3c479e3467Peter Collingbourne  if (&__libc_stack_end) {
42826337b60b1d551c4744454edd8e5ef3c479e3467Peter Collingbourne#endif
42926337b60b1d551c4744454edd8e5ef3c479e3467Peter Collingbourne    uptr* stack_end = (uptr*)__libc_stack_end;
43026337b60b1d551c4744454edd8e5ef3c479e3467Peter Collingbourne    int argc = *stack_end;
43126337b60b1d551c4744454edd8e5ef3c479e3467Peter Collingbourne    *argv = (char**)(stack_end + 1);
43226337b60b1d551c4744454edd8e5ef3c479e3467Peter Collingbourne    *envp = (char**)(stack_end + argc + 2);
43326337b60b1d551c4744454edd8e5ef3c479e3467Peter Collingbourne#if !SANITIZER_GO
43426337b60b1d551c4744454edd8e5ef3c479e3467Peter Collingbourne  } else {
43526337b60b1d551c4744454edd8e5ef3c479e3467Peter Collingbourne    static const int kMaxArgv = 2000, kMaxEnvp = 2000;
43626337b60b1d551c4744454edd8e5ef3c479e3467Peter Collingbourne    ReadNullSepFileToArray("/proc/self/cmdline", argv, kMaxArgv);
43726337b60b1d551c4744454edd8e5ef3c479e3467Peter Collingbourne    ReadNullSepFileToArray("/proc/self/environ", envp, kMaxEnvp);
43826337b60b1d551c4744454edd8e5ef3c479e3467Peter Collingbourne  }
43926337b60b1d551c4744454edd8e5ef3c479e3467Peter Collingbourne#endif
440eab061185ec0046d447b298a1dff84f028202a3cEvgeniy Stepanov}
441eab061185ec0046d447b298a1dff84f028202a3cEvgeniy Stepanov
442eab061185ec0046d447b298a1dff84f028202a3cEvgeniy Stepanovvoid ReExec() {
44323709c9ad9ac7c45de288f5260403426bf932db7Peter Collingbourne  char **argv, **envp;
444eab061185ec0046d447b298a1dff84f028202a3cEvgeniy Stepanov  GetArgsAndEnv(&argv, &envp);
4459578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne  uptr rv = internal_execve("/proc/self/exe", argv, envp);
4469578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne  int rverrno;
4479578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne  CHECK_EQ(internal_iserror(rv, &rverrno), true);
4489578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne  Printf("execve failed, errno %d\n", rverrno);
449f35eae83757946decb312deab3f0fe155fe5d580Evgeniy Stepanov  Die();
450d7e5bb4043adf4756e6f8cfe0f5a3165b185474dAlexey Samsonov}
451d7e5bb4043adf4756e6f8cfe0f5a3165b185474dAlexey Samsonov
452f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukovenum MutexState {
453f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov  MtxUnlocked = 0,
454f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov  MtxLocked = 1,
455f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov  MtxSleeping = 2
456f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov};
457f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov
45893af5948d3e0c5bdc396f432dd0ae782f499c449Alexey SamsonovBlockingMutex::BlockingMutex() {
45993af5948d3e0c5bdc396f432dd0ae782f499c449Alexey Samsonov  internal_memset(this, 0, sizeof(*this));
46093af5948d3e0c5bdc396f432dd0ae782f499c449Alexey Samsonov}
46193af5948d3e0c5bdc396f432dd0ae782f499c449Alexey Samsonov
462f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukovvoid BlockingMutex::Lock() {
46386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  CHECK_EQ(owner_, 0);
464f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov  atomic_uint32_t *m = reinterpret_cast<atomic_uint32_t *>(&opaque_storage_);
465f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov  if (atomic_exchange(m, MtxLocked, memory_order_acquire) == MtxUnlocked)
466f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov    return;
4672d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  while (atomic_exchange(m, MtxSleeping, memory_order_acquire) != MtxUnlocked) {
4682d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#if SANITIZER_FREEBSD
4692d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    _umtx_op(m, UMTX_OP_WAIT_UINT, MtxSleeping, 0, 0);
4702d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#else
4712d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    internal_syscall(SYSCALL(futex), (uptr)m, FUTEX_WAIT, MtxSleeping, 0, 0, 0);
4722d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#endif
4732d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  }
474f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov}
475f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov
476f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukovvoid BlockingMutex::Unlock() {
477f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov  atomic_uint32_t *m = reinterpret_cast<atomic_uint32_t *>(&opaque_storage_);
478f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov  u32 v = atomic_exchange(m, MtxUnlocked, memory_order_relaxed);
47948526014de78e21f7ed027a60670016bc7f5d292Dmitry Vyukov  CHECK_NE(v, MtxUnlocked);
4802d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  if (v == MtxSleeping) {
4812d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#if SANITIZER_FREEBSD
4822d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    _umtx_op(m, UMTX_OP_WAKE, 1, 0, 0);
4832d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#else
4842d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    internal_syscall(SYSCALL(futex), (uptr)m, FUTEX_WAKE, 1, 0, 0, 0);
4852d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#endif
4862d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  }
487f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov}
488f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov
489ce700979f644c790c2d9d80f5cc2a1ada0380284Alexey Samsonovvoid BlockingMutex::CheckLocked() {
490ce700979f644c790c2d9d80f5cc2a1ada0380284Alexey Samsonov  atomic_uint32_t *m = reinterpret_cast<atomic_uint32_t *>(&opaque_storage_);
491ce700979f644c790c2d9d80f5cc2a1ada0380284Alexey Samsonov  CHECK_NE(MtxUnlocked, atomic_load(m, memory_order_relaxed));
492ce700979f644c790c2d9d80f5cc2a1ada0380284Alexey Samsonov}
493ce700979f644c790c2d9d80f5cc2a1ada0380284Alexey Samsonov
4946fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany// ----------------- sanitizer_linux.h
4956fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany// The actual size of this structure is specified by d_reclen.
4966fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany// Note that getdents64 uses a different structure format. We only provide the
4976fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany// 32-bit syscall here.
4986fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryanystruct linux_dirent {
4992d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#if SANITIZER_X32
5002d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  u64 d_ino;
5012d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  u64 d_off;
5022d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#else
5036fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany  unsigned long      d_ino;
5046fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany  unsigned long      d_off;
5052d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#endif
5066fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany  unsigned short     d_reclen;
5076fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany  char               d_name[256];
5086fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany};
5096fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany
5106fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany// Syscall wrappers.
5119578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourneuptr internal_ptrace(int request, int pid, void *addr, void *data) {
5122d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  return internal_syscall(SYSCALL(ptrace), request, pid, (uptr)addr,
5132d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines                          (uptr)data);
5149578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne}
5159578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne
5169578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourneuptr internal_waitpid(int pid, int *status, int options) {
5172d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  return internal_syscall(SYSCALL(wait4), pid, (uptr)status, options,
518e041c6024b3ebf1365c0f99732fc69c607577571Kostya Serebryany                          0 /* rusage */);
5196fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany}
5206fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany
5219578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourneuptr internal_getpid() {
5222d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  return internal_syscall(SYSCALL(getpid));
5236fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany}
5246fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany
5259578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourneuptr internal_getppid() {
5262d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  return internal_syscall(SYSCALL(getppid));
5276fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany}
5286fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany
5299578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourneuptr internal_getdents(fd_t fd, struct linux_dirent *dirp, unsigned int count) {
5302d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#if SANITIZER_USES_CANONICAL_LINUX_SYSCALLS
5312d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  return internal_syscall(SYSCALL(getdents64), fd, (uptr)dirp, count);
5322d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#else
5332d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  return internal_syscall(SYSCALL(getdents), fd, (uptr)dirp, count);
5342d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#endif
5356fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany}
5366fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany
5379578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourneuptr internal_lseek(fd_t fd, OFF_T offset, int whence) {
5382d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  return internal_syscall(SYSCALL(lseek), fd, offset, whence);
5396fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany}
5406fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany
5412d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#if SANITIZER_LINUX
5429578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourneuptr internal_prctl(int option, uptr arg2, uptr arg3, uptr arg4, uptr arg5) {
5432d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  return internal_syscall(SYSCALL(prctl), option, arg2, arg3, arg4, arg5);
5446fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany}
5452d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#endif
5466fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany
5479578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourneuptr internal_sigaltstack(const struct sigaltstack *ss,
5486fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany                         struct sigaltstack *oss) {
5492d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  return internal_syscall(SYSCALL(sigaltstack), (uptr)ss, (uptr)oss);
5502d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines}
5512d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
5522d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesint internal_fork() {
5532d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#if SANITIZER_USES_CANONICAL_LINUX_SYSCALLS
5542d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  return internal_syscall(SYSCALL(clone), SIGCHLD, 0);
5552d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#else
5562d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  return internal_syscall(SYSCALL(fork));
5572d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#endif
5586fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany}
5596fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany
5602d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#if SANITIZER_LINUX
5617c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar#define SA_RESTORER 0x04000000
5622d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines// Doesn't set sa_restorer, use with caution (see below).
5632d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesint internal_sigaction_norestorer(int signum, const void *act, void *oldact) {
5642d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  __sanitizer_kernel_sigaction_t k_act, k_oldact;
5652d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  internal_memset(&k_act, 0, sizeof(__sanitizer_kernel_sigaction_t));
5662d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  internal_memset(&k_oldact, 0, sizeof(__sanitizer_kernel_sigaction_t));
5676d1862363c88c183b0ed7740fca876342cf0474bStephen Hines  const __sanitizer_sigaction *u_act = (const __sanitizer_sigaction *)act;
5682d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  __sanitizer_sigaction *u_oldact = (__sanitizer_sigaction *)oldact;
5692d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  if (u_act) {
5702d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    k_act.handler = u_act->handler;
5712d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    k_act.sigaction = u_act->sigaction;
5722d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    internal_memcpy(&k_act.sa_mask, &u_act->sa_mask,
5732d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines                    sizeof(__sanitizer_kernel_sigset_t));
5747c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar    // Without SA_RESTORER kernel ignores the calls (probably returns EINVAL).
5757c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar    k_act.sa_flags = u_act->sa_flags | SA_RESTORER;
5762d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    // FIXME: most often sa_restorer is unset, however the kernel requires it
5772d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    // to point to a valid signal restorer that calls the rt_sigreturn syscall.
5782d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    // If sa_restorer passed to the kernel is NULL, the program may crash upon
5792d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    // signal delivery or fail to unwind the stack in the signal handler.
5802d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    // libc implementation of sigaction() passes its own restorer to
5812d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    // rt_sigaction, so we need to do the same (we'll need to reimplement the
5822d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    // restorers; for x86_64 the restorer address can be obtained from
5832d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    // oldact->sa_restorer upon a call to sigaction(xxx, NULL, oldact).
5842d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    k_act.sa_restorer = u_act->sa_restorer;
5852d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  }
5862d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
5872d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  uptr result = internal_syscall(SYSCALL(rt_sigaction), (uptr)signum,
5882d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines      (uptr)(u_act ? &k_act : NULL),
5892d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines      (uptr)(u_oldact ? &k_oldact : NULL),
5902d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines      (uptr)sizeof(__sanitizer_kernel_sigset_t));
5912d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
5922d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  if ((result == 0) && u_oldact) {
5932d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    u_oldact->handler = k_oldact.handler;
5942d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    u_oldact->sigaction = k_oldact.sigaction;
5952d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    internal_memcpy(&u_oldact->sa_mask, &k_oldact.sa_mask,
5962d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines                    sizeof(__sanitizer_kernel_sigset_t));
5972d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    u_oldact->sa_flags = k_oldact.sa_flags;
5982d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    u_oldact->sa_restorer = k_oldact.sa_restorer;
5992d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  }
6002d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  return result;
6010f7a2acb3326a5900d1a1339ebf959b14b372e0dDmitry Vyukov}
6022d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#endif  // SANITIZER_LINUX
6030f7a2acb3326a5900d1a1339ebf959b14b372e0dDmitry Vyukov
6042d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesuptr internal_sigprocmask(int how, __sanitizer_sigset_t *set,
6052d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    __sanitizer_sigset_t *oldset) {
6062d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#if SANITIZER_FREEBSD
6072d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  return internal_syscall(SYSCALL(sigprocmask), how, set, oldset);
6082d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#else
6092d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  __sanitizer_kernel_sigset_t *k_set = (__sanitizer_kernel_sigset_t *)set;
6102d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  __sanitizer_kernel_sigset_t *k_oldset = (__sanitizer_kernel_sigset_t *)oldset;
6112d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  return internal_syscall(SYSCALL(rt_sigprocmask), (uptr)how,
6122d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines                          (uptr)&k_set->sig[0], (uptr)&k_oldset->sig[0],
6132d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines                          sizeof(__sanitizer_kernel_sigset_t));
6142d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#endif
6150f7a2acb3326a5900d1a1339ebf959b14b372e0dDmitry Vyukov}
6160f7a2acb3326a5900d1a1339ebf959b14b372e0dDmitry Vyukov
6172d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesvoid internal_sigfillset(__sanitizer_sigset_t *set) {
6180f7a2acb3326a5900d1a1339ebf959b14b372e0dDmitry Vyukov  internal_memset(set, 0xff, sizeof(*set));
6190f7a2acb3326a5900d1a1339ebf959b14b372e0dDmitry Vyukov}
6200f7a2acb3326a5900d1a1339ebf959b14b372e0dDmitry Vyukov
6212d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#if SANITIZER_LINUX
6222d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesvoid internal_sigdelset(__sanitizer_sigset_t *set, int signum) {
6230f7a2acb3326a5900d1a1339ebf959b14b372e0dDmitry Vyukov  signum -= 1;
6240f7a2acb3326a5900d1a1339ebf959b14b372e0dDmitry Vyukov  CHECK_GE(signum, 0);
6250f7a2acb3326a5900d1a1339ebf959b14b372e0dDmitry Vyukov  CHECK_LT(signum, sizeof(*set) * 8);
6262d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  __sanitizer_kernel_sigset_t *k_set = (__sanitizer_kernel_sigset_t *)set;
6272d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  const uptr idx = signum / (sizeof(k_set->sig[0]) * 8);
6282d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  const uptr bit = signum % (sizeof(k_set->sig[0]) * 8);
6292d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  k_set->sig[idx] &= ~(1 << bit);
6300f7a2acb3326a5900d1a1339ebf959b14b372e0dDmitry Vyukov}
6312d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#endif  // SANITIZER_LINUX
6320f7a2acb3326a5900d1a1339ebf959b14b372e0dDmitry Vyukov
6336fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany// ThreadLister implementation.
6346fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya SerebryanyThreadLister::ThreadLister(int pid)
6356fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany  : pid_(pid),
6366fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany    descriptor_(-1),
63710f3ab775088bec69dd9e7b611f9b4e152f629bcAlexey Samsonov    buffer_(4096),
6386fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany    error_(true),
63910f3ab775088bec69dd9e7b611f9b4e152f629bcAlexey Samsonov    entry_((struct linux_dirent *)buffer_.data()),
6406fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany    bytes_read_(0) {
6416fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany  char task_directory_path[80];
6426fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany  internal_snprintf(task_directory_path, sizeof(task_directory_path),
6436fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany                    "/proc/%d/task/", pid);
6449578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne  uptr openrv = internal_open(task_directory_path, O_RDONLY | O_DIRECTORY);
6459578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne  if (internal_iserror(openrv)) {
6466fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany    error_ = true;
6476fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany    Report("Can't open /proc/%d/task for reading.\n", pid);
6486fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany  } else {
6496fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany    error_ = false;
6509578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne    descriptor_ = openrv;
6516fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany  }
6526fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany}
6536fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany
6546fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryanyint ThreadLister::GetNextTID() {
6556fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany  int tid = -1;
6566fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany  do {
6576fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany    if (error_)
6586fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany      return -1;
6596fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany    if ((char *)entry_ >= &buffer_[bytes_read_] && !GetDirectoryEntries())
6606fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany      return -1;
6616fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany    if (entry_->d_ino != 0 && entry_->d_name[0] >= '0' &&
6626fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany        entry_->d_name[0] <= '9') {
6636fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany      // Found a valid tid.
6646fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany      tid = (int)internal_atoll(entry_->d_name);
6656fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany    }
6666fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany    entry_ = (struct linux_dirent *)(((char *)entry_) + entry_->d_reclen);
6676fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany  } while (tid < 0);
6686fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany  return tid;
6696fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany}
6706fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany
6716fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryanyvoid ThreadLister::Reset() {
6726fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany  if (error_ || descriptor_ < 0)
6736fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany    return;
6746fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany  internal_lseek(descriptor_, 0, SEEK_SET);
6756fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany}
6766fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany
6776fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya SerebryanyThreadLister::~ThreadLister() {
6786fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany  if (descriptor_ >= 0)
6796fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany    internal_close(descriptor_);
6806fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany}
6816fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany
6826fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryanybool ThreadLister::error() { return error_; }
6836fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany
6846fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryanybool ThreadLister::GetDirectoryEntries() {
6856fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany  CHECK_GE(descriptor_, 0);
6866fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany  CHECK_NE(error_, true);
6876fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany  bytes_read_ = internal_getdents(descriptor_,
68810f3ab775088bec69dd9e7b611f9b4e152f629bcAlexey Samsonov                                  (struct linux_dirent *)buffer_.data(),
68910f3ab775088bec69dd9e7b611f9b4e152f629bcAlexey Samsonov                                  buffer_.size());
6909578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne  if (internal_iserror(bytes_read_)) {
6916fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany    Report("Can't read directory entries from /proc/%d/task.\n", pid_);
6926fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany    error_ = true;
6936fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany    return false;
6946fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany  } else if (bytes_read_ == 0) {
6956fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany    return false;
6966fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany  }
69710f3ab775088bec69dd9e7b611f9b4e152f629bcAlexey Samsonov  entry_ = (struct linux_dirent *)buffer_.data();
6986fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany  return true;
6996fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany}
7006fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany
7014df343a31cf57c309cf102b9aef870458318f579Peter Collingbourneuptr GetPageSize() {
7022d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#if SANITIZER_LINUX && (defined(__x86_64__) || defined(__i386__))
7034df343a31cf57c309cf102b9aef870458318f579Peter Collingbourne  return EXEC_PAGESIZE;
704a8bc34e420d27c47560b0742cec295e40b0f430eKostya Serebryany#else
705a8bc34e420d27c47560b0742cec295e40b0f430eKostya Serebryany  return sysconf(_SC_PAGESIZE);  // EXEC_PAGESIZE may not be trustworthy.
706a8bc34e420d27c47560b0742cec295e40b0f430eKostya Serebryany#endif
7074df343a31cf57c309cf102b9aef870458318f579Peter Collingbourne}
7084df343a31cf57c309cf102b9aef870458318f579Peter Collingbourne
7097847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonovuptr ReadBinaryName(/*out*/char *buf, uptr buf_len) {
7106a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines#if SANITIZER_FREEBSD
711cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar  const int Mib[] = { CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, -1 };
712cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar  const char *default_module_name = "kern.proc.pathname";
7136a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines  size_t Size = buf_len;
714cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar  bool IsErr = (sysctl(Mib, ARRAY_SIZE(Mib), buf, &Size, NULL, 0) != 0);
7156a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines  int readlink_error = IsErr ? errno : 0;
7166a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines  uptr module_name_len = Size;
7176a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines#else
718cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar  const char *default_module_name = "/proc/self/exe";
7197847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov  uptr module_name_len = internal_readlink(
720cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar      default_module_name, buf, buf_len);
7217847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov  int readlink_error;
7226a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines  bool IsErr = internal_iserror(module_name_len, &readlink_error);
7236a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines#endif
7246a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines  if (IsErr) {
725cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar    // We can't read binary name for some reason, assume it's unknown.
726cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar    Report("WARNING: reading executable name failed with errno %d, "
7276a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines           "some stack frames may not be symbolized\n", readlink_error);
728cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar    module_name_len = internal_snprintf(buf, buf_len, "%s",
729cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar                                        default_module_name);
7307847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov    CHECK_LT(module_name_len, buf_len);
7317847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov  }
7327847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov  return module_name_len;
7337847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov}
7347847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov
7353de0086409d143a612a54a7a0ed809e286656188Sergey Matveev// Match full names of the form /path/to/base_name{-,.}*
7363de0086409d143a612a54a7a0ed809e286656188Sergey Matveevbool LibraryNameIs(const char *full_name, const char *base_name) {
7373de0086409d143a612a54a7a0ed809e286656188Sergey Matveev  const char *name = full_name;
7383de0086409d143a612a54a7a0ed809e286656188Sergey Matveev  // Strip path.
7393de0086409d143a612a54a7a0ed809e286656188Sergey Matveev  while (*name != '\0') name++;
7403de0086409d143a612a54a7a0ed809e286656188Sergey Matveev  while (name > full_name && *name != '/') name--;
7413de0086409d143a612a54a7a0ed809e286656188Sergey Matveev  if (*name == '/') name++;
7423de0086409d143a612a54a7a0ed809e286656188Sergey Matveev  uptr base_name_length = internal_strlen(base_name);
7433de0086409d143a612a54a7a0ed809e286656188Sergey Matveev  if (internal_strncmp(name, base_name, base_name_length)) return false;
7443de0086409d143a612a54a7a0ed809e286656188Sergey Matveev  return (name[base_name_length] == '-' || name[base_name_length] == '.');
7453de0086409d143a612a54a7a0ed809e286656188Sergey Matveev}
7463de0086409d143a612a54a7a0ed809e286656188Sergey Matveev
747d054abef27369471e154ec5693949538c2fdffd9Evgeniy Stepanov#if !SANITIZER_ANDROID
7482e75ac983cb233daa1abfa35fb33d2bafffe2ab1Peter Collingbourne// Call cb for each region mapped by map.
7492e75ac983cb233daa1abfa35fb33d2bafffe2ab1Peter Collingbournevoid ForEachMappedRegion(link_map *map, void (*cb)(const void *, uptr)) {
75086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  CHECK_NE(map, nullptr);
7512d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#if !SANITIZER_FREEBSD
7522e75ac983cb233daa1abfa35fb33d2bafffe2ab1Peter Collingbourne  typedef ElfW(Phdr) Elf_Phdr;
7532e75ac983cb233daa1abfa35fb33d2bafffe2ab1Peter Collingbourne  typedef ElfW(Ehdr) Elf_Ehdr;
7542d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#endif  // !SANITIZER_FREEBSD
7552e75ac983cb233daa1abfa35fb33d2bafffe2ab1Peter Collingbourne  char *base = (char *)map->l_addr;
7562e75ac983cb233daa1abfa35fb33d2bafffe2ab1Peter Collingbourne  Elf_Ehdr *ehdr = (Elf_Ehdr *)base;
7572e75ac983cb233daa1abfa35fb33d2bafffe2ab1Peter Collingbourne  char *phdrs = base + ehdr->e_phoff;
7582e75ac983cb233daa1abfa35fb33d2bafffe2ab1Peter Collingbourne  char *phdrs_end = phdrs + ehdr->e_phnum * ehdr->e_phentsize;
7592e75ac983cb233daa1abfa35fb33d2bafffe2ab1Peter Collingbourne
7602e75ac983cb233daa1abfa35fb33d2bafffe2ab1Peter Collingbourne  // Find the segment with the minimum base so we can "relocate" the p_vaddr
7612e75ac983cb233daa1abfa35fb33d2bafffe2ab1Peter Collingbourne  // fields.  Typically ET_DYN objects (DSOs) have base of zero and ET_EXEC
7622e75ac983cb233daa1abfa35fb33d2bafffe2ab1Peter Collingbourne  // objects have a non-zero base.
763f50b0fc601aea71d9fb22f01a11c7e206c666edcPeter Collingbourne  uptr preferred_base = (uptr)-1;
7642e75ac983cb233daa1abfa35fb33d2bafffe2ab1Peter Collingbourne  for (char *iter = phdrs; iter != phdrs_end; iter += ehdr->e_phentsize) {
7652e75ac983cb233daa1abfa35fb33d2bafffe2ab1Peter Collingbourne    Elf_Phdr *phdr = (Elf_Phdr *)iter;
7662e75ac983cb233daa1abfa35fb33d2bafffe2ab1Peter Collingbourne    if (phdr->p_type == PT_LOAD && preferred_base > (uptr)phdr->p_vaddr)
7672e75ac983cb233daa1abfa35fb33d2bafffe2ab1Peter Collingbourne      preferred_base = (uptr)phdr->p_vaddr;
7682e75ac983cb233daa1abfa35fb33d2bafffe2ab1Peter Collingbourne  }
7692e75ac983cb233daa1abfa35fb33d2bafffe2ab1Peter Collingbourne
7702e75ac983cb233daa1abfa35fb33d2bafffe2ab1Peter Collingbourne  // Compute the delta from the real base to get a relocation delta.
7712e75ac983cb233daa1abfa35fb33d2bafffe2ab1Peter Collingbourne  sptr delta = (uptr)base - preferred_base;
7722e75ac983cb233daa1abfa35fb33d2bafffe2ab1Peter Collingbourne  // Now we can figure out what the loader really mapped.
7732e75ac983cb233daa1abfa35fb33d2bafffe2ab1Peter Collingbourne  for (char *iter = phdrs; iter != phdrs_end; iter += ehdr->e_phentsize) {
7742e75ac983cb233daa1abfa35fb33d2bafffe2ab1Peter Collingbourne    Elf_Phdr *phdr = (Elf_Phdr *)iter;
7752e75ac983cb233daa1abfa35fb33d2bafffe2ab1Peter Collingbourne    if (phdr->p_type == PT_LOAD) {
7762e75ac983cb233daa1abfa35fb33d2bafffe2ab1Peter Collingbourne      uptr seg_start = phdr->p_vaddr + delta;
7772e75ac983cb233daa1abfa35fb33d2bafffe2ab1Peter Collingbourne      uptr seg_end = seg_start + phdr->p_memsz;
7782e75ac983cb233daa1abfa35fb33d2bafffe2ab1Peter Collingbourne      // None of these values are aligned.  We consider the ragged edges of the
7792e75ac983cb233daa1abfa35fb33d2bafffe2ab1Peter Collingbourne      // load command as defined, since they are mapped from the file.
7802e75ac983cb233daa1abfa35fb33d2bafffe2ab1Peter Collingbourne      seg_start = RoundDownTo(seg_start, GetPageSizeCached());
7812e75ac983cb233daa1abfa35fb33d2bafffe2ab1Peter Collingbourne      seg_end = RoundUpTo(seg_end, GetPageSizeCached());
7822e75ac983cb233daa1abfa35fb33d2bafffe2ab1Peter Collingbourne      cb((void *)seg_start, seg_end - seg_start);
7832e75ac983cb233daa1abfa35fb33d2bafffe2ab1Peter Collingbourne    }
7842e75ac983cb233daa1abfa35fb33d2bafffe2ab1Peter Collingbourne  }
7852e75ac983cb233daa1abfa35fb33d2bafffe2ab1Peter Collingbourne}
786d054abef27369471e154ec5693949538c2fdffd9Evgeniy Stepanov#endif
7872e75ac983cb233daa1abfa35fb33d2bafffe2ab1Peter Collingbourne
7882d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#if defined(__x86_64__) && SANITIZER_LINUX
789cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev// We cannot use glibc's clone wrapper, because it messes with the child
790cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev// task's TLS. It writes the PID and TID of the child task to its thread
791cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev// descriptor, but in our case the child task shares the thread descriptor with
792cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev// the parent (because we don't know how to allocate a new thread
793cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev// descriptor to keep glibc happy). So the stock version of clone(), when
794cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev// used with CLONE_VM, would end up corrupting the parent's thread descriptor.
795cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveevuptr internal_clone(int (*fn)(void *), void *child_stack, int flags, void *arg,
796cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev                    int *parent_tidptr, void *newtls, int *child_tidptr) {
797cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev  long long res;
798cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev  if (!fn || !child_stack)
799cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev    return -EINVAL;
800cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev  CHECK_EQ(0, (uptr)child_stack % 16);
801e041c6024b3ebf1365c0f99732fc69c607577571Kostya Serebryany  child_stack = (char *)child_stack - 2 * sizeof(unsigned long long);
802e041c6024b3ebf1365c0f99732fc69c607577571Kostya Serebryany  ((unsigned long long *)child_stack)[0] = (uptr)fn;
803e041c6024b3ebf1365c0f99732fc69c607577571Kostya Serebryany  ((unsigned long long *)child_stack)[1] = (uptr)arg;
804e041c6024b3ebf1365c0f99732fc69c607577571Kostya Serebryany  register void *r8 __asm__("r8") = newtls;
805e041c6024b3ebf1365c0f99732fc69c607577571Kostya Serebryany  register int *r10 __asm__("r10") = child_tidptr;
806cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev  __asm__ __volatile__(
8072d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines                       /* %rax = syscall(%rax = SYSCALL(clone),
808cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev                        *                %rdi = flags,
809cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev                        *                %rsi = child_stack,
810cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev                        *                %rdx = parent_tidptr,
811cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev                        *                %r8  = new_tls,
812cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev                        *                %r10 = child_tidptr)
813cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev                        */
814cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev                       "syscall\n"
815cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev
816cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev                       /* if (%rax != 0)
817cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev                        *   return;
818cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev                        */
819cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev                       "testq  %%rax,%%rax\n"
820cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev                       "jnz    1f\n"
821cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev
822cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev                       /* In the child. Terminate unwind chain. */
823497ae56316cd05a0d539e0d6e065bbaee254aca3Sergey Matveev                       // XXX: We should also terminate the CFI unwind chain
824497ae56316cd05a0d539e0d6e065bbaee254aca3Sergey Matveev                       // here. Unfortunately clang 3.2 doesn't support the
825497ae56316cd05a0d539e0d6e065bbaee254aca3Sergey Matveev                       // necessary CFI directives, so we skip that part.
826cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev                       "xorq   %%rbp,%%rbp\n"
827cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev
828cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev                       /* Call "fn(arg)". */
829cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev                       "popq   %%rax\n"
830cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev                       "popq   %%rdi\n"
831cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev                       "call   *%%rax\n"
832cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev
833cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev                       /* Call _exit(%rax). */
834cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev                       "movq   %%rax,%%rdi\n"
835cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev                       "movq   %2,%%rax\n"
836cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev                       "syscall\n"
837cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev
838cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev                       /* Return to parent. */
839cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev                     "1:\n"
840cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev                       : "=a" (res)
8412d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines                       : "a"(SYSCALL(clone)), "i"(SYSCALL(exit)),
842cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev                         "S"(child_stack),
843cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev                         "D"(flags),
844cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev                         "d"(parent_tidptr),
845e041c6024b3ebf1365c0f99732fc69c607577571Kostya Serebryany                         "r"(r8),
846e041c6024b3ebf1365c0f99732fc69c607577571Kostya Serebryany                         "r"(r10)
847e041c6024b3ebf1365c0f99732fc69c607577571Kostya Serebryany                       : "rsp", "memory", "r11", "rcx");
848cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev  return res;
849cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev}
85086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines#elif defined(__mips__)
85186277eb844c4983c81de62d7c050e92fe7155788Stephen Hinesuptr internal_clone(int (*fn)(void *), void *child_stack, int flags, void *arg,
85286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines                    int *parent_tidptr, void *newtls, int *child_tidptr) {
853cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar  long long res;
854cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar  if (!fn || !child_stack)
855cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar    return -EINVAL;
856cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar  CHECK_EQ(0, (uptr)child_stack % 16);
857cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar  child_stack = (char *)child_stack - 2 * sizeof(unsigned long long);
858cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar  ((unsigned long long *)child_stack)[0] = (uptr)fn;
859cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar  ((unsigned long long *)child_stack)[1] = (uptr)arg;
860cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar  register void *a3 __asm__("$7") = newtls;
861cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar  register int *a4 __asm__("$8") = child_tidptr;
862cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar  // We don't have proper CFI directives here because it requires alot of code
863cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar  // for very marginal benefits.
864cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar  __asm__ __volatile__(
865cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar                       /* $v0 = syscall($v0 = __NR_clone,
866cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar                        * $a0 = flags,
867cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar                        * $a1 = child_stack,
868cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar                        * $a2 = parent_tidptr,
869cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar                        * $a3 = new_tls,
870cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar                        * $a4 = child_tidptr)
871cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar                        */
872cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar                       ".cprestore 16;\n"
873cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar                       "move $4,%1;\n"
874cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar                       "move $5,%2;\n"
875cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar                       "move $6,%3;\n"
876cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar                       "move $7,%4;\n"
877cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar                       /* Store the fifth argument on stack
878cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar                        * if we are using 32-bit abi.
879cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar                        */
880cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar#if SANITIZER_WORDSIZE == 32
881cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar                       "lw %5,16($29);\n"
882cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar#else
883cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar                       "move $8,%5;\n"
884cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar#endif
885cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar                       "li $2,%6;\n"
886cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar                       "syscall;\n"
887cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar
888cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar                       /* if ($v0 != 0)
889cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar                        * return;
890cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar                        */
891cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar                       "bnez $2,1f;\n"
892cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar
893cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar                       /* Call "fn(arg)". */
894cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar                       "ld $25,0($29);\n"
895cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar                       "ld $4,8($29);\n"
896cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar                       "jal $25;\n"
897cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar
898cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar                       /* Call _exit($v0). */
899cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar                       "move $4,$2;\n"
900cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar                       "li $2,%7;\n"
901cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar                       "syscall;\n"
902cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar
903cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar                       /* Return to parent. */
904cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar                     "1:\n"
905cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar                       : "=r" (res)
906cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar                       : "r"(flags),
907cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar                         "r"(child_stack),
908cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar                         "r"(parent_tidptr),
909cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar                         "r"(a3),
910cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar                         "r"(a4),
911cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar                         "i"(__NR_clone),
912cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar                         "i"(__NR_exit)
913cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar                       : "memory", "$29" );
914cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar  return res;
91586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines}
9162d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#endif  // defined(__x86_64__) && SANITIZER_LINUX
9172d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
9182d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#if SANITIZER_ANDROID
919aafc5c8d620e24104f1ca340d97286b15a5cec90Evgeniy Stepanovstatic atomic_uint8_t android_log_initialized;
920aafc5c8d620e24104f1ca340d97286b15a5cec90Evgeniy Stepanov
921aafc5c8d620e24104f1ca340d97286b15a5cec90Evgeniy Stepanovvoid AndroidLogInit() {
922aafc5c8d620e24104f1ca340d97286b15a5cec90Evgeniy Stepanov  atomic_store(&android_log_initialized, 1, memory_order_release);
923aafc5c8d620e24104f1ca340d97286b15a5cec90Evgeniy Stepanov}
9242d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines// This thing is not, strictly speaking, async signal safe, but it does not seem
9252d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines// to cause any issues. Alternative is writing to log devices directly, but
9262d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines// their location and message format might change in the future, so we'd really
9272d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines// like to avoid that.
9282d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesvoid AndroidLogWrite(const char *buffer) {
929aafc5c8d620e24104f1ca340d97286b15a5cec90Evgeniy Stepanov  if (!atomic_load(&android_log_initialized, memory_order_acquire))
930aafc5c8d620e24104f1ca340d97286b15a5cec90Evgeniy Stepanov    return;
931aafc5c8d620e24104f1ca340d97286b15a5cec90Evgeniy Stepanov
9322d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  char *copy = internal_strdup(buffer);
9332d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  char *p = copy;
9342d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  char *q;
9352d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  // __android_log_write has an implicit message length limit.
9362d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  // Print one line at a time.
9372d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  do {
9382d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    q = internal_strchr(p, '\n');
9392d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    if (q) *q = '\0';
9402d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    __android_log_write(ANDROID_LOG_INFO, NULL, p);
9412d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    if (q) p = q + 1;
9422d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  } while (q);
9432d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  InternalFree(copy);
9442d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines}
9452d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
9462d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesvoid GetExtraActivationFlags(char *buf, uptr size) {
9472d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  CHECK(size > PROP_VALUE_MAX);
9482d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  __system_property_get("asan.options", buf);
9492d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines}
950cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar
951cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar#if __ANDROID_API__ < 21
952cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainarextern "C" __attribute__((weak)) int dl_iterate_phdr(
953cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar    int (*)(struct dl_phdr_info *, size_t, void *), void *);
954cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar#endif
955cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar
956cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainarstatic int dl_iterate_phdr_test_cb(struct dl_phdr_info *info, size_t size,
957cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar                                   void *data) {
958cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar  // Any name starting with "lib" indicated a bug in L where library base names
959cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar  // are returned instead of paths.
960cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar  if (info->dlpi_name && info->dlpi_name[0] == 'l' &&
961cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar      info->dlpi_name[1] == 'i' && info->dlpi_name[2] == 'b') {
962cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar    *(bool *)data = true;
963cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar    return 1;
964cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar  }
965cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar  return 0;
966cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar}
967cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar
968cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainarstatic atomic_uint32_t android_api_level;
969cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar
970cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainarstatic u32 AndroidDetectApiLevel() {
971cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar  if (!&dl_iterate_phdr)
972cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar    return 19; // K or lower
973cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar  bool base_name_seen = false;
974cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar  dl_iterate_phdr(dl_iterate_phdr_test_cb, &base_name_seen);
975cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar  if (base_name_seen)
976cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar    return 22; // L MR1
977cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar  return 23;   // post-L
978cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar  // Plain L (API level 21) is completely broken wrt ASan and not very
979cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar  // interesting to detect.
980cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar}
981cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar
982cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainaru32 AndroidGetApiLevel() {
983cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar  u32 level = atomic_load(&android_api_level, memory_order_relaxed);
984cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar  if (level) return level;
985cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar  level = AndroidDetectApiLevel();
986cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar  atomic_store(&android_api_level, level, memory_order_relaxed);
987cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar  return level;
988cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar}
989cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar
9902d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#endif
9912d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
9922d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesbool IsDeadlySignal(int signum) {
993cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar  if (common_flags()->handle_abort && signum == SIGABRT)
994cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar    return true;
99586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  return (signum == SIGSEGV || signum == SIGBUS) && common_flags()->handle_segv;
99686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines}
99786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines
99886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines#ifndef SANITIZER_GO
99986277eb844c4983c81de62d7c050e92fe7155788Stephen Hinesvoid *internal_start_thread(void(*func)(void *arg), void *arg) {
100086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  // Start the thread with signals blocked, otherwise it can steal user signals.
100186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  __sanitizer_sigset_t set, old;
100286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  internal_sigfillset(&set);
1003cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar#if SANITIZER_LINUX
1004cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar  // Glibc uses SIGSETXID signal during setuid call. If this signal is blocked
1005cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar  // on any thread, setuid call hangs (see test/tsan/setuid.c).
1006cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar  internal_sigdelset(&set, 33);
1007cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar#endif
100886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  internal_sigprocmask(SIG_SETMASK, &set, &old);
100986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  void *th;
101086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  real_pthread_create(&th, 0, (void*(*)(void *arg))func, arg);
101186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  internal_sigprocmask(SIG_SETMASK, &old, 0);
101286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  return th;
10132d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines}
10142d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
101586277eb844c4983c81de62d7c050e92fe7155788Stephen Hinesvoid internal_join_thread(void *th) {
101686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  real_pthread_join(th, 0);
101786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines}
101886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines#else
101986277eb844c4983c81de62d7c050e92fe7155788Stephen Hinesvoid *internal_start_thread(void (*func)(void *), void *arg) { return 0; }
102086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines
102186277eb844c4983c81de62d7c050e92fe7155788Stephen Hinesvoid internal_join_thread(void *th) {}
102286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines#endif
102386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines
10247c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainarvoid GetPcSpBp(void *context, uptr *pc, uptr *sp, uptr *bp) {
10257c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar#if defined(__arm__)
10267c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar  ucontext_t *ucontext = (ucontext_t*)context;
10277c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar  *pc = ucontext->uc_mcontext.arm_pc;
10287c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar  *bp = ucontext->uc_mcontext.arm_fp;
10297c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar  *sp = ucontext->uc_mcontext.arm_sp;
10307c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar#elif defined(__aarch64__)
10317c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar  ucontext_t *ucontext = (ucontext_t*)context;
10327c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar  *pc = ucontext->uc_mcontext.pc;
10337c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar  *bp = ucontext->uc_mcontext.regs[29];
10347c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar  *sp = ucontext->uc_mcontext.sp;
10357c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar#elif defined(__hppa__)
10367c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar  ucontext_t *ucontext = (ucontext_t*)context;
10377c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar  *pc = ucontext->uc_mcontext.sc_iaoq[0];
10387c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar  /* GCC uses %r3 whenever a frame pointer is needed.  */
10397c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar  *bp = ucontext->uc_mcontext.sc_gr[3];
10407c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar  *sp = ucontext->uc_mcontext.sc_gr[30];
10417c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar#elif defined(__x86_64__)
10427c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar# if SANITIZER_FREEBSD
10437c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar  ucontext_t *ucontext = (ucontext_t*)context;
10447c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar  *pc = ucontext->uc_mcontext.mc_rip;
10457c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar  *bp = ucontext->uc_mcontext.mc_rbp;
10467c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar  *sp = ucontext->uc_mcontext.mc_rsp;
10477c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar# else
10487c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar  ucontext_t *ucontext = (ucontext_t*)context;
10497c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar  *pc = ucontext->uc_mcontext.gregs[REG_RIP];
10507c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar  *bp = ucontext->uc_mcontext.gregs[REG_RBP];
10517c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar  *sp = ucontext->uc_mcontext.gregs[REG_RSP];
10527c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar# endif
10537c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar#elif defined(__i386__)
10547c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar# if SANITIZER_FREEBSD
10557c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar  ucontext_t *ucontext = (ucontext_t*)context;
10567c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar  *pc = ucontext->uc_mcontext.mc_eip;
10577c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar  *bp = ucontext->uc_mcontext.mc_ebp;
10587c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar  *sp = ucontext->uc_mcontext.mc_esp;
10597c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar# else
10607c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar  ucontext_t *ucontext = (ucontext_t*)context;
10617c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar  *pc = ucontext->uc_mcontext.gregs[REG_EIP];
10627c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar  *bp = ucontext->uc_mcontext.gregs[REG_EBP];
10637c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar  *sp = ucontext->uc_mcontext.gregs[REG_ESP];
10647c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar# endif
10657c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar#elif defined(__powerpc__) || defined(__powerpc64__)
10667c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar  ucontext_t *ucontext = (ucontext_t*)context;
10677c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar  *pc = ucontext->uc_mcontext.regs->nip;
10687c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar  *sp = ucontext->uc_mcontext.regs->gpr[PT_R1];
10697c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar  // The powerpc{,64}-linux ABIs do not specify r31 as the frame
10707c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar  // pointer, but GCC always uses r31 when we need a frame pointer.
10717c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar  *bp = ucontext->uc_mcontext.regs->gpr[PT_R31];
10727c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar#elif defined(__sparc__)
10737c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar  ucontext_t *ucontext = (ucontext_t*)context;
10747c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar  uptr *stk_ptr;
10757c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar# if defined (__arch64__)
10767c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar  *pc = ucontext->uc_mcontext.mc_gregs[MC_PC];
10777c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar  *sp = ucontext->uc_mcontext.mc_gregs[MC_O6];
10787c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar  stk_ptr = (uptr *) (*sp + 2047);
10797c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar  *bp = stk_ptr[15];
10807c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar# else
10817c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar  *pc = ucontext->uc_mcontext.gregs[REG_PC];
10827c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar  *sp = ucontext->uc_mcontext.gregs[REG_O6];
10837c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar  stk_ptr = (uptr *) *sp;
10847c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar  *bp = stk_ptr[15];
10857c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar# endif
10867c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar#elif defined(__mips__)
10877c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar  ucontext_t *ucontext = (ucontext_t*)context;
1088cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar  *pc = ucontext->uc_mcontext.pc;
10897c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar  *bp = ucontext->uc_mcontext.gregs[30];
10907c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar  *sp = ucontext->uc_mcontext.gregs[29];
10917c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar#else
10927c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar# error "Unsupported arch"
10937c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar#endif
10947c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar}
10957c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar
1096ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov}  // namespace __sanitizer
1097ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov
10982d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#endif  // SANITIZER_FREEBSD || SANITIZER_LINUX
1099