sanitizer_linux.cc revision 7c9150579ed0278492f51cc8434b1d63a44b9bd1
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) 3986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines#include <sys/types.h> 4086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines#define stat kernel_stat 4186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines#include <asm/stat.h> 4286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines#undef stat 4386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines#endif 4486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines 45b114ed83859d8d4964ac2284584733bcd2acf4f6Evgeniy Stepanov#include <dlfcn.h> 4635a7faf1fbfac678136e79d53824672dafb7d13eAlexey Samsonov#include <errno.h> 47c5d465136b911bf925f2a631e2b79f1c03e8a1b0Alexey Samsonov#include <fcntl.h> 486d40a0a2ffa6735e45bd1d62c94ff725fd3e8b71Peter Collingbourne#if !SANITIZER_ANDROID 492e75ac983cb233daa1abfa35fb33d2bafffe2ab1Peter Collingbourne#include <link.h> 506d40a0a2ffa6735e45bd1d62c94ff725fd3e8b71Peter Collingbourne#endif 51e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov#include <pthread.h> 520969bcf2c936126b1f6e636b978aade8fc207437Alexey Samsonov#include <sched.h> 53ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov#include <sys/mman.h> 546fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany#include <sys/ptrace.h> 55e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov#include <sys/resource.h> 56c5d465136b911bf925f2a631e2b79f1c03e8a1b0Alexey Samsonov#include <sys/stat.h> 57ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov#include <sys/syscall.h> 58e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov#include <sys/time.h> 59ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov#include <sys/types.h> 607c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar#include <ucontext.h> 61ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov#include <unistd.h> 6235a7faf1fbfac678136e79d53824672dafb7d13eAlexey Samsonov 632d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#if SANITIZER_FREEBSD 646a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines#include <sys/sysctl.h> 652d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#include <machine/atomic.h> 662d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesextern "C" { 672d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines// <sys/umtx.h> must be included after <errno.h> and <sys/types.h> on 682d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines// FreeBSD 9.2 and 10.0. 692d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#include <sys/umtx.h> 702d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines} 716a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hinesextern char **environ; // provided by crt1 722d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#endif // SANITIZER_FREEBSD 732d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines 7424e13723f8477d8c42ab8b2a7f4f69fc089842f1Evgeniy Stepanov#if !SANITIZER_ANDROID 7535a7faf1fbfac678136e79d53824672dafb7d13eAlexey Samsonov#include <sys/signal.h> 7635a7faf1fbfac678136e79d53824672dafb7d13eAlexey Samsonov#endif 77fa5c41eddf77a3614da0f62044ebf741d86aeab7Dmitry Vyukov 782d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#if SANITIZER_ANDROID 792d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#include <android/log.h> 802d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#include <sys/system_properties.h> 812d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#endif 822d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines 832d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#if SANITIZER_LINUX 844bebe7bab966c82f0a8952f797ed3d490624dc62Dmitry Vyukov// <linux/time.h> 854bebe7bab966c82f0a8952f797ed3d490624dc62Dmitry Vyukovstruct kernel_timeval { 864bebe7bab966c82f0a8952f797ed3d490624dc62Dmitry Vyukov long tv_sec; 874bebe7bab966c82f0a8952f797ed3d490624dc62Dmitry Vyukov long tv_usec; 884bebe7bab966c82f0a8952f797ed3d490624dc62Dmitry Vyukov}; 894bebe7bab966c82f0a8952f797ed3d490624dc62Dmitry Vyukov 90fa5c41eddf77a3614da0f62044ebf741d86aeab7Dmitry Vyukov// <linux/futex.h> is broken on some linux distributions. 91fa5c41eddf77a3614da0f62044ebf741d86aeab7Dmitry Vyukovconst int FUTEX_WAIT = 0; 92fa5c41eddf77a3614da0f62044ebf741d86aeab7Dmitry Vyukovconst int FUTEX_WAKE = 1; 932d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#endif // SANITIZER_LINUX 94ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov 952d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines// Are we using 32-bit or 64-bit Linux syscalls? 965af39e50366f1aacbebc284f572f08ad1ad07357Kostya Serebryany// x32 (which defines __x86_64__) has SANITIZER_WORDSIZE == 32 9708bfe4988de493dd3e61d02759b3f19c42f8fb78Kostya Serebryany// but it still needs to use 64-bit syscalls. 982d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#if SANITIZER_LINUX && (defined(__x86_64__) || SANITIZER_WORDSIZE == 64) 999d0dbbaf33e5c2fe280f141e30be497d62b703a8Kostya Serebryany# define SANITIZER_LINUX_USES_64BIT_SYSCALLS 1 1009d0dbbaf33e5c2fe280f141e30be497d62b703a8Kostya Serebryany#else 1019d0dbbaf33e5c2fe280f141e30be497d62b703a8Kostya Serebryany# define SANITIZER_LINUX_USES_64BIT_SYSCALLS 0 1029d0dbbaf33e5c2fe280f141e30be497d62b703a8Kostya Serebryany#endif 1039d0dbbaf33e5c2fe280f141e30be497d62b703a8Kostya Serebryany 104ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonovnamespace __sanitizer { 105ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov 1062d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#if SANITIZER_LINUX && defined(__x86_64__) 1079578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne#include "sanitizer_syscall_linux_x86_64.inc" 1089578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne#else 1099578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne#include "sanitizer_syscall_generic.inc" 1109578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne#endif 1119578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne 112e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov// --------------- sanitizer_libc.h 11386277eb844c4983c81de62d7c050e92fe7155788Stephen Hinesuptr internal_mmap(void *addr, uptr length, int prot, int flags, int fd, 11486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines u64 offset) { 1152d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#if SANITIZER_FREEBSD || SANITIZER_LINUX_USES_64BIT_SYSCALLS 1162d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines return internal_syscall(SYSCALL(mmap), (uptr)addr, length, prot, flags, fd, 117e041c6024b3ebf1365c0f99732fc69c607577571Kostya Serebryany offset); 118ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov#else 11986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines // mmap2 specifies file offset in 4096-byte units. 12086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines CHECK(IsAligned(offset, 4096)); 1212d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines return internal_syscall(SYSCALL(mmap2), addr, length, prot, flags, fd, 12286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines offset / 4096); 123ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov#endif 124ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov} 125ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov 1269578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourneuptr internal_munmap(void *addr, uptr length) { 1272d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines return internal_syscall(SYSCALL(munmap), (uptr)addr, length); 1281f11d31faa5ed89b74f7d543b1182fe8de198be5Alexey Samsonov} 1291f11d31faa5ed89b74f7d543b1182fe8de198be5Alexey Samsonov 1309578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourneuptr internal_close(fd_t fd) { 1312d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines return internal_syscall(SYSCALL(close), fd); 132a56aefd2e01940fcf88d1426f9de3d5e4b1ee203Alexey Samsonov} 133a56aefd2e01940fcf88d1426f9de3d5e4b1ee203Alexey Samsonov 1349578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourneuptr internal_open(const char *filename, int flags) { 1352d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#if SANITIZER_USES_CANONICAL_LINUX_SYSCALLS 1362d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines return internal_syscall(SYSCALL(openat), AT_FDCWD, (uptr)filename, flags); 1372d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#else 1382d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines return internal_syscall(SYSCALL(open), (uptr)filename, flags); 1392d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#endif 140ee7cc4454421a176d23442382afd9a01d36e7ad4Alexey Samsonov} 141ee7cc4454421a176d23442382afd9a01d36e7ad4Alexey Samsonov 1429578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourneuptr internal_open(const char *filename, int flags, u32 mode) { 1432d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#if SANITIZER_USES_CANONICAL_LINUX_SYSCALLS 1442d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines return internal_syscall(SYSCALL(openat), AT_FDCWD, (uptr)filename, flags, 1452d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines mode); 1462d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#else 1472d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines return internal_syscall(SYSCALL(open), (uptr)filename, flags, mode); 1482d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#endif 149ee7cc4454421a176d23442382afd9a01d36e7ad4Alexey Samsonov} 150ee7cc4454421a176d23442382afd9a01d36e7ad4Alexey Samsonov 151a56aefd2e01940fcf88d1426f9de3d5e4b1ee203Alexey Samsonovuptr internal_read(fd_t fd, void *buf, uptr count) { 1523334e12d33261cb8f211f2f49f28ddfa027a40c3Evgeniy Stepanov sptr res; 1532d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines HANDLE_EINTR(res, (sptr)internal_syscall(SYSCALL(read), fd, (uptr)buf, 1542d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines count)); 1553334e12d33261cb8f211f2f49f28ddfa027a40c3Evgeniy Stepanov return res; 156a56aefd2e01940fcf88d1426f9de3d5e4b1ee203Alexey Samsonov} 157a56aefd2e01940fcf88d1426f9de3d5e4b1ee203Alexey Samsonov 158a56aefd2e01940fcf88d1426f9de3d5e4b1ee203Alexey Samsonovuptr internal_write(fd_t fd, const void *buf, uptr count) { 1593334e12d33261cb8f211f2f49f28ddfa027a40c3Evgeniy Stepanov sptr res; 1602d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines HANDLE_EINTR(res, (sptr)internal_syscall(SYSCALL(write), fd, (uptr)buf, 1612d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines count)); 1623334e12d33261cb8f211f2f49f28ddfa027a40c3Evgeniy Stepanov return res; 163a56aefd2e01940fcf88d1426f9de3d5e4b1ee203Alexey Samsonov} 164a56aefd2e01940fcf88d1426f9de3d5e4b1ee203Alexey Samsonov 1652d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesuptr internal_ftruncate(fd_t fd, uptr size) { 1662d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines sptr res; 1677c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar HANDLE_EINTR(res, (sptr)internal_syscall(SYSCALL(ftruncate), fd, 1687c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar (OFF_T)size)); 1692d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines return res; 1702d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines} 1712d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines 1722d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#if !SANITIZER_LINUX_USES_64BIT_SYSCALLS && !SANITIZER_FREEBSD 1732be3a283939d4fc14ad86f6cd8be34b1468f22baEvgeniy Stepanovstatic void stat64_to_stat(struct stat64 *in, struct stat *out) { 1742be3a283939d4fc14ad86f6cd8be34b1468f22baEvgeniy Stepanov internal_memset(out, 0, sizeof(*out)); 1752be3a283939d4fc14ad86f6cd8be34b1468f22baEvgeniy Stepanov out->st_dev = in->st_dev; 1762be3a283939d4fc14ad86f6cd8be34b1468f22baEvgeniy Stepanov out->st_ino = in->st_ino; 1772be3a283939d4fc14ad86f6cd8be34b1468f22baEvgeniy Stepanov out->st_mode = in->st_mode; 1782be3a283939d4fc14ad86f6cd8be34b1468f22baEvgeniy Stepanov out->st_nlink = in->st_nlink; 1792be3a283939d4fc14ad86f6cd8be34b1468f22baEvgeniy Stepanov out->st_uid = in->st_uid; 1802be3a283939d4fc14ad86f6cd8be34b1468f22baEvgeniy Stepanov out->st_gid = in->st_gid; 1812be3a283939d4fc14ad86f6cd8be34b1468f22baEvgeniy Stepanov out->st_rdev = in->st_rdev; 1822be3a283939d4fc14ad86f6cd8be34b1468f22baEvgeniy Stepanov out->st_size = in->st_size; 1832be3a283939d4fc14ad86f6cd8be34b1468f22baEvgeniy Stepanov out->st_blksize = in->st_blksize; 1842be3a283939d4fc14ad86f6cd8be34b1468f22baEvgeniy Stepanov out->st_blocks = in->st_blocks; 1852be3a283939d4fc14ad86f6cd8be34b1468f22baEvgeniy Stepanov out->st_atime = in->st_atime; 1862be3a283939d4fc14ad86f6cd8be34b1468f22baEvgeniy Stepanov out->st_mtime = in->st_mtime; 1872be3a283939d4fc14ad86f6cd8be34b1468f22baEvgeniy Stepanov out->st_ctime = in->st_ctime; 1882be3a283939d4fc14ad86f6cd8be34b1468f22baEvgeniy Stepanov out->st_ino = in->st_ino; 1892be3a283939d4fc14ad86f6cd8be34b1468f22baEvgeniy Stepanov} 1902be3a283939d4fc14ad86f6cd8be34b1468f22baEvgeniy Stepanov#endif 1912be3a283939d4fc14ad86f6cd8be34b1468f22baEvgeniy Stepanov 19286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines#if defined(__mips64) 19386277eb844c4983c81de62d7c050e92fe7155788Stephen Hinesstatic void kernel_stat_to_stat(struct kernel_stat *in, struct stat *out) { 19486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines internal_memset(out, 0, sizeof(*out)); 19586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines out->st_dev = in->st_dev; 19686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines out->st_ino = in->st_ino; 19786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines out->st_mode = in->st_mode; 19886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines out->st_nlink = in->st_nlink; 19986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines out->st_uid = in->st_uid; 20086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines out->st_gid = in->st_gid; 20186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines out->st_rdev = in->st_rdev; 20286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines out->st_size = in->st_size; 20386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines out->st_blksize = in->st_blksize; 20486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines out->st_blocks = in->st_blocks; 20586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines out->st_atime = in->st_atime_nsec; 20686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines out->st_mtime = in->st_mtime_nsec; 20786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines out->st_ctime = in->st_ctime_nsec; 20886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines out->st_ino = in->st_ino; 20986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines} 21086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines#endif 21186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines 2129578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourneuptr internal_stat(const char *path, void *buf) { 2132d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#if SANITIZER_FREEBSD 2142d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines return internal_syscall(SYSCALL(stat), path, buf); 2152d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#elif SANITIZER_USES_CANONICAL_LINUX_SYSCALLS 2162d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines return internal_syscall(SYSCALL(newfstatat), AT_FDCWD, (uptr)path, 2172d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines (uptr)buf, 0); 2182d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#elif SANITIZER_LINUX_USES_64BIT_SYSCALLS 21986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines# if defined(__mips64) 22086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines // For mips64, stat syscall fills buffer in the format of kernel_stat 22186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines struct kernel_stat kbuf; 22286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines int res = internal_syscall(SYSCALL(stat), path, &kbuf); 22386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines kernel_stat_to_stat(&kbuf, (struct stat *)buf); 22486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines return res; 22586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines# else 2262d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines return internal_syscall(SYSCALL(stat), (uptr)path, (uptr)buf); 22786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines# endif 2284c9317a7b61e136f832d2ede70f557963fd46bceAlexey Samsonov#else 2292be3a283939d4fc14ad86f6cd8be34b1468f22baEvgeniy Stepanov struct stat64 buf64; 2302d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines int res = internal_syscall(SYSCALL(stat64), path, &buf64); 2312be3a283939d4fc14ad86f6cd8be34b1468f22baEvgeniy Stepanov stat64_to_stat(&buf64, (struct stat *)buf); 2322be3a283939d4fc14ad86f6cd8be34b1468f22baEvgeniy Stepanov return res; 2334c9317a7b61e136f832d2ede70f557963fd46bceAlexey Samsonov#endif 2344c9317a7b61e136f832d2ede70f557963fd46bceAlexey Samsonov} 2354c9317a7b61e136f832d2ede70f557963fd46bceAlexey Samsonov 2369578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourneuptr internal_lstat(const char *path, void *buf) { 2372d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#if SANITIZER_FREEBSD 2382d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines return internal_syscall(SYSCALL(lstat), path, buf); 2392d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#elif SANITIZER_USES_CANONICAL_LINUX_SYSCALLS 2402d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines return internal_syscall(SYSCALL(newfstatat), AT_FDCWD, (uptr)path, 2412d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines (uptr)buf, AT_SYMLINK_NOFOLLOW); 2422d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#elif SANITIZER_LINUX_USES_64BIT_SYSCALLS 2432d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines return internal_syscall(SYSCALL(lstat), (uptr)path, (uptr)buf); 2444c9317a7b61e136f832d2ede70f557963fd46bceAlexey Samsonov#else 2452be3a283939d4fc14ad86f6cd8be34b1468f22baEvgeniy Stepanov struct stat64 buf64; 2462d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines int res = internal_syscall(SYSCALL(lstat64), path, &buf64); 2472be3a283939d4fc14ad86f6cd8be34b1468f22baEvgeniy Stepanov stat64_to_stat(&buf64, (struct stat *)buf); 2482be3a283939d4fc14ad86f6cd8be34b1468f22baEvgeniy Stepanov return res; 2494c9317a7b61e136f832d2ede70f557963fd46bceAlexey Samsonov#endif 2504c9317a7b61e136f832d2ede70f557963fd46bceAlexey Samsonov} 2514c9317a7b61e136f832d2ede70f557963fd46bceAlexey Samsonov 2529578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourneuptr internal_fstat(fd_t fd, void *buf) { 2532d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#if SANITIZER_FREEBSD || SANITIZER_LINUX_USES_64BIT_SYSCALLS 2542d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines return internal_syscall(SYSCALL(fstat), fd, (uptr)buf); 2554c9317a7b61e136f832d2ede70f557963fd46bceAlexey Samsonov#else 2562be3a283939d4fc14ad86f6cd8be34b1468f22baEvgeniy Stepanov struct stat64 buf64; 2572d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines int res = internal_syscall(SYSCALL(fstat64), fd, &buf64); 2582be3a283939d4fc14ad86f6cd8be34b1468f22baEvgeniy Stepanov stat64_to_stat(&buf64, (struct stat *)buf); 2592be3a283939d4fc14ad86f6cd8be34b1468f22baEvgeniy Stepanov return res; 2604c9317a7b61e136f832d2ede70f557963fd46bceAlexey Samsonov#endif 2614c9317a7b61e136f832d2ede70f557963fd46bceAlexey Samsonov} 2624c9317a7b61e136f832d2ede70f557963fd46bceAlexey Samsonov 2638e820fcf7aafeb8101322182d742fcf99255d972Alexey Samsonovuptr internal_filesize(fd_t fd) { 264a68633fb76208137ccb807914df52758ee5ca6f0Alexey Samsonov struct stat st; 2654c9317a7b61e136f832d2ede70f557963fd46bceAlexey Samsonov if (internal_fstat(fd, &st)) 2664c9317a7b61e136f832d2ede70f557963fd46bceAlexey Samsonov return -1; 2678e820fcf7aafeb8101322182d742fcf99255d972Alexey Samsonov return (uptr)st.st_size; 2688e820fcf7aafeb8101322182d742fcf99255d972Alexey Samsonov} 2698e820fcf7aafeb8101322182d742fcf99255d972Alexey Samsonov 2709578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourneuptr internal_dup2(int oldfd, int newfd) { 2712d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#if SANITIZER_USES_CANONICAL_LINUX_SYSCALLS 2722d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines return internal_syscall(SYSCALL(dup3), oldfd, newfd, 0); 2732d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#else 2742d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines return internal_syscall(SYSCALL(dup2), oldfd, newfd); 2752d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#endif 2768e820fcf7aafeb8101322182d742fcf99255d972Alexey Samsonov} 2778e820fcf7aafeb8101322182d742fcf99255d972Alexey Samsonov 278d1b8f588d6b712b6ff2b3d58c73d71614f520122Alexey Samsonovuptr internal_readlink(const char *path, char *buf, uptr bufsize) { 2792d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#if SANITIZER_USES_CANONICAL_LINUX_SYSCALLS 2802d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines return internal_syscall(SYSCALL(readlinkat), AT_FDCWD, 2812d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines (uptr)path, (uptr)buf, bufsize); 2822d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#else 2832d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines return internal_syscall(SYSCALL(readlink), (uptr)path, (uptr)buf, bufsize); 2842d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#endif 285d1b8f588d6b712b6ff2b3d58c73d71614f520122Alexey Samsonov} 286d1b8f588d6b712b6ff2b3d58c73d71614f520122Alexey Samsonov 2879578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourneuptr internal_unlink(const char *path) { 2882d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#if SANITIZER_USES_CANONICAL_LINUX_SYSCALLS 2892d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines return internal_syscall(SYSCALL(unlinkat), AT_FDCWD, (uptr)path, 0); 2902d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#else 2912d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines return internal_syscall(SYSCALL(unlink), (uptr)path); 2922d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#endif 2932d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines} 2942d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines 2952d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesuptr internal_rename(const char *oldpath, const char *newpath) { 2962d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#if SANITIZER_USES_CANONICAL_LINUX_SYSCALLS 2972d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines return internal_syscall(SYSCALL(renameat), AT_FDCWD, (uptr)oldpath, AT_FDCWD, 2982d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines (uptr)newpath); 2992d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#else 3002d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines return internal_syscall(SYSCALL(rename), (uptr)oldpath, (uptr)newpath); 3012d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#endif 3026d6ab9eeea4a99370d7ab18ce80eb96091e2cf3fDmitry Vyukov} 3036d6ab9eeea4a99370d7ab18ce80eb96091e2cf3fDmitry Vyukov 3049578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourneuptr internal_sched_yield() { 3052d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines return internal_syscall(SYSCALL(sched_yield)); 3060969bcf2c936126b1f6e636b978aade8fc207437Alexey Samsonov} 3070969bcf2c936126b1f6e636b978aade8fc207437Alexey Samsonov 308f882247088952deed954a19d745c2dd8871e2035Alexey Samsonovvoid internal__exit(int exitcode) { 3092d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#if SANITIZER_FREEBSD 3102d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines internal_syscall(SYSCALL(exit), exitcode); 3112d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#else 3122d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines internal_syscall(SYSCALL(exit_group), exitcode); 3132d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#endif 314f882247088952deed954a19d745c2dd8871e2035Alexey Samsonov Die(); // Unreachable. 315f882247088952deed954a19d745c2dd8871e2035Alexey Samsonov} 316f882247088952deed954a19d745c2dd8871e2035Alexey Samsonov 3179578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourneuptr internal_execve(const char *filename, char *const argv[], 3189578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne char *const envp[]) { 3192d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines return internal_syscall(SYSCALL(execve), (uptr)filename, (uptr)argv, 3202d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines (uptr)envp); 3219578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne} 3229578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne 323e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov// ----------------- sanitizer_common.h 32493b4cafd631b661b4b612ccdc0938f7f1e1c86d6Alexey Samsonovbool FileExists(const char *filename) { 3252d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines struct stat st; 32686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines#if SANITIZER_USES_CANONICAL_LINUX_SYSCALLS 3272d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines if (internal_syscall(SYSCALL(newfstatat), AT_FDCWD, filename, &st, 0)) 3282d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#else 3292be3a283939d4fc14ad86f6cd8be34b1468f22baEvgeniy Stepanov if (internal_stat(filename, &st)) 33086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines#endif 33193b4cafd631b661b4b612ccdc0938f7f1e1c86d6Alexey Samsonov return false; 33293b4cafd631b661b4b612ccdc0938f7f1e1c86d6Alexey Samsonov // Sanity check: filename is a regular file. 33393b4cafd631b661b4b612ccdc0938f7f1e1c86d6Alexey Samsonov return S_ISREG(st.st_mode); 33493b4cafd631b661b4b612ccdc0938f7f1e1c86d6Alexey Samsonov} 33593b4cafd631b661b4b612ccdc0938f7f1e1c86d6Alexey Samsonov 336e0023f74ea88efee329f68391b70f8adc6b21617Dmitry Vyukovuptr GetTid() { 3372d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#if SANITIZER_FREEBSD 3382d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines return (uptr)pthread_self(); 3392d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#else 3402d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines return internal_syscall(SYSCALL(gettid)); 3412d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#endif 342e0023f74ea88efee329f68391b70f8adc6b21617Dmitry Vyukov} 343e0023f74ea88efee329f68391b70f8adc6b21617Dmitry Vyukov 3444bebe7bab966c82f0a8952f797ed3d490624dc62Dmitry Vyukovu64 NanoTime() { 3452d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#if SANITIZER_FREEBSD 3462d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines timeval tv; 3472d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#else 3485e7ba22755b994e4f6aaf8cc00773c4d1b8dbf07Peter Collingbourne kernel_timeval tv; 3492d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#endif 3505e7ba22755b994e4f6aaf8cc00773c4d1b8dbf07Peter Collingbourne internal_memset(&tv, 0, sizeof(tv)); 3512d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines internal_syscall(SYSCALL(gettimeofday), (uptr)&tv, 0); 3524bebe7bab966c82f0a8952f797ed3d490624dc62Dmitry Vyukov return (u64)tv.tv_sec * 1000*1000*1000 + tv.tv_usec * 1000; 3534bebe7bab966c82f0a8952f797ed3d490624dc62Dmitry Vyukov} 3544bebe7bab966c82f0a8952f797ed3d490624dc62Dmitry Vyukov 3556a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines// Like getenv, but reads env directly from /proc (on Linux) or parses the 3566a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines// 'environ' array (on FreeBSD) and does not use libc. This function should be 3576a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines// called first inside __asan_init. 3583dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonovconst char *GetEnv(const char *name) { 3596a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines#if SANITIZER_FREEBSD 3606a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines if (::environ != 0) { 3616a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines uptr NameLen = internal_strlen(name); 3626a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines for (char **Env = ::environ; *Env != 0; Env++) { 3636a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines if (internal_strncmp(*Env, name, NameLen) == 0 && (*Env)[NameLen] == '=') 3646a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines return (*Env) + NameLen + 1; 3656a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines } 3666a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines } 3676a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines return 0; // Not found. 3686a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines#elif SANITIZER_LINUX 3693dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov static char *environ; 3703dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov static uptr len; 3713dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov static bool inited; 3723dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov if (!inited) { 3733dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov inited = true; 3743dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov uptr environ_size; 3753dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov len = ReadFileToBuffer("/proc/self/environ", 3763dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov &environ, &environ_size, 1 << 26); 3773dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov } 3783dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov if (!environ || len == 0) return 0; 3793dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov uptr namelen = internal_strlen(name); 3803dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov const char *p = environ; 3813dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov while (*p != '\0') { // will happen at the \0\0 that terminates the buffer 3823dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov // proc file has the format NAME=value\0NAME=value\0NAME=value\0... 3833dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov const char* endp = 3843dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov (char*)internal_memchr(p, '\0', len - (p - environ)); 3853dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov if (endp == 0) // this entry isn't NUL terminated 3863dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov return 0; 3873dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov else if (!internal_memcmp(p, name, namelen) && p[namelen] == '=') // Match. 3883dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov return p + namelen + 1; // point after = 3893dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov p = endp + 1; 3903dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov } 3913dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov return 0; // Not found. 3926a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines#else 3936a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines#error "Unsupported platform" 3946a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines#endif 3953dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov} 3963dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov 397eab061185ec0046d447b298a1dff84f028202a3cEvgeniy Stepanovextern "C" { 3983c80c6c574850106481f82b9e23d1c728458d4a9Timur Iskhodzhanov SANITIZER_WEAK_ATTRIBUTE extern void *__libc_stack_end; 399eab061185ec0046d447b298a1dff84f028202a3cEvgeniy Stepanov} 400eab061185ec0046d447b298a1dff84f028202a3cEvgeniy Stepanov 40126337b60b1d551c4744454edd8e5ef3c479e3467Peter Collingbourne#if !SANITIZER_GO 40223709c9ad9ac7c45de288f5260403426bf932db7Peter Collingbournestatic void ReadNullSepFileToArray(const char *path, char ***arr, 40323709c9ad9ac7c45de288f5260403426bf932db7Peter Collingbourne int arr_size) { 40423709c9ad9ac7c45de288f5260403426bf932db7Peter Collingbourne char *buff; 405d7e5bb4043adf4756e6f8cfe0f5a3165b185474dAlexey Samsonov uptr buff_size = 0; 40623709c9ad9ac7c45de288f5260403426bf932db7Peter Collingbourne *arr = (char **)MmapOrDie(arr_size * sizeof(char *), "NullSepFileArray"); 40723709c9ad9ac7c45de288f5260403426bf932db7Peter Collingbourne ReadFileToBuffer(path, &buff, &buff_size, 1024 * 1024); 40823709c9ad9ac7c45de288f5260403426bf932db7Peter Collingbourne (*arr)[0] = buff; 40923709c9ad9ac7c45de288f5260403426bf932db7Peter Collingbourne int count, i; 41023709c9ad9ac7c45de288f5260403426bf932db7Peter Collingbourne for (count = 1, i = 1; ; i++) { 411d7e5bb4043adf4756e6f8cfe0f5a3165b185474dAlexey Samsonov if (buff[i] == 0) { 412d7e5bb4043adf4756e6f8cfe0f5a3165b185474dAlexey Samsonov if (buff[i+1] == 0) break; 41323709c9ad9ac7c45de288f5260403426bf932db7Peter Collingbourne (*arr)[count] = &buff[i+1]; 41423709c9ad9ac7c45de288f5260403426bf932db7Peter Collingbourne CHECK_LE(count, arr_size - 1); // FIXME: make this more flexible. 41523709c9ad9ac7c45de288f5260403426bf932db7Peter Collingbourne count++; 416d7e5bb4043adf4756e6f8cfe0f5a3165b185474dAlexey Samsonov } 417d7e5bb4043adf4756e6f8cfe0f5a3165b185474dAlexey Samsonov } 41823709c9ad9ac7c45de288f5260403426bf932db7Peter Collingbourne (*arr)[count] = 0; 41923709c9ad9ac7c45de288f5260403426bf932db7Peter Collingbourne} 42026337b60b1d551c4744454edd8e5ef3c479e3467Peter Collingbourne#endif 42123709c9ad9ac7c45de288f5260403426bf932db7Peter Collingbourne 42226337b60b1d551c4744454edd8e5ef3c479e3467Peter Collingbournestatic void GetArgsAndEnv(char*** argv, char*** envp) { 42326337b60b1d551c4744454edd8e5ef3c479e3467Peter Collingbourne#if !SANITIZER_GO 42426337b60b1d551c4744454edd8e5ef3c479e3467Peter Collingbourne if (&__libc_stack_end) { 42526337b60b1d551c4744454edd8e5ef3c479e3467Peter Collingbourne#endif 42626337b60b1d551c4744454edd8e5ef3c479e3467Peter Collingbourne uptr* stack_end = (uptr*)__libc_stack_end; 42726337b60b1d551c4744454edd8e5ef3c479e3467Peter Collingbourne int argc = *stack_end; 42826337b60b1d551c4744454edd8e5ef3c479e3467Peter Collingbourne *argv = (char**)(stack_end + 1); 42926337b60b1d551c4744454edd8e5ef3c479e3467Peter Collingbourne *envp = (char**)(stack_end + argc + 2); 43026337b60b1d551c4744454edd8e5ef3c479e3467Peter Collingbourne#if !SANITIZER_GO 43126337b60b1d551c4744454edd8e5ef3c479e3467Peter Collingbourne } else { 43226337b60b1d551c4744454edd8e5ef3c479e3467Peter Collingbourne static const int kMaxArgv = 2000, kMaxEnvp = 2000; 43326337b60b1d551c4744454edd8e5ef3c479e3467Peter Collingbourne ReadNullSepFileToArray("/proc/self/cmdline", argv, kMaxArgv); 43426337b60b1d551c4744454edd8e5ef3c479e3467Peter Collingbourne ReadNullSepFileToArray("/proc/self/environ", envp, kMaxEnvp); 43526337b60b1d551c4744454edd8e5ef3c479e3467Peter Collingbourne } 43626337b60b1d551c4744454edd8e5ef3c479e3467Peter Collingbourne#endif 437eab061185ec0046d447b298a1dff84f028202a3cEvgeniy Stepanov} 438eab061185ec0046d447b298a1dff84f028202a3cEvgeniy Stepanov 439eab061185ec0046d447b298a1dff84f028202a3cEvgeniy Stepanovvoid ReExec() { 44023709c9ad9ac7c45de288f5260403426bf932db7Peter Collingbourne char **argv, **envp; 441eab061185ec0046d447b298a1dff84f028202a3cEvgeniy Stepanov GetArgsAndEnv(&argv, &envp); 4429578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne uptr rv = internal_execve("/proc/self/exe", argv, envp); 4439578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne int rverrno; 4449578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne CHECK_EQ(internal_iserror(rv, &rverrno), true); 4459578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne Printf("execve failed, errno %d\n", rverrno); 446f35eae83757946decb312deab3f0fe155fe5d580Evgeniy Stepanov Die(); 447d7e5bb4043adf4756e6f8cfe0f5a3165b185474dAlexey Samsonov} 448d7e5bb4043adf4756e6f8cfe0f5a3165b185474dAlexey Samsonov 449f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukovenum MutexState { 450f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov MtxUnlocked = 0, 451f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov MtxLocked = 1, 452f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov MtxSleeping = 2 453f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov}; 454f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov 45593af5948d3e0c5bdc396f432dd0ae782f499c449Alexey SamsonovBlockingMutex::BlockingMutex() { 45693af5948d3e0c5bdc396f432dd0ae782f499c449Alexey Samsonov internal_memset(this, 0, sizeof(*this)); 45793af5948d3e0c5bdc396f432dd0ae782f499c449Alexey Samsonov} 45893af5948d3e0c5bdc396f432dd0ae782f499c449Alexey Samsonov 459f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukovvoid BlockingMutex::Lock() { 46086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines CHECK_EQ(owner_, 0); 461f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov atomic_uint32_t *m = reinterpret_cast<atomic_uint32_t *>(&opaque_storage_); 462f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov if (atomic_exchange(m, MtxLocked, memory_order_acquire) == MtxUnlocked) 463f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov return; 4642d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines while (atomic_exchange(m, MtxSleeping, memory_order_acquire) != MtxUnlocked) { 4652d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#if SANITIZER_FREEBSD 4662d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines _umtx_op(m, UMTX_OP_WAIT_UINT, MtxSleeping, 0, 0); 4672d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#else 4682d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines internal_syscall(SYSCALL(futex), (uptr)m, FUTEX_WAIT, MtxSleeping, 0, 0, 0); 4692d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#endif 4702d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines } 471f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov} 472f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov 473f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukovvoid BlockingMutex::Unlock() { 474f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov atomic_uint32_t *m = reinterpret_cast<atomic_uint32_t *>(&opaque_storage_); 475f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov u32 v = atomic_exchange(m, MtxUnlocked, memory_order_relaxed); 47648526014de78e21f7ed027a60670016bc7f5d292Dmitry Vyukov CHECK_NE(v, MtxUnlocked); 4772d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines if (v == MtxSleeping) { 4782d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#if SANITIZER_FREEBSD 4792d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines _umtx_op(m, UMTX_OP_WAKE, 1, 0, 0); 4802d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#else 4812d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines internal_syscall(SYSCALL(futex), (uptr)m, FUTEX_WAKE, 1, 0, 0, 0); 4822d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#endif 4832d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines } 484f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov} 485f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov 486ce700979f644c790c2d9d80f5cc2a1ada0380284Alexey Samsonovvoid BlockingMutex::CheckLocked() { 487ce700979f644c790c2d9d80f5cc2a1ada0380284Alexey Samsonov atomic_uint32_t *m = reinterpret_cast<atomic_uint32_t *>(&opaque_storage_); 488ce700979f644c790c2d9d80f5cc2a1ada0380284Alexey Samsonov CHECK_NE(MtxUnlocked, atomic_load(m, memory_order_relaxed)); 489ce700979f644c790c2d9d80f5cc2a1ada0380284Alexey Samsonov} 490ce700979f644c790c2d9d80f5cc2a1ada0380284Alexey Samsonov 4916fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany// ----------------- sanitizer_linux.h 4926fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany// The actual size of this structure is specified by d_reclen. 4936fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany// Note that getdents64 uses a different structure format. We only provide the 4946fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany// 32-bit syscall here. 4956fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryanystruct linux_dirent { 4962d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#if SANITIZER_X32 4972d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines u64 d_ino; 4982d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines u64 d_off; 4992d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#else 5006fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany unsigned long d_ino; 5016fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany unsigned long d_off; 5022d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#endif 5036fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany unsigned short d_reclen; 5046fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany char d_name[256]; 5056fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany}; 5066fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany 5076fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany// Syscall wrappers. 5089578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourneuptr internal_ptrace(int request, int pid, void *addr, void *data) { 5092d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines return internal_syscall(SYSCALL(ptrace), request, pid, (uptr)addr, 5102d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines (uptr)data); 5119578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne} 5129578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne 5139578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourneuptr internal_waitpid(int pid, int *status, int options) { 5142d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines return internal_syscall(SYSCALL(wait4), pid, (uptr)status, options, 515e041c6024b3ebf1365c0f99732fc69c607577571Kostya Serebryany 0 /* rusage */); 5166fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany} 5176fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany 5189578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourneuptr internal_getpid() { 5192d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines return internal_syscall(SYSCALL(getpid)); 5206fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany} 5216fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany 5229578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourneuptr internal_getppid() { 5232d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines return internal_syscall(SYSCALL(getppid)); 5246fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany} 5256fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany 5269578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourneuptr internal_getdents(fd_t fd, struct linux_dirent *dirp, unsigned int count) { 5272d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#if SANITIZER_USES_CANONICAL_LINUX_SYSCALLS 5282d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines return internal_syscall(SYSCALL(getdents64), fd, (uptr)dirp, count); 5292d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#else 5302d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines return internal_syscall(SYSCALL(getdents), fd, (uptr)dirp, count); 5312d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#endif 5326fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany} 5336fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany 5349578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourneuptr internal_lseek(fd_t fd, OFF_T offset, int whence) { 5352d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines return internal_syscall(SYSCALL(lseek), fd, offset, whence); 5366fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany} 5376fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany 5382d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#if SANITIZER_LINUX 5399578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourneuptr internal_prctl(int option, uptr arg2, uptr arg3, uptr arg4, uptr arg5) { 5402d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines return internal_syscall(SYSCALL(prctl), option, arg2, arg3, arg4, arg5); 5416fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany} 5422d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#endif 5436fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany 5449578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourneuptr internal_sigaltstack(const struct sigaltstack *ss, 5456fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany struct sigaltstack *oss) { 5462d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines return internal_syscall(SYSCALL(sigaltstack), (uptr)ss, (uptr)oss); 5472d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines} 5482d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines 5492d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesint internal_fork() { 5502d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#if SANITIZER_USES_CANONICAL_LINUX_SYSCALLS 5512d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines return internal_syscall(SYSCALL(clone), SIGCHLD, 0); 5522d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#else 5532d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines return internal_syscall(SYSCALL(fork)); 5542d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#endif 5556fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany} 5566fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany 5572d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#if SANITIZER_LINUX 5587c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar#define SA_RESTORER 0x04000000 5592d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines// Doesn't set sa_restorer, use with caution (see below). 5602d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesint internal_sigaction_norestorer(int signum, const void *act, void *oldact) { 5612d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines __sanitizer_kernel_sigaction_t k_act, k_oldact; 5622d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines internal_memset(&k_act, 0, sizeof(__sanitizer_kernel_sigaction_t)); 5632d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines internal_memset(&k_oldact, 0, sizeof(__sanitizer_kernel_sigaction_t)); 5646d1862363c88c183b0ed7740fca876342cf0474bStephen Hines const __sanitizer_sigaction *u_act = (const __sanitizer_sigaction *)act; 5652d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines __sanitizer_sigaction *u_oldact = (__sanitizer_sigaction *)oldact; 5662d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines if (u_act) { 5672d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines k_act.handler = u_act->handler; 5682d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines k_act.sigaction = u_act->sigaction; 5692d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines internal_memcpy(&k_act.sa_mask, &u_act->sa_mask, 5702d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines sizeof(__sanitizer_kernel_sigset_t)); 5717c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar // Without SA_RESTORER kernel ignores the calls (probably returns EINVAL). 5727c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar k_act.sa_flags = u_act->sa_flags | SA_RESTORER; 5732d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines // FIXME: most often sa_restorer is unset, however the kernel requires it 5742d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines // to point to a valid signal restorer that calls the rt_sigreturn syscall. 5752d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines // If sa_restorer passed to the kernel is NULL, the program may crash upon 5762d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines // signal delivery or fail to unwind the stack in the signal handler. 5772d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines // libc implementation of sigaction() passes its own restorer to 5782d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines // rt_sigaction, so we need to do the same (we'll need to reimplement the 5792d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines // restorers; for x86_64 the restorer address can be obtained from 5802d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines // oldact->sa_restorer upon a call to sigaction(xxx, NULL, oldact). 5812d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines k_act.sa_restorer = u_act->sa_restorer; 5822d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines } 5832d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines 5842d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines uptr result = internal_syscall(SYSCALL(rt_sigaction), (uptr)signum, 5852d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines (uptr)(u_act ? &k_act : NULL), 5862d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines (uptr)(u_oldact ? &k_oldact : NULL), 5872d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines (uptr)sizeof(__sanitizer_kernel_sigset_t)); 5882d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines 5892d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines if ((result == 0) && u_oldact) { 5902d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines u_oldact->handler = k_oldact.handler; 5912d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines u_oldact->sigaction = k_oldact.sigaction; 5922d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines internal_memcpy(&u_oldact->sa_mask, &k_oldact.sa_mask, 5932d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines sizeof(__sanitizer_kernel_sigset_t)); 5942d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines u_oldact->sa_flags = k_oldact.sa_flags; 5952d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines u_oldact->sa_restorer = k_oldact.sa_restorer; 5962d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines } 5972d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines return result; 5980f7a2acb3326a5900d1a1339ebf959b14b372e0dDmitry Vyukov} 5992d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#endif // SANITIZER_LINUX 6000f7a2acb3326a5900d1a1339ebf959b14b372e0dDmitry Vyukov 6012d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesuptr internal_sigprocmask(int how, __sanitizer_sigset_t *set, 6022d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines __sanitizer_sigset_t *oldset) { 6032d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#if SANITIZER_FREEBSD 6042d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines return internal_syscall(SYSCALL(sigprocmask), how, set, oldset); 6052d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#else 6062d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines __sanitizer_kernel_sigset_t *k_set = (__sanitizer_kernel_sigset_t *)set; 6072d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines __sanitizer_kernel_sigset_t *k_oldset = (__sanitizer_kernel_sigset_t *)oldset; 6082d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines return internal_syscall(SYSCALL(rt_sigprocmask), (uptr)how, 6092d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines (uptr)&k_set->sig[0], (uptr)&k_oldset->sig[0], 6102d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines sizeof(__sanitizer_kernel_sigset_t)); 6112d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#endif 6120f7a2acb3326a5900d1a1339ebf959b14b372e0dDmitry Vyukov} 6130f7a2acb3326a5900d1a1339ebf959b14b372e0dDmitry Vyukov 6142d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesvoid internal_sigfillset(__sanitizer_sigset_t *set) { 6150f7a2acb3326a5900d1a1339ebf959b14b372e0dDmitry Vyukov internal_memset(set, 0xff, sizeof(*set)); 6160f7a2acb3326a5900d1a1339ebf959b14b372e0dDmitry Vyukov} 6170f7a2acb3326a5900d1a1339ebf959b14b372e0dDmitry Vyukov 6182d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#if SANITIZER_LINUX 6192d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesvoid internal_sigdelset(__sanitizer_sigset_t *set, int signum) { 6200f7a2acb3326a5900d1a1339ebf959b14b372e0dDmitry Vyukov signum -= 1; 6210f7a2acb3326a5900d1a1339ebf959b14b372e0dDmitry Vyukov CHECK_GE(signum, 0); 6220f7a2acb3326a5900d1a1339ebf959b14b372e0dDmitry Vyukov CHECK_LT(signum, sizeof(*set) * 8); 6232d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines __sanitizer_kernel_sigset_t *k_set = (__sanitizer_kernel_sigset_t *)set; 6242d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines const uptr idx = signum / (sizeof(k_set->sig[0]) * 8); 6252d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines const uptr bit = signum % (sizeof(k_set->sig[0]) * 8); 6262d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines k_set->sig[idx] &= ~(1 << bit); 6270f7a2acb3326a5900d1a1339ebf959b14b372e0dDmitry Vyukov} 6282d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#endif // SANITIZER_LINUX 6290f7a2acb3326a5900d1a1339ebf959b14b372e0dDmitry Vyukov 6306fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany// ThreadLister implementation. 6316fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya SerebryanyThreadLister::ThreadLister(int pid) 6326fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany : pid_(pid), 6336fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany descriptor_(-1), 63410f3ab775088bec69dd9e7b611f9b4e152f629bcAlexey Samsonov buffer_(4096), 6356fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany error_(true), 63610f3ab775088bec69dd9e7b611f9b4e152f629bcAlexey Samsonov entry_((struct linux_dirent *)buffer_.data()), 6376fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany bytes_read_(0) { 6386fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany char task_directory_path[80]; 6396fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany internal_snprintf(task_directory_path, sizeof(task_directory_path), 6406fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany "/proc/%d/task/", pid); 6419578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne uptr openrv = internal_open(task_directory_path, O_RDONLY | O_DIRECTORY); 6429578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne if (internal_iserror(openrv)) { 6436fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany error_ = true; 6446fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany Report("Can't open /proc/%d/task for reading.\n", pid); 6456fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany } else { 6466fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany error_ = false; 6479578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne descriptor_ = openrv; 6486fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany } 6496fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany} 6506fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany 6516fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryanyint ThreadLister::GetNextTID() { 6526fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany int tid = -1; 6536fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany do { 6546fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany if (error_) 6556fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany return -1; 6566fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany if ((char *)entry_ >= &buffer_[bytes_read_] && !GetDirectoryEntries()) 6576fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany return -1; 6586fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany if (entry_->d_ino != 0 && entry_->d_name[0] >= '0' && 6596fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany entry_->d_name[0] <= '9') { 6606fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany // Found a valid tid. 6616fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany tid = (int)internal_atoll(entry_->d_name); 6626fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany } 6636fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany entry_ = (struct linux_dirent *)(((char *)entry_) + entry_->d_reclen); 6646fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany } while (tid < 0); 6656fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany return tid; 6666fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany} 6676fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany 6686fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryanyvoid ThreadLister::Reset() { 6696fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany if (error_ || descriptor_ < 0) 6706fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany return; 6716fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany internal_lseek(descriptor_, 0, SEEK_SET); 6726fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany} 6736fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany 6746fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya SerebryanyThreadLister::~ThreadLister() { 6756fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany if (descriptor_ >= 0) 6766fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany internal_close(descriptor_); 6776fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany} 6786fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany 6796fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryanybool ThreadLister::error() { return error_; } 6806fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany 6816fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryanybool ThreadLister::GetDirectoryEntries() { 6826fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany CHECK_GE(descriptor_, 0); 6836fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany CHECK_NE(error_, true); 6846fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany bytes_read_ = internal_getdents(descriptor_, 68510f3ab775088bec69dd9e7b611f9b4e152f629bcAlexey Samsonov (struct linux_dirent *)buffer_.data(), 68610f3ab775088bec69dd9e7b611f9b4e152f629bcAlexey Samsonov buffer_.size()); 6879578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne if (internal_iserror(bytes_read_)) { 6886fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany Report("Can't read directory entries from /proc/%d/task.\n", pid_); 6896fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany error_ = true; 6906fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany return false; 6916fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany } else if (bytes_read_ == 0) { 6926fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany return false; 6936fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany } 69410f3ab775088bec69dd9e7b611f9b4e152f629bcAlexey Samsonov entry_ = (struct linux_dirent *)buffer_.data(); 6956fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany return true; 6966fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany} 6976fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany 6984df343a31cf57c309cf102b9aef870458318f579Peter Collingbourneuptr GetPageSize() { 6992d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#if SANITIZER_LINUX && (defined(__x86_64__) || defined(__i386__)) 7004df343a31cf57c309cf102b9aef870458318f579Peter Collingbourne return EXEC_PAGESIZE; 701a8bc34e420d27c47560b0742cec295e40b0f430eKostya Serebryany#else 702a8bc34e420d27c47560b0742cec295e40b0f430eKostya Serebryany return sysconf(_SC_PAGESIZE); // EXEC_PAGESIZE may not be trustworthy. 703a8bc34e420d27c47560b0742cec295e40b0f430eKostya Serebryany#endif 7044df343a31cf57c309cf102b9aef870458318f579Peter Collingbourne} 7054df343a31cf57c309cf102b9aef870458318f579Peter Collingbourne 7067847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonovstatic char proc_self_exe_cache_str[kMaxPathLength]; 7077847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonovstatic uptr proc_self_exe_cache_len = 0; 7087847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov 7097847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonovuptr ReadBinaryName(/*out*/char *buf, uptr buf_len) { 7106a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines if (proc_self_exe_cache_len > 0) { 7116a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines // If available, use the cached module name. 7126a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines uptr module_name_len = 7136a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines internal_snprintf(buf, buf_len, "%s", proc_self_exe_cache_str); 7146a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines CHECK_LT(module_name_len, buf_len); 7156a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines return module_name_len; 7166a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines } 7176a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines#if SANITIZER_FREEBSD 7186a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines const int Mib[4] = { CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, -1 }; 7196a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines size_t Size = buf_len; 7206a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines bool IsErr = (sysctl(Mib, 4, buf, &Size, NULL, 0) != 0); 7216a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines int readlink_error = IsErr ? errno : 0; 7226a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines uptr module_name_len = Size; 7236a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines#else 7247847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov uptr module_name_len = internal_readlink( 7257847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov "/proc/self/exe", buf, buf_len); 7267847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov int readlink_error; 7276a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines bool IsErr = internal_iserror(module_name_len, &readlink_error); 7286a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines#endif 7296a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines if (IsErr) { 7306a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines // We can't read /proc/self/exe for some reason, assume the name of the 7316a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines // binary is unknown. 7326a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines Report("WARNING: readlink(\"/proc/self/exe\") failed with errno %d, " 7336a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines "some stack frames may not be symbolized\n", readlink_error); 7346a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines module_name_len = internal_snprintf(buf, buf_len, "/proc/self/exe"); 7357847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov CHECK_LT(module_name_len, buf_len); 7367847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov } 7377847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov return module_name_len; 7387847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov} 7397847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov 7407847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonovvoid CacheBinaryName() { 7417847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov if (!proc_self_exe_cache_len) { 7427847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov proc_self_exe_cache_len = 7437847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov ReadBinaryName(proc_self_exe_cache_str, kMaxPathLength); 7447847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov } 7457847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov} 7467847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov 7473de0086409d143a612a54a7a0ed809e286656188Sergey Matveev// Match full names of the form /path/to/base_name{-,.}* 7483de0086409d143a612a54a7a0ed809e286656188Sergey Matveevbool LibraryNameIs(const char *full_name, const char *base_name) { 7493de0086409d143a612a54a7a0ed809e286656188Sergey Matveev const char *name = full_name; 7503de0086409d143a612a54a7a0ed809e286656188Sergey Matveev // Strip path. 7513de0086409d143a612a54a7a0ed809e286656188Sergey Matveev while (*name != '\0') name++; 7523de0086409d143a612a54a7a0ed809e286656188Sergey Matveev while (name > full_name && *name != '/') name--; 7533de0086409d143a612a54a7a0ed809e286656188Sergey Matveev if (*name == '/') name++; 7543de0086409d143a612a54a7a0ed809e286656188Sergey Matveev uptr base_name_length = internal_strlen(base_name); 7553de0086409d143a612a54a7a0ed809e286656188Sergey Matveev if (internal_strncmp(name, base_name, base_name_length)) return false; 7563de0086409d143a612a54a7a0ed809e286656188Sergey Matveev return (name[base_name_length] == '-' || name[base_name_length] == '.'); 7573de0086409d143a612a54a7a0ed809e286656188Sergey Matveev} 7583de0086409d143a612a54a7a0ed809e286656188Sergey Matveev 759d054abef27369471e154ec5693949538c2fdffd9Evgeniy Stepanov#if !SANITIZER_ANDROID 7602e75ac983cb233daa1abfa35fb33d2bafffe2ab1Peter Collingbourne// Call cb for each region mapped by map. 7612e75ac983cb233daa1abfa35fb33d2bafffe2ab1Peter Collingbournevoid ForEachMappedRegion(link_map *map, void (*cb)(const void *, uptr)) { 76286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines CHECK_NE(map, nullptr); 7632d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#if !SANITIZER_FREEBSD 7642e75ac983cb233daa1abfa35fb33d2bafffe2ab1Peter Collingbourne typedef ElfW(Phdr) Elf_Phdr; 7652e75ac983cb233daa1abfa35fb33d2bafffe2ab1Peter Collingbourne typedef ElfW(Ehdr) Elf_Ehdr; 7662d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#endif // !SANITIZER_FREEBSD 7672e75ac983cb233daa1abfa35fb33d2bafffe2ab1Peter Collingbourne char *base = (char *)map->l_addr; 7682e75ac983cb233daa1abfa35fb33d2bafffe2ab1Peter Collingbourne Elf_Ehdr *ehdr = (Elf_Ehdr *)base; 7692e75ac983cb233daa1abfa35fb33d2bafffe2ab1Peter Collingbourne char *phdrs = base + ehdr->e_phoff; 7702e75ac983cb233daa1abfa35fb33d2bafffe2ab1Peter Collingbourne char *phdrs_end = phdrs + ehdr->e_phnum * ehdr->e_phentsize; 7712e75ac983cb233daa1abfa35fb33d2bafffe2ab1Peter Collingbourne 7722e75ac983cb233daa1abfa35fb33d2bafffe2ab1Peter Collingbourne // Find the segment with the minimum base so we can "relocate" the p_vaddr 7732e75ac983cb233daa1abfa35fb33d2bafffe2ab1Peter Collingbourne // fields. Typically ET_DYN objects (DSOs) have base of zero and ET_EXEC 7742e75ac983cb233daa1abfa35fb33d2bafffe2ab1Peter Collingbourne // objects have a non-zero base. 775f50b0fc601aea71d9fb22f01a11c7e206c666edcPeter Collingbourne uptr preferred_base = (uptr)-1; 7762e75ac983cb233daa1abfa35fb33d2bafffe2ab1Peter Collingbourne for (char *iter = phdrs; iter != phdrs_end; iter += ehdr->e_phentsize) { 7772e75ac983cb233daa1abfa35fb33d2bafffe2ab1Peter Collingbourne Elf_Phdr *phdr = (Elf_Phdr *)iter; 7782e75ac983cb233daa1abfa35fb33d2bafffe2ab1Peter Collingbourne if (phdr->p_type == PT_LOAD && preferred_base > (uptr)phdr->p_vaddr) 7792e75ac983cb233daa1abfa35fb33d2bafffe2ab1Peter Collingbourne preferred_base = (uptr)phdr->p_vaddr; 7802e75ac983cb233daa1abfa35fb33d2bafffe2ab1Peter Collingbourne } 7812e75ac983cb233daa1abfa35fb33d2bafffe2ab1Peter Collingbourne 7822e75ac983cb233daa1abfa35fb33d2bafffe2ab1Peter Collingbourne // Compute the delta from the real base to get a relocation delta. 7832e75ac983cb233daa1abfa35fb33d2bafffe2ab1Peter Collingbourne sptr delta = (uptr)base - preferred_base; 7842e75ac983cb233daa1abfa35fb33d2bafffe2ab1Peter Collingbourne // Now we can figure out what the loader really mapped. 7852e75ac983cb233daa1abfa35fb33d2bafffe2ab1Peter Collingbourne for (char *iter = phdrs; iter != phdrs_end; iter += ehdr->e_phentsize) { 7862e75ac983cb233daa1abfa35fb33d2bafffe2ab1Peter Collingbourne Elf_Phdr *phdr = (Elf_Phdr *)iter; 7872e75ac983cb233daa1abfa35fb33d2bafffe2ab1Peter Collingbourne if (phdr->p_type == PT_LOAD) { 7882e75ac983cb233daa1abfa35fb33d2bafffe2ab1Peter Collingbourne uptr seg_start = phdr->p_vaddr + delta; 7892e75ac983cb233daa1abfa35fb33d2bafffe2ab1Peter Collingbourne uptr seg_end = seg_start + phdr->p_memsz; 7902e75ac983cb233daa1abfa35fb33d2bafffe2ab1Peter Collingbourne // None of these values are aligned. We consider the ragged edges of the 7912e75ac983cb233daa1abfa35fb33d2bafffe2ab1Peter Collingbourne // load command as defined, since they are mapped from the file. 7922e75ac983cb233daa1abfa35fb33d2bafffe2ab1Peter Collingbourne seg_start = RoundDownTo(seg_start, GetPageSizeCached()); 7932e75ac983cb233daa1abfa35fb33d2bafffe2ab1Peter Collingbourne seg_end = RoundUpTo(seg_end, GetPageSizeCached()); 7942e75ac983cb233daa1abfa35fb33d2bafffe2ab1Peter Collingbourne cb((void *)seg_start, seg_end - seg_start); 7952e75ac983cb233daa1abfa35fb33d2bafffe2ab1Peter Collingbourne } 7962e75ac983cb233daa1abfa35fb33d2bafffe2ab1Peter Collingbourne } 7972e75ac983cb233daa1abfa35fb33d2bafffe2ab1Peter Collingbourne} 798d054abef27369471e154ec5693949538c2fdffd9Evgeniy Stepanov#endif 7992e75ac983cb233daa1abfa35fb33d2bafffe2ab1Peter Collingbourne 8002d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#if defined(__x86_64__) && SANITIZER_LINUX 801cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev// We cannot use glibc's clone wrapper, because it messes with the child 802cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev// task's TLS. It writes the PID and TID of the child task to its thread 803cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev// descriptor, but in our case the child task shares the thread descriptor with 804cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev// the parent (because we don't know how to allocate a new thread 805cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev// descriptor to keep glibc happy). So the stock version of clone(), when 806cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev// used with CLONE_VM, would end up corrupting the parent's thread descriptor. 807cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveevuptr internal_clone(int (*fn)(void *), void *child_stack, int flags, void *arg, 808cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev int *parent_tidptr, void *newtls, int *child_tidptr) { 809cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev long long res; 810cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev if (!fn || !child_stack) 811cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev return -EINVAL; 812cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev CHECK_EQ(0, (uptr)child_stack % 16); 813e041c6024b3ebf1365c0f99732fc69c607577571Kostya Serebryany child_stack = (char *)child_stack - 2 * sizeof(unsigned long long); 814e041c6024b3ebf1365c0f99732fc69c607577571Kostya Serebryany ((unsigned long long *)child_stack)[0] = (uptr)fn; 815e041c6024b3ebf1365c0f99732fc69c607577571Kostya Serebryany ((unsigned long long *)child_stack)[1] = (uptr)arg; 816e041c6024b3ebf1365c0f99732fc69c607577571Kostya Serebryany register void *r8 __asm__("r8") = newtls; 817e041c6024b3ebf1365c0f99732fc69c607577571Kostya Serebryany register int *r10 __asm__("r10") = child_tidptr; 818cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev __asm__ __volatile__( 8192d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines /* %rax = syscall(%rax = SYSCALL(clone), 820cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev * %rdi = flags, 821cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev * %rsi = child_stack, 822cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev * %rdx = parent_tidptr, 823cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev * %r8 = new_tls, 824cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev * %r10 = child_tidptr) 825cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev */ 826cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev "syscall\n" 827cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev 828cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev /* if (%rax != 0) 829cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev * return; 830cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev */ 831cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev "testq %%rax,%%rax\n" 832cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev "jnz 1f\n" 833cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev 834cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev /* In the child. Terminate unwind chain. */ 835497ae56316cd05a0d539e0d6e065bbaee254aca3Sergey Matveev // XXX: We should also terminate the CFI unwind chain 836497ae56316cd05a0d539e0d6e065bbaee254aca3Sergey Matveev // here. Unfortunately clang 3.2 doesn't support the 837497ae56316cd05a0d539e0d6e065bbaee254aca3Sergey Matveev // necessary CFI directives, so we skip that part. 838cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev "xorq %%rbp,%%rbp\n" 839cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev 840cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev /* Call "fn(arg)". */ 841cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev "popq %%rax\n" 842cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev "popq %%rdi\n" 843cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev "call *%%rax\n" 844cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev 845cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev /* Call _exit(%rax). */ 846cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev "movq %%rax,%%rdi\n" 847cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev "movq %2,%%rax\n" 848cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev "syscall\n" 849cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev 850cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev /* Return to parent. */ 851cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev "1:\n" 852cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev : "=a" (res) 8532d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines : "a"(SYSCALL(clone)), "i"(SYSCALL(exit)), 854cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev "S"(child_stack), 855cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev "D"(flags), 856cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev "d"(parent_tidptr), 857e041c6024b3ebf1365c0f99732fc69c607577571Kostya Serebryany "r"(r8), 858e041c6024b3ebf1365c0f99732fc69c607577571Kostya Serebryany "r"(r10) 859e041c6024b3ebf1365c0f99732fc69c607577571Kostya Serebryany : "rsp", "memory", "r11", "rcx"); 860cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev return res; 861cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev} 86286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines#elif defined(__mips__) 86386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines// TODO(sagarthakur): clone function is to be rewritten in assembly. 86486277eb844c4983c81de62d7c050e92fe7155788Stephen Hinesuptr internal_clone(int (*fn)(void *), void *child_stack, int flags, void *arg, 86586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines int *parent_tidptr, void *newtls, int *child_tidptr) { 86686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines return clone(fn, child_stack, flags, arg, parent_tidptr, 86786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines newtls, child_tidptr); 86886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines} 8692d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#endif // defined(__x86_64__) && SANITIZER_LINUX 8702d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines 8712d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#if SANITIZER_ANDROID 872aafc5c8d620e24104f1ca340d97286b15a5cec90Evgeniy Stepanovstatic atomic_uint8_t android_log_initialized; 873aafc5c8d620e24104f1ca340d97286b15a5cec90Evgeniy Stepanov 874aafc5c8d620e24104f1ca340d97286b15a5cec90Evgeniy Stepanovvoid AndroidLogInit() { 875aafc5c8d620e24104f1ca340d97286b15a5cec90Evgeniy Stepanov atomic_store(&android_log_initialized, 1, memory_order_release); 876aafc5c8d620e24104f1ca340d97286b15a5cec90Evgeniy Stepanov} 8772d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines// This thing is not, strictly speaking, async signal safe, but it does not seem 8782d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines// to cause any issues. Alternative is writing to log devices directly, but 8792d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines// their location and message format might change in the future, so we'd really 8802d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines// like to avoid that. 8812d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesvoid AndroidLogWrite(const char *buffer) { 882aafc5c8d620e24104f1ca340d97286b15a5cec90Evgeniy Stepanov if (!atomic_load(&android_log_initialized, memory_order_acquire)) 883aafc5c8d620e24104f1ca340d97286b15a5cec90Evgeniy Stepanov return; 884aafc5c8d620e24104f1ca340d97286b15a5cec90Evgeniy Stepanov 8852d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines char *copy = internal_strdup(buffer); 8862d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines char *p = copy; 8872d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines char *q; 8882d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines // __android_log_write has an implicit message length limit. 8892d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines // Print one line at a time. 8902d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines do { 8912d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines q = internal_strchr(p, '\n'); 8922d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines if (q) *q = '\0'; 8932d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines __android_log_write(ANDROID_LOG_INFO, NULL, p); 8942d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines if (q) p = q + 1; 8952d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines } while (q); 8962d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines InternalFree(copy); 8972d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines} 8982d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines 8992d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesvoid GetExtraActivationFlags(char *buf, uptr size) { 9002d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines CHECK(size > PROP_VALUE_MAX); 9012d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines __system_property_get("asan.options", buf); 9022d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines} 9032d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#endif 9042d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines 9052d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesbool IsDeadlySignal(int signum) { 90686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines return (signum == SIGSEGV || signum == SIGBUS) && common_flags()->handle_segv; 90786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines} 90886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines 90986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines#ifndef SANITIZER_GO 91086277eb844c4983c81de62d7c050e92fe7155788Stephen Hinesvoid *internal_start_thread(void(*func)(void *arg), void *arg) { 91186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines // Start the thread with signals blocked, otherwise it can steal user signals. 91286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines __sanitizer_sigset_t set, old; 91386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines internal_sigfillset(&set); 91486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines internal_sigprocmask(SIG_SETMASK, &set, &old); 91586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines void *th; 91686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines real_pthread_create(&th, 0, (void*(*)(void *arg))func, arg); 91786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines internal_sigprocmask(SIG_SETMASK, &old, 0); 91886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines return th; 9192d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines} 9202d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines 92186277eb844c4983c81de62d7c050e92fe7155788Stephen Hinesvoid internal_join_thread(void *th) { 92286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines real_pthread_join(th, 0); 92386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines} 92486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines#else 92586277eb844c4983c81de62d7c050e92fe7155788Stephen Hinesvoid *internal_start_thread(void (*func)(void *), void *arg) { return 0; } 92686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines 92786277eb844c4983c81de62d7c050e92fe7155788Stephen Hinesvoid internal_join_thread(void *th) {} 92886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines#endif 92986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines 9307c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainarvoid GetPcSpBp(void *context, uptr *pc, uptr *sp, uptr *bp) { 9317c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar#if defined(__arm__) 9327c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar ucontext_t *ucontext = (ucontext_t*)context; 9337c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar *pc = ucontext->uc_mcontext.arm_pc; 9347c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar *bp = ucontext->uc_mcontext.arm_fp; 9357c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar *sp = ucontext->uc_mcontext.arm_sp; 9367c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar#elif defined(__aarch64__) 9377c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar ucontext_t *ucontext = (ucontext_t*)context; 9387c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar *pc = ucontext->uc_mcontext.pc; 9397c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar *bp = ucontext->uc_mcontext.regs[29]; 9407c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar *sp = ucontext->uc_mcontext.sp; 9417c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar#elif defined(__hppa__) 9427c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar ucontext_t *ucontext = (ucontext_t*)context; 9437c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar *pc = ucontext->uc_mcontext.sc_iaoq[0]; 9447c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar /* GCC uses %r3 whenever a frame pointer is needed. */ 9457c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar *bp = ucontext->uc_mcontext.sc_gr[3]; 9467c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar *sp = ucontext->uc_mcontext.sc_gr[30]; 9477c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar#elif defined(__x86_64__) 9487c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar# if SANITIZER_FREEBSD 9497c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar ucontext_t *ucontext = (ucontext_t*)context; 9507c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar *pc = ucontext->uc_mcontext.mc_rip; 9517c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar *bp = ucontext->uc_mcontext.mc_rbp; 9527c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar *sp = ucontext->uc_mcontext.mc_rsp; 9537c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar# else 9547c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar ucontext_t *ucontext = (ucontext_t*)context; 9557c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar *pc = ucontext->uc_mcontext.gregs[REG_RIP]; 9567c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar *bp = ucontext->uc_mcontext.gregs[REG_RBP]; 9577c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar *sp = ucontext->uc_mcontext.gregs[REG_RSP]; 9587c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar# endif 9597c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar#elif defined(__i386__) 9607c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar# if SANITIZER_FREEBSD 9617c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar ucontext_t *ucontext = (ucontext_t*)context; 9627c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar *pc = ucontext->uc_mcontext.mc_eip; 9637c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar *bp = ucontext->uc_mcontext.mc_ebp; 9647c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar *sp = ucontext->uc_mcontext.mc_esp; 9657c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar# else 9667c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar ucontext_t *ucontext = (ucontext_t*)context; 9677c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar *pc = ucontext->uc_mcontext.gregs[REG_EIP]; 9687c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar *bp = ucontext->uc_mcontext.gregs[REG_EBP]; 9697c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar *sp = ucontext->uc_mcontext.gregs[REG_ESP]; 9707c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar# endif 9717c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar#elif defined(__powerpc__) || defined(__powerpc64__) 9727c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar ucontext_t *ucontext = (ucontext_t*)context; 9737c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar *pc = ucontext->uc_mcontext.regs->nip; 9747c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar *sp = ucontext->uc_mcontext.regs->gpr[PT_R1]; 9757c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar // The powerpc{,64}-linux ABIs do not specify r31 as the frame 9767c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar // pointer, but GCC always uses r31 when we need a frame pointer. 9777c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar *bp = ucontext->uc_mcontext.regs->gpr[PT_R31]; 9787c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar#elif defined(__sparc__) 9797c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar ucontext_t *ucontext = (ucontext_t*)context; 9807c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar uptr *stk_ptr; 9817c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar# if defined (__arch64__) 9827c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar *pc = ucontext->uc_mcontext.mc_gregs[MC_PC]; 9837c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar *sp = ucontext->uc_mcontext.mc_gregs[MC_O6]; 9847c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar stk_ptr = (uptr *) (*sp + 2047); 9857c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar *bp = stk_ptr[15]; 9867c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar# else 9877c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar *pc = ucontext->uc_mcontext.gregs[REG_PC]; 9887c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar *sp = ucontext->uc_mcontext.gregs[REG_O6]; 9897c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar stk_ptr = (uptr *) *sp; 9907c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar *bp = stk_ptr[15]; 9917c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar# endif 9927c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar#elif defined(__mips__) 9937c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar ucontext_t *ucontext = (ucontext_t*)context; 9947c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar *pc = ucontext->uc_mcontext.gregs[31]; 9957c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar *bp = ucontext->uc_mcontext.gregs[30]; 9967c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar *sp = ucontext->uc_mcontext.gregs[29]; 9977c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar#else 9987c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar# error "Unsupported arch" 9997c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar#endif 10007c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar} 10017c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar 1002ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov} // namespace __sanitizer 1003ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov 10042d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#endif // SANITIZER_FREEBSD || SANITIZER_LINUX 1005