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