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"
16799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar
172d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#if SANITIZER_FREEBSD || SANITIZER_LINUX
18ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov
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
63c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar#include <sys/exec.h>
646a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines#include <sys/sysctl.h>
65c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar#include <vm/vm_param.h>
66c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar#include <vm/pmap.h>
672d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#include <machine/atomic.h>
682d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesextern "C" {
692d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines// <sys/umtx.h> must be included after <errno.h> and <sys/types.h> on
702d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines// FreeBSD 9.2 and 10.0.
712d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#include <sys/umtx.h>
722d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines}
736a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hinesextern char **environ;  // provided by crt1
742d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#endif  // SANITIZER_FREEBSD
752d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
7624e13723f8477d8c42ab8b2a7f4f69fc089842f1Evgeniy Stepanov#if !SANITIZER_ANDROID
7735a7faf1fbfac678136e79d53824672dafb7d13eAlexey Samsonov#include <sys/signal.h>
7835a7faf1fbfac678136e79d53824672dafb7d13eAlexey Samsonov#endif
79fa5c41eddf77a3614da0f62044ebf741d86aeab7Dmitry Vyukov
802d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#if SANITIZER_LINUX
814bebe7bab966c82f0a8952f797ed3d490624dc62Dmitry Vyukov// <linux/time.h>
824bebe7bab966c82f0a8952f797ed3d490624dc62Dmitry Vyukovstruct kernel_timeval {
834bebe7bab966c82f0a8952f797ed3d490624dc62Dmitry Vyukov  long tv_sec;
844bebe7bab966c82f0a8952f797ed3d490624dc62Dmitry Vyukov  long tv_usec;
854bebe7bab966c82f0a8952f797ed3d490624dc62Dmitry Vyukov};
864bebe7bab966c82f0a8952f797ed3d490624dc62Dmitry Vyukov
87fa5c41eddf77a3614da0f62044ebf741d86aeab7Dmitry Vyukov// <linux/futex.h> is broken on some linux distributions.
88fa5c41eddf77a3614da0f62044ebf741d86aeab7Dmitry Vyukovconst int FUTEX_WAIT = 0;
89fa5c41eddf77a3614da0f62044ebf741d86aeab7Dmitry Vyukovconst int FUTEX_WAKE = 1;
902d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#endif  // SANITIZER_LINUX
91ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov
922d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines// Are we using 32-bit or 64-bit Linux syscalls?
935af39e50366f1aacbebc284f572f08ad1ad07357Kostya Serebryany// x32 (which defines __x86_64__) has SANITIZER_WORDSIZE == 32
9408bfe4988de493dd3e61d02759b3f19c42f8fb78Kostya Serebryany// but it still needs to use 64-bit syscalls.
95799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar#if SANITIZER_LINUX && (defined(__x86_64__) || defined(__powerpc64__) || \
96799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar    SANITIZER_WORDSIZE == 64)
979d0dbbaf33e5c2fe280f141e30be497d62b703a8Kostya Serebryany# define SANITIZER_LINUX_USES_64BIT_SYSCALLS 1
989d0dbbaf33e5c2fe280f141e30be497d62b703a8Kostya Serebryany#else
999d0dbbaf33e5c2fe280f141e30be497d62b703a8Kostya Serebryany# define SANITIZER_LINUX_USES_64BIT_SYSCALLS 0
1009d0dbbaf33e5c2fe280f141e30be497d62b703a8Kostya Serebryany#endif
1019d0dbbaf33e5c2fe280f141e30be497d62b703a8Kostya Serebryany
102c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar#if defined(__x86_64__)
103c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainarextern "C" {
104c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainarextern void internal_sigreturn();
105c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar}
106c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar#endif
107c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar
108ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonovnamespace __sanitizer {
109ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov
1102d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#if SANITIZER_LINUX && defined(__x86_64__)
1119578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne#include "sanitizer_syscall_linux_x86_64.inc"
112799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar#elif SANITIZER_LINUX && defined(__aarch64__)
113799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar#include "sanitizer_syscall_linux_aarch64.inc"
1149578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne#else
1159578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne#include "sanitizer_syscall_generic.inc"
1169578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne#endif
1179578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne
118e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov// --------------- sanitizer_libc.h
119c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar#if !SANITIZER_S390
12086277eb844c4983c81de62d7c050e92fe7155788Stephen Hinesuptr internal_mmap(void *addr, uptr length, int prot, int flags, int fd,
121799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar                   OFF_T offset) {
1222d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#if SANITIZER_FREEBSD || SANITIZER_LINUX_USES_64BIT_SYSCALLS
1232d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  return internal_syscall(SYSCALL(mmap), (uptr)addr, length, prot, flags, fd,
124e041c6024b3ebf1365c0f99732fc69c607577571Kostya Serebryany                          offset);
125ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov#else
12686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  // mmap2 specifies file offset in 4096-byte units.
12786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  CHECK(IsAligned(offset, 4096));
1282d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  return internal_syscall(SYSCALL(mmap2), addr, length, prot, flags, fd,
12986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines                          offset / 4096);
130ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov#endif
131ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov}
132c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar#endif // !SANITIZER_S390
133ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov
1349578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourneuptr internal_munmap(void *addr, uptr length) {
1352d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  return internal_syscall(SYSCALL(munmap), (uptr)addr, length);
1361f11d31faa5ed89b74f7d543b1182fe8de198be5Alexey Samsonov}
1371f11d31faa5ed89b74f7d543b1182fe8de198be5Alexey Samsonov
138259f7063e3e4c4b94dded1e90ab0a943d0fa737bPirama Arumuga Nainarint internal_mprotect(void *addr, uptr length, int prot) {
139259f7063e3e4c4b94dded1e90ab0a943d0fa737bPirama Arumuga Nainar  return internal_syscall(SYSCALL(mprotect), (uptr)addr, length, prot);
140259f7063e3e4c4b94dded1e90ab0a943d0fa737bPirama Arumuga Nainar}
141259f7063e3e4c4b94dded1e90ab0a943d0fa737bPirama Arumuga Nainar
1429578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourneuptr internal_close(fd_t fd) {
1432d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  return internal_syscall(SYSCALL(close), fd);
144a56aefd2e01940fcf88d1426f9de3d5e4b1ee203Alexey Samsonov}
145a56aefd2e01940fcf88d1426f9de3d5e4b1ee203Alexey Samsonov
1469578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourneuptr internal_open(const char *filename, int flags) {
1472d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#if SANITIZER_USES_CANONICAL_LINUX_SYSCALLS
1482d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  return internal_syscall(SYSCALL(openat), AT_FDCWD, (uptr)filename, flags);
1492d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#else
1502d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  return internal_syscall(SYSCALL(open), (uptr)filename, flags);
1512d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#endif
152ee7cc4454421a176d23442382afd9a01d36e7ad4Alexey Samsonov}
153ee7cc4454421a176d23442382afd9a01d36e7ad4Alexey Samsonov
1549578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourneuptr internal_open(const char *filename, int flags, u32 mode) {
1552d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#if SANITIZER_USES_CANONICAL_LINUX_SYSCALLS
1562d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  return internal_syscall(SYSCALL(openat), AT_FDCWD, (uptr)filename, flags,
1572d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines                          mode);
1582d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#else
1592d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  return internal_syscall(SYSCALL(open), (uptr)filename, flags, mode);
1602d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#endif
161ee7cc4454421a176d23442382afd9a01d36e7ad4Alexey Samsonov}
162ee7cc4454421a176d23442382afd9a01d36e7ad4Alexey Samsonov
163a56aefd2e01940fcf88d1426f9de3d5e4b1ee203Alexey Samsonovuptr internal_read(fd_t fd, void *buf, uptr count) {
1643334e12d33261cb8f211f2f49f28ddfa027a40c3Evgeniy Stepanov  sptr res;
1652d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  HANDLE_EINTR(res, (sptr)internal_syscall(SYSCALL(read), fd, (uptr)buf,
1662d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines               count));
1673334e12d33261cb8f211f2f49f28ddfa027a40c3Evgeniy Stepanov  return res;
168a56aefd2e01940fcf88d1426f9de3d5e4b1ee203Alexey Samsonov}
169a56aefd2e01940fcf88d1426f9de3d5e4b1ee203Alexey Samsonov
170a56aefd2e01940fcf88d1426f9de3d5e4b1ee203Alexey Samsonovuptr internal_write(fd_t fd, const void *buf, uptr count) {
1713334e12d33261cb8f211f2f49f28ddfa027a40c3Evgeniy Stepanov  sptr res;
1722d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  HANDLE_EINTR(res, (sptr)internal_syscall(SYSCALL(write), fd, (uptr)buf,
1732d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines               count));
1743334e12d33261cb8f211f2f49f28ddfa027a40c3Evgeniy Stepanov  return res;
175a56aefd2e01940fcf88d1426f9de3d5e4b1ee203Alexey Samsonov}
176a56aefd2e01940fcf88d1426f9de3d5e4b1ee203Alexey Samsonov
1772d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesuptr internal_ftruncate(fd_t fd, uptr size) {
1782d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  sptr res;
1797c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar  HANDLE_EINTR(res, (sptr)internal_syscall(SYSCALL(ftruncate), fd,
1807c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar               (OFF_T)size));
1812d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  return res;
1822d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines}
1832d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
1842d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#if !SANITIZER_LINUX_USES_64BIT_SYSCALLS && !SANITIZER_FREEBSD
1852be3a283939d4fc14ad86f6cd8be34b1468f22baEvgeniy Stepanovstatic void stat64_to_stat(struct stat64 *in, struct stat *out) {
1862be3a283939d4fc14ad86f6cd8be34b1468f22baEvgeniy Stepanov  internal_memset(out, 0, sizeof(*out));
1872be3a283939d4fc14ad86f6cd8be34b1468f22baEvgeniy Stepanov  out->st_dev = in->st_dev;
1882be3a283939d4fc14ad86f6cd8be34b1468f22baEvgeniy Stepanov  out->st_ino = in->st_ino;
1892be3a283939d4fc14ad86f6cd8be34b1468f22baEvgeniy Stepanov  out->st_mode = in->st_mode;
1902be3a283939d4fc14ad86f6cd8be34b1468f22baEvgeniy Stepanov  out->st_nlink = in->st_nlink;
1912be3a283939d4fc14ad86f6cd8be34b1468f22baEvgeniy Stepanov  out->st_uid = in->st_uid;
1922be3a283939d4fc14ad86f6cd8be34b1468f22baEvgeniy Stepanov  out->st_gid = in->st_gid;
1932be3a283939d4fc14ad86f6cd8be34b1468f22baEvgeniy Stepanov  out->st_rdev = in->st_rdev;
1942be3a283939d4fc14ad86f6cd8be34b1468f22baEvgeniy Stepanov  out->st_size = in->st_size;
1952be3a283939d4fc14ad86f6cd8be34b1468f22baEvgeniy Stepanov  out->st_blksize = in->st_blksize;
1962be3a283939d4fc14ad86f6cd8be34b1468f22baEvgeniy Stepanov  out->st_blocks = in->st_blocks;
1972be3a283939d4fc14ad86f6cd8be34b1468f22baEvgeniy Stepanov  out->st_atime = in->st_atime;
1982be3a283939d4fc14ad86f6cd8be34b1468f22baEvgeniy Stepanov  out->st_mtime = in->st_mtime;
1992be3a283939d4fc14ad86f6cd8be34b1468f22baEvgeniy Stepanov  out->st_ctime = in->st_ctime;
2002be3a283939d4fc14ad86f6cd8be34b1468f22baEvgeniy Stepanov  out->st_ino = in->st_ino;
2012be3a283939d4fc14ad86f6cd8be34b1468f22baEvgeniy Stepanov}
2022be3a283939d4fc14ad86f6cd8be34b1468f22baEvgeniy Stepanov#endif
2032be3a283939d4fc14ad86f6cd8be34b1468f22baEvgeniy Stepanov
20486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines#if defined(__mips64)
20586277eb844c4983c81de62d7c050e92fe7155788Stephen Hinesstatic void kernel_stat_to_stat(struct kernel_stat *in, struct stat *out) {
20686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  internal_memset(out, 0, sizeof(*out));
20786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  out->st_dev = in->st_dev;
20886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  out->st_ino = in->st_ino;
20986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  out->st_mode = in->st_mode;
21086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  out->st_nlink = in->st_nlink;
21186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  out->st_uid = in->st_uid;
21286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  out->st_gid = in->st_gid;
21386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  out->st_rdev = in->st_rdev;
21486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  out->st_size = in->st_size;
21586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  out->st_blksize = in->st_blksize;
21686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  out->st_blocks = in->st_blocks;
21786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  out->st_atime = in->st_atime_nsec;
21886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  out->st_mtime = in->st_mtime_nsec;
21986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  out->st_ctime = in->st_ctime_nsec;
22086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  out->st_ino = in->st_ino;
22186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines}
22286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines#endif
22386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines
2249578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourneuptr internal_stat(const char *path, void *buf) {
2252d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#if SANITIZER_FREEBSD
2262d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  return internal_syscall(SYSCALL(stat), path, buf);
2272d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#elif SANITIZER_USES_CANONICAL_LINUX_SYSCALLS
2282d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  return internal_syscall(SYSCALL(newfstatat), AT_FDCWD, (uptr)path,
2292d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines                          (uptr)buf, 0);
2302d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#elif SANITIZER_LINUX_USES_64BIT_SYSCALLS
23186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines# if defined(__mips64)
23286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  // For mips64, stat syscall fills buffer in the format of kernel_stat
23386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  struct kernel_stat kbuf;
23486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  int res = internal_syscall(SYSCALL(stat), path, &kbuf);
23586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  kernel_stat_to_stat(&kbuf, (struct stat *)buf);
23686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  return res;
23786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines# else
2382d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  return internal_syscall(SYSCALL(stat), (uptr)path, (uptr)buf);
23986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines# endif
2404c9317a7b61e136f832d2ede70f557963fd46bceAlexey Samsonov#else
2412be3a283939d4fc14ad86f6cd8be34b1468f22baEvgeniy Stepanov  struct stat64 buf64;
2422d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  int res = internal_syscall(SYSCALL(stat64), path, &buf64);
2432be3a283939d4fc14ad86f6cd8be34b1468f22baEvgeniy Stepanov  stat64_to_stat(&buf64, (struct stat *)buf);
2442be3a283939d4fc14ad86f6cd8be34b1468f22baEvgeniy Stepanov  return res;
2454c9317a7b61e136f832d2ede70f557963fd46bceAlexey Samsonov#endif
2464c9317a7b61e136f832d2ede70f557963fd46bceAlexey Samsonov}
2474c9317a7b61e136f832d2ede70f557963fd46bceAlexey Samsonov
2489578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourneuptr internal_lstat(const char *path, void *buf) {
2492d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#if SANITIZER_FREEBSD
2502d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  return internal_syscall(SYSCALL(lstat), path, buf);
2512d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#elif SANITIZER_USES_CANONICAL_LINUX_SYSCALLS
2522d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  return internal_syscall(SYSCALL(newfstatat), AT_FDCWD, (uptr)path,
2532d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines                         (uptr)buf, AT_SYMLINK_NOFOLLOW);
2542d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#elif SANITIZER_LINUX_USES_64BIT_SYSCALLS
255c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar# if SANITIZER_MIPS64
256c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  // For mips64, lstat syscall fills buffer in the format of kernel_stat
257c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  struct kernel_stat kbuf;
258c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  int res = internal_syscall(SYSCALL(lstat), path, &kbuf);
259c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  kernel_stat_to_stat(&kbuf, (struct stat *)buf);
260c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  return res;
261c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar# else
2622d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  return internal_syscall(SYSCALL(lstat), (uptr)path, (uptr)buf);
263c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar# endif
2644c9317a7b61e136f832d2ede70f557963fd46bceAlexey Samsonov#else
2652be3a283939d4fc14ad86f6cd8be34b1468f22baEvgeniy Stepanov  struct stat64 buf64;
2662d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  int res = internal_syscall(SYSCALL(lstat64), path, &buf64);
2672be3a283939d4fc14ad86f6cd8be34b1468f22baEvgeniy Stepanov  stat64_to_stat(&buf64, (struct stat *)buf);
2682be3a283939d4fc14ad86f6cd8be34b1468f22baEvgeniy Stepanov  return res;
2694c9317a7b61e136f832d2ede70f557963fd46bceAlexey Samsonov#endif
2704c9317a7b61e136f832d2ede70f557963fd46bceAlexey Samsonov}
2714c9317a7b61e136f832d2ede70f557963fd46bceAlexey Samsonov
2729578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourneuptr internal_fstat(fd_t fd, void *buf) {
2732d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#if SANITIZER_FREEBSD || SANITIZER_LINUX_USES_64BIT_SYSCALLS
274c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar# if SANITIZER_MIPS64
275c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  // For mips64, fstat syscall fills buffer in the format of kernel_stat
276c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  struct kernel_stat kbuf;
277c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  int res = internal_syscall(SYSCALL(fstat), fd, &kbuf);
278c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  kernel_stat_to_stat(&kbuf, (struct stat *)buf);
279c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  return res;
280c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar# else
2812d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  return internal_syscall(SYSCALL(fstat), fd, (uptr)buf);
282c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar# endif
2834c9317a7b61e136f832d2ede70f557963fd46bceAlexey Samsonov#else
2842be3a283939d4fc14ad86f6cd8be34b1468f22baEvgeniy Stepanov  struct stat64 buf64;
2852d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  int res = internal_syscall(SYSCALL(fstat64), fd, &buf64);
2862be3a283939d4fc14ad86f6cd8be34b1468f22baEvgeniy Stepanov  stat64_to_stat(&buf64, (struct stat *)buf);
2872be3a283939d4fc14ad86f6cd8be34b1468f22baEvgeniy Stepanov  return res;
2884c9317a7b61e136f832d2ede70f557963fd46bceAlexey Samsonov#endif
2894c9317a7b61e136f832d2ede70f557963fd46bceAlexey Samsonov}
2904c9317a7b61e136f832d2ede70f557963fd46bceAlexey Samsonov
2918e820fcf7aafeb8101322182d742fcf99255d972Alexey Samsonovuptr internal_filesize(fd_t fd) {
292a68633fb76208137ccb807914df52758ee5ca6f0Alexey Samsonov  struct stat st;
2934c9317a7b61e136f832d2ede70f557963fd46bceAlexey Samsonov  if (internal_fstat(fd, &st))
2944c9317a7b61e136f832d2ede70f557963fd46bceAlexey Samsonov    return -1;
2958e820fcf7aafeb8101322182d742fcf99255d972Alexey Samsonov  return (uptr)st.st_size;
2968e820fcf7aafeb8101322182d742fcf99255d972Alexey Samsonov}
2978e820fcf7aafeb8101322182d742fcf99255d972Alexey Samsonov
2989578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourneuptr internal_dup2(int oldfd, int newfd) {
2992d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#if SANITIZER_USES_CANONICAL_LINUX_SYSCALLS
3002d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  return internal_syscall(SYSCALL(dup3), oldfd, newfd, 0);
3012d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#else
3022d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  return internal_syscall(SYSCALL(dup2), oldfd, newfd);
3032d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#endif
3048e820fcf7aafeb8101322182d742fcf99255d972Alexey Samsonov}
3058e820fcf7aafeb8101322182d742fcf99255d972Alexey Samsonov
306d1b8f588d6b712b6ff2b3d58c73d71614f520122Alexey Samsonovuptr internal_readlink(const char *path, char *buf, uptr bufsize) {
3072d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#if SANITIZER_USES_CANONICAL_LINUX_SYSCALLS
3082d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  return internal_syscall(SYSCALL(readlinkat), AT_FDCWD,
3092d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines                          (uptr)path, (uptr)buf, bufsize);
3102d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#else
3112d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  return internal_syscall(SYSCALL(readlink), (uptr)path, (uptr)buf, bufsize);
3122d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#endif
313d1b8f588d6b712b6ff2b3d58c73d71614f520122Alexey Samsonov}
314d1b8f588d6b712b6ff2b3d58c73d71614f520122Alexey Samsonov
3159578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourneuptr internal_unlink(const char *path) {
3162d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#if SANITIZER_USES_CANONICAL_LINUX_SYSCALLS
3172d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  return internal_syscall(SYSCALL(unlinkat), AT_FDCWD, (uptr)path, 0);
3182d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#else
3192d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  return internal_syscall(SYSCALL(unlink), (uptr)path);
3202d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#endif
3212d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines}
3222d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
3232d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesuptr internal_rename(const char *oldpath, const char *newpath) {
3242d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#if SANITIZER_USES_CANONICAL_LINUX_SYSCALLS
3252d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  return internal_syscall(SYSCALL(renameat), AT_FDCWD, (uptr)oldpath, AT_FDCWD,
3262d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines                          (uptr)newpath);
3272d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#else
3282d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  return internal_syscall(SYSCALL(rename), (uptr)oldpath, (uptr)newpath);
3292d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#endif
3306d6ab9eeea4a99370d7ab18ce80eb96091e2cf3fDmitry Vyukov}
3316d6ab9eeea4a99370d7ab18ce80eb96091e2cf3fDmitry Vyukov
3329578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourneuptr internal_sched_yield() {
3332d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  return internal_syscall(SYSCALL(sched_yield));
3340969bcf2c936126b1f6e636b978aade8fc207437Alexey Samsonov}
3350969bcf2c936126b1f6e636b978aade8fc207437Alexey Samsonov
336f882247088952deed954a19d745c2dd8871e2035Alexey Samsonovvoid internal__exit(int exitcode) {
3372d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#if SANITIZER_FREEBSD
3382d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  internal_syscall(SYSCALL(exit), exitcode);
3392d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#else
3402d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  internal_syscall(SYSCALL(exit_group), exitcode);
3412d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#endif
342f882247088952deed954a19d745c2dd8871e2035Alexey Samsonov  Die();  // Unreachable.
343f882247088952deed954a19d745c2dd8871e2035Alexey Samsonov}
344f882247088952deed954a19d745c2dd8871e2035Alexey Samsonov
345c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainarunsigned int internal_sleep(unsigned int seconds) {
346c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  struct timespec ts;
347c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  ts.tv_sec = 1;
348c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  ts.tv_nsec = 0;
349c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  int res = internal_syscall(SYSCALL(nanosleep), &ts, &ts);
350c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  if (res) return ts.tv_sec;
351c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  return 0;
352c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar}
353c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar
3549578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourneuptr internal_execve(const char *filename, char *const argv[],
3559578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne                     char *const envp[]) {
3562d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  return internal_syscall(SYSCALL(execve), (uptr)filename, (uptr)argv,
3572d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines                          (uptr)envp);
3589578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne}
3599578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne
360e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov// ----------------- sanitizer_common.h
36193b4cafd631b661b4b612ccdc0938f7f1e1c86d6Alexey Samsonovbool FileExists(const char *filename) {
3622d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  struct stat st;
36386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines#if SANITIZER_USES_CANONICAL_LINUX_SYSCALLS
3642d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  if (internal_syscall(SYSCALL(newfstatat), AT_FDCWD, filename, &st, 0))
3652d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#else
3662be3a283939d4fc14ad86f6cd8be34b1468f22baEvgeniy Stepanov  if (internal_stat(filename, &st))
36786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines#endif
36893b4cafd631b661b4b612ccdc0938f7f1e1c86d6Alexey Samsonov    return false;
36993b4cafd631b661b4b612ccdc0938f7f1e1c86d6Alexey Samsonov  // Sanity check: filename is a regular file.
37093b4cafd631b661b4b612ccdc0938f7f1e1c86d6Alexey Samsonov  return S_ISREG(st.st_mode);
37193b4cafd631b661b4b612ccdc0938f7f1e1c86d6Alexey Samsonov}
37293b4cafd631b661b4b612ccdc0938f7f1e1c86d6Alexey Samsonov
373e0023f74ea88efee329f68391b70f8adc6b21617Dmitry Vyukovuptr GetTid() {
3742d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#if SANITIZER_FREEBSD
3752d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  return (uptr)pthread_self();
3762d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#else
3772d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  return internal_syscall(SYSCALL(gettid));
3782d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#endif
379e0023f74ea88efee329f68391b70f8adc6b21617Dmitry Vyukov}
380e0023f74ea88efee329f68391b70f8adc6b21617Dmitry Vyukov
3814bebe7bab966c82f0a8952f797ed3d490624dc62Dmitry Vyukovu64 NanoTime() {
3822d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#if SANITIZER_FREEBSD
3832d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  timeval tv;
3842d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#else
3855e7ba22755b994e4f6aaf8cc00773c4d1b8dbf07Peter Collingbourne  kernel_timeval tv;
3862d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#endif
3875e7ba22755b994e4f6aaf8cc00773c4d1b8dbf07Peter Collingbourne  internal_memset(&tv, 0, sizeof(tv));
3882d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  internal_syscall(SYSCALL(gettimeofday), (uptr)&tv, 0);
3894bebe7bab966c82f0a8952f797ed3d490624dc62Dmitry Vyukov  return (u64)tv.tv_sec * 1000*1000*1000 + tv.tv_usec * 1000;
3904bebe7bab966c82f0a8952f797ed3d490624dc62Dmitry Vyukov}
3914bebe7bab966c82f0a8952f797ed3d490624dc62Dmitry Vyukov
3926a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines// Like getenv, but reads env directly from /proc (on Linux) or parses the
3936a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines// 'environ' array (on FreeBSD) and does not use libc. This function should be
3946a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines// called first inside __asan_init.
3953dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonovconst char *GetEnv(const char *name) {
3966a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines#if SANITIZER_FREEBSD
3976a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines  if (::environ != 0) {
3986a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines    uptr NameLen = internal_strlen(name);
3996a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines    for (char **Env = ::environ; *Env != 0; Env++) {
4006a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines      if (internal_strncmp(*Env, name, NameLen) == 0 && (*Env)[NameLen] == '=')
4016a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines        return (*Env) + NameLen + 1;
4026a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines    }
4036a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines  }
4046a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines  return 0;  // Not found.
4056a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines#elif SANITIZER_LINUX
4063dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov  static char *environ;
4073dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov  static uptr len;
4083dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov  static bool inited;
4093dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov  if (!inited) {
4103dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov    inited = true;
4113dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov    uptr environ_size;
412799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar    if (!ReadFileToBuffer("/proc/self/environ", &environ, &environ_size, &len))
413799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar      environ = nullptr;
4143dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov  }
415799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar  if (!environ || len == 0) return nullptr;
4163dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov  uptr namelen = internal_strlen(name);
4173dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov  const char *p = environ;
4183dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov  while (*p != '\0') {  // will happen at the \0\0 that terminates the buffer
4193dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov    // proc file has the format NAME=value\0NAME=value\0NAME=value\0...
4203dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov    const char* endp =
4213dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov        (char*)internal_memchr(p, '\0', len - (p - environ));
422799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar    if (!endp)  // this entry isn't NUL terminated
423799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar      return nullptr;
4243dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov    else if (!internal_memcmp(p, name, namelen) && p[namelen] == '=')  // Match.
4253dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov      return p + namelen + 1;  // point after =
4263dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov    p = endp + 1;
4273dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov  }
428799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar  return nullptr;  // Not found.
4296a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines#else
4306a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines#error "Unsupported platform"
4316a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines#endif
4323dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov}
4333dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov
434c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar#if !SANITIZER_FREEBSD
435eab061185ec0046d447b298a1dff84f028202a3cEvgeniy Stepanovextern "C" {
4363c80c6c574850106481f82b9e23d1c728458d4a9Timur Iskhodzhanov  SANITIZER_WEAK_ATTRIBUTE extern void *__libc_stack_end;
437eab061185ec0046d447b298a1dff84f028202a3cEvgeniy Stepanov}
438c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar#endif
439eab061185ec0046d447b298a1dff84f028202a3cEvgeniy Stepanov
440c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar#if !SANITIZER_GO && !SANITIZER_FREEBSD
44123709c9ad9ac7c45de288f5260403426bf932db7Peter Collingbournestatic void ReadNullSepFileToArray(const char *path, char ***arr,
44223709c9ad9ac7c45de288f5260403426bf932db7Peter Collingbourne                                   int arr_size) {
44323709c9ad9ac7c45de288f5260403426bf932db7Peter Collingbourne  char *buff;
444799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar  uptr buff_size;
445799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar  uptr buff_len;
44623709c9ad9ac7c45de288f5260403426bf932db7Peter Collingbourne  *arr = (char **)MmapOrDie(arr_size * sizeof(char *), "NullSepFileArray");
447799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar  if (!ReadFileToBuffer(path, &buff, &buff_size, &buff_len, 1024 * 1024)) {
448799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar    (*arr)[0] = nullptr;
449799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar    return;
450799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar  }
45123709c9ad9ac7c45de288f5260403426bf932db7Peter Collingbourne  (*arr)[0] = buff;
45223709c9ad9ac7c45de288f5260403426bf932db7Peter Collingbourne  int count, i;
45323709c9ad9ac7c45de288f5260403426bf932db7Peter Collingbourne  for (count = 1, i = 1; ; i++) {
454d7e5bb4043adf4756e6f8cfe0f5a3165b185474dAlexey Samsonov    if (buff[i] == 0) {
455d7e5bb4043adf4756e6f8cfe0f5a3165b185474dAlexey Samsonov      if (buff[i+1] == 0) break;
45623709c9ad9ac7c45de288f5260403426bf932db7Peter Collingbourne      (*arr)[count] = &buff[i+1];
45723709c9ad9ac7c45de288f5260403426bf932db7Peter Collingbourne      CHECK_LE(count, arr_size - 1);  // FIXME: make this more flexible.
45823709c9ad9ac7c45de288f5260403426bf932db7Peter Collingbourne      count++;
459d7e5bb4043adf4756e6f8cfe0f5a3165b185474dAlexey Samsonov    }
460d7e5bb4043adf4756e6f8cfe0f5a3165b185474dAlexey Samsonov  }
461799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar  (*arr)[count] = nullptr;
46223709c9ad9ac7c45de288f5260403426bf932db7Peter Collingbourne}
46326337b60b1d551c4744454edd8e5ef3c479e3467Peter Collingbourne#endif
46423709c9ad9ac7c45de288f5260403426bf932db7Peter Collingbourne
465c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainarstatic void GetArgsAndEnv(char ***argv, char ***envp) {
466c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar#if !SANITIZER_FREEBSD
46726337b60b1d551c4744454edd8e5ef3c479e3467Peter Collingbourne#if !SANITIZER_GO
46826337b60b1d551c4744454edd8e5ef3c479e3467Peter Collingbourne  if (&__libc_stack_end) {
46926337b60b1d551c4744454edd8e5ef3c479e3467Peter Collingbourne#endif
47026337b60b1d551c4744454edd8e5ef3c479e3467Peter Collingbourne    uptr* stack_end = (uptr*)__libc_stack_end;
47126337b60b1d551c4744454edd8e5ef3c479e3467Peter Collingbourne    int argc = *stack_end;
47226337b60b1d551c4744454edd8e5ef3c479e3467Peter Collingbourne    *argv = (char**)(stack_end + 1);
47326337b60b1d551c4744454edd8e5ef3c479e3467Peter Collingbourne    *envp = (char**)(stack_end + argc + 2);
47426337b60b1d551c4744454edd8e5ef3c479e3467Peter Collingbourne#if !SANITIZER_GO
47526337b60b1d551c4744454edd8e5ef3c479e3467Peter Collingbourne  } else {
47626337b60b1d551c4744454edd8e5ef3c479e3467Peter Collingbourne    static const int kMaxArgv = 2000, kMaxEnvp = 2000;
47726337b60b1d551c4744454edd8e5ef3c479e3467Peter Collingbourne    ReadNullSepFileToArray("/proc/self/cmdline", argv, kMaxArgv);
47826337b60b1d551c4744454edd8e5ef3c479e3467Peter Collingbourne    ReadNullSepFileToArray("/proc/self/environ", envp, kMaxEnvp);
47926337b60b1d551c4744454edd8e5ef3c479e3467Peter Collingbourne  }
48026337b60b1d551c4744454edd8e5ef3c479e3467Peter Collingbourne#endif
481c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar#else
482c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  // On FreeBSD, retrieving the argument and environment arrays is done via the
483c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  // kern.ps_strings sysctl, which returns a pointer to a structure containing
484c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  // this information. See also <sys/exec.h>.
485c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  ps_strings *pss;
486c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  size_t sz = sizeof(pss);
487c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  if (sysctlbyname("kern.ps_strings", &pss, &sz, NULL, 0) == -1) {
488c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar    Printf("sysctl kern.ps_strings failed\n");
489c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar    Die();
490c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  }
491c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  *argv = pss->ps_argvstr;
492c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  *envp = pss->ps_envstr;
493c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar#endif
494c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar}
495c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar
496c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainarchar **GetArgv() {
497c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  char **argv, **envp;
498c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  GetArgsAndEnv(&argv, &envp);
499c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  return argv;
500eab061185ec0046d447b298a1dff84f028202a3cEvgeniy Stepanov}
501eab061185ec0046d447b298a1dff84f028202a3cEvgeniy Stepanov
502eab061185ec0046d447b298a1dff84f028202a3cEvgeniy Stepanovvoid ReExec() {
50323709c9ad9ac7c45de288f5260403426bf932db7Peter Collingbourne  char **argv, **envp;
504eab061185ec0046d447b298a1dff84f028202a3cEvgeniy Stepanov  GetArgsAndEnv(&argv, &envp);
5059578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne  uptr rv = internal_execve("/proc/self/exe", argv, envp);
5069578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne  int rverrno;
5079578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne  CHECK_EQ(internal_iserror(rv, &rverrno), true);
5089578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne  Printf("execve failed, errno %d\n", rverrno);
509f35eae83757946decb312deab3f0fe155fe5d580Evgeniy Stepanov  Die();
510d7e5bb4043adf4756e6f8cfe0f5a3165b185474dAlexey Samsonov}
511d7e5bb4043adf4756e6f8cfe0f5a3165b185474dAlexey Samsonov
512f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukovenum MutexState {
513f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov  MtxUnlocked = 0,
514f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov  MtxLocked = 1,
515f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov  MtxSleeping = 2
516f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov};
517f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov
51893af5948d3e0c5bdc396f432dd0ae782f499c449Alexey SamsonovBlockingMutex::BlockingMutex() {
51993af5948d3e0c5bdc396f432dd0ae782f499c449Alexey Samsonov  internal_memset(this, 0, sizeof(*this));
52093af5948d3e0c5bdc396f432dd0ae782f499c449Alexey Samsonov}
52193af5948d3e0c5bdc396f432dd0ae782f499c449Alexey Samsonov
522f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukovvoid BlockingMutex::Lock() {
52386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  CHECK_EQ(owner_, 0);
524f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov  atomic_uint32_t *m = reinterpret_cast<atomic_uint32_t *>(&opaque_storage_);
525f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov  if (atomic_exchange(m, MtxLocked, memory_order_acquire) == MtxUnlocked)
526f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov    return;
5272d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  while (atomic_exchange(m, MtxSleeping, memory_order_acquire) != MtxUnlocked) {
5282d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#if SANITIZER_FREEBSD
5292d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    _umtx_op(m, UMTX_OP_WAIT_UINT, MtxSleeping, 0, 0);
5302d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#else
5312d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    internal_syscall(SYSCALL(futex), (uptr)m, FUTEX_WAIT, MtxSleeping, 0, 0, 0);
5322d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#endif
5332d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  }
534f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov}
535f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov
536f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukovvoid BlockingMutex::Unlock() {
537f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov  atomic_uint32_t *m = reinterpret_cast<atomic_uint32_t *>(&opaque_storage_);
538f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov  u32 v = atomic_exchange(m, MtxUnlocked, memory_order_relaxed);
53948526014de78e21f7ed027a60670016bc7f5d292Dmitry Vyukov  CHECK_NE(v, MtxUnlocked);
5402d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  if (v == MtxSleeping) {
5412d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#if SANITIZER_FREEBSD
5422d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    _umtx_op(m, UMTX_OP_WAKE, 1, 0, 0);
5432d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#else
5442d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    internal_syscall(SYSCALL(futex), (uptr)m, FUTEX_WAKE, 1, 0, 0, 0);
5452d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#endif
5462d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  }
547f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov}
548f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov
549ce700979f644c790c2d9d80f5cc2a1ada0380284Alexey Samsonovvoid BlockingMutex::CheckLocked() {
550ce700979f644c790c2d9d80f5cc2a1ada0380284Alexey Samsonov  atomic_uint32_t *m = reinterpret_cast<atomic_uint32_t *>(&opaque_storage_);
551ce700979f644c790c2d9d80f5cc2a1ada0380284Alexey Samsonov  CHECK_NE(MtxUnlocked, atomic_load(m, memory_order_relaxed));
552ce700979f644c790c2d9d80f5cc2a1ada0380284Alexey Samsonov}
553ce700979f644c790c2d9d80f5cc2a1ada0380284Alexey Samsonov
5546fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany// ----------------- sanitizer_linux.h
5556fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany// The actual size of this structure is specified by d_reclen.
5566fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany// Note that getdents64 uses a different structure format. We only provide the
5576fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany// 32-bit syscall here.
5586fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryanystruct linux_dirent {
559799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar#if SANITIZER_X32 || defined(__aarch64__)
5602d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  u64 d_ino;
5612d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  u64 d_off;
5622d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#else
5636fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany  unsigned long      d_ino;
5646fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany  unsigned long      d_off;
5652d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#endif
5666fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany  unsigned short     d_reclen;
567799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar#ifdef __aarch64__
568799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar  unsigned char      d_type;
569799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar#endif
5706fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany  char               d_name[256];
5716fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany};
5726fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany
5736fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany// Syscall wrappers.
5749578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourneuptr internal_ptrace(int request, int pid, void *addr, void *data) {
5752d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  return internal_syscall(SYSCALL(ptrace), request, pid, (uptr)addr,
5762d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines                          (uptr)data);
5779578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne}
5789578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne
5799578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourneuptr internal_waitpid(int pid, int *status, int options) {
5802d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  return internal_syscall(SYSCALL(wait4), pid, (uptr)status, options,
581e041c6024b3ebf1365c0f99732fc69c607577571Kostya Serebryany                          0 /* rusage */);
5826fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany}
5836fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany
5849578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourneuptr internal_getpid() {
5852d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  return internal_syscall(SYSCALL(getpid));
5866fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany}
5876fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany
5889578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourneuptr internal_getppid() {
5892d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  return internal_syscall(SYSCALL(getppid));
5906fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany}
5916fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany
5929578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourneuptr internal_getdents(fd_t fd, struct linux_dirent *dirp, unsigned int count) {
5932d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#if SANITIZER_USES_CANONICAL_LINUX_SYSCALLS
5942d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  return internal_syscall(SYSCALL(getdents64), fd, (uptr)dirp, count);
5952d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#else
5962d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  return internal_syscall(SYSCALL(getdents), fd, (uptr)dirp, count);
5972d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#endif
5986fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany}
5996fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany
6009578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourneuptr internal_lseek(fd_t fd, OFF_T offset, int whence) {
6012d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  return internal_syscall(SYSCALL(lseek), fd, offset, whence);
6026fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany}
6036fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany
6042d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#if SANITIZER_LINUX
6059578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourneuptr internal_prctl(int option, uptr arg2, uptr arg3, uptr arg4, uptr arg5) {
6062d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  return internal_syscall(SYSCALL(prctl), option, arg2, arg3, arg4, arg5);
6076fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany}
6082d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#endif
6096fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany
6109578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourneuptr internal_sigaltstack(const struct sigaltstack *ss,
6116fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany                         struct sigaltstack *oss) {
6122d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  return internal_syscall(SYSCALL(sigaltstack), (uptr)ss, (uptr)oss);
6132d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines}
6142d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
6152d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesint internal_fork() {
6162d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#if SANITIZER_USES_CANONICAL_LINUX_SYSCALLS
6172d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  return internal_syscall(SYSCALL(clone), SIGCHLD, 0);
6182d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#else
6192d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  return internal_syscall(SYSCALL(fork));
6202d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#endif
6216fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany}
6226fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany
6232d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#if SANITIZER_LINUX
6247c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar#define SA_RESTORER 0x04000000
625c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar// Doesn't set sa_restorer if the caller did not set it, so use with caution
626c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar//(see below).
6272d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesint internal_sigaction_norestorer(int signum, const void *act, void *oldact) {
6282d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  __sanitizer_kernel_sigaction_t k_act, k_oldact;
6292d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  internal_memset(&k_act, 0, sizeof(__sanitizer_kernel_sigaction_t));
6302d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  internal_memset(&k_oldact, 0, sizeof(__sanitizer_kernel_sigaction_t));
6316d1862363c88c183b0ed7740fca876342cf0474bStephen Hines  const __sanitizer_sigaction *u_act = (const __sanitizer_sigaction *)act;
6322d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  __sanitizer_sigaction *u_oldact = (__sanitizer_sigaction *)oldact;
6332d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  if (u_act) {
6342d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    k_act.handler = u_act->handler;
6352d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    k_act.sigaction = u_act->sigaction;
6362d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    internal_memcpy(&k_act.sa_mask, &u_act->sa_mask,
6372d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines                    sizeof(__sanitizer_kernel_sigset_t));
6387c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar    // Without SA_RESTORER kernel ignores the calls (probably returns EINVAL).
6397c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar    k_act.sa_flags = u_act->sa_flags | SA_RESTORER;
6402d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    // FIXME: most often sa_restorer is unset, however the kernel requires it
6412d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    // to point to a valid signal restorer that calls the rt_sigreturn syscall.
6422d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    // If sa_restorer passed to the kernel is NULL, the program may crash upon
6432d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    // signal delivery or fail to unwind the stack in the signal handler.
6442d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    // libc implementation of sigaction() passes its own restorer to
6452d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    // rt_sigaction, so we need to do the same (we'll need to reimplement the
6462d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    // restorers; for x86_64 the restorer address can be obtained from
6472d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    // oldact->sa_restorer upon a call to sigaction(xxx, NULL, oldact).
648a822161eb8bad420c4978112dbf22378a5ceb175Stephen Hines#if !SANITIZER_ANDROID || !SANITIZER_MIPS32
6492d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    k_act.sa_restorer = u_act->sa_restorer;
650a822161eb8bad420c4978112dbf22378a5ceb175Stephen Hines#endif
6512d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  }
6522d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
6532d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  uptr result = internal_syscall(SYSCALL(rt_sigaction), (uptr)signum,
654799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar      (uptr)(u_act ? &k_act : nullptr),
655799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar      (uptr)(u_oldact ? &k_oldact : nullptr),
6562d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines      (uptr)sizeof(__sanitizer_kernel_sigset_t));
6572d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
6582d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  if ((result == 0) && u_oldact) {
6592d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    u_oldact->handler = k_oldact.handler;
6602d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    u_oldact->sigaction = k_oldact.sigaction;
6612d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    internal_memcpy(&u_oldact->sa_mask, &k_oldact.sa_mask,
6622d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines                    sizeof(__sanitizer_kernel_sigset_t));
6632d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    u_oldact->sa_flags = k_oldact.sa_flags;
664a822161eb8bad420c4978112dbf22378a5ceb175Stephen Hines#if !SANITIZER_ANDROID || !SANITIZER_MIPS32
6652d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    u_oldact->sa_restorer = k_oldact.sa_restorer;
666a822161eb8bad420c4978112dbf22378a5ceb175Stephen Hines#endif
6672d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  }
6682d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  return result;
6690f7a2acb3326a5900d1a1339ebf959b14b372e0dDmitry Vyukov}
670c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar
671c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar// Invokes sigaction via a raw syscall with a restorer, but does not support
672c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar// all platforms yet.
673c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar// We disable for Go simply because we have not yet added to buildgo.sh.
674c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar#if defined(__x86_64__) && !SANITIZER_GO
675c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainarint internal_sigaction_syscall(int signum, const void *act, void *oldact) {
676c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  if (act == nullptr)
677c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar    return internal_sigaction_norestorer(signum, act, oldact);
678c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  __sanitizer_sigaction u_adjust;
679c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  internal_memcpy(&u_adjust, act, sizeof(u_adjust));
680c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar#if !SANITIZER_ANDROID || !SANITIZER_MIPS32
681c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar    if (u_adjust.sa_restorer == nullptr) {
682c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar      u_adjust.sa_restorer = internal_sigreturn;
683c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar    }
684c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar#endif
685c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar    return internal_sigaction_norestorer(signum, (const void *)&u_adjust,
686c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar                                         oldact);
687c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar}
688c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar#endif // defined(__x86_64__) && !SANITIZER_GO
6892d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#endif  // SANITIZER_LINUX
6900f7a2acb3326a5900d1a1339ebf959b14b372e0dDmitry Vyukov
6912d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesuptr internal_sigprocmask(int how, __sanitizer_sigset_t *set,
6922d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    __sanitizer_sigset_t *oldset) {
6932d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#if SANITIZER_FREEBSD
6942d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  return internal_syscall(SYSCALL(sigprocmask), how, set, oldset);
6952d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#else
6962d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  __sanitizer_kernel_sigset_t *k_set = (__sanitizer_kernel_sigset_t *)set;
6972d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  __sanitizer_kernel_sigset_t *k_oldset = (__sanitizer_kernel_sigset_t *)oldset;
6982d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  return internal_syscall(SYSCALL(rt_sigprocmask), (uptr)how,
6992d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines                          (uptr)&k_set->sig[0], (uptr)&k_oldset->sig[0],
7002d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines                          sizeof(__sanitizer_kernel_sigset_t));
7012d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#endif
7020f7a2acb3326a5900d1a1339ebf959b14b372e0dDmitry Vyukov}
7030f7a2acb3326a5900d1a1339ebf959b14b372e0dDmitry Vyukov
7042d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesvoid internal_sigfillset(__sanitizer_sigset_t *set) {
7050f7a2acb3326a5900d1a1339ebf959b14b372e0dDmitry Vyukov  internal_memset(set, 0xff, sizeof(*set));
7060f7a2acb3326a5900d1a1339ebf959b14b372e0dDmitry Vyukov}
7070f7a2acb3326a5900d1a1339ebf959b14b372e0dDmitry Vyukov
708c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainarvoid internal_sigemptyset(__sanitizer_sigset_t *set) {
709c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  internal_memset(set, 0, sizeof(*set));
710c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar}
711c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar
7122d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#if SANITIZER_LINUX
7132d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesvoid internal_sigdelset(__sanitizer_sigset_t *set, int signum) {
7140f7a2acb3326a5900d1a1339ebf959b14b372e0dDmitry Vyukov  signum -= 1;
7150f7a2acb3326a5900d1a1339ebf959b14b372e0dDmitry Vyukov  CHECK_GE(signum, 0);
7160f7a2acb3326a5900d1a1339ebf959b14b372e0dDmitry Vyukov  CHECK_LT(signum, sizeof(*set) * 8);
7172d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  __sanitizer_kernel_sigset_t *k_set = (__sanitizer_kernel_sigset_t *)set;
7182d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  const uptr idx = signum / (sizeof(k_set->sig[0]) * 8);
7192d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  const uptr bit = signum % (sizeof(k_set->sig[0]) * 8);
7202d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  k_set->sig[idx] &= ~(1 << bit);
7210f7a2acb3326a5900d1a1339ebf959b14b372e0dDmitry Vyukov}
722c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar
723c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainarbool internal_sigismember(__sanitizer_sigset_t *set, int signum) {
724c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  signum -= 1;
725c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  CHECK_GE(signum, 0);
726c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  CHECK_LT(signum, sizeof(*set) * 8);
727c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  __sanitizer_kernel_sigset_t *k_set = (__sanitizer_kernel_sigset_t *)set;
728c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  const uptr idx = signum / (sizeof(k_set->sig[0]) * 8);
729c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  const uptr bit = signum % (sizeof(k_set->sig[0]) * 8);
730c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  return k_set->sig[idx] & (1 << bit);
731c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar}
7322d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#endif  // SANITIZER_LINUX
7330f7a2acb3326a5900d1a1339ebf959b14b372e0dDmitry Vyukov
7346fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany// ThreadLister implementation.
7356fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya SerebryanyThreadLister::ThreadLister(int pid)
7366fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany  : pid_(pid),
7376fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany    descriptor_(-1),
73810f3ab775088bec69dd9e7b611f9b4e152f629bcAlexey Samsonov    buffer_(4096),
7396fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany    error_(true),
74010f3ab775088bec69dd9e7b611f9b4e152f629bcAlexey Samsonov    entry_((struct linux_dirent *)buffer_.data()),
7416fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany    bytes_read_(0) {
7426fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany  char task_directory_path[80];
7436fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany  internal_snprintf(task_directory_path, sizeof(task_directory_path),
7446fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany                    "/proc/%d/task/", pid);
7459578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne  uptr openrv = internal_open(task_directory_path, O_RDONLY | O_DIRECTORY);
7469578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne  if (internal_iserror(openrv)) {
7476fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany    error_ = true;
7486fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany    Report("Can't open /proc/%d/task for reading.\n", pid);
7496fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany  } else {
7506fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany    error_ = false;
7519578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne    descriptor_ = openrv;
7526fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany  }
7536fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany}
7546fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany
7556fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryanyint ThreadLister::GetNextTID() {
7566fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany  int tid = -1;
7576fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany  do {
7586fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany    if (error_)
7596fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany      return -1;
7606fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany    if ((char *)entry_ >= &buffer_[bytes_read_] && !GetDirectoryEntries())
7616fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany      return -1;
7626fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany    if (entry_->d_ino != 0 && entry_->d_name[0] >= '0' &&
7636fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany        entry_->d_name[0] <= '9') {
7646fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany      // Found a valid tid.
7656fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany      tid = (int)internal_atoll(entry_->d_name);
7666fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany    }
7676fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany    entry_ = (struct linux_dirent *)(((char *)entry_) + entry_->d_reclen);
7686fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany  } while (tid < 0);
7696fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany  return tid;
7706fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany}
7716fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany
7726fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryanyvoid ThreadLister::Reset() {
7736fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany  if (error_ || descriptor_ < 0)
7746fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany    return;
7756fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany  internal_lseek(descriptor_, 0, SEEK_SET);
7766fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany}
7776fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany
7786fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya SerebryanyThreadLister::~ThreadLister() {
7796fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany  if (descriptor_ >= 0)
7806fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany    internal_close(descriptor_);
7816fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany}
7826fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany
7836fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryanybool ThreadLister::error() { return error_; }
7846fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany
7856fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryanybool ThreadLister::GetDirectoryEntries() {
7866fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany  CHECK_GE(descriptor_, 0);
7876fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany  CHECK_NE(error_, true);
7886fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany  bytes_read_ = internal_getdents(descriptor_,
78910f3ab775088bec69dd9e7b611f9b4e152f629bcAlexey Samsonov                                  (struct linux_dirent *)buffer_.data(),
79010f3ab775088bec69dd9e7b611f9b4e152f629bcAlexey Samsonov                                  buffer_.size());
7919578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne  if (internal_iserror(bytes_read_)) {
7926fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany    Report("Can't read directory entries from /proc/%d/task.\n", pid_);
7936fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany    error_ = true;
7946fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany    return false;
7956fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany  } else if (bytes_read_ == 0) {
7966fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany    return false;
7976fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany  }
79810f3ab775088bec69dd9e7b611f9b4e152f629bcAlexey Samsonov  entry_ = (struct linux_dirent *)buffer_.data();
7996fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany  return true;
8006fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany}
8016fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany
8024df343a31cf57c309cf102b9aef870458318f579Peter Collingbourneuptr GetPageSize() {
803c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar// Android post-M sysconf(_SC_PAGESIZE) crashes if called from .preinit_array.
804c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar#if SANITIZER_ANDROID
805c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  return 4096;
806c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar#elif SANITIZER_LINUX && (defined(__x86_64__) || defined(__i386__))
8074df343a31cf57c309cf102b9aef870458318f579Peter Collingbourne  return EXEC_PAGESIZE;
808a8bc34e420d27c47560b0742cec295e40b0f430eKostya Serebryany#else
809a8bc34e420d27c47560b0742cec295e40b0f430eKostya Serebryany  return sysconf(_SC_PAGESIZE);  // EXEC_PAGESIZE may not be trustworthy.
810a8bc34e420d27c47560b0742cec295e40b0f430eKostya Serebryany#endif
8114df343a31cf57c309cf102b9aef870458318f579Peter Collingbourne}
8124df343a31cf57c309cf102b9aef870458318f579Peter Collingbourne
8137847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonovuptr ReadBinaryName(/*out*/char *buf, uptr buf_len) {
8146a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines#if SANITIZER_FREEBSD
815cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar  const int Mib[] = { CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, -1 };
816cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar  const char *default_module_name = "kern.proc.pathname";
8176a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines  size_t Size = buf_len;
818cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar  bool IsErr = (sysctl(Mib, ARRAY_SIZE(Mib), buf, &Size, NULL, 0) != 0);
8196a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines  int readlink_error = IsErr ? errno : 0;
8206a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines  uptr module_name_len = Size;
8216a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines#else
822cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar  const char *default_module_name = "/proc/self/exe";
8237847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov  uptr module_name_len = internal_readlink(
824cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar      default_module_name, buf, buf_len);
8257847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov  int readlink_error;
8266a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines  bool IsErr = internal_iserror(module_name_len, &readlink_error);
8276a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines#endif
8286a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines  if (IsErr) {
829cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar    // We can't read binary name for some reason, assume it's unknown.
830cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar    Report("WARNING: reading executable name failed with errno %d, "
8316a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines           "some stack frames may not be symbolized\n", readlink_error);
832cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar    module_name_len = internal_snprintf(buf, buf_len, "%s",
833cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar                                        default_module_name);
8347847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov    CHECK_LT(module_name_len, buf_len);
8357847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov  }
8367847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov  return module_name_len;
8377847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov}
8387847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov
839799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainaruptr ReadLongProcessName(/*out*/ char *buf, uptr buf_len) {
840799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar#if SANITIZER_LINUX
841799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar  char *tmpbuf;
842799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar  uptr tmpsize;
843799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar  uptr tmplen;
844799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar  if (ReadFileToBuffer("/proc/self/cmdline", &tmpbuf, &tmpsize, &tmplen,
845799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar                       1024 * 1024)) {
846799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar    internal_strncpy(buf, tmpbuf, buf_len);
847799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar    UnmapOrDie(tmpbuf, tmpsize);
848799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar    return internal_strlen(buf);
849799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar  }
850799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar#endif
851799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar  return ReadBinaryName(buf, buf_len);
852799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar}
853799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar
8543de0086409d143a612a54a7a0ed809e286656188Sergey Matveev// Match full names of the form /path/to/base_name{-,.}*
8553de0086409d143a612a54a7a0ed809e286656188Sergey Matveevbool LibraryNameIs(const char *full_name, const char *base_name) {
8563de0086409d143a612a54a7a0ed809e286656188Sergey Matveev  const char *name = full_name;
8573de0086409d143a612a54a7a0ed809e286656188Sergey Matveev  // Strip path.
8583de0086409d143a612a54a7a0ed809e286656188Sergey Matveev  while (*name != '\0') name++;
8593de0086409d143a612a54a7a0ed809e286656188Sergey Matveev  while (name > full_name && *name != '/') name--;
8603de0086409d143a612a54a7a0ed809e286656188Sergey Matveev  if (*name == '/') name++;
8613de0086409d143a612a54a7a0ed809e286656188Sergey Matveev  uptr base_name_length = internal_strlen(base_name);
8623de0086409d143a612a54a7a0ed809e286656188Sergey Matveev  if (internal_strncmp(name, base_name, base_name_length)) return false;
8633de0086409d143a612a54a7a0ed809e286656188Sergey Matveev  return (name[base_name_length] == '-' || name[base_name_length] == '.');
8643de0086409d143a612a54a7a0ed809e286656188Sergey Matveev}
8653de0086409d143a612a54a7a0ed809e286656188Sergey Matveev
866d054abef27369471e154ec5693949538c2fdffd9Evgeniy Stepanov#if !SANITIZER_ANDROID
8672e75ac983cb233daa1abfa35fb33d2bafffe2ab1Peter Collingbourne// Call cb for each region mapped by map.
8682e75ac983cb233daa1abfa35fb33d2bafffe2ab1Peter Collingbournevoid ForEachMappedRegion(link_map *map, void (*cb)(const void *, uptr)) {
86986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  CHECK_NE(map, nullptr);
8702d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#if !SANITIZER_FREEBSD
8712e75ac983cb233daa1abfa35fb33d2bafffe2ab1Peter Collingbourne  typedef ElfW(Phdr) Elf_Phdr;
8722e75ac983cb233daa1abfa35fb33d2bafffe2ab1Peter Collingbourne  typedef ElfW(Ehdr) Elf_Ehdr;
8732d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#endif  // !SANITIZER_FREEBSD
8742e75ac983cb233daa1abfa35fb33d2bafffe2ab1Peter Collingbourne  char *base = (char *)map->l_addr;
8752e75ac983cb233daa1abfa35fb33d2bafffe2ab1Peter Collingbourne  Elf_Ehdr *ehdr = (Elf_Ehdr *)base;
8762e75ac983cb233daa1abfa35fb33d2bafffe2ab1Peter Collingbourne  char *phdrs = base + ehdr->e_phoff;
8772e75ac983cb233daa1abfa35fb33d2bafffe2ab1Peter Collingbourne  char *phdrs_end = phdrs + ehdr->e_phnum * ehdr->e_phentsize;
8782e75ac983cb233daa1abfa35fb33d2bafffe2ab1Peter Collingbourne
8792e75ac983cb233daa1abfa35fb33d2bafffe2ab1Peter Collingbourne  // Find the segment with the minimum base so we can "relocate" the p_vaddr
8802e75ac983cb233daa1abfa35fb33d2bafffe2ab1Peter Collingbourne  // fields.  Typically ET_DYN objects (DSOs) have base of zero and ET_EXEC
8812e75ac983cb233daa1abfa35fb33d2bafffe2ab1Peter Collingbourne  // objects have a non-zero base.
882f50b0fc601aea71d9fb22f01a11c7e206c666edcPeter Collingbourne  uptr preferred_base = (uptr)-1;
8832e75ac983cb233daa1abfa35fb33d2bafffe2ab1Peter Collingbourne  for (char *iter = phdrs; iter != phdrs_end; iter += ehdr->e_phentsize) {
8842e75ac983cb233daa1abfa35fb33d2bafffe2ab1Peter Collingbourne    Elf_Phdr *phdr = (Elf_Phdr *)iter;
8852e75ac983cb233daa1abfa35fb33d2bafffe2ab1Peter Collingbourne    if (phdr->p_type == PT_LOAD && preferred_base > (uptr)phdr->p_vaddr)
8862e75ac983cb233daa1abfa35fb33d2bafffe2ab1Peter Collingbourne      preferred_base = (uptr)phdr->p_vaddr;
8872e75ac983cb233daa1abfa35fb33d2bafffe2ab1Peter Collingbourne  }
8882e75ac983cb233daa1abfa35fb33d2bafffe2ab1Peter Collingbourne
8892e75ac983cb233daa1abfa35fb33d2bafffe2ab1Peter Collingbourne  // Compute the delta from the real base to get a relocation delta.
8902e75ac983cb233daa1abfa35fb33d2bafffe2ab1Peter Collingbourne  sptr delta = (uptr)base - preferred_base;
8912e75ac983cb233daa1abfa35fb33d2bafffe2ab1Peter Collingbourne  // Now we can figure out what the loader really mapped.
8922e75ac983cb233daa1abfa35fb33d2bafffe2ab1Peter Collingbourne  for (char *iter = phdrs; iter != phdrs_end; iter += ehdr->e_phentsize) {
8932e75ac983cb233daa1abfa35fb33d2bafffe2ab1Peter Collingbourne    Elf_Phdr *phdr = (Elf_Phdr *)iter;
8942e75ac983cb233daa1abfa35fb33d2bafffe2ab1Peter Collingbourne    if (phdr->p_type == PT_LOAD) {
8952e75ac983cb233daa1abfa35fb33d2bafffe2ab1Peter Collingbourne      uptr seg_start = phdr->p_vaddr + delta;
8962e75ac983cb233daa1abfa35fb33d2bafffe2ab1Peter Collingbourne      uptr seg_end = seg_start + phdr->p_memsz;
8972e75ac983cb233daa1abfa35fb33d2bafffe2ab1Peter Collingbourne      // None of these values are aligned.  We consider the ragged edges of the
8982e75ac983cb233daa1abfa35fb33d2bafffe2ab1Peter Collingbourne      // load command as defined, since they are mapped from the file.
8992e75ac983cb233daa1abfa35fb33d2bafffe2ab1Peter Collingbourne      seg_start = RoundDownTo(seg_start, GetPageSizeCached());
9002e75ac983cb233daa1abfa35fb33d2bafffe2ab1Peter Collingbourne      seg_end = RoundUpTo(seg_end, GetPageSizeCached());
9012e75ac983cb233daa1abfa35fb33d2bafffe2ab1Peter Collingbourne      cb((void *)seg_start, seg_end - seg_start);
9022e75ac983cb233daa1abfa35fb33d2bafffe2ab1Peter Collingbourne    }
9032e75ac983cb233daa1abfa35fb33d2bafffe2ab1Peter Collingbourne  }
9042e75ac983cb233daa1abfa35fb33d2bafffe2ab1Peter Collingbourne}
905d054abef27369471e154ec5693949538c2fdffd9Evgeniy Stepanov#endif
9062e75ac983cb233daa1abfa35fb33d2bafffe2ab1Peter Collingbourne
9072d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#if defined(__x86_64__) && SANITIZER_LINUX
908cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev// We cannot use glibc's clone wrapper, because it messes with the child
909cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev// task's TLS. It writes the PID and TID of the child task to its thread
910cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev// descriptor, but in our case the child task shares the thread descriptor with
911cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev// the parent (because we don't know how to allocate a new thread
912cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev// descriptor to keep glibc happy). So the stock version of clone(), when
913cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev// used with CLONE_VM, would end up corrupting the parent's thread descriptor.
914cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveevuptr internal_clone(int (*fn)(void *), void *child_stack, int flags, void *arg,
915cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev                    int *parent_tidptr, void *newtls, int *child_tidptr) {
916cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev  long long res;
917cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev  if (!fn || !child_stack)
918cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev    return -EINVAL;
919cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev  CHECK_EQ(0, (uptr)child_stack % 16);
920e041c6024b3ebf1365c0f99732fc69c607577571Kostya Serebryany  child_stack = (char *)child_stack - 2 * sizeof(unsigned long long);
921e041c6024b3ebf1365c0f99732fc69c607577571Kostya Serebryany  ((unsigned long long *)child_stack)[0] = (uptr)fn;
922e041c6024b3ebf1365c0f99732fc69c607577571Kostya Serebryany  ((unsigned long long *)child_stack)[1] = (uptr)arg;
923e041c6024b3ebf1365c0f99732fc69c607577571Kostya Serebryany  register void *r8 __asm__("r8") = newtls;
924e041c6024b3ebf1365c0f99732fc69c607577571Kostya Serebryany  register int *r10 __asm__("r10") = child_tidptr;
925cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev  __asm__ __volatile__(
9262d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines                       /* %rax = syscall(%rax = SYSCALL(clone),
927cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev                        *                %rdi = flags,
928cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev                        *                %rsi = child_stack,
929cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev                        *                %rdx = parent_tidptr,
930cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev                        *                %r8  = new_tls,
931cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev                        *                %r10 = child_tidptr)
932cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev                        */
933cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev                       "syscall\n"
934cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev
935cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev                       /* if (%rax != 0)
936cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev                        *   return;
937cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev                        */
938cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev                       "testq  %%rax,%%rax\n"
939cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev                       "jnz    1f\n"
940cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev
941cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev                       /* In the child. Terminate unwind chain. */
942497ae56316cd05a0d539e0d6e065bbaee254aca3Sergey Matveev                       // XXX: We should also terminate the CFI unwind chain
943497ae56316cd05a0d539e0d6e065bbaee254aca3Sergey Matveev                       // here. Unfortunately clang 3.2 doesn't support the
944497ae56316cd05a0d539e0d6e065bbaee254aca3Sergey Matveev                       // necessary CFI directives, so we skip that part.
945cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev                       "xorq   %%rbp,%%rbp\n"
946cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev
947cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev                       /* Call "fn(arg)". */
948cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev                       "popq   %%rax\n"
949cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev                       "popq   %%rdi\n"
950cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev                       "call   *%%rax\n"
951cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev
952cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev                       /* Call _exit(%rax). */
953cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev                       "movq   %%rax,%%rdi\n"
954cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev                       "movq   %2,%%rax\n"
955cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev                       "syscall\n"
956cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev
957cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev                       /* Return to parent. */
958cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev                     "1:\n"
959cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev                       : "=a" (res)
9602d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines                       : "a"(SYSCALL(clone)), "i"(SYSCALL(exit)),
961cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev                         "S"(child_stack),
962cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev                         "D"(flags),
963cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev                         "d"(parent_tidptr),
964e041c6024b3ebf1365c0f99732fc69c607577571Kostya Serebryany                         "r"(r8),
965e041c6024b3ebf1365c0f99732fc69c607577571Kostya Serebryany                         "r"(r10)
966e041c6024b3ebf1365c0f99732fc69c607577571Kostya Serebryany                       : "rsp", "memory", "r11", "rcx");
967cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev  return res;
968cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev}
96986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines#elif defined(__mips__)
97086277eb844c4983c81de62d7c050e92fe7155788Stephen Hinesuptr internal_clone(int (*fn)(void *), void *child_stack, int flags, void *arg,
97186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines                    int *parent_tidptr, void *newtls, int *child_tidptr) {
972cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar  long long res;
973cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar  if (!fn || !child_stack)
974cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar    return -EINVAL;
975cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar  CHECK_EQ(0, (uptr)child_stack % 16);
976cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar  child_stack = (char *)child_stack - 2 * sizeof(unsigned long long);
977cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar  ((unsigned long long *)child_stack)[0] = (uptr)fn;
978cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar  ((unsigned long long *)child_stack)[1] = (uptr)arg;
979cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar  register void *a3 __asm__("$7") = newtls;
980cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar  register int *a4 __asm__("$8") = child_tidptr;
981cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar  // We don't have proper CFI directives here because it requires alot of code
982cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar  // for very marginal benefits.
983cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar  __asm__ __volatile__(
984cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar                       /* $v0 = syscall($v0 = __NR_clone,
985cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar                        * $a0 = flags,
986cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar                        * $a1 = child_stack,
987cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar                        * $a2 = parent_tidptr,
988cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar                        * $a3 = new_tls,
989cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar                        * $a4 = child_tidptr)
990cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar                        */
991cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar                       ".cprestore 16;\n"
992cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar                       "move $4,%1;\n"
993cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar                       "move $5,%2;\n"
994cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar                       "move $6,%3;\n"
995cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar                       "move $7,%4;\n"
996cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar                       /* Store the fifth argument on stack
997cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar                        * if we are using 32-bit abi.
998cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar                        */
999cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar#if SANITIZER_WORDSIZE == 32
1000cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar                       "lw %5,16($29);\n"
1001cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar#else
1002cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar                       "move $8,%5;\n"
1003cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar#endif
1004cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar                       "li $2,%6;\n"
1005cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar                       "syscall;\n"
1006cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar
1007cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar                       /* if ($v0 != 0)
1008cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar                        * return;
1009cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar                        */
1010cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar                       "bnez $2,1f;\n"
1011cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar
1012cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar                       /* Call "fn(arg)". */
1013c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar#if SANITIZER_WORDSIZE == 32
1014c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar#ifdef __BIG_ENDIAN__
1015c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar                       "lw $25,4($29);\n"
1016c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar                       "lw $4,12($29);\n"
1017c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar#else
1018c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar                       "lw $25,0($29);\n"
1019c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar                       "lw $4,8($29);\n"
1020c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar#endif
1021c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar#else
1022cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar                       "ld $25,0($29);\n"
1023cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar                       "ld $4,8($29);\n"
1024c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar#endif
1025cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar                       "jal $25;\n"
1026cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar
1027cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar                       /* Call _exit($v0). */
1028cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar                       "move $4,$2;\n"
1029cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar                       "li $2,%7;\n"
1030cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar                       "syscall;\n"
1031cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar
1032cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar                       /* Return to parent. */
1033cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar                     "1:\n"
1034cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar                       : "=r" (res)
1035cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar                       : "r"(flags),
1036cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar                         "r"(child_stack),
1037cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar                         "r"(parent_tidptr),
1038cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar                         "r"(a3),
1039cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar                         "r"(a4),
1040cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar                         "i"(__NR_clone),
1041cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar                         "i"(__NR_exit)
1042cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar                       : "memory", "$29" );
1043cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar  return res;
104486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines}
1045799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar#elif defined(__aarch64__)
1046799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainaruptr internal_clone(int (*fn)(void *), void *child_stack, int flags, void *arg,
1047799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar                    int *parent_tidptr, void *newtls, int *child_tidptr) {
1048799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar  long long res;
1049799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar  if (!fn || !child_stack)
1050799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar    return -EINVAL;
1051799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar  CHECK_EQ(0, (uptr)child_stack % 16);
1052799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar  child_stack = (char *)child_stack - 2 * sizeof(unsigned long long);
1053799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar  ((unsigned long long *)child_stack)[0] = (uptr)fn;
1054799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar  ((unsigned long long *)child_stack)[1] = (uptr)arg;
10552d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
1056799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar  register int (*__fn)(void *)  __asm__("x0") = fn;
1057799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar  register void *__stack __asm__("x1") = child_stack;
1058799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar  register int   __flags __asm__("x2") = flags;
1059799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar  register void *__arg   __asm__("x3") = arg;
1060799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar  register int  *__ptid  __asm__("x4") = parent_tidptr;
1061799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar  register void *__tls   __asm__("x5") = newtls;
1062799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar  register int  *__ctid  __asm__("x6") = child_tidptr;
1063aafc5c8d620e24104f1ca340d97286b15a5cec90Evgeniy Stepanov
1064799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar  __asm__ __volatile__(
1065799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar                       "mov x0,x2\n" /* flags  */
1066799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar                       "mov x2,x4\n" /* ptid  */
1067799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar                       "mov x3,x5\n" /* tls  */
1068799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar                       "mov x4,x6\n" /* ctid  */
1069799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar                       "mov x8,%9\n" /* clone  */
1070aafc5c8d620e24104f1ca340d97286b15a5cec90Evgeniy Stepanov
1071799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar                       "svc 0x0\n"
1072799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar
1073799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar                       /* if (%r0 != 0)
1074799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar                        *   return %r0;
1075799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar                        */
1076799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar                       "cmp x0, #0\n"
1077799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar                       "bne 1f\n"
1078799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar
1079799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar                       /* In the child, now. Call "fn(arg)". */
1080799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar                       "ldp x1, x0, [sp], #16\n"
1081799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar                       "blr x1\n"
1082799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar
1083799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar                       /* Call _exit(%r0).  */
1084799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar                       "mov x8, %10\n"
1085799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar                       "svc 0x0\n"
1086799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar                     "1:\n"
1087799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar
1088799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar                       : "=r" (res)
1089799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar                       : "i"(-EINVAL),
1090799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar                         "r"(__fn), "r"(__stack), "r"(__flags), "r"(__arg),
1091799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar                         "r"(__ptid), "r"(__tls), "r"(__ctid),
1092799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar                         "i"(__NR_clone), "i"(__NR_exit)
1093799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar                       : "x30", "memory");
1094799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar  return res;
10952d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines}
1096799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar#elif defined(__powerpc64__)
1097799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainaruptr internal_clone(int (*fn)(void *), void *child_stack, int flags, void *arg,
1098799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar                   int *parent_tidptr, void *newtls, int *child_tidptr) {
1099799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar  long long res;
1100799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar/* Stack frame offsets.  */
1101799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar#if _CALL_ELF != 2
1102799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar#define FRAME_MIN_SIZE         112
1103799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar#define FRAME_TOC_SAVE         40
1104799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar#else
1105799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar#define FRAME_MIN_SIZE         32
1106799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar#define FRAME_TOC_SAVE         24
1107799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar#endif
1108799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar  if (!fn || !child_stack)
1109799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar    return -EINVAL;
1110799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar  CHECK_EQ(0, (uptr)child_stack % 16);
1111799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar  child_stack = (char *)child_stack - 2 * sizeof(unsigned long long);
1112799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar  ((unsigned long long *)child_stack)[0] = (uptr)fn;
1113799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar  ((unsigned long long *)child_stack)[1] = (uptr)arg;
11142d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
1115799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar  register int (*__fn)(void *) __asm__("r3") = fn;
1116799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar  register void *__cstack      __asm__("r4") = child_stack;
1117799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar  register int __flags         __asm__("r5") = flags;
1118799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar  register void * __arg        __asm__("r6") = arg;
1119799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar  register int * __ptidptr     __asm__("r7") = parent_tidptr;
1120799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar  register void * __newtls     __asm__("r8") = newtls;
1121799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar  register int * __ctidptr     __asm__("r9") = child_tidptr;
1122799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar
1123799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar __asm__ __volatile__(
1124799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar           /* fn, arg, child_stack are saved acrVoss the syscall */
1125799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar           "mr 28, %5\n\t"
1126799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar           "mr 29, %6\n\t"
1127799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar           "mr 27, %8\n\t"
1128799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar
1129799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar           /* syscall
1130799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar             r3 == flags
1131799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar             r4 == child_stack
1132799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar             r5 == parent_tidptr
1133799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar             r6 == newtls
1134799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar             r7 == child_tidptr */
1135799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar           "mr 3, %7\n\t"
1136799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar           "mr 5, %9\n\t"
1137799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar           "mr 6, %10\n\t"
1138799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar           "mr 7, %11\n\t"
1139799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar           "li 0, %3\n\t"
1140799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar           "sc\n\t"
1141799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar
1142799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar           /* Test if syscall was successful */
1143799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar           "cmpdi  cr1, 3, 0\n\t"
1144799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar           "crandc cr1*4+eq, cr1*4+eq, cr0*4+so\n\t"
1145799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar           "bne-   cr1, 1f\n\t"
1146799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar
1147799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar           /* Do the function call */
1148799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar           "std   2, %13(1)\n\t"
1149799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar#if _CALL_ELF != 2
1150799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar           "ld    0, 0(28)\n\t"
1151799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar           "ld    2, 8(28)\n\t"
1152799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar           "mtctr 0\n\t"
1153799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar#else
1154799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar           "mr    12, 28\n\t"
1155799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar           "mtctr 12\n\t"
1156799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar#endif
1157799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar           "mr    3, 27\n\t"
1158799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar           "bctrl\n\t"
1159799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar           "ld    2, %13(1)\n\t"
1160799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar
1161799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar           /* Call _exit(r3) */
1162799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar           "li 0, %4\n\t"
1163799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar           "sc\n\t"
1164799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar
1165799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar           /* Return to parent */
1166799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar           "1:\n\t"
1167799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar           "mr %0, 3\n\t"
1168799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar             : "=r" (res)
1169799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar             : "0" (-1), "i" (EINVAL),
1170799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar               "i" (__NR_clone), "i" (__NR_exit),
1171799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar               "r" (__fn), "r" (__cstack), "r" (__flags),
1172799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar               "r" (__arg), "r" (__ptidptr), "r" (__newtls),
1173799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar               "r" (__ctidptr), "i" (FRAME_MIN_SIZE), "i" (FRAME_TOC_SAVE)
1174799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar             : "cr0", "cr1", "memory", "ctr",
1175799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar               "r0", "r29", "r27", "r28");
1176799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar  return res;
11772d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines}
1178799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar#endif  // defined(__x86_64__) && SANITIZER_LINUX
1179cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar
1180799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar#if SANITIZER_ANDROID
1181cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar#if __ANDROID_API__ < 21
1182cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainarextern "C" __attribute__((weak)) int dl_iterate_phdr(
1183cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar    int (*)(struct dl_phdr_info *, size_t, void *), void *);
1184cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar#endif
1185cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar
1186cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainarstatic int dl_iterate_phdr_test_cb(struct dl_phdr_info *info, size_t size,
1187cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar                                   void *data) {
1188799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar  // Any name starting with "lib" indicates a bug in L where library base names
1189cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar  // are returned instead of paths.
1190cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar  if (info->dlpi_name && info->dlpi_name[0] == 'l' &&
1191cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar      info->dlpi_name[1] == 'i' && info->dlpi_name[2] == 'b') {
1192cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar    *(bool *)data = true;
1193cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar    return 1;
1194cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar  }
1195cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar  return 0;
1196cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar}
1197cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar
1198cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainarstatic atomic_uint32_t android_api_level;
1199cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar
1200799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainarstatic AndroidApiLevel AndroidDetectApiLevel() {
1201cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar  if (!&dl_iterate_phdr)
1202799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar    return ANDROID_KITKAT; // K or lower
1203cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar  bool base_name_seen = false;
1204cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar  dl_iterate_phdr(dl_iterate_phdr_test_cb, &base_name_seen);
1205cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar  if (base_name_seen)
1206799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar    return ANDROID_LOLLIPOP_MR1; // L MR1
1207799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar  return ANDROID_POST_LOLLIPOP;   // post-L
1208cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar  // Plain L (API level 21) is completely broken wrt ASan and not very
1209cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar  // interesting to detect.
1210cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar}
1211cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar
1212799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga NainarAndroidApiLevel AndroidGetApiLevel() {
1213799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar  AndroidApiLevel level =
1214799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar      (AndroidApiLevel)atomic_load(&android_api_level, memory_order_relaxed);
1215cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar  if (level) return level;
1216cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar  level = AndroidDetectApiLevel();
1217cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar  atomic_store(&android_api_level, level, memory_order_relaxed);
1218cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar  return level;
1219cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar}
1220cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar
12212d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#endif
12222d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
1223c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainarbool IsHandledDeadlySignal(int signum) {
1224cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar  if (common_flags()->handle_abort && signum == SIGABRT)
1225cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar    return true;
1226799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar  if (common_flags()->handle_sigill && signum == SIGILL)
1227799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar    return true;
1228799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar  if (common_flags()->handle_sigfpe && signum == SIGFPE)
1229799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar    return true;
123086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  return (signum == SIGSEGV || signum == SIGBUS) && common_flags()->handle_segv;
123186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines}
123286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines
123386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines#ifndef SANITIZER_GO
123486277eb844c4983c81de62d7c050e92fe7155788Stephen Hinesvoid *internal_start_thread(void(*func)(void *arg), void *arg) {
123586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  // Start the thread with signals blocked, otherwise it can steal user signals.
123686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  __sanitizer_sigset_t set, old;
123786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  internal_sigfillset(&set);
1238799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar#if SANITIZER_LINUX && !SANITIZER_ANDROID
1239cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar  // Glibc uses SIGSETXID signal during setuid call. If this signal is blocked
1240cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar  // on any thread, setuid call hangs (see test/tsan/setuid.c).
1241cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar  internal_sigdelset(&set, 33);
1242cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar#endif
124386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  internal_sigprocmask(SIG_SETMASK, &set, &old);
124486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  void *th;
1245799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar  real_pthread_create(&th, nullptr, (void*(*)(void *arg))func, arg);
1246799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar  internal_sigprocmask(SIG_SETMASK, &old, nullptr);
124786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  return th;
12482d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines}
12492d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
125086277eb844c4983c81de62d7c050e92fe7155788Stephen Hinesvoid internal_join_thread(void *th) {
1251799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar  real_pthread_join(th, nullptr);
125286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines}
125386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines#else
125486277eb844c4983c81de62d7c050e92fe7155788Stephen Hinesvoid *internal_start_thread(void (*func)(void *), void *arg) { return 0; }
125586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines
125686277eb844c4983c81de62d7c050e92fe7155788Stephen Hinesvoid internal_join_thread(void *th) {}
125786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines#endif
125886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines
1259c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar#if defined(__aarch64__)
1260c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar// Android headers in the older NDK releases miss this definition.
1261c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainarstruct __sanitizer_esr_context {
1262c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  struct _aarch64_ctx head;
1263c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  uint64_t esr;
1264c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar};
1265c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar
1266c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainarstatic bool Aarch64GetESR(ucontext_t *ucontext, u64 *esr) {
1267c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  static const u32 kEsrMagic = 0x45535201;
1268c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  u8 *aux = ucontext->uc_mcontext.__reserved;
1269c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  while (true) {
1270c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar    _aarch64_ctx *ctx = (_aarch64_ctx *)aux;
1271c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar    if (ctx->size == 0) break;
1272c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar    if (ctx->magic == kEsrMagic) {
1273c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar      *esr = ((__sanitizer_esr_context *)ctx)->esr;
1274c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar      return true;
1275c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar    }
1276c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar    aux += ctx->size;
1277c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  }
1278c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  return false;
1279c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar}
1280c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar#endif
1281c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar
1282c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga NainarSignalContext::WriteFlag SignalContext::GetWriteFlag(void *context) {
1283c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  ucontext_t *ucontext = (ucontext_t *)context;
1284c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar#if defined(__x86_64__) || defined(__i386__)
1285c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  static const uptr PF_WRITE = 1U << 1;
1286c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar#if SANITIZER_FREEBSD
1287c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  uptr err = ucontext->uc_mcontext.mc_err;
1288c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar#else
1289c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  uptr err = ucontext->uc_mcontext.gregs[REG_ERR];
1290c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar#endif
1291c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  return err & PF_WRITE ? WRITE : READ;
1292c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar#elif defined(__arm__)
1293c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  static const uptr FSR_WRITE = 1U << 11;
1294c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  uptr fsr = ucontext->uc_mcontext.error_code;
1295c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  // FSR bits 5:0 describe the abort type, and are never 0 (or so it seems).
1296c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  // Zero FSR indicates an older kernel that does not pass this information to
1297c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  // the userspace.
1298c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  if (fsr == 0) return UNKNOWN;
1299c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  return fsr & FSR_WRITE ? WRITE : READ;
1300c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar#elif defined(__aarch64__)
1301c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  static const u64 ESR_ELx_WNR = 1U << 6;
1302c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  u64 esr;
1303c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  if (!Aarch64GetESR(ucontext, &esr)) return UNKNOWN;
1304c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  return esr & ESR_ELx_WNR ? WRITE : READ;
1305c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar#else
1306c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  (void)ucontext;
1307c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  return UNKNOWN;  // FIXME: Implement.
1308c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar#endif
1309c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar}
1310c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar
13117c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainarvoid GetPcSpBp(void *context, uptr *pc, uptr *sp, uptr *bp) {
13127c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar#if defined(__arm__)
13137c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar  ucontext_t *ucontext = (ucontext_t*)context;
13147c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar  *pc = ucontext->uc_mcontext.arm_pc;
13157c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar  *bp = ucontext->uc_mcontext.arm_fp;
13167c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar  *sp = ucontext->uc_mcontext.arm_sp;
13177c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar#elif defined(__aarch64__)
13187c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar  ucontext_t *ucontext = (ucontext_t*)context;
13197c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar  *pc = ucontext->uc_mcontext.pc;
13207c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar  *bp = ucontext->uc_mcontext.regs[29];
13217c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar  *sp = ucontext->uc_mcontext.sp;
13227c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar#elif defined(__hppa__)
13237c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar  ucontext_t *ucontext = (ucontext_t*)context;
13247c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar  *pc = ucontext->uc_mcontext.sc_iaoq[0];
13257c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar  /* GCC uses %r3 whenever a frame pointer is needed.  */
13267c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar  *bp = ucontext->uc_mcontext.sc_gr[3];
13277c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar  *sp = ucontext->uc_mcontext.sc_gr[30];
13287c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar#elif defined(__x86_64__)
13297c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar# if SANITIZER_FREEBSD
13307c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar  ucontext_t *ucontext = (ucontext_t*)context;
13317c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar  *pc = ucontext->uc_mcontext.mc_rip;
13327c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar  *bp = ucontext->uc_mcontext.mc_rbp;
13337c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar  *sp = ucontext->uc_mcontext.mc_rsp;
13347c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar# else
13357c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar  ucontext_t *ucontext = (ucontext_t*)context;
13367c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar  *pc = ucontext->uc_mcontext.gregs[REG_RIP];
13377c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar  *bp = ucontext->uc_mcontext.gregs[REG_RBP];
13387c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar  *sp = ucontext->uc_mcontext.gregs[REG_RSP];
13397c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar# endif
13407c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar#elif defined(__i386__)
13417c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar# if SANITIZER_FREEBSD
13427c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar  ucontext_t *ucontext = (ucontext_t*)context;
13437c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar  *pc = ucontext->uc_mcontext.mc_eip;
13447c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar  *bp = ucontext->uc_mcontext.mc_ebp;
13457c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar  *sp = ucontext->uc_mcontext.mc_esp;
13467c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar# else
13477c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar  ucontext_t *ucontext = (ucontext_t*)context;
13487c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar  *pc = ucontext->uc_mcontext.gregs[REG_EIP];
13497c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar  *bp = ucontext->uc_mcontext.gregs[REG_EBP];
13507c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar  *sp = ucontext->uc_mcontext.gregs[REG_ESP];
13517c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar# endif
13527c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar#elif defined(__powerpc__) || defined(__powerpc64__)
13537c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar  ucontext_t *ucontext = (ucontext_t*)context;
13547c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar  *pc = ucontext->uc_mcontext.regs->nip;
13557c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar  *sp = ucontext->uc_mcontext.regs->gpr[PT_R1];
13567c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar  // The powerpc{,64}-linux ABIs do not specify r31 as the frame
13577c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar  // pointer, but GCC always uses r31 when we need a frame pointer.
13587c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar  *bp = ucontext->uc_mcontext.regs->gpr[PT_R31];
13597c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar#elif defined(__sparc__)
13607c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar  ucontext_t *ucontext = (ucontext_t*)context;
13617c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar  uptr *stk_ptr;
13627c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar# if defined (__arch64__)
13637c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar  *pc = ucontext->uc_mcontext.mc_gregs[MC_PC];
13647c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar  *sp = ucontext->uc_mcontext.mc_gregs[MC_O6];
13657c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar  stk_ptr = (uptr *) (*sp + 2047);
13667c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar  *bp = stk_ptr[15];
13677c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar# else
13687c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar  *pc = ucontext->uc_mcontext.gregs[REG_PC];
13697c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar  *sp = ucontext->uc_mcontext.gregs[REG_O6];
13707c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar  stk_ptr = (uptr *) *sp;
13717c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar  *bp = stk_ptr[15];
13727c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar# endif
13737c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar#elif defined(__mips__)
13747c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar  ucontext_t *ucontext = (ucontext_t*)context;
1375cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar  *pc = ucontext->uc_mcontext.pc;
13767c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar  *bp = ucontext->uc_mcontext.gregs[30];
13777c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar  *sp = ucontext->uc_mcontext.gregs[29];
1378c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar#elif defined(__s390__)
1379c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  ucontext_t *ucontext = (ucontext_t*)context;
1380c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar# if defined(__s390x__)
1381c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  *pc = ucontext->uc_mcontext.psw.addr;
1382c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar# else
1383c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  *pc = ucontext->uc_mcontext.psw.addr & 0x7fffffff;
1384c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar# endif
1385c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  *bp = ucontext->uc_mcontext.gregs[11];
1386c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  *sp = ucontext->uc_mcontext.gregs[15];
13877c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar#else
13887c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar# error "Unsupported arch"
13897c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar#endif
13907c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar}
13917c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar
1392799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainarvoid MaybeReexec() {
1393799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar  // No need to re-exec on Linux.
1394799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar}
1395799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar
1396799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar} // namespace __sanitizer
1397ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov
1398799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar#endif // SANITIZER_FREEBSD || SANITIZER_LINUX
1399