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