sanitizer_linux.cc revision 497ae56316cd05a0d539e0d6e065bbaee254aca3
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" 265ce93fc96ab5e2defd85890da63b51cc4c57a2afAlexander Potapenko#include "sanitizer_symbolizer.h" 27ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov 28088ea2b46f97172bd0b0663a629e11cf826b84f7Peter Collingbourne#include <asm/param.h> 29b114ed83859d8d4964ac2284584733bcd2acf4f6Evgeniy Stepanov#include <dlfcn.h> 3035a7faf1fbfac678136e79d53824672dafb7d13eAlexey Samsonov#include <errno.h> 31c5d465136b911bf925f2a631e2b79f1c03e8a1b0Alexey Samsonov#include <fcntl.h> 326d40a0a2ffa6735e45bd1d62c94ff725fd3e8b71Peter Collingbourne#if !SANITIZER_ANDROID 332e75ac983cb233daa1abfa35fb33d2bafffe2ab1Peter Collingbourne#include <link.h> 346d40a0a2ffa6735e45bd1d62c94ff725fd3e8b71Peter Collingbourne#endif 35e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov#include <pthread.h> 360969bcf2c936126b1f6e636b978aade8fc207437Alexey Samsonov#include <sched.h> 37ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov#include <sys/mman.h> 386fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany#include <sys/ptrace.h> 39e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov#include <sys/resource.h> 40c5d465136b911bf925f2a631e2b79f1c03e8a1b0Alexey Samsonov#include <sys/stat.h> 41ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov#include <sys/syscall.h> 42e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov#include <sys/time.h> 43ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov#include <sys/types.h> 44ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov#include <unistd.h> 45a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryany#include <unwind.h> 4635a7faf1fbfac678136e79d53824672dafb7d13eAlexey Samsonov 4724e13723f8477d8c42ab8b2a7f4f69fc089842f1Evgeniy Stepanov#if !SANITIZER_ANDROID 4835a7faf1fbfac678136e79d53824672dafb7d13eAlexey Samsonov#include <sys/signal.h> 4935a7faf1fbfac678136e79d53824672dafb7d13eAlexey Samsonov#endif 50fa5c41eddf77a3614da0f62044ebf741d86aeab7Dmitry Vyukov 514bebe7bab966c82f0a8952f797ed3d490624dc62Dmitry Vyukov// <linux/time.h> 524bebe7bab966c82f0a8952f797ed3d490624dc62Dmitry Vyukovstruct kernel_timeval { 534bebe7bab966c82f0a8952f797ed3d490624dc62Dmitry Vyukov long tv_sec; 544bebe7bab966c82f0a8952f797ed3d490624dc62Dmitry Vyukov long tv_usec; 554bebe7bab966c82f0a8952f797ed3d490624dc62Dmitry Vyukov}; 564bebe7bab966c82f0a8952f797ed3d490624dc62Dmitry Vyukov 57fa5c41eddf77a3614da0f62044ebf741d86aeab7Dmitry Vyukov// <linux/futex.h> is broken on some linux distributions. 58fa5c41eddf77a3614da0f62044ebf741d86aeab7Dmitry Vyukovconst int FUTEX_WAIT = 0; 59fa5c41eddf77a3614da0f62044ebf741d86aeab7Dmitry Vyukovconst int FUTEX_WAKE = 1; 60ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov 619d0dbbaf33e5c2fe280f141e30be497d62b703a8Kostya Serebryany// Are we using 32-bit or 64-bit syscalls? 625af39e50366f1aacbebc284f572f08ad1ad07357Kostya Serebryany// x32 (which defines __x86_64__) has SANITIZER_WORDSIZE == 32 6308bfe4988de493dd3e61d02759b3f19c42f8fb78Kostya Serebryany// but it still needs to use 64-bit syscalls. 645af39e50366f1aacbebc284f572f08ad1ad07357Kostya Serebryany#if defined(__x86_64__) || SANITIZER_WORDSIZE == 64 659d0dbbaf33e5c2fe280f141e30be497d62b703a8Kostya Serebryany# define SANITIZER_LINUX_USES_64BIT_SYSCALLS 1 669d0dbbaf33e5c2fe280f141e30be497d62b703a8Kostya Serebryany#else 679d0dbbaf33e5c2fe280f141e30be497d62b703a8Kostya Serebryany# define SANITIZER_LINUX_USES_64BIT_SYSCALLS 0 689d0dbbaf33e5c2fe280f141e30be497d62b703a8Kostya Serebryany#endif 699d0dbbaf33e5c2fe280f141e30be497d62b703a8Kostya Serebryany 70ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonovnamespace __sanitizer { 71ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov 729578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne#ifdef __x86_64__ 739578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne#include "sanitizer_syscall_linux_x86_64.inc" 749578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne#else 759578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne#include "sanitizer_syscall_generic.inc" 769578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne#endif 779578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne 78e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov// --------------- sanitizer_libc.h 799578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourneuptr internal_mmap(void *addr, uptr length, int prot, int flags, 80ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov int fd, u64 offset) { 819d0dbbaf33e5c2fe280f141e30be497d62b703a8Kostya Serebryany#if SANITIZER_LINUX_USES_64BIT_SYSCALLS 829578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne return internal_syscall(__NR_mmap, addr, length, prot, flags, fd, offset); 83ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov#else 849578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne return internal_syscall(__NR_mmap2, addr, length, prot, flags, fd, offset); 85ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov#endif 86ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov} 87ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov 889578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourneuptr internal_munmap(void *addr, uptr length) { 899578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne return internal_syscall(__NR_munmap, addr, length); 901f11d31faa5ed89b74f7d543b1182fe8de198be5Alexey Samsonov} 911f11d31faa5ed89b74f7d543b1182fe8de198be5Alexey Samsonov 929578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourneuptr internal_close(fd_t fd) { 939578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne return internal_syscall(__NR_close, fd); 94a56aefd2e01940fcf88d1426f9de3d5e4b1ee203Alexey Samsonov} 95a56aefd2e01940fcf88d1426f9de3d5e4b1ee203Alexey Samsonov 969578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourneuptr internal_open(const char *filename, int flags) { 979578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne return internal_syscall(__NR_open, filename, flags); 98ee7cc4454421a176d23442382afd9a01d36e7ad4Alexey Samsonov} 99ee7cc4454421a176d23442382afd9a01d36e7ad4Alexey Samsonov 1009578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourneuptr internal_open(const char *filename, int flags, u32 mode) { 1019578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne return internal_syscall(__NR_open, filename, flags, mode); 102ee7cc4454421a176d23442382afd9a01d36e7ad4Alexey Samsonov} 103ee7cc4454421a176d23442382afd9a01d36e7ad4Alexey Samsonov 1049578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourneuptr OpenFile(const char *filename, bool write) { 105ee7cc4454421a176d23442382afd9a01d36e7ad4Alexey Samsonov return internal_open(filename, 1069b8a9c1b1ce4659457178ff4c0838ac1b35ca9dcKostya Serebryany write ? O_WRONLY | O_CREAT /*| O_CLOEXEC*/ : O_RDONLY, 0660); 107c5d465136b911bf925f2a631e2b79f1c03e8a1b0Alexey Samsonov} 108c5d465136b911bf925f2a631e2b79f1c03e8a1b0Alexey Samsonov 109a56aefd2e01940fcf88d1426f9de3d5e4b1ee203Alexey Samsonovuptr internal_read(fd_t fd, void *buf, uptr count) { 1103334e12d33261cb8f211f2f49f28ddfa027a40c3Evgeniy Stepanov sptr res; 1119578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne HANDLE_EINTR(res, (sptr)internal_syscall(__NR_read, fd, buf, count)); 1123334e12d33261cb8f211f2f49f28ddfa027a40c3Evgeniy Stepanov return res; 113a56aefd2e01940fcf88d1426f9de3d5e4b1ee203Alexey Samsonov} 114a56aefd2e01940fcf88d1426f9de3d5e4b1ee203Alexey Samsonov 115a56aefd2e01940fcf88d1426f9de3d5e4b1ee203Alexey Samsonovuptr internal_write(fd_t fd, const void *buf, uptr count) { 1163334e12d33261cb8f211f2f49f28ddfa027a40c3Evgeniy Stepanov sptr res; 1179578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne HANDLE_EINTR(res, (sptr)internal_syscall(__NR_write, fd, buf, count)); 1183334e12d33261cb8f211f2f49f28ddfa027a40c3Evgeniy Stepanov return res; 119a56aefd2e01940fcf88d1426f9de3d5e4b1ee203Alexey Samsonov} 120a56aefd2e01940fcf88d1426f9de3d5e4b1ee203Alexey Samsonov 1212be3a283939d4fc14ad86f6cd8be34b1468f22baEvgeniy Stepanov#if !SANITIZER_LINUX_USES_64BIT_SYSCALLS 1222be3a283939d4fc14ad86f6cd8be34b1468f22baEvgeniy Stepanovstatic void stat64_to_stat(struct stat64 *in, struct stat *out) { 1232be3a283939d4fc14ad86f6cd8be34b1468f22baEvgeniy Stepanov internal_memset(out, 0, sizeof(*out)); 1242be3a283939d4fc14ad86f6cd8be34b1468f22baEvgeniy Stepanov out->st_dev = in->st_dev; 1252be3a283939d4fc14ad86f6cd8be34b1468f22baEvgeniy Stepanov out->st_ino = in->st_ino; 1262be3a283939d4fc14ad86f6cd8be34b1468f22baEvgeniy Stepanov out->st_mode = in->st_mode; 1272be3a283939d4fc14ad86f6cd8be34b1468f22baEvgeniy Stepanov out->st_nlink = in->st_nlink; 1282be3a283939d4fc14ad86f6cd8be34b1468f22baEvgeniy Stepanov out->st_uid = in->st_uid; 1292be3a283939d4fc14ad86f6cd8be34b1468f22baEvgeniy Stepanov out->st_gid = in->st_gid; 1302be3a283939d4fc14ad86f6cd8be34b1468f22baEvgeniy Stepanov out->st_rdev = in->st_rdev; 1312be3a283939d4fc14ad86f6cd8be34b1468f22baEvgeniy Stepanov out->st_size = in->st_size; 1322be3a283939d4fc14ad86f6cd8be34b1468f22baEvgeniy Stepanov out->st_blksize = in->st_blksize; 1332be3a283939d4fc14ad86f6cd8be34b1468f22baEvgeniy Stepanov out->st_blocks = in->st_blocks; 1342be3a283939d4fc14ad86f6cd8be34b1468f22baEvgeniy Stepanov out->st_atime = in->st_atime; 1352be3a283939d4fc14ad86f6cd8be34b1468f22baEvgeniy Stepanov out->st_mtime = in->st_mtime; 1362be3a283939d4fc14ad86f6cd8be34b1468f22baEvgeniy Stepanov out->st_ctime = in->st_ctime; 1372be3a283939d4fc14ad86f6cd8be34b1468f22baEvgeniy Stepanov out->st_ino = in->st_ino; 1382be3a283939d4fc14ad86f6cd8be34b1468f22baEvgeniy Stepanov} 1392be3a283939d4fc14ad86f6cd8be34b1468f22baEvgeniy Stepanov#endif 1402be3a283939d4fc14ad86f6cd8be34b1468f22baEvgeniy Stepanov 1419578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourneuptr internal_stat(const char *path, void *buf) { 1424c9317a7b61e136f832d2ede70f557963fd46bceAlexey Samsonov#if SANITIZER_LINUX_USES_64BIT_SYSCALLS 1439578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne return internal_syscall(__NR_stat, path, buf); 1444c9317a7b61e136f832d2ede70f557963fd46bceAlexey Samsonov#else 1452be3a283939d4fc14ad86f6cd8be34b1468f22baEvgeniy Stepanov struct stat64 buf64; 1469578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne int res = internal_syscall(__NR_stat64, path, &buf64); 1472be3a283939d4fc14ad86f6cd8be34b1468f22baEvgeniy Stepanov stat64_to_stat(&buf64, (struct stat *)buf); 1482be3a283939d4fc14ad86f6cd8be34b1468f22baEvgeniy Stepanov return res; 1494c9317a7b61e136f832d2ede70f557963fd46bceAlexey Samsonov#endif 1504c9317a7b61e136f832d2ede70f557963fd46bceAlexey Samsonov} 1514c9317a7b61e136f832d2ede70f557963fd46bceAlexey Samsonov 1529578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourneuptr internal_lstat(const char *path, void *buf) { 1534c9317a7b61e136f832d2ede70f557963fd46bceAlexey Samsonov#if SANITIZER_LINUX_USES_64BIT_SYSCALLS 1549578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne return internal_syscall(__NR_lstat, path, buf); 1554c9317a7b61e136f832d2ede70f557963fd46bceAlexey Samsonov#else 1562be3a283939d4fc14ad86f6cd8be34b1468f22baEvgeniy Stepanov struct stat64 buf64; 1579578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne int res = internal_syscall(__NR_lstat64, path, &buf64); 1582be3a283939d4fc14ad86f6cd8be34b1468f22baEvgeniy Stepanov stat64_to_stat(&buf64, (struct stat *)buf); 1592be3a283939d4fc14ad86f6cd8be34b1468f22baEvgeniy Stepanov return res; 1604c9317a7b61e136f832d2ede70f557963fd46bceAlexey Samsonov#endif 1614c9317a7b61e136f832d2ede70f557963fd46bceAlexey Samsonov} 1624c9317a7b61e136f832d2ede70f557963fd46bceAlexey Samsonov 1639578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourneuptr internal_fstat(fd_t fd, void *buf) { 1644c9317a7b61e136f832d2ede70f557963fd46bceAlexey Samsonov#if SANITIZER_LINUX_USES_64BIT_SYSCALLS 1659578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne return internal_syscall(__NR_fstat, fd, buf); 1664c9317a7b61e136f832d2ede70f557963fd46bceAlexey Samsonov#else 1672be3a283939d4fc14ad86f6cd8be34b1468f22baEvgeniy Stepanov struct stat64 buf64; 1689578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne int res = internal_syscall(__NR_fstat64, fd, &buf64); 1692be3a283939d4fc14ad86f6cd8be34b1468f22baEvgeniy Stepanov stat64_to_stat(&buf64, (struct stat *)buf); 1702be3a283939d4fc14ad86f6cd8be34b1468f22baEvgeniy Stepanov return res; 1714c9317a7b61e136f832d2ede70f557963fd46bceAlexey Samsonov#endif 1724c9317a7b61e136f832d2ede70f557963fd46bceAlexey Samsonov} 1734c9317a7b61e136f832d2ede70f557963fd46bceAlexey Samsonov 1748e820fcf7aafeb8101322182d742fcf99255d972Alexey Samsonovuptr internal_filesize(fd_t fd) { 175a68633fb76208137ccb807914df52758ee5ca6f0Alexey Samsonov struct stat st; 1764c9317a7b61e136f832d2ede70f557963fd46bceAlexey Samsonov if (internal_fstat(fd, &st)) 1774c9317a7b61e136f832d2ede70f557963fd46bceAlexey Samsonov return -1; 1788e820fcf7aafeb8101322182d742fcf99255d972Alexey Samsonov return (uptr)st.st_size; 1798e820fcf7aafeb8101322182d742fcf99255d972Alexey Samsonov} 1808e820fcf7aafeb8101322182d742fcf99255d972Alexey Samsonov 1819578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourneuptr internal_dup2(int oldfd, int newfd) { 1829578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne return internal_syscall(__NR_dup2, oldfd, newfd); 1838e820fcf7aafeb8101322182d742fcf99255d972Alexey Samsonov} 1848e820fcf7aafeb8101322182d742fcf99255d972Alexey Samsonov 185d1b8f588d6b712b6ff2b3d58c73d71614f520122Alexey Samsonovuptr internal_readlink(const char *path, char *buf, uptr bufsize) { 1869578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne return internal_syscall(__NR_readlink, path, buf, bufsize); 187d1b8f588d6b712b6ff2b3d58c73d71614f520122Alexey Samsonov} 188d1b8f588d6b712b6ff2b3d58c73d71614f520122Alexey Samsonov 1899578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourneuptr internal_unlink(const char *path) { 1909578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne return internal_syscall(__NR_unlink, path); 1916d6ab9eeea4a99370d7ab18ce80eb96091e2cf3fDmitry Vyukov} 1926d6ab9eeea4a99370d7ab18ce80eb96091e2cf3fDmitry Vyukov 1939578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourneuptr internal_sched_yield() { 1949578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne return internal_syscall(__NR_sched_yield); 1950969bcf2c936126b1f6e636b978aade8fc207437Alexey Samsonov} 1960969bcf2c936126b1f6e636b978aade8fc207437Alexey Samsonov 197f882247088952deed954a19d745c2dd8871e2035Alexey Samsonovvoid internal__exit(int exitcode) { 1989578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne internal_syscall(__NR_exit_group, exitcode); 199f882247088952deed954a19d745c2dd8871e2035Alexey Samsonov Die(); // Unreachable. 200f882247088952deed954a19d745c2dd8871e2035Alexey Samsonov} 201f882247088952deed954a19d745c2dd8871e2035Alexey Samsonov 2029578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourneuptr internal_execve(const char *filename, char *const argv[], 2039578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne char *const envp[]) { 2049578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne return internal_syscall(__NR_execve, filename, argv, envp); 2059578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne} 2069578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne 207e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov// ----------------- sanitizer_common.h 20893b4cafd631b661b4b612ccdc0938f7f1e1c86d6Alexey Samsonovbool FileExists(const char *filename) { 20993b4cafd631b661b4b612ccdc0938f7f1e1c86d6Alexey Samsonov struct stat st; 2102be3a283939d4fc14ad86f6cd8be34b1468f22baEvgeniy Stepanov if (internal_stat(filename, &st)) 21193b4cafd631b661b4b612ccdc0938f7f1e1c86d6Alexey Samsonov return false; 21293b4cafd631b661b4b612ccdc0938f7f1e1c86d6Alexey Samsonov // Sanity check: filename is a regular file. 21393b4cafd631b661b4b612ccdc0938f7f1e1c86d6Alexey Samsonov return S_ISREG(st.st_mode); 21493b4cafd631b661b4b612ccdc0938f7f1e1c86d6Alexey Samsonov} 21593b4cafd631b661b4b612ccdc0938f7f1e1c86d6Alexey Samsonov 216e0023f74ea88efee329f68391b70f8adc6b21617Dmitry Vyukovuptr GetTid() { 2179578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne return internal_syscall(__NR_gettid); 218e0023f74ea88efee329f68391b70f8adc6b21617Dmitry Vyukov} 219e0023f74ea88efee329f68391b70f8adc6b21617Dmitry Vyukov 2204bebe7bab966c82f0a8952f797ed3d490624dc62Dmitry Vyukovu64 NanoTime() { 221e57f26b5c99cedd56de76f3a10cadcecece768bdDmitry Vyukov kernel_timeval tv = {}; 2229578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne internal_syscall(__NR_gettimeofday, &tv, 0); 2234bebe7bab966c82f0a8952f797ed3d490624dc62Dmitry Vyukov return (u64)tv.tv_sec * 1000*1000*1000 + tv.tv_usec * 1000; 2244bebe7bab966c82f0a8952f797ed3d490624dc62Dmitry Vyukov} 2254bebe7bab966c82f0a8952f797ed3d490624dc62Dmitry Vyukov 2263dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov// Like getenv, but reads env directly from /proc and does not use libc. 2273dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov// This function should be called first inside __asan_init. 2283dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonovconst char *GetEnv(const char *name) { 2293dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov static char *environ; 2303dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov static uptr len; 2313dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov static bool inited; 2323dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov if (!inited) { 2333dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov inited = true; 2343dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov uptr environ_size; 2353dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov len = ReadFileToBuffer("/proc/self/environ", 2363dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov &environ, &environ_size, 1 << 26); 2373dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov } 2383dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov if (!environ || len == 0) return 0; 2393dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov uptr namelen = internal_strlen(name); 2403dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov const char *p = environ; 2413dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov while (*p != '\0') { // will happen at the \0\0 that terminates the buffer 2423dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov // proc file has the format NAME=value\0NAME=value\0NAME=value\0... 2433dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov const char* endp = 2443dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov (char*)internal_memchr(p, '\0', len - (p - environ)); 2453dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov if (endp == 0) // this entry isn't NUL terminated 2463dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov return 0; 2473dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov else if (!internal_memcmp(p, name, namelen) && p[namelen] == '=') // Match. 2483dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov return p + namelen + 1; // point after = 2493dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov p = endp + 1; 2503dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov } 2513dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov return 0; // Not found. 2523dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov} 2533dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov 254eab061185ec0046d447b298a1dff84f028202a3cEvgeniy Stepanovextern "C" { 2553c80c6c574850106481f82b9e23d1c728458d4a9Timur Iskhodzhanov SANITIZER_WEAK_ATTRIBUTE extern void *__libc_stack_end; 256eab061185ec0046d447b298a1dff84f028202a3cEvgeniy Stepanov} 257eab061185ec0046d447b298a1dff84f028202a3cEvgeniy Stepanov 25826337b60b1d551c4744454edd8e5ef3c479e3467Peter Collingbourne#if !SANITIZER_GO 25923709c9ad9ac7c45de288f5260403426bf932db7Peter Collingbournestatic void ReadNullSepFileToArray(const char *path, char ***arr, 26023709c9ad9ac7c45de288f5260403426bf932db7Peter Collingbourne int arr_size) { 26123709c9ad9ac7c45de288f5260403426bf932db7Peter Collingbourne char *buff; 262d7e5bb4043adf4756e6f8cfe0f5a3165b185474dAlexey Samsonov uptr buff_size = 0; 26323709c9ad9ac7c45de288f5260403426bf932db7Peter Collingbourne *arr = (char **)MmapOrDie(arr_size * sizeof(char *), "NullSepFileArray"); 26423709c9ad9ac7c45de288f5260403426bf932db7Peter Collingbourne ReadFileToBuffer(path, &buff, &buff_size, 1024 * 1024); 26523709c9ad9ac7c45de288f5260403426bf932db7Peter Collingbourne (*arr)[0] = buff; 26623709c9ad9ac7c45de288f5260403426bf932db7Peter Collingbourne int count, i; 26723709c9ad9ac7c45de288f5260403426bf932db7Peter Collingbourne for (count = 1, i = 1; ; i++) { 268d7e5bb4043adf4756e6f8cfe0f5a3165b185474dAlexey Samsonov if (buff[i] == 0) { 269d7e5bb4043adf4756e6f8cfe0f5a3165b185474dAlexey Samsonov if (buff[i+1] == 0) break; 27023709c9ad9ac7c45de288f5260403426bf932db7Peter Collingbourne (*arr)[count] = &buff[i+1]; 27123709c9ad9ac7c45de288f5260403426bf932db7Peter Collingbourne CHECK_LE(count, arr_size - 1); // FIXME: make this more flexible. 27223709c9ad9ac7c45de288f5260403426bf932db7Peter Collingbourne count++; 273d7e5bb4043adf4756e6f8cfe0f5a3165b185474dAlexey Samsonov } 274d7e5bb4043adf4756e6f8cfe0f5a3165b185474dAlexey Samsonov } 27523709c9ad9ac7c45de288f5260403426bf932db7Peter Collingbourne (*arr)[count] = 0; 27623709c9ad9ac7c45de288f5260403426bf932db7Peter Collingbourne} 27726337b60b1d551c4744454edd8e5ef3c479e3467Peter Collingbourne#endif 27823709c9ad9ac7c45de288f5260403426bf932db7Peter Collingbourne 27926337b60b1d551c4744454edd8e5ef3c479e3467Peter Collingbournestatic void GetArgsAndEnv(char*** argv, char*** envp) { 28026337b60b1d551c4744454edd8e5ef3c479e3467Peter Collingbourne#if !SANITIZER_GO 28126337b60b1d551c4744454edd8e5ef3c479e3467Peter Collingbourne if (&__libc_stack_end) { 28226337b60b1d551c4744454edd8e5ef3c479e3467Peter Collingbourne#endif 28326337b60b1d551c4744454edd8e5ef3c479e3467Peter Collingbourne uptr* stack_end = (uptr*)__libc_stack_end; 28426337b60b1d551c4744454edd8e5ef3c479e3467Peter Collingbourne int argc = *stack_end; 28526337b60b1d551c4744454edd8e5ef3c479e3467Peter Collingbourne *argv = (char**)(stack_end + 1); 28626337b60b1d551c4744454edd8e5ef3c479e3467Peter Collingbourne *envp = (char**)(stack_end + argc + 2); 28726337b60b1d551c4744454edd8e5ef3c479e3467Peter Collingbourne#if !SANITIZER_GO 28826337b60b1d551c4744454edd8e5ef3c479e3467Peter Collingbourne } else { 28926337b60b1d551c4744454edd8e5ef3c479e3467Peter Collingbourne static const int kMaxArgv = 2000, kMaxEnvp = 2000; 29026337b60b1d551c4744454edd8e5ef3c479e3467Peter Collingbourne ReadNullSepFileToArray("/proc/self/cmdline", argv, kMaxArgv); 29126337b60b1d551c4744454edd8e5ef3c479e3467Peter Collingbourne ReadNullSepFileToArray("/proc/self/environ", envp, kMaxEnvp); 29226337b60b1d551c4744454edd8e5ef3c479e3467Peter Collingbourne } 29326337b60b1d551c4744454edd8e5ef3c479e3467Peter Collingbourne#endif 294eab061185ec0046d447b298a1dff84f028202a3cEvgeniy Stepanov} 295eab061185ec0046d447b298a1dff84f028202a3cEvgeniy Stepanov 296eab061185ec0046d447b298a1dff84f028202a3cEvgeniy Stepanovvoid ReExec() { 29723709c9ad9ac7c45de288f5260403426bf932db7Peter Collingbourne char **argv, **envp; 298eab061185ec0046d447b298a1dff84f028202a3cEvgeniy Stepanov GetArgsAndEnv(&argv, &envp); 2999578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne uptr rv = internal_execve("/proc/self/exe", argv, envp); 3009578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne int rverrno; 3019578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne CHECK_EQ(internal_iserror(rv, &rverrno), true); 3029578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne Printf("execve failed, errno %d\n", rverrno); 303f35eae83757946decb312deab3f0fe155fe5d580Evgeniy Stepanov Die(); 304d7e5bb4043adf4756e6f8cfe0f5a3165b185474dAlexey Samsonov} 305d7e5bb4043adf4756e6f8cfe0f5a3165b185474dAlexey Samsonov 30625742574510cfb41b97e32f63f107fbb9b328d13Alexander Potapenkovoid PrepareForSandboxing() { 30725742574510cfb41b97e32f63f107fbb9b328d13Alexander Potapenko // Some kinds of sandboxes may forbid filesystem access, so we won't be able 30825742574510cfb41b97e32f63f107fbb9b328d13Alexander Potapenko // to read the file mappings from /proc/self/maps. Luckily, neither the 30925742574510cfb41b97e32f63f107fbb9b328d13Alexander Potapenko // process will be able to load additional libraries, so it's fine to use the 31025742574510cfb41b97e32f63f107fbb9b328d13Alexander Potapenko // cached mappings. 31125742574510cfb41b97e32f63f107fbb9b328d13Alexander Potapenko MemoryMappingLayout::CacheMemoryMappings(); 3125ce93fc96ab5e2defd85890da63b51cc4c57a2afAlexander Potapenko // Same for /proc/self/exe in the symbolizer. 313cac631e3a63ec6c8a74008fe358af9c4b2306582Alexey Samsonov#if !SANITIZER_GO 3147847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov getSymbolizer()->PrepareForSandboxing(); 315cac631e3a63ec6c8a74008fe358af9c4b2306582Alexey Samsonov#endif 31625742574510cfb41b97e32f63f107fbb9b328d13Alexander Potapenko} 31725742574510cfb41b97e32f63f107fbb9b328d13Alexander Potapenko 318e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov// ----------------- sanitizer_procmaps.h 319286dd3f8afe6700e5dd9b0bdb7afd23121c98c12Dmitry Vyukov// Linker initialized. 320286dd3f8afe6700e5dd9b0bdb7afd23121c98c12Dmitry VyukovProcSelfMapsBuff MemoryMappingLayout::cached_proc_self_maps_; 321ad91267d45fef531c1082ab7974e4cc78aba5280Alexander PotapenkoStaticSpinMutex MemoryMappingLayout::cache_lock_; // Linker initialized. 32293da8b6a5e0ed2ca621897504c5d06449b3d7077Alexander Potapenko 3239ae2883d88dd28b9c5dc862107e6e6d12a35926eAlexander PotapenkoMemoryMappingLayout::MemoryMappingLayout(bool cache_enabled) { 324ad91267d45fef531c1082ab7974e4cc78aba5280Alexander Potapenko proc_self_maps_.len = 325ad91267d45fef531c1082ab7974e4cc78aba5280Alexander Potapenko ReadFileToBuffer("/proc/self/maps", &proc_self_maps_.data, 326ad91267d45fef531c1082ab7974e4cc78aba5280Alexander Potapenko &proc_self_maps_.mmaped_size, 1 << 26); 3279ae2883d88dd28b9c5dc862107e6e6d12a35926eAlexander Potapenko if (cache_enabled) { 3289ae2883d88dd28b9c5dc862107e6e6d12a35926eAlexander Potapenko if (proc_self_maps_.mmaped_size == 0) { 3299ae2883d88dd28b9c5dc862107e6e6d12a35926eAlexander Potapenko LoadFromCache(); 3309ae2883d88dd28b9c5dc862107e6e6d12a35926eAlexander Potapenko CHECK_GT(proc_self_maps_.len, 0); 3319ae2883d88dd28b9c5dc862107e6e6d12a35926eAlexander Potapenko } 3329ae2883d88dd28b9c5dc862107e6e6d12a35926eAlexander Potapenko } else { 3339ae2883d88dd28b9c5dc862107e6e6d12a35926eAlexander Potapenko CHECK_GT(proc_self_maps_.mmaped_size, 0); 33493da8b6a5e0ed2ca621897504c5d06449b3d7077Alexander Potapenko } 3356895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov Reset(); 33693da8b6a5e0ed2ca621897504c5d06449b3d7077Alexander Potapenko // FIXME: in the future we may want to cache the mappings on demand only. 3379ae2883d88dd28b9c5dc862107e6e6d12a35926eAlexander Potapenko if (cache_enabled) 3389ae2883d88dd28b9c5dc862107e6e6d12a35926eAlexander Potapenko CacheMemoryMappings(); 3396895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov} 3406895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov 341e1f5dac9296df08ff83ae5fca51ce4da995b55cfAlexey SamsonovMemoryMappingLayout::~MemoryMappingLayout() { 3427385f8b8b8723064910cf9737dc929e90aeac548Alexander Potapenko // Only unmap the buffer if it is different from the cached one. Otherwise 3437385f8b8b8723064910cf9737dc929e90aeac548Alexander Potapenko // it will be unmapped when the cache is refreshed. 3447385f8b8b8723064910cf9737dc929e90aeac548Alexander Potapenko if (proc_self_maps_.data != cached_proc_self_maps_.data) { 3457385f8b8b8723064910cf9737dc929e90aeac548Alexander Potapenko UnmapOrDie(proc_self_maps_.data, proc_self_maps_.mmaped_size); 3467385f8b8b8723064910cf9737dc929e90aeac548Alexander Potapenko } 3476895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov} 3486895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov 349e1f5dac9296df08ff83ae5fca51ce4da995b55cfAlexey Samsonovvoid MemoryMappingLayout::Reset() { 350ad91267d45fef531c1082ab7974e4cc78aba5280Alexander Potapenko current_ = proc_self_maps_.data; 3516895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov} 3526895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov 35393da8b6a5e0ed2ca621897504c5d06449b3d7077Alexander Potapenko// static 35493da8b6a5e0ed2ca621897504c5d06449b3d7077Alexander Potapenkovoid MemoryMappingLayout::CacheMemoryMappings() { 35593da8b6a5e0ed2ca621897504c5d06449b3d7077Alexander Potapenko SpinMutexLock l(&cache_lock_); 35693da8b6a5e0ed2ca621897504c5d06449b3d7077Alexander Potapenko // Don't invalidate the cache if the mappings are unavailable. 357ad91267d45fef531c1082ab7974e4cc78aba5280Alexander Potapenko ProcSelfMapsBuff old_proc_self_maps; 358ad91267d45fef531c1082ab7974e4cc78aba5280Alexander Potapenko old_proc_self_maps = cached_proc_self_maps_; 359ad91267d45fef531c1082ab7974e4cc78aba5280Alexander Potapenko cached_proc_self_maps_.len = 360ad91267d45fef531c1082ab7974e4cc78aba5280Alexander Potapenko ReadFileToBuffer("/proc/self/maps", &cached_proc_self_maps_.data, 361ad91267d45fef531c1082ab7974e4cc78aba5280Alexander Potapenko &cached_proc_self_maps_.mmaped_size, 1 << 26); 362ad91267d45fef531c1082ab7974e4cc78aba5280Alexander Potapenko if (cached_proc_self_maps_.mmaped_size == 0) { 363ad91267d45fef531c1082ab7974e4cc78aba5280Alexander Potapenko cached_proc_self_maps_ = old_proc_self_maps; 36493da8b6a5e0ed2ca621897504c5d06449b3d7077Alexander Potapenko } else { 365ad91267d45fef531c1082ab7974e4cc78aba5280Alexander Potapenko if (old_proc_self_maps.mmaped_size) { 366ad91267d45fef531c1082ab7974e4cc78aba5280Alexander Potapenko UnmapOrDie(old_proc_self_maps.data, 367ad91267d45fef531c1082ab7974e4cc78aba5280Alexander Potapenko old_proc_self_maps.mmaped_size); 36893da8b6a5e0ed2ca621897504c5d06449b3d7077Alexander Potapenko } 36993da8b6a5e0ed2ca621897504c5d06449b3d7077Alexander Potapenko } 37093da8b6a5e0ed2ca621897504c5d06449b3d7077Alexander Potapenko} 37193da8b6a5e0ed2ca621897504c5d06449b3d7077Alexander Potapenko 37293da8b6a5e0ed2ca621897504c5d06449b3d7077Alexander Potapenkovoid MemoryMappingLayout::LoadFromCache() { 37393da8b6a5e0ed2ca621897504c5d06449b3d7077Alexander Potapenko SpinMutexLock l(&cache_lock_); 374ad91267d45fef531c1082ab7974e4cc78aba5280Alexander Potapenko if (cached_proc_self_maps_.data) { 375286dd3f8afe6700e5dd9b0bdb7afd23121c98c12Dmitry Vyukov proc_self_maps_ = cached_proc_self_maps_; 37693da8b6a5e0ed2ca621897504c5d06449b3d7077Alexander Potapenko } 37793da8b6a5e0ed2ca621897504c5d06449b3d7077Alexander Potapenko} 37893da8b6a5e0ed2ca621897504c5d06449b3d7077Alexander Potapenko 379a4e4744778e6b3067f5cf223cf28bb586c1ecf67Kostya Serebryany// Parse a hex value in str and update str. 380a4e4744778e6b3067f5cf223cf28bb586c1ecf67Kostya Serebryanystatic uptr ParseHex(char **str) { 381a4e4744778e6b3067f5cf223cf28bb586c1ecf67Kostya Serebryany uptr x = 0; 382a4e4744778e6b3067f5cf223cf28bb586c1ecf67Kostya Serebryany char *s; 383a4e4744778e6b3067f5cf223cf28bb586c1ecf67Kostya Serebryany for (s = *str; ; s++) { 384a4e4744778e6b3067f5cf223cf28bb586c1ecf67Kostya Serebryany char c = *s; 385a4e4744778e6b3067f5cf223cf28bb586c1ecf67Kostya Serebryany uptr v = 0; 386a4e4744778e6b3067f5cf223cf28bb586c1ecf67Kostya Serebryany if (c >= '0' && c <= '9') 387a4e4744778e6b3067f5cf223cf28bb586c1ecf67Kostya Serebryany v = c - '0'; 388a4e4744778e6b3067f5cf223cf28bb586c1ecf67Kostya Serebryany else if (c >= 'a' && c <= 'f') 389a4e4744778e6b3067f5cf223cf28bb586c1ecf67Kostya Serebryany v = c - 'a' + 10; 390a4e4744778e6b3067f5cf223cf28bb586c1ecf67Kostya Serebryany else if (c >= 'A' && c <= 'F') 391a4e4744778e6b3067f5cf223cf28bb586c1ecf67Kostya Serebryany v = c - 'A' + 10; 392a4e4744778e6b3067f5cf223cf28bb586c1ecf67Kostya Serebryany else 393a4e4744778e6b3067f5cf223cf28bb586c1ecf67Kostya Serebryany break; 394a4e4744778e6b3067f5cf223cf28bb586c1ecf67Kostya Serebryany x = x * 16 + v; 395a4e4744778e6b3067f5cf223cf28bb586c1ecf67Kostya Serebryany } 396a4e4744778e6b3067f5cf223cf28bb586c1ecf67Kostya Serebryany *str = s; 397a4e4744778e6b3067f5cf223cf28bb586c1ecf67Kostya Serebryany return x; 398a4e4744778e6b3067f5cf223cf28bb586c1ecf67Kostya Serebryany} 399a4e4744778e6b3067f5cf223cf28bb586c1ecf67Kostya Serebryany 400ab11e0b10d077945a6e681766b41e12ac6aeb0f0Alexey Samsonovstatic bool IsOneOf(char c, char c1, char c2) { 401a4e4744778e6b3067f5cf223cf28bb586c1ecf67Kostya Serebryany return c == c1 || c == c2; 402a4e4744778e6b3067f5cf223cf28bb586c1ecf67Kostya Serebryany} 403a4e4744778e6b3067f5cf223cf28bb586c1ecf67Kostya Serebryany 404a4e4744778e6b3067f5cf223cf28bb586c1ecf67Kostya Serebryanystatic bool IsDecimal(char c) { 405a4e4744778e6b3067f5cf223cf28bb586c1ecf67Kostya Serebryany return c >= '0' && c <= '9'; 406a4e4744778e6b3067f5cf223cf28bb586c1ecf67Kostya Serebryany} 407a4e4744778e6b3067f5cf223cf28bb586c1ecf67Kostya Serebryany 4082e13ca86c9ce926e6fefd528892592326478ac6cAlexander Potapenkostatic bool IsHex(char c) { 4092e13ca86c9ce926e6fefd528892592326478ac6cAlexander Potapenko return (c >= '0' && c <= '9') 4102e13ca86c9ce926e6fefd528892592326478ac6cAlexander Potapenko || (c >= 'a' && c <= 'f'); 4112e13ca86c9ce926e6fefd528892592326478ac6cAlexander Potapenko} 4122e13ca86c9ce926e6fefd528892592326478ac6cAlexander Potapenko 4132e13ca86c9ce926e6fefd528892592326478ac6cAlexander Potapenkostatic uptr ReadHex(const char *p) { 4142e13ca86c9ce926e6fefd528892592326478ac6cAlexander Potapenko uptr v = 0; 4152e13ca86c9ce926e6fefd528892592326478ac6cAlexander Potapenko for (; IsHex(p[0]); p++) { 4162e13ca86c9ce926e6fefd528892592326478ac6cAlexander Potapenko if (p[0] >= '0' && p[0] <= '9') 4172e13ca86c9ce926e6fefd528892592326478ac6cAlexander Potapenko v = v * 16 + p[0] - '0'; 4182e13ca86c9ce926e6fefd528892592326478ac6cAlexander Potapenko else 4192e13ca86c9ce926e6fefd528892592326478ac6cAlexander Potapenko v = v * 16 + p[0] - 'a' + 10; 4202e13ca86c9ce926e6fefd528892592326478ac6cAlexander Potapenko } 4212e13ca86c9ce926e6fefd528892592326478ac6cAlexander Potapenko return v; 4222e13ca86c9ce926e6fefd528892592326478ac6cAlexander Potapenko} 4232e13ca86c9ce926e6fefd528892592326478ac6cAlexander Potapenko 4242e13ca86c9ce926e6fefd528892592326478ac6cAlexander Potapenkostatic uptr ReadDecimal(const char *p) { 4252e13ca86c9ce926e6fefd528892592326478ac6cAlexander Potapenko uptr v = 0; 4262e13ca86c9ce926e6fefd528892592326478ac6cAlexander Potapenko for (; IsDecimal(p[0]); p++) 4272e13ca86c9ce926e6fefd528892592326478ac6cAlexander Potapenko v = v * 10 + p[0] - '0'; 4282e13ca86c9ce926e6fefd528892592326478ac6cAlexander Potapenko return v; 4292e13ca86c9ce926e6fefd528892592326478ac6cAlexander Potapenko} 4302e13ca86c9ce926e6fefd528892592326478ac6cAlexander Potapenko 4312e13ca86c9ce926e6fefd528892592326478ac6cAlexander Potapenko 432e1f5dac9296df08ff83ae5fca51ce4da995b55cfAlexey Samsonovbool MemoryMappingLayout::Next(uptr *start, uptr *end, uptr *offset, 43345717c9d5e39a434749ae10509111f9df1b2cdf4Alexey Samsonov char filename[], uptr filename_size, 43445717c9d5e39a434749ae10509111f9df1b2cdf4Alexey Samsonov uptr *protection) { 435ad91267d45fef531c1082ab7974e4cc78aba5280Alexander Potapenko char *last = proc_self_maps_.data + proc_self_maps_.len; 4366895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov if (current_ >= last) return false; 4376895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov uptr dummy; 4386895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov if (!start) start = &dummy; 4396895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov if (!end) end = &dummy; 4406895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov if (!offset) offset = &dummy; 4416895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov char *next_line = (char*)internal_memchr(current_, '\n', last - current_); 4426895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov if (next_line == 0) 4436895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov next_line = last; 444a4e4744778e6b3067f5cf223cf28bb586c1ecf67Kostya Serebryany // Example: 08048000-08056000 r-xp 00000000 03:0c 64593 /foo/bar 445a4e4744778e6b3067f5cf223cf28bb586c1ecf67Kostya Serebryany *start = ParseHex(¤t_); 446bb8a9511bc748d6a4fd601d713bda584ef7bb772Kostya Serebryany CHECK_EQ(*current_++, '-'); 447a4e4744778e6b3067f5cf223cf28bb586c1ecf67Kostya Serebryany *end = ParseHex(¤t_); 448bb8a9511bc748d6a4fd601d713bda584ef7bb772Kostya Serebryany CHECK_EQ(*current_++, ' '); 44945717c9d5e39a434749ae10509111f9df1b2cdf4Alexey Samsonov uptr local_protection = 0; 450ab11e0b10d077945a6e681766b41e12ac6aeb0f0Alexey Samsonov CHECK(IsOneOf(*current_, '-', 'r')); 45145717c9d5e39a434749ae10509111f9df1b2cdf4Alexey Samsonov if (*current_++ == 'r') 45245717c9d5e39a434749ae10509111f9df1b2cdf4Alexey Samsonov local_protection |= kProtectionRead; 453ab11e0b10d077945a6e681766b41e12ac6aeb0f0Alexey Samsonov CHECK(IsOneOf(*current_, '-', 'w')); 45445717c9d5e39a434749ae10509111f9df1b2cdf4Alexey Samsonov if (*current_++ == 'w') 45545717c9d5e39a434749ae10509111f9df1b2cdf4Alexey Samsonov local_protection |= kProtectionWrite; 456ab11e0b10d077945a6e681766b41e12ac6aeb0f0Alexey Samsonov CHECK(IsOneOf(*current_, '-', 'x')); 45745717c9d5e39a434749ae10509111f9df1b2cdf4Alexey Samsonov if (*current_++ == 'x') 45845717c9d5e39a434749ae10509111f9df1b2cdf4Alexey Samsonov local_protection |= kProtectionExecute; 459ab11e0b10d077945a6e681766b41e12ac6aeb0f0Alexey Samsonov CHECK(IsOneOf(*current_, 's', 'p')); 46045717c9d5e39a434749ae10509111f9df1b2cdf4Alexey Samsonov if (*current_++ == 's') 46145717c9d5e39a434749ae10509111f9df1b2cdf4Alexey Samsonov local_protection |= kProtectionShared; 46245717c9d5e39a434749ae10509111f9df1b2cdf4Alexey Samsonov if (protection) { 46345717c9d5e39a434749ae10509111f9df1b2cdf4Alexey Samsonov *protection = local_protection; 46445717c9d5e39a434749ae10509111f9df1b2cdf4Alexey Samsonov } 465bb8a9511bc748d6a4fd601d713bda584ef7bb772Kostya Serebryany CHECK_EQ(*current_++, ' '); 466a4e4744778e6b3067f5cf223cf28bb586c1ecf67Kostya Serebryany *offset = ParseHex(¤t_); 467bb8a9511bc748d6a4fd601d713bda584ef7bb772Kostya Serebryany CHECK_EQ(*current_++, ' '); 468a4e4744778e6b3067f5cf223cf28bb586c1ecf67Kostya Serebryany ParseHex(¤t_); 469bb8a9511bc748d6a4fd601d713bda584ef7bb772Kostya Serebryany CHECK_EQ(*current_++, ':'); 470a4e4744778e6b3067f5cf223cf28bb586c1ecf67Kostya Serebryany ParseHex(¤t_); 471bb8a9511bc748d6a4fd601d713bda584ef7bb772Kostya Serebryany CHECK_EQ(*current_++, ' '); 472a4e4744778e6b3067f5cf223cf28bb586c1ecf67Kostya Serebryany while (IsDecimal(*current_)) 473a4e4744778e6b3067f5cf223cf28bb586c1ecf67Kostya Serebryany current_++; 4742592a0614d91fe947cd04fe7e2719d273e3e4880Kostya Serebryany // Qemu may lack the trailing space. 4752592a0614d91fe947cd04fe7e2719d273e3e4880Kostya Serebryany // http://code.google.com/p/address-sanitizer/issues/detail?id=160 4762592a0614d91fe947cd04fe7e2719d273e3e4880Kostya Serebryany // CHECK_EQ(*current_++, ' '); 4776895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov // Skip spaces. 4786895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov while (current_ < next_line && *current_ == ' ') 4796895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov current_++; 4806895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov // Fill in the filename. 4816895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov uptr i = 0; 4826895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov while (current_ < next_line) { 4836895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov if (filename && i < filename_size - 1) 4846895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov filename[i++] = *current_; 4856895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov current_++; 4866895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov } 4876895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov if (filename && i < filename_size) 4886895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov filename[i] = 0; 4896895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov current_ = next_line + 1; 4906895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov return true; 4916895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov} 4926895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov 493e1f5dac9296df08ff83ae5fca51ce4da995b55cfAlexey Samsonov// Gets the object name and the offset by walking MemoryMappingLayout. 494e1f5dac9296df08ff83ae5fca51ce4da995b55cfAlexey Samsonovbool MemoryMappingLayout::GetObjectNameAndOffset(uptr addr, uptr *offset, 495e1f5dac9296df08ff83ae5fca51ce4da995b55cfAlexey Samsonov char filename[], 49645717c9d5e39a434749ae10509111f9df1b2cdf4Alexey Samsonov uptr filename_size, 49745717c9d5e39a434749ae10509111f9df1b2cdf4Alexey Samsonov uptr *protection) { 49845717c9d5e39a434749ae10509111f9df1b2cdf4Alexey Samsonov return IterateForObjectNameAndOffset(addr, offset, filename, filename_size, 49945717c9d5e39a434749ae10509111f9df1b2cdf4Alexey Samsonov protection); 5006895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov} 5016895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov 5022e13ca86c9ce926e6fefd528892592326478ac6cAlexander Potapenkovoid GetMemoryProfile(fill_profile_f cb, uptr *stats, uptr stats_size) { 5032e13ca86c9ce926e6fefd528892592326478ac6cAlexander Potapenko char *smaps = 0; 5042e13ca86c9ce926e6fefd528892592326478ac6cAlexander Potapenko uptr smaps_cap = 0; 5052e13ca86c9ce926e6fefd528892592326478ac6cAlexander Potapenko uptr smaps_len = ReadFileToBuffer("/proc/self/smaps", 5062e13ca86c9ce926e6fefd528892592326478ac6cAlexander Potapenko &smaps, &smaps_cap, 64<<20); 5072e13ca86c9ce926e6fefd528892592326478ac6cAlexander Potapenko uptr start = 0; 5082e13ca86c9ce926e6fefd528892592326478ac6cAlexander Potapenko bool file = false; 5092e13ca86c9ce926e6fefd528892592326478ac6cAlexander Potapenko const char *pos = smaps; 5102e13ca86c9ce926e6fefd528892592326478ac6cAlexander Potapenko while (pos < smaps + smaps_len) { 5112e13ca86c9ce926e6fefd528892592326478ac6cAlexander Potapenko if (IsHex(pos[0])) { 5122e13ca86c9ce926e6fefd528892592326478ac6cAlexander Potapenko start = ReadHex(pos); 5132e13ca86c9ce926e6fefd528892592326478ac6cAlexander Potapenko for (; *pos != '/' && *pos > '\n'; pos++) {} 5142e13ca86c9ce926e6fefd528892592326478ac6cAlexander Potapenko file = *pos == '/'; 5152e13ca86c9ce926e6fefd528892592326478ac6cAlexander Potapenko } else if (internal_strncmp(pos, "Rss:", 4) == 0) { 5162e13ca86c9ce926e6fefd528892592326478ac6cAlexander Potapenko for (; *pos < '0' || *pos > '9'; pos++) {} 5172e13ca86c9ce926e6fefd528892592326478ac6cAlexander Potapenko uptr rss = ReadDecimal(pos) * 1024; 5182e13ca86c9ce926e6fefd528892592326478ac6cAlexander Potapenko cb(start, rss, file, stats, stats_size); 5192e13ca86c9ce926e6fefd528892592326478ac6cAlexander Potapenko } 5202e13ca86c9ce926e6fefd528892592326478ac6cAlexander Potapenko while (*pos++ != '\n') {} 5212e13ca86c9ce926e6fefd528892592326478ac6cAlexander Potapenko } 5222e13ca86c9ce926e6fefd528892592326478ac6cAlexander Potapenko UnmapOrDie(smaps, smaps_cap); 5232e13ca86c9ce926e6fefd528892592326478ac6cAlexander Potapenko} 5242e13ca86c9ce926e6fefd528892592326478ac6cAlexander Potapenko 525f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukovenum MutexState { 526f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov MtxUnlocked = 0, 527f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov MtxLocked = 1, 528f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov MtxSleeping = 2 529f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov}; 530f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov 531f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry VyukovBlockingMutex::BlockingMutex(LinkerInitialized) { 532d164ed175a61529589938b3db3cab076a19acf67Dmitry Vyukov CHECK_EQ(owner_, 0); 533f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov} 534f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov 53593af5948d3e0c5bdc396f432dd0ae782f499c449Alexey SamsonovBlockingMutex::BlockingMutex() { 53693af5948d3e0c5bdc396f432dd0ae782f499c449Alexey Samsonov internal_memset(this, 0, sizeof(*this)); 53793af5948d3e0c5bdc396f432dd0ae782f499c449Alexey Samsonov} 53893af5948d3e0c5bdc396f432dd0ae782f499c449Alexey Samsonov 539f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukovvoid BlockingMutex::Lock() { 540f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov atomic_uint32_t *m = reinterpret_cast<atomic_uint32_t *>(&opaque_storage_); 541f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov if (atomic_exchange(m, MtxLocked, memory_order_acquire) == MtxUnlocked) 542f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov return; 543f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov while (atomic_exchange(m, MtxSleeping, memory_order_acquire) != MtxUnlocked) 5449578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne internal_syscall(__NR_futex, m, FUTEX_WAIT, MtxSleeping, 0, 0, 0); 545f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov} 546f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov 547f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukovvoid BlockingMutex::Unlock() { 548f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov atomic_uint32_t *m = reinterpret_cast<atomic_uint32_t *>(&opaque_storage_); 549f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov u32 v = atomic_exchange(m, MtxUnlocked, memory_order_relaxed); 55048526014de78e21f7ed027a60670016bc7f5d292Dmitry Vyukov CHECK_NE(v, MtxUnlocked); 551f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov if (v == MtxSleeping) 5529578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne internal_syscall(__NR_futex, m, FUTEX_WAKE, 1, 0, 0, 0); 553f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov} 554f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov 555ce700979f644c790c2d9d80f5cc2a1ada0380284Alexey Samsonovvoid BlockingMutex::CheckLocked() { 556ce700979f644c790c2d9d80f5cc2a1ada0380284Alexey Samsonov atomic_uint32_t *m = reinterpret_cast<atomic_uint32_t *>(&opaque_storage_); 557ce700979f644c790c2d9d80f5cc2a1ada0380284Alexey Samsonov CHECK_NE(MtxUnlocked, atomic_load(m, memory_order_relaxed)); 558ce700979f644c790c2d9d80f5cc2a1ada0380284Alexey Samsonov} 559ce700979f644c790c2d9d80f5cc2a1ada0380284Alexey Samsonov 5606fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany// ----------------- sanitizer_linux.h 5616fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany// The actual size of this structure is specified by d_reclen. 5626fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany// Note that getdents64 uses a different structure format. We only provide the 5636fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany// 32-bit syscall here. 5646fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryanystruct linux_dirent { 5656fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany unsigned long d_ino; 5666fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany unsigned long d_off; 5676fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany unsigned short d_reclen; 5686fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany char d_name[256]; 5696fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany}; 5706fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany 5716fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany// Syscall wrappers. 5729578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourneuptr internal_ptrace(int request, int pid, void *addr, void *data) { 5739578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne return internal_syscall(__NR_ptrace, request, pid, addr, data); 5749578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne} 5759578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne 5769578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourneuptr internal_waitpid(int pid, int *status, int options) { 5779578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne return internal_syscall(__NR_wait4, pid, status, options, 0 /* rusage */); 5786fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany} 5796fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany 5809578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourneuptr internal_getpid() { 5819578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne return internal_syscall(__NR_getpid); 5826fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany} 5836fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany 5849578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourneuptr internal_getppid() { 5859578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne return internal_syscall(__NR_getppid); 5866fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany} 5876fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany 5889578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourneuptr internal_getdents(fd_t fd, struct linux_dirent *dirp, unsigned int count) { 5899578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne return internal_syscall(__NR_getdents, fd, dirp, count); 5906fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany} 5916fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany 5929578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourneuptr internal_lseek(fd_t fd, OFF_T offset, int whence) { 5939578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne return internal_syscall(__NR_lseek, fd, offset, whence); 5946fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany} 5956fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany 5969578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourneuptr internal_prctl(int option, uptr arg2, uptr arg3, uptr arg4, uptr arg5) { 5979578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne return internal_syscall(__NR_prctl, option, arg2, arg3, arg4, arg5); 5986fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany} 5996fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany 6009578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourneuptr internal_sigaltstack(const struct sigaltstack *ss, 6016fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany struct sigaltstack *oss) { 6029578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne return internal_syscall(__NR_sigaltstack, ss, oss); 6036fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany} 6046fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany 6056fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany// ThreadLister implementation. 6066fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya SerebryanyThreadLister::ThreadLister(int pid) 6076fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany : pid_(pid), 6086fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany descriptor_(-1), 60910f3ab775088bec69dd9e7b611f9b4e152f629bcAlexey Samsonov buffer_(4096), 6106fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany error_(true), 61110f3ab775088bec69dd9e7b611f9b4e152f629bcAlexey Samsonov entry_((struct linux_dirent *)buffer_.data()), 6126fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany bytes_read_(0) { 6136fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany char task_directory_path[80]; 6146fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany internal_snprintf(task_directory_path, sizeof(task_directory_path), 6156fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany "/proc/%d/task/", pid); 6169578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne uptr openrv = internal_open(task_directory_path, O_RDONLY | O_DIRECTORY); 6179578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne if (internal_iserror(openrv)) { 6186fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany error_ = true; 6196fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany Report("Can't open /proc/%d/task for reading.\n", pid); 6206fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany } else { 6216fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany error_ = false; 6229578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne descriptor_ = openrv; 6236fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany } 6246fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany} 6256fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany 6266fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryanyint ThreadLister::GetNextTID() { 6276fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany int tid = -1; 6286fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany do { 6296fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany if (error_) 6306fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany return -1; 6316fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany if ((char *)entry_ >= &buffer_[bytes_read_] && !GetDirectoryEntries()) 6326fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany return -1; 6336fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany if (entry_->d_ino != 0 && entry_->d_name[0] >= '0' && 6346fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany entry_->d_name[0] <= '9') { 6356fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany // Found a valid tid. 6366fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany tid = (int)internal_atoll(entry_->d_name); 6376fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany } 6386fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany entry_ = (struct linux_dirent *)(((char *)entry_) + entry_->d_reclen); 6396fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany } while (tid < 0); 6406fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany return tid; 6416fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany} 6426fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany 6436fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryanyvoid ThreadLister::Reset() { 6446fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany if (error_ || descriptor_ < 0) 6456fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany return; 6466fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany internal_lseek(descriptor_, 0, SEEK_SET); 6476fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany} 6486fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany 6496fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya SerebryanyThreadLister::~ThreadLister() { 6506fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany if (descriptor_ >= 0) 6516fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany internal_close(descriptor_); 6526fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany} 6536fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany 6546fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryanybool ThreadLister::error() { return error_; } 6556fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany 6566fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryanybool ThreadLister::GetDirectoryEntries() { 6576fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany CHECK_GE(descriptor_, 0); 6586fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany CHECK_NE(error_, true); 6596fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany bytes_read_ = internal_getdents(descriptor_, 66010f3ab775088bec69dd9e7b611f9b4e152f629bcAlexey Samsonov (struct linux_dirent *)buffer_.data(), 66110f3ab775088bec69dd9e7b611f9b4e152f629bcAlexey Samsonov buffer_.size()); 6629578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne if (internal_iserror(bytes_read_)) { 6636fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany Report("Can't read directory entries from /proc/%d/task.\n", pid_); 6646fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany error_ = true; 6656fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany return false; 6666fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany } else if (bytes_read_ == 0) { 6676fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany return false; 6686fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany } 66910f3ab775088bec69dd9e7b611f9b4e152f629bcAlexey Samsonov entry_ = (struct linux_dirent *)buffer_.data(); 6706fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany return true; 6716fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany} 6726fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany 6734df343a31cf57c309cf102b9aef870458318f579Peter Collingbourneuptr GetPageSize() { 674a8bc34e420d27c47560b0742cec295e40b0f430eKostya Serebryany#if defined(__x86_64__) || defined(__i386__) 6754df343a31cf57c309cf102b9aef870458318f579Peter Collingbourne return EXEC_PAGESIZE; 676a8bc34e420d27c47560b0742cec295e40b0f430eKostya Serebryany#else 677a8bc34e420d27c47560b0742cec295e40b0f430eKostya Serebryany return sysconf(_SC_PAGESIZE); // EXEC_PAGESIZE may not be trustworthy. 678a8bc34e420d27c47560b0742cec295e40b0f430eKostya Serebryany#endif 6794df343a31cf57c309cf102b9aef870458318f579Peter Collingbourne} 6804df343a31cf57c309cf102b9aef870458318f579Peter Collingbourne 6817847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonovstatic char proc_self_exe_cache_str[kMaxPathLength]; 6827847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonovstatic uptr proc_self_exe_cache_len = 0; 6837847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov 6847847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonovuptr ReadBinaryName(/*out*/char *buf, uptr buf_len) { 6857847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov uptr module_name_len = internal_readlink( 6867847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov "/proc/self/exe", buf, buf_len); 6877847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov int readlink_error; 688356cff7bb61083db3915cf571c5358aa8d3830baNick Lewycky if (internal_iserror(module_name_len, &readlink_error)) { 6897847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov if (proc_self_exe_cache_len) { 6907847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov // If available, use the cached module name. 6917847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov CHECK_LE(proc_self_exe_cache_len, buf_len); 6927847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov internal_strncpy(buf, proc_self_exe_cache_str, buf_len); 6937847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov module_name_len = internal_strlen(proc_self_exe_cache_str); 6947847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov } else { 6957847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov // We can't read /proc/self/exe for some reason, assume the name of the 6967847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov // binary is unknown. 6977847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov Report("WARNING: readlink(\"/proc/self/exe\") failed with errno %d, " 6987847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov "some stack frames may not be symbolized\n", readlink_error); 6997847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov module_name_len = internal_snprintf(buf, buf_len, "/proc/self/exe"); 7007847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov } 7017847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov CHECK_LT(module_name_len, buf_len); 7027847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov buf[module_name_len] = '\0'; 7037847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov } 7047847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov return module_name_len; 7057847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov} 7067847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov 7077847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonovvoid CacheBinaryName() { 7087847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov if (!proc_self_exe_cache_len) { 7097847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov proc_self_exe_cache_len = 7107847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov ReadBinaryName(proc_self_exe_cache_str, kMaxPathLength); 7117847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov } 7127847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov} 7137847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov 7143de0086409d143a612a54a7a0ed809e286656188Sergey Matveev// Match full names of the form /path/to/base_name{-,.}* 7153de0086409d143a612a54a7a0ed809e286656188Sergey Matveevbool LibraryNameIs(const char *full_name, const char *base_name) { 7163de0086409d143a612a54a7a0ed809e286656188Sergey Matveev const char *name = full_name; 7173de0086409d143a612a54a7a0ed809e286656188Sergey Matveev // Strip path. 7183de0086409d143a612a54a7a0ed809e286656188Sergey Matveev while (*name != '\0') name++; 7193de0086409d143a612a54a7a0ed809e286656188Sergey Matveev while (name > full_name && *name != '/') name--; 7203de0086409d143a612a54a7a0ed809e286656188Sergey Matveev if (*name == '/') name++; 7213de0086409d143a612a54a7a0ed809e286656188Sergey Matveev uptr base_name_length = internal_strlen(base_name); 7223de0086409d143a612a54a7a0ed809e286656188Sergey Matveev if (internal_strncmp(name, base_name, base_name_length)) return false; 7233de0086409d143a612a54a7a0ed809e286656188Sergey Matveev return (name[base_name_length] == '-' || name[base_name_length] == '.'); 7243de0086409d143a612a54a7a0ed809e286656188Sergey Matveev} 7253de0086409d143a612a54a7a0ed809e286656188Sergey Matveev 726d054abef27369471e154ec5693949538c2fdffd9Evgeniy Stepanov#if !SANITIZER_ANDROID 7272e75ac983cb233daa1abfa35fb33d2bafffe2ab1Peter Collingbourne// Call cb for each region mapped by map. 7282e75ac983cb233daa1abfa35fb33d2bafffe2ab1Peter Collingbournevoid ForEachMappedRegion(link_map *map, void (*cb)(const void *, uptr)) { 7292e75ac983cb233daa1abfa35fb33d2bafffe2ab1Peter Collingbourne typedef ElfW(Phdr) Elf_Phdr; 7302e75ac983cb233daa1abfa35fb33d2bafffe2ab1Peter Collingbourne typedef ElfW(Ehdr) Elf_Ehdr; 7312e75ac983cb233daa1abfa35fb33d2bafffe2ab1Peter Collingbourne char *base = (char *)map->l_addr; 7322e75ac983cb233daa1abfa35fb33d2bafffe2ab1Peter Collingbourne Elf_Ehdr *ehdr = (Elf_Ehdr *)base; 7332e75ac983cb233daa1abfa35fb33d2bafffe2ab1Peter Collingbourne char *phdrs = base + ehdr->e_phoff; 7342e75ac983cb233daa1abfa35fb33d2bafffe2ab1Peter Collingbourne char *phdrs_end = phdrs + ehdr->e_phnum * ehdr->e_phentsize; 7352e75ac983cb233daa1abfa35fb33d2bafffe2ab1Peter Collingbourne 7362e75ac983cb233daa1abfa35fb33d2bafffe2ab1Peter Collingbourne // Find the segment with the minimum base so we can "relocate" the p_vaddr 7372e75ac983cb233daa1abfa35fb33d2bafffe2ab1Peter Collingbourne // fields. Typically ET_DYN objects (DSOs) have base of zero and ET_EXEC 7382e75ac983cb233daa1abfa35fb33d2bafffe2ab1Peter Collingbourne // objects have a non-zero base. 739f50b0fc601aea71d9fb22f01a11c7e206c666edcPeter Collingbourne uptr preferred_base = (uptr)-1; 7402e75ac983cb233daa1abfa35fb33d2bafffe2ab1Peter Collingbourne for (char *iter = phdrs; iter != phdrs_end; iter += ehdr->e_phentsize) { 7412e75ac983cb233daa1abfa35fb33d2bafffe2ab1Peter Collingbourne Elf_Phdr *phdr = (Elf_Phdr *)iter; 7422e75ac983cb233daa1abfa35fb33d2bafffe2ab1Peter Collingbourne if (phdr->p_type == PT_LOAD && preferred_base > (uptr)phdr->p_vaddr) 7432e75ac983cb233daa1abfa35fb33d2bafffe2ab1Peter Collingbourne preferred_base = (uptr)phdr->p_vaddr; 7442e75ac983cb233daa1abfa35fb33d2bafffe2ab1Peter Collingbourne } 7452e75ac983cb233daa1abfa35fb33d2bafffe2ab1Peter Collingbourne 7462e75ac983cb233daa1abfa35fb33d2bafffe2ab1Peter Collingbourne // Compute the delta from the real base to get a relocation delta. 7472e75ac983cb233daa1abfa35fb33d2bafffe2ab1Peter Collingbourne sptr delta = (uptr)base - preferred_base; 7482e75ac983cb233daa1abfa35fb33d2bafffe2ab1Peter Collingbourne // Now we can figure out what the loader really mapped. 7492e75ac983cb233daa1abfa35fb33d2bafffe2ab1Peter Collingbourne for (char *iter = phdrs; iter != phdrs_end; iter += ehdr->e_phentsize) { 7502e75ac983cb233daa1abfa35fb33d2bafffe2ab1Peter Collingbourne Elf_Phdr *phdr = (Elf_Phdr *)iter; 7512e75ac983cb233daa1abfa35fb33d2bafffe2ab1Peter Collingbourne if (phdr->p_type == PT_LOAD) { 7522e75ac983cb233daa1abfa35fb33d2bafffe2ab1Peter Collingbourne uptr seg_start = phdr->p_vaddr + delta; 7532e75ac983cb233daa1abfa35fb33d2bafffe2ab1Peter Collingbourne uptr seg_end = seg_start + phdr->p_memsz; 7542e75ac983cb233daa1abfa35fb33d2bafffe2ab1Peter Collingbourne // None of these values are aligned. We consider the ragged edges of the 7552e75ac983cb233daa1abfa35fb33d2bafffe2ab1Peter Collingbourne // load command as defined, since they are mapped from the file. 7562e75ac983cb233daa1abfa35fb33d2bafffe2ab1Peter Collingbourne seg_start = RoundDownTo(seg_start, GetPageSizeCached()); 7572e75ac983cb233daa1abfa35fb33d2bafffe2ab1Peter Collingbourne seg_end = RoundUpTo(seg_end, GetPageSizeCached()); 7582e75ac983cb233daa1abfa35fb33d2bafffe2ab1Peter Collingbourne cb((void *)seg_start, seg_end - seg_start); 7592e75ac983cb233daa1abfa35fb33d2bafffe2ab1Peter Collingbourne } 7602e75ac983cb233daa1abfa35fb33d2bafffe2ab1Peter Collingbourne } 7612e75ac983cb233daa1abfa35fb33d2bafffe2ab1Peter Collingbourne} 762d054abef27369471e154ec5693949538c2fdffd9Evgeniy Stepanov#endif 7632e75ac983cb233daa1abfa35fb33d2bafffe2ab1Peter Collingbourne 764cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev#if defined(__x86_64__) 765cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev// We cannot use glibc's clone wrapper, because it messes with the child 766cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev// task's TLS. It writes the PID and TID of the child task to its thread 767cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev// descriptor, but in our case the child task shares the thread descriptor with 768cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev// the parent (because we don't know how to allocate a new thread 769cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev// descriptor to keep glibc happy). So the stock version of clone(), when 770cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev// used with CLONE_VM, would end up corrupting the parent's thread descriptor. 771cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveevuptr internal_clone(int (*fn)(void *), void *child_stack, int flags, void *arg, 772cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev int *parent_tidptr, void *newtls, int *child_tidptr) { 773cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev long long res; 774cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev if (!fn || !child_stack) 775cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev return -EINVAL; 776cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev CHECK_EQ(0, (uptr)child_stack % 16); 777cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev child_stack = (char *)child_stack - 2 * sizeof(void *); 778cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev ((void **)child_stack)[0] = (void *)(uptr)fn; 779cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev ((void **)child_stack)[1] = arg; 780cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev __asm__ __volatile__( 781cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev /* %rax = syscall(%rax = __NR_clone, 782cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev * %rdi = flags, 783cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev * %rsi = child_stack, 784cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev * %rdx = parent_tidptr, 785cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev * %r8 = new_tls, 786cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev * %r10 = child_tidptr) 787cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev */ 788cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev "movq %6,%%r8\n" 789cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev "movq %7,%%r10\n" 790cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev "syscall\n" 791cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev 792cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev /* if (%rax != 0) 793cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev * return; 794cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev */ 795cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev "testq %%rax,%%rax\n" 796cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev "jnz 1f\n" 797cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev 798cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev /* In the child. Terminate unwind chain. */ 799497ae56316cd05a0d539e0d6e065bbaee254aca3Sergey Matveev // XXX: We should also terminate the CFI unwind chain 800497ae56316cd05a0d539e0d6e065bbaee254aca3Sergey Matveev // here. Unfortunately clang 3.2 doesn't support the 801497ae56316cd05a0d539e0d6e065bbaee254aca3Sergey Matveev // necessary CFI directives, so we skip that part. 802cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev "xorq %%rbp,%%rbp\n" 803cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev 804cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev /* Call "fn(arg)". */ 805cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev "popq %%rax\n" 806cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev "popq %%rdi\n" 807cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev "call *%%rax\n" 808cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev 809cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev /* Call _exit(%rax). */ 810cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev "movq %%rax,%%rdi\n" 811cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev "movq %2,%%rax\n" 812cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev "syscall\n" 813cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev 814cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev /* Return to parent. */ 815cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev "1:\n" 816cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev : "=a" (res) 817cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev : "a"(__NR_clone), "i"(__NR_exit), 818cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev "S"(child_stack), 819cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev "D"(flags), 820cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev "d"(parent_tidptr), 821cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev "r"(newtls), 822cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev "r"(child_tidptr) 823cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev : "rsp", "memory", "r8", "r10", "r11", "rcx"); 824cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev return res; 825cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev} 826cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev#endif // defined(__x86_64__) 827ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov} // namespace __sanitizer 828ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov 82946f9395baf65e17f1a3f7a3a1deee72a1560ac53Alexey Samsonov#endif // SANITIZER_LINUX 830