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