sanitizer_linux.cc revision 9578a3ecfc35a264ede1135033398e2a77a6cad6
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" 1624e13723f8477d8c42ab8b2a7f4f69fc089842f1Evgeniy Stepanov#if SANITIZER_LINUX 17ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov 186895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov#include "sanitizer_common.h" 1994b5036ee6ba866e1702848855b6d687d1e70afaAlexey Samsonov#include "sanitizer_internal_defs.h" 20ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov#include "sanitizer_libc.h" 216fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany#include "sanitizer_linux.h" 2293da8b6a5e0ed2ca621897504c5d06449b3d7077Alexander Potapenko#include "sanitizer_mutex.h" 23a68633fb76208137ccb807914df52758ee5ca6f0Alexey Samsonov#include "sanitizer_placement_new.h" 246895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov#include "sanitizer_procmaps.h" 25a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryany#include "sanitizer_stacktrace.h" 26ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov 2735f1c1f7d4f18097c9eca2ce5f6c34a686707829Sergey Matveev#ifdef __x86_64__ 2824323de08fa8850712d56621bff29dbbbd0285a9Sergey Matveev#include <asm/prctl.h> 2935f1c1f7d4f18097c9eca2ce5f6c34a686707829Sergey Matveev#endif 30b114ed83859d8d4964ac2284584733bcd2acf4f6Evgeniy Stepanov#include <dlfcn.h> 3135a7faf1fbfac678136e79d53824672dafb7d13eAlexey Samsonov#include <errno.h> 32c5d465136b911bf925f2a631e2b79f1c03e8a1b0Alexey Samsonov#include <fcntl.h> 33e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov#include <pthread.h> 340969bcf2c936126b1f6e636b978aade8fc207437Alexey Samsonov#include <sched.h> 35ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov#include <sys/mman.h> 366fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany#include <sys/ptrace.h> 37e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov#include <sys/resource.h> 38c5d465136b911bf925f2a631e2b79f1c03e8a1b0Alexey Samsonov#include <sys/stat.h> 39ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov#include <sys/syscall.h> 40e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov#include <sys/time.h> 41ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov#include <sys/types.h> 42fa5c41eddf77a3614da0f62044ebf741d86aeab7Dmitry Vyukov#include <sys/prctl.h> 43ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov#include <unistd.h> 44a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryany#include <unwind.h> 4535a7faf1fbfac678136e79d53824672dafb7d13eAlexey Samsonov 4624e13723f8477d8c42ab8b2a7f4f69fc089842f1Evgeniy Stepanov#if !SANITIZER_ANDROID 4735a7faf1fbfac678136e79d53824672dafb7d13eAlexey Samsonov#include <sys/signal.h> 4835a7faf1fbfac678136e79d53824672dafb7d13eAlexey Samsonov#endif 49fa5c41eddf77a3614da0f62044ebf741d86aeab7Dmitry Vyukov 504bebe7bab966c82f0a8952f797ed3d490624dc62Dmitry Vyukov// <linux/time.h> 514bebe7bab966c82f0a8952f797ed3d490624dc62Dmitry Vyukovstruct kernel_timeval { 524bebe7bab966c82f0a8952f797ed3d490624dc62Dmitry Vyukov long tv_sec; 534bebe7bab966c82f0a8952f797ed3d490624dc62Dmitry Vyukov long tv_usec; 544bebe7bab966c82f0a8952f797ed3d490624dc62Dmitry Vyukov}; 554bebe7bab966c82f0a8952f797ed3d490624dc62Dmitry Vyukov 56fa5c41eddf77a3614da0f62044ebf741d86aeab7Dmitry Vyukov// <linux/futex.h> is broken on some linux distributions. 57fa5c41eddf77a3614da0f62044ebf741d86aeab7Dmitry Vyukovconst int FUTEX_WAIT = 0; 58fa5c41eddf77a3614da0f62044ebf741d86aeab7Dmitry Vyukovconst int FUTEX_WAKE = 1; 59ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov 609d0dbbaf33e5c2fe280f141e30be497d62b703a8Kostya Serebryany// Are we using 32-bit or 64-bit syscalls? 615af39e50366f1aacbebc284f572f08ad1ad07357Kostya Serebryany// x32 (which defines __x86_64__) has SANITIZER_WORDSIZE == 32 6208bfe4988de493dd3e61d02759b3f19c42f8fb78Kostya Serebryany// but it still needs to use 64-bit syscalls. 635af39e50366f1aacbebc284f572f08ad1ad07357Kostya Serebryany#if defined(__x86_64__) || SANITIZER_WORDSIZE == 64 649d0dbbaf33e5c2fe280f141e30be497d62b703a8Kostya Serebryany# define SANITIZER_LINUX_USES_64BIT_SYSCALLS 1 659d0dbbaf33e5c2fe280f141e30be497d62b703a8Kostya Serebryany#else 669d0dbbaf33e5c2fe280f141e30be497d62b703a8Kostya Serebryany# define SANITIZER_LINUX_USES_64BIT_SYSCALLS 0 679d0dbbaf33e5c2fe280f141e30be497d62b703a8Kostya Serebryany#endif 689d0dbbaf33e5c2fe280f141e30be497d62b703a8Kostya Serebryany 6935f1c1f7d4f18097c9eca2ce5f6c34a686707829Sergey Matveev#ifdef __x86_64__ 7024323de08fa8850712d56621bff29dbbbd0285a9Sergey Matveevextern "C" int arch_prctl(int code, __sanitizer::uptr *addr); 7135f1c1f7d4f18097c9eca2ce5f6c34a686707829Sergey Matveev#endif 7224323de08fa8850712d56621bff29dbbbd0285a9Sergey Matveev 73ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonovnamespace __sanitizer { 74ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov 759578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne#ifdef __x86_64__ 769578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne#include "sanitizer_syscall_linux_x86_64.inc" 779578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne#else 789578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne#include "sanitizer_syscall_generic.inc" 799578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne#endif 809578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne 81e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov// --------------- sanitizer_libc.h 829578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourneuptr internal_mmap(void *addr, uptr length, int prot, int flags, 83ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov int fd, u64 offset) { 849d0dbbaf33e5c2fe280f141e30be497d62b703a8Kostya Serebryany#if SANITIZER_LINUX_USES_64BIT_SYSCALLS 859578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne return internal_syscall(__NR_mmap, addr, length, prot, flags, fd, offset); 86ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov#else 879578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne return internal_syscall(__NR_mmap2, addr, length, prot, flags, fd, offset); 88ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov#endif 89ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov} 90ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov 919578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourneuptr internal_munmap(void *addr, uptr length) { 929578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne return internal_syscall(__NR_munmap, addr, length); 931f11d31faa5ed89b74f7d543b1182fe8de198be5Alexey Samsonov} 941f11d31faa5ed89b74f7d543b1182fe8de198be5Alexey Samsonov 959578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourneuptr internal_close(fd_t fd) { 969578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne return internal_syscall(__NR_close, fd); 97a56aefd2e01940fcf88d1426f9de3d5e4b1ee203Alexey Samsonov} 98a56aefd2e01940fcf88d1426f9de3d5e4b1ee203Alexey Samsonov 999578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourneuptr internal_open(const char *filename, int flags) { 1009578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne return internal_syscall(__NR_open, filename, flags); 101ee7cc4454421a176d23442382afd9a01d36e7ad4Alexey Samsonov} 102ee7cc4454421a176d23442382afd9a01d36e7ad4Alexey Samsonov 1039578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourneuptr internal_open(const char *filename, int flags, u32 mode) { 1049578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne return internal_syscall(__NR_open, filename, flags, mode); 105ee7cc4454421a176d23442382afd9a01d36e7ad4Alexey Samsonov} 106ee7cc4454421a176d23442382afd9a01d36e7ad4Alexey Samsonov 1079578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourneuptr OpenFile(const char *filename, bool write) { 108ee7cc4454421a176d23442382afd9a01d36e7ad4Alexey Samsonov return internal_open(filename, 1099b8a9c1b1ce4659457178ff4c0838ac1b35ca9dcKostya Serebryany write ? O_WRONLY | O_CREAT /*| O_CLOEXEC*/ : O_RDONLY, 0660); 110c5d465136b911bf925f2a631e2b79f1c03e8a1b0Alexey Samsonov} 111c5d465136b911bf925f2a631e2b79f1c03e8a1b0Alexey Samsonov 112a56aefd2e01940fcf88d1426f9de3d5e4b1ee203Alexey Samsonovuptr internal_read(fd_t fd, void *buf, uptr count) { 1133334e12d33261cb8f211f2f49f28ddfa027a40c3Evgeniy Stepanov sptr res; 1149578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne HANDLE_EINTR(res, (sptr)internal_syscall(__NR_read, fd, buf, count)); 1153334e12d33261cb8f211f2f49f28ddfa027a40c3Evgeniy Stepanov return res; 116a56aefd2e01940fcf88d1426f9de3d5e4b1ee203Alexey Samsonov} 117a56aefd2e01940fcf88d1426f9de3d5e4b1ee203Alexey Samsonov 118a56aefd2e01940fcf88d1426f9de3d5e4b1ee203Alexey Samsonovuptr internal_write(fd_t fd, const void *buf, uptr count) { 1193334e12d33261cb8f211f2f49f28ddfa027a40c3Evgeniy Stepanov sptr res; 1209578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne HANDLE_EINTR(res, (sptr)internal_syscall(__NR_write, fd, buf, count)); 1213334e12d33261cb8f211f2f49f28ddfa027a40c3Evgeniy Stepanov return res; 122a56aefd2e01940fcf88d1426f9de3d5e4b1ee203Alexey Samsonov} 123a56aefd2e01940fcf88d1426f9de3d5e4b1ee203Alexey Samsonov 1242be3a283939d4fc14ad86f6cd8be34b1468f22baEvgeniy Stepanov#if !SANITIZER_LINUX_USES_64BIT_SYSCALLS 1252be3a283939d4fc14ad86f6cd8be34b1468f22baEvgeniy Stepanovstatic void stat64_to_stat(struct stat64 *in, struct stat *out) { 1262be3a283939d4fc14ad86f6cd8be34b1468f22baEvgeniy Stepanov internal_memset(out, 0, sizeof(*out)); 1272be3a283939d4fc14ad86f6cd8be34b1468f22baEvgeniy Stepanov out->st_dev = in->st_dev; 1282be3a283939d4fc14ad86f6cd8be34b1468f22baEvgeniy Stepanov out->st_ino = in->st_ino; 1292be3a283939d4fc14ad86f6cd8be34b1468f22baEvgeniy Stepanov out->st_mode = in->st_mode; 1302be3a283939d4fc14ad86f6cd8be34b1468f22baEvgeniy Stepanov out->st_nlink = in->st_nlink; 1312be3a283939d4fc14ad86f6cd8be34b1468f22baEvgeniy Stepanov out->st_uid = in->st_uid; 1322be3a283939d4fc14ad86f6cd8be34b1468f22baEvgeniy Stepanov out->st_gid = in->st_gid; 1332be3a283939d4fc14ad86f6cd8be34b1468f22baEvgeniy Stepanov out->st_rdev = in->st_rdev; 1342be3a283939d4fc14ad86f6cd8be34b1468f22baEvgeniy Stepanov out->st_size = in->st_size; 1352be3a283939d4fc14ad86f6cd8be34b1468f22baEvgeniy Stepanov out->st_blksize = in->st_blksize; 1362be3a283939d4fc14ad86f6cd8be34b1468f22baEvgeniy Stepanov out->st_blocks = in->st_blocks; 1372be3a283939d4fc14ad86f6cd8be34b1468f22baEvgeniy Stepanov out->st_atime = in->st_atime; 1382be3a283939d4fc14ad86f6cd8be34b1468f22baEvgeniy Stepanov out->st_mtime = in->st_mtime; 1392be3a283939d4fc14ad86f6cd8be34b1468f22baEvgeniy Stepanov out->st_ctime = in->st_ctime; 1402be3a283939d4fc14ad86f6cd8be34b1468f22baEvgeniy Stepanov out->st_ino = in->st_ino; 1412be3a283939d4fc14ad86f6cd8be34b1468f22baEvgeniy Stepanov} 1422be3a283939d4fc14ad86f6cd8be34b1468f22baEvgeniy Stepanov#endif 1432be3a283939d4fc14ad86f6cd8be34b1468f22baEvgeniy Stepanov 1449578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourneuptr internal_stat(const char *path, void *buf) { 1454c9317a7b61e136f832d2ede70f557963fd46bceAlexey Samsonov#if SANITIZER_LINUX_USES_64BIT_SYSCALLS 1469578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne return internal_syscall(__NR_stat, path, buf); 1474c9317a7b61e136f832d2ede70f557963fd46bceAlexey Samsonov#else 1482be3a283939d4fc14ad86f6cd8be34b1468f22baEvgeniy Stepanov struct stat64 buf64; 1499578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne int res = internal_syscall(__NR_stat64, path, &buf64); 1502be3a283939d4fc14ad86f6cd8be34b1468f22baEvgeniy Stepanov stat64_to_stat(&buf64, (struct stat *)buf); 1512be3a283939d4fc14ad86f6cd8be34b1468f22baEvgeniy Stepanov return res; 1524c9317a7b61e136f832d2ede70f557963fd46bceAlexey Samsonov#endif 1534c9317a7b61e136f832d2ede70f557963fd46bceAlexey Samsonov} 1544c9317a7b61e136f832d2ede70f557963fd46bceAlexey Samsonov 1559578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourneuptr internal_lstat(const char *path, void *buf) { 1564c9317a7b61e136f832d2ede70f557963fd46bceAlexey Samsonov#if SANITIZER_LINUX_USES_64BIT_SYSCALLS 1579578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne return internal_syscall(__NR_lstat, path, buf); 1584c9317a7b61e136f832d2ede70f557963fd46bceAlexey Samsonov#else 1592be3a283939d4fc14ad86f6cd8be34b1468f22baEvgeniy Stepanov struct stat64 buf64; 1609578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne int res = internal_syscall(__NR_lstat64, path, &buf64); 1612be3a283939d4fc14ad86f6cd8be34b1468f22baEvgeniy Stepanov stat64_to_stat(&buf64, (struct stat *)buf); 1622be3a283939d4fc14ad86f6cd8be34b1468f22baEvgeniy Stepanov return res; 1634c9317a7b61e136f832d2ede70f557963fd46bceAlexey Samsonov#endif 1644c9317a7b61e136f832d2ede70f557963fd46bceAlexey Samsonov} 1654c9317a7b61e136f832d2ede70f557963fd46bceAlexey Samsonov 1669578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourneuptr internal_fstat(fd_t fd, void *buf) { 1674c9317a7b61e136f832d2ede70f557963fd46bceAlexey Samsonov#if SANITIZER_LINUX_USES_64BIT_SYSCALLS 1689578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne return internal_syscall(__NR_fstat, fd, buf); 1694c9317a7b61e136f832d2ede70f557963fd46bceAlexey Samsonov#else 1702be3a283939d4fc14ad86f6cd8be34b1468f22baEvgeniy Stepanov struct stat64 buf64; 1719578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne int res = internal_syscall(__NR_fstat64, fd, &buf64); 1722be3a283939d4fc14ad86f6cd8be34b1468f22baEvgeniy Stepanov stat64_to_stat(&buf64, (struct stat *)buf); 1732be3a283939d4fc14ad86f6cd8be34b1468f22baEvgeniy Stepanov return res; 1744c9317a7b61e136f832d2ede70f557963fd46bceAlexey Samsonov#endif 1754c9317a7b61e136f832d2ede70f557963fd46bceAlexey Samsonov} 1764c9317a7b61e136f832d2ede70f557963fd46bceAlexey Samsonov 1778e820fcf7aafeb8101322182d742fcf99255d972Alexey Samsonovuptr internal_filesize(fd_t fd) { 178a68633fb76208137ccb807914df52758ee5ca6f0Alexey Samsonov struct stat st; 1794c9317a7b61e136f832d2ede70f557963fd46bceAlexey Samsonov if (internal_fstat(fd, &st)) 1804c9317a7b61e136f832d2ede70f557963fd46bceAlexey Samsonov return -1; 1818e820fcf7aafeb8101322182d742fcf99255d972Alexey Samsonov return (uptr)st.st_size; 1828e820fcf7aafeb8101322182d742fcf99255d972Alexey Samsonov} 1838e820fcf7aafeb8101322182d742fcf99255d972Alexey Samsonov 1849578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourneuptr internal_dup2(int oldfd, int newfd) { 1859578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne return internal_syscall(__NR_dup2, oldfd, newfd); 1868e820fcf7aafeb8101322182d742fcf99255d972Alexey Samsonov} 1878e820fcf7aafeb8101322182d742fcf99255d972Alexey Samsonov 188d1b8f588d6b712b6ff2b3d58c73d71614f520122Alexey Samsonovuptr internal_readlink(const char *path, char *buf, uptr bufsize) { 1899578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne return internal_syscall(__NR_readlink, path, buf, bufsize); 190d1b8f588d6b712b6ff2b3d58c73d71614f520122Alexey Samsonov} 191d1b8f588d6b712b6ff2b3d58c73d71614f520122Alexey Samsonov 1929578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourneuptr internal_unlink(const char *path) { 1939578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne return internal_syscall(__NR_unlink, path); 1946d6ab9eeea4a99370d7ab18ce80eb96091e2cf3fDmitry Vyukov} 1956d6ab9eeea4a99370d7ab18ce80eb96091e2cf3fDmitry Vyukov 1969578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourneuptr internal_sched_yield() { 1979578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne return internal_syscall(__NR_sched_yield); 1980969bcf2c936126b1f6e636b978aade8fc207437Alexey Samsonov} 1990969bcf2c936126b1f6e636b978aade8fc207437Alexey Samsonov 200f882247088952deed954a19d745c2dd8871e2035Alexey Samsonovvoid internal__exit(int exitcode) { 2019578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne internal_syscall(__NR_exit_group, exitcode); 202f882247088952deed954a19d745c2dd8871e2035Alexey Samsonov Die(); // Unreachable. 203f882247088952deed954a19d745c2dd8871e2035Alexey Samsonov} 204f882247088952deed954a19d745c2dd8871e2035Alexey Samsonov 2059578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourneuptr internal_execve(const char *filename, char *const argv[], 2069578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne char *const envp[]) { 2079578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne return internal_syscall(__NR_execve, filename, argv, envp); 2089578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne} 2099578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne 210e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov// ----------------- sanitizer_common.h 21193b4cafd631b661b4b612ccdc0938f7f1e1c86d6Alexey Samsonovbool FileExists(const char *filename) { 21293b4cafd631b661b4b612ccdc0938f7f1e1c86d6Alexey Samsonov struct stat st; 2132be3a283939d4fc14ad86f6cd8be34b1468f22baEvgeniy Stepanov if (internal_stat(filename, &st)) 21493b4cafd631b661b4b612ccdc0938f7f1e1c86d6Alexey Samsonov return false; 21593b4cafd631b661b4b612ccdc0938f7f1e1c86d6Alexey Samsonov // Sanity check: filename is a regular file. 21693b4cafd631b661b4b612ccdc0938f7f1e1c86d6Alexey Samsonov return S_ISREG(st.st_mode); 21793b4cafd631b661b4b612ccdc0938f7f1e1c86d6Alexey Samsonov} 21893b4cafd631b661b4b612ccdc0938f7f1e1c86d6Alexey Samsonov 219e0023f74ea88efee329f68391b70f8adc6b21617Dmitry Vyukovuptr GetTid() { 2209578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne return internal_syscall(__NR_gettid); 221e0023f74ea88efee329f68391b70f8adc6b21617Dmitry Vyukov} 222e0023f74ea88efee329f68391b70f8adc6b21617Dmitry Vyukov 2234bebe7bab966c82f0a8952f797ed3d490624dc62Dmitry Vyukovu64 NanoTime() { 2244bebe7bab966c82f0a8952f797ed3d490624dc62Dmitry Vyukov kernel_timeval tv; 2259578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne internal_syscall(__NR_gettimeofday, &tv, 0); 2264bebe7bab966c82f0a8952f797ed3d490624dc62Dmitry Vyukov return (u64)tv.tv_sec * 1000*1000*1000 + tv.tv_usec * 1000; 2274bebe7bab966c82f0a8952f797ed3d490624dc62Dmitry Vyukov} 2284bebe7bab966c82f0a8952f797ed3d490624dc62Dmitry Vyukov 229ed996f79710f532bf231537e44d5c8c9c9d57e8dAlexey Samsonovvoid GetThreadStackTopAndBottom(bool at_initialization, uptr *stack_top, 230e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov uptr *stack_bottom) { 231e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov static const uptr kMaxThreadStackSize = 256 * (1 << 20); // 256M 232e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov CHECK(stack_top); 233e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov CHECK(stack_bottom); 234ed996f79710f532bf231537e44d5c8c9c9d57e8dAlexey Samsonov if (at_initialization) { 235e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov // This is the main thread. Libpthread may not be initialized yet. 236e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov struct rlimit rl; 2376985085c4860bf945358f227ddba26511ae770e9Kostya Serebryany CHECK_EQ(getrlimit(RLIMIT_STACK, &rl), 0); 238e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov 239e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov // Find the mapping that contains a stack variable. 2409ae2883d88dd28b9c5dc862107e6e6d12a35926eAlexander Potapenko MemoryMappingLayout proc_maps(/*cache_enabled*/true); 241e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov uptr start, end, offset; 242e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov uptr prev_end = 0; 24345717c9d5e39a434749ae10509111f9df1b2cdf4Alexey Samsonov while (proc_maps.Next(&start, &end, &offset, 0, 0, /* protection */0)) { 244e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov if ((uptr)&rl < end) 245e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov break; 246e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov prev_end = end; 247e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov } 248e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov CHECK((uptr)&rl >= start && (uptr)&rl < end); 249e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov 250e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov // Get stacksize from rlimit, but clip it so that it does not overlap 251e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov // with other mappings. 252e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov uptr stacksize = rl.rlim_cur; 253e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov if (stacksize > end - prev_end) 254e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov stacksize = end - prev_end; 255e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov // When running with unlimited stack size, we still want to set some limit. 256e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov // The unlimited stack size is caused by 'ulimit -s unlimited'. 257e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov // Also, for some reason, GNU make spawns subprocesses with unlimited stack. 258e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov if (stacksize > kMaxThreadStackSize) 259e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov stacksize = kMaxThreadStackSize; 260e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov *stack_top = end; 261e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov *stack_bottom = end - stacksize; 262e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov return; 263e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov } 264e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov pthread_attr_t attr; 2656985085c4860bf945358f227ddba26511ae770e9Kostya Serebryany CHECK_EQ(pthread_getattr_np(pthread_self(), &attr), 0); 266e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov uptr stacksize = 0; 267e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov void *stackaddr = 0; 268e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov pthread_attr_getstack(&attr, &stackaddr, (size_t*)&stacksize); 269e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov pthread_attr_destroy(&attr); 270e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov 271e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov *stack_top = (uptr)stackaddr + stacksize; 272e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov *stack_bottom = (uptr)stackaddr; 273e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov CHECK(stacksize < kMaxThreadStackSize); // Sanity check. 274e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov} 275e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov 2763dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov// Like getenv, but reads env directly from /proc and does not use libc. 2773dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov// This function should be called first inside __asan_init. 2783dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonovconst char *GetEnv(const char *name) { 2793dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov static char *environ; 2803dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov static uptr len; 2813dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov static bool inited; 2823dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov if (!inited) { 2833dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov inited = true; 2843dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov uptr environ_size; 2853dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov len = ReadFileToBuffer("/proc/self/environ", 2863dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov &environ, &environ_size, 1 << 26); 2873dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov } 2883dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov if (!environ || len == 0) return 0; 2893dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov uptr namelen = internal_strlen(name); 2903dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov const char *p = environ; 2913dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov while (*p != '\0') { // will happen at the \0\0 that terminates the buffer 2923dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov // proc file has the format NAME=value\0NAME=value\0NAME=value\0... 2933dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov const char* endp = 2943dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov (char*)internal_memchr(p, '\0', len - (p - environ)); 2953dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov if (endp == 0) // this entry isn't NUL terminated 2963dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov return 0; 2973dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov else if (!internal_memcmp(p, name, namelen) && p[namelen] == '=') // Match. 2983dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov return p + namelen + 1; // point after = 2993dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov p = endp + 1; 3003dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov } 3013dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov return 0; // Not found. 3023dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov} 3033dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov 304ff7c14f911463db91b574533f62eb847a2e08b1cAlexey Samsonov// Does not compile for Go because dlsym() requires -ldl 305ff7c14f911463db91b574533f62eb847a2e08b1cAlexey Samsonov#ifndef SANITIZER_GO 306ff7c14f911463db91b574533f62eb847a2e08b1cAlexey Samsonovbool SetEnv(const char *name, const char *value) { 307ff7c14f911463db91b574533f62eb847a2e08b1cAlexey Samsonov void *f = dlsym(RTLD_NEXT, "setenv"); 308ff7c14f911463db91b574533f62eb847a2e08b1cAlexey Samsonov if (f == 0) 309ff7c14f911463db91b574533f62eb847a2e08b1cAlexey Samsonov return false; 310ff7c14f911463db91b574533f62eb847a2e08b1cAlexey Samsonov typedef int(*setenv_ft)(const char *name, const char *value, int overwrite); 311ff7c14f911463db91b574533f62eb847a2e08b1cAlexey Samsonov setenv_ft setenv_f; 312ff7c14f911463db91b574533f62eb847a2e08b1cAlexey Samsonov CHECK_EQ(sizeof(setenv_f), sizeof(f)); 313ff7c14f911463db91b574533f62eb847a2e08b1cAlexey Samsonov internal_memcpy(&setenv_f, &f, sizeof(f)); 314ff7c14f911463db91b574533f62eb847a2e08b1cAlexey Samsonov return setenv_f(name, value, 1) == 0; 315ff7c14f911463db91b574533f62eb847a2e08b1cAlexey Samsonov} 316ff7c14f911463db91b574533f62eb847a2e08b1cAlexey Samsonov#endif 317ff7c14f911463db91b574533f62eb847a2e08b1cAlexey Samsonov 318eab061185ec0046d447b298a1dff84f028202a3cEvgeniy Stepanov#ifdef __GLIBC__ 319eab061185ec0046d447b298a1dff84f028202a3cEvgeniy Stepanov 320eab061185ec0046d447b298a1dff84f028202a3cEvgeniy Stepanovextern "C" { 321eab061185ec0046d447b298a1dff84f028202a3cEvgeniy Stepanov extern void *__libc_stack_end; 322eab061185ec0046d447b298a1dff84f028202a3cEvgeniy Stepanov} 323eab061185ec0046d447b298a1dff84f028202a3cEvgeniy Stepanov 324eab061185ec0046d447b298a1dff84f028202a3cEvgeniy Stepanovstatic void GetArgsAndEnv(char ***argv, char ***envp) { 325eab061185ec0046d447b298a1dff84f028202a3cEvgeniy Stepanov uptr *stack_end = (uptr *)__libc_stack_end; 326eab061185ec0046d447b298a1dff84f028202a3cEvgeniy Stepanov int argc = *stack_end; 327eab061185ec0046d447b298a1dff84f028202a3cEvgeniy Stepanov *argv = (char**)(stack_end + 1); 328eab061185ec0046d447b298a1dff84f028202a3cEvgeniy Stepanov *envp = (char**)(stack_end + argc + 2); 329eab061185ec0046d447b298a1dff84f028202a3cEvgeniy Stepanov} 330eab061185ec0046d447b298a1dff84f028202a3cEvgeniy Stepanov 331eab061185ec0046d447b298a1dff84f028202a3cEvgeniy Stepanov#else // __GLIBC__ 332eab061185ec0046d447b298a1dff84f028202a3cEvgeniy Stepanov 33323709c9ad9ac7c45de288f5260403426bf932db7Peter Collingbournestatic void ReadNullSepFileToArray(const char *path, char ***arr, 33423709c9ad9ac7c45de288f5260403426bf932db7Peter Collingbourne int arr_size) { 33523709c9ad9ac7c45de288f5260403426bf932db7Peter Collingbourne char *buff; 336d7e5bb4043adf4756e6f8cfe0f5a3165b185474dAlexey Samsonov uptr buff_size = 0; 33723709c9ad9ac7c45de288f5260403426bf932db7Peter Collingbourne *arr = (char **)MmapOrDie(arr_size * sizeof(char *), "NullSepFileArray"); 33823709c9ad9ac7c45de288f5260403426bf932db7Peter Collingbourne ReadFileToBuffer(path, &buff, &buff_size, 1024 * 1024); 33923709c9ad9ac7c45de288f5260403426bf932db7Peter Collingbourne (*arr)[0] = buff; 34023709c9ad9ac7c45de288f5260403426bf932db7Peter Collingbourne int count, i; 34123709c9ad9ac7c45de288f5260403426bf932db7Peter Collingbourne for (count = 1, i = 1; ; i++) { 342d7e5bb4043adf4756e6f8cfe0f5a3165b185474dAlexey Samsonov if (buff[i] == 0) { 343d7e5bb4043adf4756e6f8cfe0f5a3165b185474dAlexey Samsonov if (buff[i+1] == 0) break; 34423709c9ad9ac7c45de288f5260403426bf932db7Peter Collingbourne (*arr)[count] = &buff[i+1]; 34523709c9ad9ac7c45de288f5260403426bf932db7Peter Collingbourne CHECK_LE(count, arr_size - 1); // FIXME: make this more flexible. 34623709c9ad9ac7c45de288f5260403426bf932db7Peter Collingbourne count++; 347d7e5bb4043adf4756e6f8cfe0f5a3165b185474dAlexey Samsonov } 348d7e5bb4043adf4756e6f8cfe0f5a3165b185474dAlexey Samsonov } 34923709c9ad9ac7c45de288f5260403426bf932db7Peter Collingbourne (*arr)[count] = 0; 35023709c9ad9ac7c45de288f5260403426bf932db7Peter Collingbourne} 35123709c9ad9ac7c45de288f5260403426bf932db7Peter Collingbourne 352eab061185ec0046d447b298a1dff84f028202a3cEvgeniy Stepanovstatic void GetArgsAndEnv(char ***argv, char ***envp) { 3537b7801d0811e7091240ddbfdcff817791973ef6fEvgeniy Stepanov static const int kMaxArgv = 2000, kMaxEnvp = 2000; 354eab061185ec0046d447b298a1dff84f028202a3cEvgeniy Stepanov ReadNullSepFileToArray("/proc/self/cmdline", argv, kMaxArgv); 355eab061185ec0046d447b298a1dff84f028202a3cEvgeniy Stepanov ReadNullSepFileToArray("/proc/self/environ", envp, kMaxEnvp); 356eab061185ec0046d447b298a1dff84f028202a3cEvgeniy Stepanov} 357eab061185ec0046d447b298a1dff84f028202a3cEvgeniy Stepanov 358eab061185ec0046d447b298a1dff84f028202a3cEvgeniy Stepanov#endif // __GLIBC__ 359eab061185ec0046d447b298a1dff84f028202a3cEvgeniy Stepanov 360eab061185ec0046d447b298a1dff84f028202a3cEvgeniy Stepanovvoid ReExec() { 36123709c9ad9ac7c45de288f5260403426bf932db7Peter Collingbourne char **argv, **envp; 362eab061185ec0046d447b298a1dff84f028202a3cEvgeniy Stepanov GetArgsAndEnv(&argv, &envp); 3639578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne uptr rv = internal_execve("/proc/self/exe", argv, envp); 3649578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne int rverrno; 3659578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne CHECK_EQ(internal_iserror(rv, &rverrno), true); 3669578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne Printf("execve failed, errno %d\n", rverrno); 367f35eae83757946decb312deab3f0fe155fe5d580Evgeniy Stepanov Die(); 368d7e5bb4043adf4756e6f8cfe0f5a3165b185474dAlexey Samsonov} 369d7e5bb4043adf4756e6f8cfe0f5a3165b185474dAlexey Samsonov 37025742574510cfb41b97e32f63f107fbb9b328d13Alexander Potapenkovoid PrepareForSandboxing() { 37125742574510cfb41b97e32f63f107fbb9b328d13Alexander Potapenko // Some kinds of sandboxes may forbid filesystem access, so we won't be able 37225742574510cfb41b97e32f63f107fbb9b328d13Alexander Potapenko // to read the file mappings from /proc/self/maps. Luckily, neither the 37325742574510cfb41b97e32f63f107fbb9b328d13Alexander Potapenko // process will be able to load additional libraries, so it's fine to use the 37425742574510cfb41b97e32f63f107fbb9b328d13Alexander Potapenko // cached mappings. 37525742574510cfb41b97e32f63f107fbb9b328d13Alexander Potapenko MemoryMappingLayout::CacheMemoryMappings(); 37625742574510cfb41b97e32f63f107fbb9b328d13Alexander Potapenko} 37725742574510cfb41b97e32f63f107fbb9b328d13Alexander Potapenko 378e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov// ----------------- sanitizer_procmaps.h 379286dd3f8afe6700e5dd9b0bdb7afd23121c98c12Dmitry Vyukov// Linker initialized. 380286dd3f8afe6700e5dd9b0bdb7afd23121c98c12Dmitry VyukovProcSelfMapsBuff MemoryMappingLayout::cached_proc_self_maps_; 381ad91267d45fef531c1082ab7974e4cc78aba5280Alexander PotapenkoStaticSpinMutex MemoryMappingLayout::cache_lock_; // Linker initialized. 38293da8b6a5e0ed2ca621897504c5d06449b3d7077Alexander Potapenko 3839ae2883d88dd28b9c5dc862107e6e6d12a35926eAlexander PotapenkoMemoryMappingLayout::MemoryMappingLayout(bool cache_enabled) { 384ad91267d45fef531c1082ab7974e4cc78aba5280Alexander Potapenko proc_self_maps_.len = 385ad91267d45fef531c1082ab7974e4cc78aba5280Alexander Potapenko ReadFileToBuffer("/proc/self/maps", &proc_self_maps_.data, 386ad91267d45fef531c1082ab7974e4cc78aba5280Alexander Potapenko &proc_self_maps_.mmaped_size, 1 << 26); 3879ae2883d88dd28b9c5dc862107e6e6d12a35926eAlexander Potapenko if (cache_enabled) { 3889ae2883d88dd28b9c5dc862107e6e6d12a35926eAlexander Potapenko if (proc_self_maps_.mmaped_size == 0) { 3899ae2883d88dd28b9c5dc862107e6e6d12a35926eAlexander Potapenko LoadFromCache(); 3909ae2883d88dd28b9c5dc862107e6e6d12a35926eAlexander Potapenko CHECK_GT(proc_self_maps_.len, 0); 3919ae2883d88dd28b9c5dc862107e6e6d12a35926eAlexander Potapenko } 3929ae2883d88dd28b9c5dc862107e6e6d12a35926eAlexander Potapenko } else { 3939ae2883d88dd28b9c5dc862107e6e6d12a35926eAlexander Potapenko CHECK_GT(proc_self_maps_.mmaped_size, 0); 39493da8b6a5e0ed2ca621897504c5d06449b3d7077Alexander Potapenko } 3956895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov Reset(); 39693da8b6a5e0ed2ca621897504c5d06449b3d7077Alexander Potapenko // FIXME: in the future we may want to cache the mappings on demand only. 3979ae2883d88dd28b9c5dc862107e6e6d12a35926eAlexander Potapenko if (cache_enabled) 3989ae2883d88dd28b9c5dc862107e6e6d12a35926eAlexander Potapenko CacheMemoryMappings(); 3996895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov} 4006895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov 401e1f5dac9296df08ff83ae5fca51ce4da995b55cfAlexey SamsonovMemoryMappingLayout::~MemoryMappingLayout() { 4027385f8b8b8723064910cf9737dc929e90aeac548Alexander Potapenko // Only unmap the buffer if it is different from the cached one. Otherwise 4037385f8b8b8723064910cf9737dc929e90aeac548Alexander Potapenko // it will be unmapped when the cache is refreshed. 4047385f8b8b8723064910cf9737dc929e90aeac548Alexander Potapenko if (proc_self_maps_.data != cached_proc_self_maps_.data) { 4057385f8b8b8723064910cf9737dc929e90aeac548Alexander Potapenko UnmapOrDie(proc_self_maps_.data, proc_self_maps_.mmaped_size); 4067385f8b8b8723064910cf9737dc929e90aeac548Alexander Potapenko } 4076895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov} 4086895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov 409e1f5dac9296df08ff83ae5fca51ce4da995b55cfAlexey Samsonovvoid MemoryMappingLayout::Reset() { 410ad91267d45fef531c1082ab7974e4cc78aba5280Alexander Potapenko current_ = proc_self_maps_.data; 4116895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov} 4126895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov 41393da8b6a5e0ed2ca621897504c5d06449b3d7077Alexander Potapenko// static 41493da8b6a5e0ed2ca621897504c5d06449b3d7077Alexander Potapenkovoid MemoryMappingLayout::CacheMemoryMappings() { 41593da8b6a5e0ed2ca621897504c5d06449b3d7077Alexander Potapenko SpinMutexLock l(&cache_lock_); 41693da8b6a5e0ed2ca621897504c5d06449b3d7077Alexander Potapenko // Don't invalidate the cache if the mappings are unavailable. 417ad91267d45fef531c1082ab7974e4cc78aba5280Alexander Potapenko ProcSelfMapsBuff old_proc_self_maps; 418ad91267d45fef531c1082ab7974e4cc78aba5280Alexander Potapenko old_proc_self_maps = cached_proc_self_maps_; 419ad91267d45fef531c1082ab7974e4cc78aba5280Alexander Potapenko cached_proc_self_maps_.len = 420ad91267d45fef531c1082ab7974e4cc78aba5280Alexander Potapenko ReadFileToBuffer("/proc/self/maps", &cached_proc_self_maps_.data, 421ad91267d45fef531c1082ab7974e4cc78aba5280Alexander Potapenko &cached_proc_self_maps_.mmaped_size, 1 << 26); 422ad91267d45fef531c1082ab7974e4cc78aba5280Alexander Potapenko if (cached_proc_self_maps_.mmaped_size == 0) { 423ad91267d45fef531c1082ab7974e4cc78aba5280Alexander Potapenko cached_proc_self_maps_ = old_proc_self_maps; 42493da8b6a5e0ed2ca621897504c5d06449b3d7077Alexander Potapenko } else { 425ad91267d45fef531c1082ab7974e4cc78aba5280Alexander Potapenko if (old_proc_self_maps.mmaped_size) { 426ad91267d45fef531c1082ab7974e4cc78aba5280Alexander Potapenko UnmapOrDie(old_proc_self_maps.data, 427ad91267d45fef531c1082ab7974e4cc78aba5280Alexander Potapenko old_proc_self_maps.mmaped_size); 42893da8b6a5e0ed2ca621897504c5d06449b3d7077Alexander Potapenko } 42993da8b6a5e0ed2ca621897504c5d06449b3d7077Alexander Potapenko } 43093da8b6a5e0ed2ca621897504c5d06449b3d7077Alexander Potapenko} 43193da8b6a5e0ed2ca621897504c5d06449b3d7077Alexander Potapenko 43293da8b6a5e0ed2ca621897504c5d06449b3d7077Alexander Potapenkovoid MemoryMappingLayout::LoadFromCache() { 43393da8b6a5e0ed2ca621897504c5d06449b3d7077Alexander Potapenko SpinMutexLock l(&cache_lock_); 434ad91267d45fef531c1082ab7974e4cc78aba5280Alexander Potapenko if (cached_proc_self_maps_.data) { 435286dd3f8afe6700e5dd9b0bdb7afd23121c98c12Dmitry Vyukov proc_self_maps_ = cached_proc_self_maps_; 43693da8b6a5e0ed2ca621897504c5d06449b3d7077Alexander Potapenko } 43793da8b6a5e0ed2ca621897504c5d06449b3d7077Alexander Potapenko} 43893da8b6a5e0ed2ca621897504c5d06449b3d7077Alexander Potapenko 439a4e4744778e6b3067f5cf223cf28bb586c1ecf67Kostya Serebryany// Parse a hex value in str and update str. 440a4e4744778e6b3067f5cf223cf28bb586c1ecf67Kostya Serebryanystatic uptr ParseHex(char **str) { 441a4e4744778e6b3067f5cf223cf28bb586c1ecf67Kostya Serebryany uptr x = 0; 442a4e4744778e6b3067f5cf223cf28bb586c1ecf67Kostya Serebryany char *s; 443a4e4744778e6b3067f5cf223cf28bb586c1ecf67Kostya Serebryany for (s = *str; ; s++) { 444a4e4744778e6b3067f5cf223cf28bb586c1ecf67Kostya Serebryany char c = *s; 445a4e4744778e6b3067f5cf223cf28bb586c1ecf67Kostya Serebryany uptr v = 0; 446a4e4744778e6b3067f5cf223cf28bb586c1ecf67Kostya Serebryany if (c >= '0' && c <= '9') 447a4e4744778e6b3067f5cf223cf28bb586c1ecf67Kostya Serebryany v = c - '0'; 448a4e4744778e6b3067f5cf223cf28bb586c1ecf67Kostya Serebryany else if (c >= 'a' && c <= 'f') 449a4e4744778e6b3067f5cf223cf28bb586c1ecf67Kostya Serebryany v = c - 'a' + 10; 450a4e4744778e6b3067f5cf223cf28bb586c1ecf67Kostya Serebryany else if (c >= 'A' && c <= 'F') 451a4e4744778e6b3067f5cf223cf28bb586c1ecf67Kostya Serebryany v = c - 'A' + 10; 452a4e4744778e6b3067f5cf223cf28bb586c1ecf67Kostya Serebryany else 453a4e4744778e6b3067f5cf223cf28bb586c1ecf67Kostya Serebryany break; 454a4e4744778e6b3067f5cf223cf28bb586c1ecf67Kostya Serebryany x = x * 16 + v; 455a4e4744778e6b3067f5cf223cf28bb586c1ecf67Kostya Serebryany } 456a4e4744778e6b3067f5cf223cf28bb586c1ecf67Kostya Serebryany *str = s; 457a4e4744778e6b3067f5cf223cf28bb586c1ecf67Kostya Serebryany return x; 458a4e4744778e6b3067f5cf223cf28bb586c1ecf67Kostya Serebryany} 459a4e4744778e6b3067f5cf223cf28bb586c1ecf67Kostya Serebryany 460ab11e0b10d077945a6e681766b41e12ac6aeb0f0Alexey Samsonovstatic bool IsOneOf(char c, char c1, char c2) { 461a4e4744778e6b3067f5cf223cf28bb586c1ecf67Kostya Serebryany return c == c1 || c == c2; 462a4e4744778e6b3067f5cf223cf28bb586c1ecf67Kostya Serebryany} 463a4e4744778e6b3067f5cf223cf28bb586c1ecf67Kostya Serebryany 464a4e4744778e6b3067f5cf223cf28bb586c1ecf67Kostya Serebryanystatic bool IsDecimal(char c) { 465a4e4744778e6b3067f5cf223cf28bb586c1ecf67Kostya Serebryany return c >= '0' && c <= '9'; 466a4e4744778e6b3067f5cf223cf28bb586c1ecf67Kostya Serebryany} 467a4e4744778e6b3067f5cf223cf28bb586c1ecf67Kostya Serebryany 468e1f5dac9296df08ff83ae5fca51ce4da995b55cfAlexey Samsonovbool MemoryMappingLayout::Next(uptr *start, uptr *end, uptr *offset, 46945717c9d5e39a434749ae10509111f9df1b2cdf4Alexey Samsonov char filename[], uptr filename_size, 47045717c9d5e39a434749ae10509111f9df1b2cdf4Alexey Samsonov uptr *protection) { 471ad91267d45fef531c1082ab7974e4cc78aba5280Alexander Potapenko char *last = proc_self_maps_.data + proc_self_maps_.len; 4726895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov if (current_ >= last) return false; 4736895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov uptr dummy; 4746895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov if (!start) start = &dummy; 4756895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov if (!end) end = &dummy; 4766895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov if (!offset) offset = &dummy; 4776895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov char *next_line = (char*)internal_memchr(current_, '\n', last - current_); 4786895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov if (next_line == 0) 4796895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov next_line = last; 480a4e4744778e6b3067f5cf223cf28bb586c1ecf67Kostya Serebryany // Example: 08048000-08056000 r-xp 00000000 03:0c 64593 /foo/bar 481a4e4744778e6b3067f5cf223cf28bb586c1ecf67Kostya Serebryany *start = ParseHex(¤t_); 482bb8a9511bc748d6a4fd601d713bda584ef7bb772Kostya Serebryany CHECK_EQ(*current_++, '-'); 483a4e4744778e6b3067f5cf223cf28bb586c1ecf67Kostya Serebryany *end = ParseHex(¤t_); 484bb8a9511bc748d6a4fd601d713bda584ef7bb772Kostya Serebryany CHECK_EQ(*current_++, ' '); 48545717c9d5e39a434749ae10509111f9df1b2cdf4Alexey Samsonov uptr local_protection = 0; 486ab11e0b10d077945a6e681766b41e12ac6aeb0f0Alexey Samsonov CHECK(IsOneOf(*current_, '-', 'r')); 48745717c9d5e39a434749ae10509111f9df1b2cdf4Alexey Samsonov if (*current_++ == 'r') 48845717c9d5e39a434749ae10509111f9df1b2cdf4Alexey Samsonov local_protection |= kProtectionRead; 489ab11e0b10d077945a6e681766b41e12ac6aeb0f0Alexey Samsonov CHECK(IsOneOf(*current_, '-', 'w')); 49045717c9d5e39a434749ae10509111f9df1b2cdf4Alexey Samsonov if (*current_++ == 'w') 49145717c9d5e39a434749ae10509111f9df1b2cdf4Alexey Samsonov local_protection |= kProtectionWrite; 492ab11e0b10d077945a6e681766b41e12ac6aeb0f0Alexey Samsonov CHECK(IsOneOf(*current_, '-', 'x')); 49345717c9d5e39a434749ae10509111f9df1b2cdf4Alexey Samsonov if (*current_++ == 'x') 49445717c9d5e39a434749ae10509111f9df1b2cdf4Alexey Samsonov local_protection |= kProtectionExecute; 495ab11e0b10d077945a6e681766b41e12ac6aeb0f0Alexey Samsonov CHECK(IsOneOf(*current_, 's', 'p')); 49645717c9d5e39a434749ae10509111f9df1b2cdf4Alexey Samsonov if (*current_++ == 's') 49745717c9d5e39a434749ae10509111f9df1b2cdf4Alexey Samsonov local_protection |= kProtectionShared; 49845717c9d5e39a434749ae10509111f9df1b2cdf4Alexey Samsonov if (protection) { 49945717c9d5e39a434749ae10509111f9df1b2cdf4Alexey Samsonov *protection = local_protection; 50045717c9d5e39a434749ae10509111f9df1b2cdf4Alexey Samsonov } 501bb8a9511bc748d6a4fd601d713bda584ef7bb772Kostya Serebryany CHECK_EQ(*current_++, ' '); 502a4e4744778e6b3067f5cf223cf28bb586c1ecf67Kostya Serebryany *offset = ParseHex(¤t_); 503bb8a9511bc748d6a4fd601d713bda584ef7bb772Kostya Serebryany CHECK_EQ(*current_++, ' '); 504a4e4744778e6b3067f5cf223cf28bb586c1ecf67Kostya Serebryany ParseHex(¤t_); 505bb8a9511bc748d6a4fd601d713bda584ef7bb772Kostya Serebryany CHECK_EQ(*current_++, ':'); 506a4e4744778e6b3067f5cf223cf28bb586c1ecf67Kostya Serebryany ParseHex(¤t_); 507bb8a9511bc748d6a4fd601d713bda584ef7bb772Kostya Serebryany CHECK_EQ(*current_++, ' '); 508a4e4744778e6b3067f5cf223cf28bb586c1ecf67Kostya Serebryany while (IsDecimal(*current_)) 509a4e4744778e6b3067f5cf223cf28bb586c1ecf67Kostya Serebryany current_++; 510bb8a9511bc748d6a4fd601d713bda584ef7bb772Kostya Serebryany CHECK_EQ(*current_++, ' '); 5116895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov // Skip spaces. 5126895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov while (current_ < next_line && *current_ == ' ') 5136895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov current_++; 5146895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov // Fill in the filename. 5156895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov uptr i = 0; 5166895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov while (current_ < next_line) { 5176895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov if (filename && i < filename_size - 1) 5186895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov filename[i++] = *current_; 5196895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov current_++; 5206895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov } 5216895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov if (filename && i < filename_size) 5226895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov filename[i] = 0; 5236895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov current_ = next_line + 1; 5246895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov return true; 5256895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov} 5266895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov 527e1f5dac9296df08ff83ae5fca51ce4da995b55cfAlexey Samsonov// Gets the object name and the offset by walking MemoryMappingLayout. 528e1f5dac9296df08ff83ae5fca51ce4da995b55cfAlexey Samsonovbool MemoryMappingLayout::GetObjectNameAndOffset(uptr addr, uptr *offset, 529e1f5dac9296df08ff83ae5fca51ce4da995b55cfAlexey Samsonov char filename[], 53045717c9d5e39a434749ae10509111f9df1b2cdf4Alexey Samsonov uptr filename_size, 53145717c9d5e39a434749ae10509111f9df1b2cdf4Alexey Samsonov uptr *protection) { 53245717c9d5e39a434749ae10509111f9df1b2cdf4Alexey Samsonov return IterateForObjectNameAndOffset(addr, offset, filename, filename_size, 53345717c9d5e39a434749ae10509111f9df1b2cdf4Alexey Samsonov protection); 5346895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov} 5356895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov 536dddb18b7be36fe1843c8b98a8d9d7614aef5ce8dKostya Serebryanybool SanitizerSetThreadName(const char *name) { 537b10a5621daa804f3a2b18fbe75d5fed2a4aeadd3Kostya Serebryany#ifdef PR_SET_NAME 5381ec519c604021162de8bdb8d433fbad1c5033200Dmitry Vyukov return 0 == prctl(PR_SET_NAME, (unsigned long)name, 0, 0, 0); // NOLINT 539b10a5621daa804f3a2b18fbe75d5fed2a4aeadd3Kostya Serebryany#else 540b10a5621daa804f3a2b18fbe75d5fed2a4aeadd3Kostya Serebryany return false; 541b10a5621daa804f3a2b18fbe75d5fed2a4aeadd3Kostya Serebryany#endif 542dddb18b7be36fe1843c8b98a8d9d7614aef5ce8dKostya Serebryany} 543dddb18b7be36fe1843c8b98a8d9d7614aef5ce8dKostya Serebryany 544dddb18b7be36fe1843c8b98a8d9d7614aef5ce8dKostya Serebryanybool SanitizerGetThreadName(char *name, int max_len) { 545b10a5621daa804f3a2b18fbe75d5fed2a4aeadd3Kostya Serebryany#ifdef PR_GET_NAME 546dddb18b7be36fe1843c8b98a8d9d7614aef5ce8dKostya Serebryany char buff[17]; 5471ec519c604021162de8bdb8d433fbad1c5033200Dmitry Vyukov if (prctl(PR_GET_NAME, (unsigned long)buff, 0, 0, 0)) // NOLINT 548dddb18b7be36fe1843c8b98a8d9d7614aef5ce8dKostya Serebryany return false; 549dddb18b7be36fe1843c8b98a8d9d7614aef5ce8dKostya Serebryany internal_strncpy(name, buff, max_len); 550dddb18b7be36fe1843c8b98a8d9d7614aef5ce8dKostya Serebryany name[max_len] = 0; 551dddb18b7be36fe1843c8b98a8d9d7614aef5ce8dKostya Serebryany return true; 552b10a5621daa804f3a2b18fbe75d5fed2a4aeadd3Kostya Serebryany#else 553b10a5621daa804f3a2b18fbe75d5fed2a4aeadd3Kostya Serebryany return false; 554b10a5621daa804f3a2b18fbe75d5fed2a4aeadd3Kostya Serebryany#endif 555dddb18b7be36fe1843c8b98a8d9d7614aef5ce8dKostya Serebryany} 556dddb18b7be36fe1843c8b98a8d9d7614aef5ce8dKostya Serebryany 5574fce4495502a3668cc4e99164ffcaea92e534d48Dmitry Vyukov#ifndef SANITIZER_GO 558a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryany//------------------------- SlowUnwindStack ----------------------------------- 559a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryany#ifdef __arm__ 560a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryany#define UNWIND_STOP _URC_END_OF_STACK 561a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryany#define UNWIND_CONTINUE _URC_NO_REASON 562a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryany#else 563a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryany#define UNWIND_STOP _URC_NORMAL_STOP 564a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryany#define UNWIND_CONTINUE _URC_NO_REASON 565a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryany#endif 566a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryany 567a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryanyuptr Unwind_GetIP(struct _Unwind_Context *ctx) { 568a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryany#ifdef __arm__ 569a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryany uptr val; 570a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryany _Unwind_VRS_Result res = _Unwind_VRS_Get(ctx, _UVRSC_CORE, 571a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryany 15 /* r15 = PC */, _UVRSD_UINT32, &val); 572a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryany CHECK(res == _UVRSR_OK && "_Unwind_VRS_Get failed"); 573a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryany // Clear the Thumb bit. 574a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryany return val & ~(uptr)1; 575a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryany#else 576a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryany return _Unwind_GetIP(ctx); 577a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryany#endif 578a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryany} 579a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryany 580a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryany_Unwind_Reason_Code Unwind_Trace(struct _Unwind_Context *ctx, void *param) { 581a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryany StackTrace *b = (StackTrace*)param; 582a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryany CHECK(b->size < b->max_size); 583a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryany uptr pc = Unwind_GetIP(ctx); 584a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryany b->trace[b->size++] = pc; 585a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryany if (b->size == b->max_size) return UNWIND_STOP; 586a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryany return UNWIND_CONTINUE; 587a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryany} 588a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryany 58949d616ec42ab420ce3ebcbe846b21e3729adf5acKostya Serebryanystatic bool MatchPc(uptr cur_pc, uptr trace_pc) { 5905e10443518154a9d68d299ef65a0a99ed42193b7Kostya Serebryany return cur_pc - trace_pc <= 64 || trace_pc - cur_pc <= 64; 59149d616ec42ab420ce3ebcbe846b21e3729adf5acKostya Serebryany} 59249d616ec42ab420ce3ebcbe846b21e3729adf5acKostya Serebryany 59349d616ec42ab420ce3ebcbe846b21e3729adf5acKostya Serebryanyvoid StackTrace::SlowUnwindStack(uptr pc, uptr max_depth) { 594a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryany this->size = 0; 595a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryany this->max_size = max_depth; 596a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryany if (max_depth > 1) { 597a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryany _Unwind_Backtrace(Unwind_Trace, this); 5985e10443518154a9d68d299ef65a0a99ed42193b7Kostya Serebryany // We need to pop a few frames so that pc is on top. 5995e10443518154a9d68d299ef65a0a99ed42193b7Kostya Serebryany // trace[0] belongs to the current function so we always pop it. 60049d616ec42ab420ce3ebcbe846b21e3729adf5acKostya Serebryany int to_pop = 1; 6015e10443518154a9d68d299ef65a0a99ed42193b7Kostya Serebryany /**/ if (size > 1 && MatchPc(pc, trace[1])) to_pop = 1; 6025e10443518154a9d68d299ef65a0a99ed42193b7Kostya Serebryany else if (size > 2 && MatchPc(pc, trace[2])) to_pop = 2; 6035e10443518154a9d68d299ef65a0a99ed42193b7Kostya Serebryany else if (size > 3 && MatchPc(pc, trace[3])) to_pop = 3; 6045e10443518154a9d68d299ef65a0a99ed42193b7Kostya Serebryany else if (size > 4 && MatchPc(pc, trace[4])) to_pop = 4; 6055e10443518154a9d68d299ef65a0a99ed42193b7Kostya Serebryany else if (size > 5 && MatchPc(pc, trace[5])) to_pop = 5; 60649d616ec42ab420ce3ebcbe846b21e3729adf5acKostya Serebryany this->PopStackFrames(to_pop); 607a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryany } 60849d616ec42ab420ce3ebcbe846b21e3729adf5acKostya Serebryany this->trace[0] = pc; 609a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryany} 610a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryany 6114fce4495502a3668cc4e99164ffcaea92e534d48Dmitry Vyukov#endif // #ifndef SANITIZER_GO 6124fce4495502a3668cc4e99164ffcaea92e534d48Dmitry Vyukov 613f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukovenum MutexState { 614f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov MtxUnlocked = 0, 615f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov MtxLocked = 1, 616f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov MtxSleeping = 2 617f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov}; 618f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov 619f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry VyukovBlockingMutex::BlockingMutex(LinkerInitialized) { 620d164ed175a61529589938b3db3cab076a19acf67Dmitry Vyukov CHECK_EQ(owner_, 0); 621f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov} 622f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov 62393af5948d3e0c5bdc396f432dd0ae782f499c449Alexey SamsonovBlockingMutex::BlockingMutex() { 62493af5948d3e0c5bdc396f432dd0ae782f499c449Alexey Samsonov internal_memset(this, 0, sizeof(*this)); 62593af5948d3e0c5bdc396f432dd0ae782f499c449Alexey Samsonov} 62693af5948d3e0c5bdc396f432dd0ae782f499c449Alexey Samsonov 627f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukovvoid BlockingMutex::Lock() { 628f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov atomic_uint32_t *m = reinterpret_cast<atomic_uint32_t *>(&opaque_storage_); 629f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov if (atomic_exchange(m, MtxLocked, memory_order_acquire) == MtxUnlocked) 630f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov return; 631f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov while (atomic_exchange(m, MtxSleeping, memory_order_acquire) != MtxUnlocked) 6329578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne internal_syscall(__NR_futex, m, FUTEX_WAIT, MtxSleeping, 0, 0, 0); 633f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov} 634f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov 635f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukovvoid BlockingMutex::Unlock() { 636f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov atomic_uint32_t *m = reinterpret_cast<atomic_uint32_t *>(&opaque_storage_); 637f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov u32 v = atomic_exchange(m, MtxUnlocked, memory_order_relaxed); 63848526014de78e21f7ed027a60670016bc7f5d292Dmitry Vyukov CHECK_NE(v, MtxUnlocked); 639f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov if (v == MtxSleeping) 6409578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne internal_syscall(__NR_futex, m, FUTEX_WAKE, 1, 0, 0, 0); 641f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov} 642f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov 643ce700979f644c790c2d9d80f5cc2a1ada0380284Alexey Samsonovvoid BlockingMutex::CheckLocked() { 644ce700979f644c790c2d9d80f5cc2a1ada0380284Alexey Samsonov atomic_uint32_t *m = reinterpret_cast<atomic_uint32_t *>(&opaque_storage_); 645ce700979f644c790c2d9d80f5cc2a1ada0380284Alexey Samsonov CHECK_NE(MtxUnlocked, atomic_load(m, memory_order_relaxed)); 646ce700979f644c790c2d9d80f5cc2a1ada0380284Alexey Samsonov} 647ce700979f644c790c2d9d80f5cc2a1ada0380284Alexey Samsonov 6486fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany// ----------------- sanitizer_linux.h 6496fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany// The actual size of this structure is specified by d_reclen. 6506fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany// Note that getdents64 uses a different structure format. We only provide the 6516fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany// 32-bit syscall here. 6526fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryanystruct linux_dirent { 6536fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany unsigned long d_ino; 6546fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany unsigned long d_off; 6556fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany unsigned short d_reclen; 6566fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany char d_name[256]; 6576fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany}; 6586fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany 6596fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany// Syscall wrappers. 6609578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourneuptr internal_ptrace(int request, int pid, void *addr, void *data) { 6619578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne return internal_syscall(__NR_ptrace, request, pid, addr, data); 6629578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne} 6639578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne 6649578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourneuptr internal_waitpid(int pid, int *status, int options) { 6659578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne return internal_syscall(__NR_wait4, pid, status, options, 0 /* rusage */); 6666fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany} 6676fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany 6689578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourneuptr internal_getpid() { 6699578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne return internal_syscall(__NR_getpid); 6706fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany} 6716fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany 6729578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourneuptr internal_getppid() { 6739578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne return internal_syscall(__NR_getppid); 6746fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany} 6756fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany 6769578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourneuptr internal_getdents(fd_t fd, struct linux_dirent *dirp, unsigned int count) { 6779578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne return internal_syscall(__NR_getdents, fd, dirp, count); 6786fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany} 6796fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany 6809578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourneuptr internal_lseek(fd_t fd, OFF_T offset, int whence) { 6819578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne return internal_syscall(__NR_lseek, fd, offset, whence); 6826fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany} 6836fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany 6849578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourneuptr internal_prctl(int option, uptr arg2, uptr arg3, uptr arg4, uptr arg5) { 6859578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne return internal_syscall(__NR_prctl, option, arg2, arg3, arg4, arg5); 6866fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany} 6876fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany 6889578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourneuptr internal_sigaltstack(const struct sigaltstack *ss, 6896fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany struct sigaltstack *oss) { 6909578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne return internal_syscall(__NR_sigaltstack, ss, oss); 6916fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany} 6926fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany 6936fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany// ThreadLister implementation. 6946fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya SerebryanyThreadLister::ThreadLister(int pid) 6956fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany : pid_(pid), 6966fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany descriptor_(-1), 69710f3ab775088bec69dd9e7b611f9b4e152f629bcAlexey Samsonov buffer_(4096), 6986fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany error_(true), 69910f3ab775088bec69dd9e7b611f9b4e152f629bcAlexey Samsonov entry_((struct linux_dirent *)buffer_.data()), 7006fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany bytes_read_(0) { 7016fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany char task_directory_path[80]; 7026fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany internal_snprintf(task_directory_path, sizeof(task_directory_path), 7036fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany "/proc/%d/task/", pid); 7049578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne uptr openrv = internal_open(task_directory_path, O_RDONLY | O_DIRECTORY); 7059578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne if (internal_iserror(openrv)) { 7066fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany error_ = true; 7076fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany Report("Can't open /proc/%d/task for reading.\n", pid); 7086fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany } else { 7096fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany error_ = false; 7109578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne descriptor_ = openrv; 7116fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany } 7126fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany} 7136fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany 7146fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryanyint ThreadLister::GetNextTID() { 7156fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany int tid = -1; 7166fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany do { 7176fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany if (error_) 7186fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany return -1; 7196fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany if ((char *)entry_ >= &buffer_[bytes_read_] && !GetDirectoryEntries()) 7206fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany return -1; 7216fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany if (entry_->d_ino != 0 && entry_->d_name[0] >= '0' && 7226fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany entry_->d_name[0] <= '9') { 7236fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany // Found a valid tid. 7246fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany tid = (int)internal_atoll(entry_->d_name); 7256fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany } 7266fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany entry_ = (struct linux_dirent *)(((char *)entry_) + entry_->d_reclen); 7276fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany } while (tid < 0); 7286fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany return tid; 7296fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany} 7306fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany 7316fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryanyvoid ThreadLister::Reset() { 7326fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany if (error_ || descriptor_ < 0) 7336fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany return; 7346fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany internal_lseek(descriptor_, 0, SEEK_SET); 7356fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany} 7366fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany 7376fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya SerebryanyThreadLister::~ThreadLister() { 7386fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany if (descriptor_ >= 0) 7396fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany internal_close(descriptor_); 7406fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany} 7416fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany 7426fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryanybool ThreadLister::error() { return error_; } 7436fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany 7446fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryanybool ThreadLister::GetDirectoryEntries() { 7456fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany CHECK_GE(descriptor_, 0); 7466fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany CHECK_NE(error_, true); 7476fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany bytes_read_ = internal_getdents(descriptor_, 74810f3ab775088bec69dd9e7b611f9b4e152f629bcAlexey Samsonov (struct linux_dirent *)buffer_.data(), 74910f3ab775088bec69dd9e7b611f9b4e152f629bcAlexey Samsonov buffer_.size()); 7509578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne if (internal_iserror(bytes_read_)) { 7516fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany Report("Can't read directory entries from /proc/%d/task.\n", pid_); 7526fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany error_ = true; 7536fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany return false; 7546fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany } else if (bytes_read_ == 0) { 7556fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany return false; 7566fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany } 75710f3ab775088bec69dd9e7b611f9b4e152f629bcAlexey Samsonov entry_ = (struct linux_dirent *)buffer_.data(); 7586fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany return true; 7596fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany} 7606fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany 761b114ed83859d8d4964ac2284584733bcd2acf4f6Evgeniy Stepanovstatic uptr g_tls_size; 762b114ed83859d8d4964ac2284584733bcd2acf4f6Evgeniy Stepanov 763b114ed83859d8d4964ac2284584733bcd2acf4f6Evgeniy Stepanov#ifdef __i386__ 764b114ed83859d8d4964ac2284584733bcd2acf4f6Evgeniy Stepanov# define DL_INTERNAL_FUNCTION __attribute__((regparm(3), stdcall)) 765b114ed83859d8d4964ac2284584733bcd2acf4f6Evgeniy Stepanov#else 766b114ed83859d8d4964ac2284584733bcd2acf4f6Evgeniy Stepanov# define DL_INTERNAL_FUNCTION 767b114ed83859d8d4964ac2284584733bcd2acf4f6Evgeniy Stepanov#endif 768b114ed83859d8d4964ac2284584733bcd2acf4f6Evgeniy Stepanov 769b114ed83859d8d4964ac2284584733bcd2acf4f6Evgeniy Stepanovvoid InitTlsSize() { 770f310654ee19b6887677a09f09e522e36e81eb9daSergey Matveev#if !defined(SANITIZER_GO) && !SANITIZER_ANDROID 771b114ed83859d8d4964ac2284584733bcd2acf4f6Evgeniy Stepanov typedef void (*get_tls_func)(size_t*, size_t*) DL_INTERNAL_FUNCTION; 772b114ed83859d8d4964ac2284584733bcd2acf4f6Evgeniy Stepanov get_tls_func get_tls; 773b114ed83859d8d4964ac2284584733bcd2acf4f6Evgeniy Stepanov void *get_tls_static_info_ptr = dlsym(RTLD_NEXT, "_dl_get_tls_static_info"); 774b114ed83859d8d4964ac2284584733bcd2acf4f6Evgeniy Stepanov CHECK_EQ(sizeof(get_tls), sizeof(get_tls_static_info_ptr)); 775b114ed83859d8d4964ac2284584733bcd2acf4f6Evgeniy Stepanov internal_memcpy(&get_tls, &get_tls_static_info_ptr, 776b114ed83859d8d4964ac2284584733bcd2acf4f6Evgeniy Stepanov sizeof(get_tls_static_info_ptr)); 777b114ed83859d8d4964ac2284584733bcd2acf4f6Evgeniy Stepanov CHECK_NE(get_tls, 0); 778b114ed83859d8d4964ac2284584733bcd2acf4f6Evgeniy Stepanov size_t tls_size = 0; 779b114ed83859d8d4964ac2284584733bcd2acf4f6Evgeniy Stepanov size_t tls_align = 0; 780b114ed83859d8d4964ac2284584733bcd2acf4f6Evgeniy Stepanov get_tls(&tls_size, &tls_align); 781b114ed83859d8d4964ac2284584733bcd2acf4f6Evgeniy Stepanov g_tls_size = tls_size; 782b114ed83859d8d4964ac2284584733bcd2acf4f6Evgeniy Stepanov#endif 783b114ed83859d8d4964ac2284584733bcd2acf4f6Evgeniy Stepanov} 784b114ed83859d8d4964ac2284584733bcd2acf4f6Evgeniy Stepanov 785b114ed83859d8d4964ac2284584733bcd2acf4f6Evgeniy Stepanovuptr GetTlsSize() { 786b114ed83859d8d4964ac2284584733bcd2acf4f6Evgeniy Stepanov return g_tls_size; 787b114ed83859d8d4964ac2284584733bcd2acf4f6Evgeniy Stepanov} 788b114ed83859d8d4964ac2284584733bcd2acf4f6Evgeniy Stepanov 78924323de08fa8850712d56621bff29dbbbd0285a9Sergey Matveev// sizeof(struct thread) from glibc. 79024323de08fa8850712d56621bff29dbbbd0285a9Sergey Matveev#ifdef __x86_64__ 79124323de08fa8850712d56621bff29dbbbd0285a9Sergey Matveevconst uptr kThreadDescriptorSize = 2304; 79224323de08fa8850712d56621bff29dbbbd0285a9Sergey Matveev 79324323de08fa8850712d56621bff29dbbbd0285a9Sergey Matveevuptr ThreadDescriptorSize() { 79424323de08fa8850712d56621bff29dbbbd0285a9Sergey Matveev return kThreadDescriptorSize; 79524323de08fa8850712d56621bff29dbbbd0285a9Sergey Matveev} 79624323de08fa8850712d56621bff29dbbbd0285a9Sergey Matveev#endif 79724323de08fa8850712d56621bff29dbbbd0285a9Sergey Matveev 79824323de08fa8850712d56621bff29dbbbd0285a9Sergey Matveevvoid GetThreadStackAndTls(bool main, uptr *stk_addr, uptr *stk_size, 79924323de08fa8850712d56621bff29dbbbd0285a9Sergey Matveev uptr *tls_addr, uptr *tls_size) { 80024323de08fa8850712d56621bff29dbbbd0285a9Sergey Matveev#ifndef SANITIZER_GO 80124323de08fa8850712d56621bff29dbbbd0285a9Sergey Matveev#ifdef __x86_64__ 80224323de08fa8850712d56621bff29dbbbd0285a9Sergey Matveev arch_prctl(ARCH_GET_FS, tls_addr); 80324323de08fa8850712d56621bff29dbbbd0285a9Sergey Matveev *tls_size = GetTlsSize(); 80424323de08fa8850712d56621bff29dbbbd0285a9Sergey Matveev *tls_addr -= *tls_size; 80524323de08fa8850712d56621bff29dbbbd0285a9Sergey Matveev *tls_addr += kThreadDescriptorSize; 80624323de08fa8850712d56621bff29dbbbd0285a9Sergey Matveev#else 80724323de08fa8850712d56621bff29dbbbd0285a9Sergey Matveev *tls_addr = 0; 80824323de08fa8850712d56621bff29dbbbd0285a9Sergey Matveev *tls_size = 0; 80924323de08fa8850712d56621bff29dbbbd0285a9Sergey Matveev#endif 81024323de08fa8850712d56621bff29dbbbd0285a9Sergey Matveev 81124323de08fa8850712d56621bff29dbbbd0285a9Sergey Matveev uptr stack_top, stack_bottom; 81224323de08fa8850712d56621bff29dbbbd0285a9Sergey Matveev GetThreadStackTopAndBottom(main, &stack_top, &stack_bottom); 81324323de08fa8850712d56621bff29dbbbd0285a9Sergey Matveev *stk_addr = stack_bottom; 81424323de08fa8850712d56621bff29dbbbd0285a9Sergey Matveev *stk_size = stack_top - stack_bottom; 81524323de08fa8850712d56621bff29dbbbd0285a9Sergey Matveev 81624323de08fa8850712d56621bff29dbbbd0285a9Sergey Matveev if (!main) { 81724323de08fa8850712d56621bff29dbbbd0285a9Sergey Matveev // If stack and tls intersect, make them non-intersecting. 81824323de08fa8850712d56621bff29dbbbd0285a9Sergey Matveev if (*tls_addr > *stk_addr && *tls_addr < *stk_addr + *stk_size) { 81924323de08fa8850712d56621bff29dbbbd0285a9Sergey Matveev CHECK_GT(*tls_addr + *tls_size, *stk_addr); 82024323de08fa8850712d56621bff29dbbbd0285a9Sergey Matveev CHECK_LE(*tls_addr + *tls_size, *stk_addr + *stk_size); 82124323de08fa8850712d56621bff29dbbbd0285a9Sergey Matveev *stk_size -= *tls_size; 82224323de08fa8850712d56621bff29dbbbd0285a9Sergey Matveev *tls_addr = *stk_addr + *stk_size; 82324323de08fa8850712d56621bff29dbbbd0285a9Sergey Matveev } 82424323de08fa8850712d56621bff29dbbbd0285a9Sergey Matveev } 82524323de08fa8850712d56621bff29dbbbd0285a9Sergey Matveev#else // SANITIZER_GO 82624323de08fa8850712d56621bff29dbbbd0285a9Sergey Matveev *stk_addr = 0; 82724323de08fa8850712d56621bff29dbbbd0285a9Sergey Matveev *stk_size = 0; 82824323de08fa8850712d56621bff29dbbbd0285a9Sergey Matveev *tls_addr = 0; 82924323de08fa8850712d56621bff29dbbbd0285a9Sergey Matveev *tls_size = 0; 83024323de08fa8850712d56621bff29dbbbd0285a9Sergey Matveev#endif // SANITIZER_GO 83124323de08fa8850712d56621bff29dbbbd0285a9Sergey Matveev} 83224323de08fa8850712d56621bff29dbbbd0285a9Sergey Matveev 833b9bf700ae7fe59e25976e0abe9636150f3a39cd2Evgeniy Stepanovvoid AdjustStackSizeLinux(void *attr_, int verbosity) { 834b9bf700ae7fe59e25976e0abe9636150f3a39cd2Evgeniy Stepanov pthread_attr_t *attr = (pthread_attr_t *)attr_; 835609a02ad07f09147e2fe7beaa257b8c607aca033Evgeniy Stepanov uptr stackaddr = 0; 836b9bf700ae7fe59e25976e0abe9636150f3a39cd2Evgeniy Stepanov size_t stacksize = 0; 837b9bf700ae7fe59e25976e0abe9636150f3a39cd2Evgeniy Stepanov pthread_attr_getstack(attr, (void**)&stackaddr, &stacksize); 838b9bf700ae7fe59e25976e0abe9636150f3a39cd2Evgeniy Stepanov // GLibC will return (0 - stacksize) as the stack address in the case when 839b9bf700ae7fe59e25976e0abe9636150f3a39cd2Evgeniy Stepanov // stacksize is set, but stackaddr is not. 840b9bf700ae7fe59e25976e0abe9636150f3a39cd2Evgeniy Stepanov bool stack_set = (stackaddr != 0) && (stackaddr + stacksize != 0); 841b9bf700ae7fe59e25976e0abe9636150f3a39cd2Evgeniy Stepanov // We place a lot of tool data into TLS, account for that. 842b9bf700ae7fe59e25976e0abe9636150f3a39cd2Evgeniy Stepanov const uptr minstacksize = GetTlsSize() + 128*1024; 843b9bf700ae7fe59e25976e0abe9636150f3a39cd2Evgeniy Stepanov if (stacksize < minstacksize) { 844b9bf700ae7fe59e25976e0abe9636150f3a39cd2Evgeniy Stepanov if (!stack_set) { 845b9bf700ae7fe59e25976e0abe9636150f3a39cd2Evgeniy Stepanov if (verbosity && stacksize != 0) 846b9bf700ae7fe59e25976e0abe9636150f3a39cd2Evgeniy Stepanov Printf("Sanitizer: increasing stacksize %zu->%zu\n", stacksize, 847b9bf700ae7fe59e25976e0abe9636150f3a39cd2Evgeniy Stepanov minstacksize); 848b9bf700ae7fe59e25976e0abe9636150f3a39cd2Evgeniy Stepanov pthread_attr_setstacksize(attr, minstacksize); 849b9bf700ae7fe59e25976e0abe9636150f3a39cd2Evgeniy Stepanov } else { 850b9bf700ae7fe59e25976e0abe9636150f3a39cd2Evgeniy Stepanov Printf("Sanitizer: pre-allocated stack size is insufficient: " 851b9bf700ae7fe59e25976e0abe9636150f3a39cd2Evgeniy Stepanov "%zu < %zu\n", stacksize, minstacksize); 852b9bf700ae7fe59e25976e0abe9636150f3a39cd2Evgeniy Stepanov Printf("Sanitizer: pthread_create is likely to fail.\n"); 853b9bf700ae7fe59e25976e0abe9636150f3a39cd2Evgeniy Stepanov } 854b9bf700ae7fe59e25976e0abe9636150f3a39cd2Evgeniy Stepanov } 855b9bf700ae7fe59e25976e0abe9636150f3a39cd2Evgeniy Stepanov} 856b9bf700ae7fe59e25976e0abe9636150f3a39cd2Evgeniy Stepanov 857ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov} // namespace __sanitizer 858ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov 85946f9395baf65e17f1a3f7a3a1deee72a1560ac53Alexey Samsonov#endif // SANITIZER_LINUX 860