sanitizer_linux.cc revision 10f3ab775088bec69dd9e7b611f9b4e152f629bc
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 27b114ed83859d8d4964ac2284584733bcd2acf4f6Evgeniy Stepanov#include <dlfcn.h> 2835a7faf1fbfac678136e79d53824672dafb7d13eAlexey Samsonov#include <errno.h> 29c5d465136b911bf925f2a631e2b79f1c03e8a1b0Alexey Samsonov#include <fcntl.h> 30e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov#include <pthread.h> 310969bcf2c936126b1f6e636b978aade8fc207437Alexey Samsonov#include <sched.h> 32ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov#include <sys/mman.h> 336fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany#include <sys/ptrace.h> 34e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov#include <sys/resource.h> 35c5d465136b911bf925f2a631e2b79f1c03e8a1b0Alexey Samsonov#include <sys/stat.h> 36ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov#include <sys/syscall.h> 37e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov#include <sys/time.h> 38ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov#include <sys/types.h> 39fa5c41eddf77a3614da0f62044ebf741d86aeab7Dmitry Vyukov#include <sys/prctl.h> 40ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov#include <unistd.h> 41a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryany#include <unwind.h> 4235a7faf1fbfac678136e79d53824672dafb7d13eAlexey Samsonov 4324e13723f8477d8c42ab8b2a7f4f69fc089842f1Evgeniy Stepanov#if !SANITIZER_ANDROID 4435a7faf1fbfac678136e79d53824672dafb7d13eAlexey Samsonov#include <sys/signal.h> 4535a7faf1fbfac678136e79d53824672dafb7d13eAlexey Samsonov#endif 46fa5c41eddf77a3614da0f62044ebf741d86aeab7Dmitry Vyukov 474bebe7bab966c82f0a8952f797ed3d490624dc62Dmitry Vyukov// <linux/time.h> 484bebe7bab966c82f0a8952f797ed3d490624dc62Dmitry Vyukovstruct kernel_timeval { 494bebe7bab966c82f0a8952f797ed3d490624dc62Dmitry Vyukov long tv_sec; 504bebe7bab966c82f0a8952f797ed3d490624dc62Dmitry Vyukov long tv_usec; 514bebe7bab966c82f0a8952f797ed3d490624dc62Dmitry Vyukov}; 524bebe7bab966c82f0a8952f797ed3d490624dc62Dmitry Vyukov 53fa5c41eddf77a3614da0f62044ebf741d86aeab7Dmitry Vyukov// <linux/futex.h> is broken on some linux distributions. 54fa5c41eddf77a3614da0f62044ebf741d86aeab7Dmitry Vyukovconst int FUTEX_WAIT = 0; 55fa5c41eddf77a3614da0f62044ebf741d86aeab7Dmitry Vyukovconst int FUTEX_WAKE = 1; 56ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov 579d0dbbaf33e5c2fe280f141e30be497d62b703a8Kostya Serebryany// Are we using 32-bit or 64-bit syscalls? 585af39e50366f1aacbebc284f572f08ad1ad07357Kostya Serebryany// x32 (which defines __x86_64__) has SANITIZER_WORDSIZE == 32 5908bfe4988de493dd3e61d02759b3f19c42f8fb78Kostya Serebryany// but it still needs to use 64-bit syscalls. 605af39e50366f1aacbebc284f572f08ad1ad07357Kostya Serebryany#if defined(__x86_64__) || SANITIZER_WORDSIZE == 64 619d0dbbaf33e5c2fe280f141e30be497d62b703a8Kostya Serebryany# define SANITIZER_LINUX_USES_64BIT_SYSCALLS 1 629d0dbbaf33e5c2fe280f141e30be497d62b703a8Kostya Serebryany#else 639d0dbbaf33e5c2fe280f141e30be497d62b703a8Kostya Serebryany# define SANITIZER_LINUX_USES_64BIT_SYSCALLS 0 649d0dbbaf33e5c2fe280f141e30be497d62b703a8Kostya Serebryany#endif 659d0dbbaf33e5c2fe280f141e30be497d62b703a8Kostya Serebryany 66ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonovnamespace __sanitizer { 67ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov 68e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov// --------------- sanitizer_libc.h 69ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonovvoid *internal_mmap(void *addr, uptr length, int prot, int flags, 70ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov int fd, u64 offset) { 719d0dbbaf33e5c2fe280f141e30be497d62b703a8Kostya Serebryany#if SANITIZER_LINUX_USES_64BIT_SYSCALLS 72ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov return (void *)syscall(__NR_mmap, addr, length, prot, flags, fd, offset); 73ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov#else 74ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov return (void *)syscall(__NR_mmap2, addr, length, prot, flags, fd, offset); 75ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov#endif 76ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov} 77ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov 781f11d31faa5ed89b74f7d543b1182fe8de198be5Alexey Samsonovint internal_munmap(void *addr, uptr length) { 791f11d31faa5ed89b74f7d543b1182fe8de198be5Alexey Samsonov return syscall(__NR_munmap, addr, length); 801f11d31faa5ed89b74f7d543b1182fe8de198be5Alexey Samsonov} 811f11d31faa5ed89b74f7d543b1182fe8de198be5Alexey Samsonov 82a56aefd2e01940fcf88d1426f9de3d5e4b1ee203Alexey Samsonovint internal_close(fd_t fd) { 83a56aefd2e01940fcf88d1426f9de3d5e4b1ee203Alexey Samsonov return syscall(__NR_close, fd); 84a56aefd2e01940fcf88d1426f9de3d5e4b1ee203Alexey Samsonov} 85a56aefd2e01940fcf88d1426f9de3d5e4b1ee203Alexey Samsonov 86ee7cc4454421a176d23442382afd9a01d36e7ad4Alexey Samsonovfd_t internal_open(const char *filename, int flags) { 87ee7cc4454421a176d23442382afd9a01d36e7ad4Alexey Samsonov return syscall(__NR_open, filename, flags); 88ee7cc4454421a176d23442382afd9a01d36e7ad4Alexey Samsonov} 89ee7cc4454421a176d23442382afd9a01d36e7ad4Alexey Samsonov 90e85c83dcee3d35068e6670ab32545953d4330335Alexey Samsonovfd_t internal_open(const char *filename, int flags, u32 mode) { 91ee7cc4454421a176d23442382afd9a01d36e7ad4Alexey Samsonov return syscall(__NR_open, filename, flags, mode); 92ee7cc4454421a176d23442382afd9a01d36e7ad4Alexey Samsonov} 93ee7cc4454421a176d23442382afd9a01d36e7ad4Alexey Samsonov 94ee7cc4454421a176d23442382afd9a01d36e7ad4Alexey Samsonovfd_t OpenFile(const char *filename, bool write) { 95ee7cc4454421a176d23442382afd9a01d36e7ad4Alexey Samsonov return internal_open(filename, 969b8a9c1b1ce4659457178ff4c0838ac1b35ca9dcKostya Serebryany write ? O_WRONLY | O_CREAT /*| O_CLOEXEC*/ : O_RDONLY, 0660); 97c5d465136b911bf925f2a631e2b79f1c03e8a1b0Alexey Samsonov} 98c5d465136b911bf925f2a631e2b79f1c03e8a1b0Alexey Samsonov 99a56aefd2e01940fcf88d1426f9de3d5e4b1ee203Alexey Samsonovuptr internal_read(fd_t fd, void *buf, uptr count) { 1003334e12d33261cb8f211f2f49f28ddfa027a40c3Evgeniy Stepanov sptr res; 1013334e12d33261cb8f211f2f49f28ddfa027a40c3Evgeniy Stepanov HANDLE_EINTR(res, (sptr)syscall(__NR_read, fd, buf, count)); 1023334e12d33261cb8f211f2f49f28ddfa027a40c3Evgeniy Stepanov return res; 103a56aefd2e01940fcf88d1426f9de3d5e4b1ee203Alexey Samsonov} 104a56aefd2e01940fcf88d1426f9de3d5e4b1ee203Alexey Samsonov 105a56aefd2e01940fcf88d1426f9de3d5e4b1ee203Alexey Samsonovuptr internal_write(fd_t fd, const void *buf, uptr count) { 1063334e12d33261cb8f211f2f49f28ddfa027a40c3Evgeniy Stepanov sptr res; 1073334e12d33261cb8f211f2f49f28ddfa027a40c3Evgeniy Stepanov HANDLE_EINTR(res, (sptr)syscall(__NR_write, fd, buf, count)); 1083334e12d33261cb8f211f2f49f28ddfa027a40c3Evgeniy Stepanov return res; 109a56aefd2e01940fcf88d1426f9de3d5e4b1ee203Alexey Samsonov} 110a56aefd2e01940fcf88d1426f9de3d5e4b1ee203Alexey Samsonov 1114c9317a7b61e136f832d2ede70f557963fd46bceAlexey Samsonovint internal_stat(const char *path, void *buf) { 1124c9317a7b61e136f832d2ede70f557963fd46bceAlexey Samsonov#if SANITIZER_LINUX_USES_64BIT_SYSCALLS 1134c9317a7b61e136f832d2ede70f557963fd46bceAlexey Samsonov return syscall(__NR_stat, path, buf); 1144c9317a7b61e136f832d2ede70f557963fd46bceAlexey Samsonov#else 1154c9317a7b61e136f832d2ede70f557963fd46bceAlexey Samsonov return syscall(__NR_stat64, path, buf); 1164c9317a7b61e136f832d2ede70f557963fd46bceAlexey Samsonov#endif 1174c9317a7b61e136f832d2ede70f557963fd46bceAlexey Samsonov} 1184c9317a7b61e136f832d2ede70f557963fd46bceAlexey Samsonov 1194c9317a7b61e136f832d2ede70f557963fd46bceAlexey Samsonovint internal_lstat(const char *path, void *buf) { 1204c9317a7b61e136f832d2ede70f557963fd46bceAlexey Samsonov#if SANITIZER_LINUX_USES_64BIT_SYSCALLS 1214c9317a7b61e136f832d2ede70f557963fd46bceAlexey Samsonov return syscall(__NR_lstat, path, buf); 1224c9317a7b61e136f832d2ede70f557963fd46bceAlexey Samsonov#else 1234c9317a7b61e136f832d2ede70f557963fd46bceAlexey Samsonov return syscall(__NR_lstat64, path, buf); 1244c9317a7b61e136f832d2ede70f557963fd46bceAlexey Samsonov#endif 1254c9317a7b61e136f832d2ede70f557963fd46bceAlexey Samsonov} 1264c9317a7b61e136f832d2ede70f557963fd46bceAlexey Samsonov 1274c9317a7b61e136f832d2ede70f557963fd46bceAlexey Samsonovint internal_fstat(fd_t fd, void *buf) { 1284c9317a7b61e136f832d2ede70f557963fd46bceAlexey Samsonov#if SANITIZER_LINUX_USES_64BIT_SYSCALLS 1294c9317a7b61e136f832d2ede70f557963fd46bceAlexey Samsonov return syscall(__NR_fstat, fd, buf); 1304c9317a7b61e136f832d2ede70f557963fd46bceAlexey Samsonov#else 1314c9317a7b61e136f832d2ede70f557963fd46bceAlexey Samsonov return syscall(__NR_fstat64, fd, buf); 1324c9317a7b61e136f832d2ede70f557963fd46bceAlexey Samsonov#endif 1334c9317a7b61e136f832d2ede70f557963fd46bceAlexey Samsonov} 1344c9317a7b61e136f832d2ede70f557963fd46bceAlexey Samsonov 1358e820fcf7aafeb8101322182d742fcf99255d972Alexey Samsonovuptr internal_filesize(fd_t fd) { 1369d0dbbaf33e5c2fe280f141e30be497d62b703a8Kostya Serebryany#if SANITIZER_LINUX_USES_64BIT_SYSCALLS 137a68633fb76208137ccb807914df52758ee5ca6f0Alexey Samsonov struct stat st; 138a68633fb76208137ccb807914df52758ee5ca6f0Alexey Samsonov#else 139a68633fb76208137ccb807914df52758ee5ca6f0Alexey Samsonov struct stat64 st; 140a68633fb76208137ccb807914df52758ee5ca6f0Alexey Samsonov#endif 1414c9317a7b61e136f832d2ede70f557963fd46bceAlexey Samsonov if (internal_fstat(fd, &st)) 1424c9317a7b61e136f832d2ede70f557963fd46bceAlexey Samsonov return -1; 1438e820fcf7aafeb8101322182d742fcf99255d972Alexey Samsonov return (uptr)st.st_size; 1448e820fcf7aafeb8101322182d742fcf99255d972Alexey Samsonov} 1458e820fcf7aafeb8101322182d742fcf99255d972Alexey Samsonov 1468e820fcf7aafeb8101322182d742fcf99255d972Alexey Samsonovint internal_dup2(int oldfd, int newfd) { 1478e820fcf7aafeb8101322182d742fcf99255d972Alexey Samsonov return syscall(__NR_dup2, oldfd, newfd); 1488e820fcf7aafeb8101322182d742fcf99255d972Alexey Samsonov} 1498e820fcf7aafeb8101322182d742fcf99255d972Alexey Samsonov 150d1b8f588d6b712b6ff2b3d58c73d71614f520122Alexey Samsonovuptr internal_readlink(const char *path, char *buf, uptr bufsize) { 151d1b8f588d6b712b6ff2b3d58c73d71614f520122Alexey Samsonov return (uptr)syscall(__NR_readlink, path, buf, bufsize); 152d1b8f588d6b712b6ff2b3d58c73d71614f520122Alexey Samsonov} 153d1b8f588d6b712b6ff2b3d58c73d71614f520122Alexey Samsonov 1546d6ab9eeea4a99370d7ab18ce80eb96091e2cf3fDmitry Vyukovint internal_unlink(const char *path) { 1556d6ab9eeea4a99370d7ab18ce80eb96091e2cf3fDmitry Vyukov return syscall(__NR_unlink, path); 1566d6ab9eeea4a99370d7ab18ce80eb96091e2cf3fDmitry Vyukov} 1576d6ab9eeea4a99370d7ab18ce80eb96091e2cf3fDmitry Vyukov 1580969bcf2c936126b1f6e636b978aade8fc207437Alexey Samsonovint internal_sched_yield() { 1590969bcf2c936126b1f6e636b978aade8fc207437Alexey Samsonov return syscall(__NR_sched_yield); 1600969bcf2c936126b1f6e636b978aade8fc207437Alexey Samsonov} 1610969bcf2c936126b1f6e636b978aade8fc207437Alexey Samsonov 162f882247088952deed954a19d745c2dd8871e2035Alexey Samsonovvoid internal__exit(int exitcode) { 163f882247088952deed954a19d745c2dd8871e2035Alexey Samsonov syscall(__NR_exit_group, exitcode); 164f882247088952deed954a19d745c2dd8871e2035Alexey Samsonov Die(); // Unreachable. 165f882247088952deed954a19d745c2dd8871e2035Alexey Samsonov} 166f882247088952deed954a19d745c2dd8871e2035Alexey Samsonov 167e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov// ----------------- sanitizer_common.h 16893b4cafd631b661b4b612ccdc0938f7f1e1c86d6Alexey Samsonovbool FileExists(const char *filename) { 1699d0dbbaf33e5c2fe280f141e30be497d62b703a8Kostya Serebryany#if SANITIZER_LINUX_USES_64BIT_SYSCALLS 17093b4cafd631b661b4b612ccdc0938f7f1e1c86d6Alexey Samsonov struct stat st; 17193b4cafd631b661b4b612ccdc0938f7f1e1c86d6Alexey Samsonov if (syscall(__NR_stat, filename, &st)) 17293b4cafd631b661b4b612ccdc0938f7f1e1c86d6Alexey Samsonov return false; 17393b4cafd631b661b4b612ccdc0938f7f1e1c86d6Alexey Samsonov#else 17493b4cafd631b661b4b612ccdc0938f7f1e1c86d6Alexey Samsonov struct stat64 st; 17593b4cafd631b661b4b612ccdc0938f7f1e1c86d6Alexey Samsonov if (syscall(__NR_stat64, filename, &st)) 17693b4cafd631b661b4b612ccdc0938f7f1e1c86d6Alexey Samsonov return false; 17793b4cafd631b661b4b612ccdc0938f7f1e1c86d6Alexey Samsonov#endif 17893b4cafd631b661b4b612ccdc0938f7f1e1c86d6Alexey Samsonov // Sanity check: filename is a regular file. 17993b4cafd631b661b4b612ccdc0938f7f1e1c86d6Alexey Samsonov return S_ISREG(st.st_mode); 18093b4cafd631b661b4b612ccdc0938f7f1e1c86d6Alexey Samsonov} 18193b4cafd631b661b4b612ccdc0938f7f1e1c86d6Alexey Samsonov 182e0023f74ea88efee329f68391b70f8adc6b21617Dmitry Vyukovuptr GetTid() { 183e0023f74ea88efee329f68391b70f8adc6b21617Dmitry Vyukov return syscall(__NR_gettid); 184e0023f74ea88efee329f68391b70f8adc6b21617Dmitry Vyukov} 185e0023f74ea88efee329f68391b70f8adc6b21617Dmitry Vyukov 1864bebe7bab966c82f0a8952f797ed3d490624dc62Dmitry Vyukovu64 NanoTime() { 1874bebe7bab966c82f0a8952f797ed3d490624dc62Dmitry Vyukov kernel_timeval tv; 1884bebe7bab966c82f0a8952f797ed3d490624dc62Dmitry Vyukov syscall(__NR_gettimeofday, &tv, 0); 1894bebe7bab966c82f0a8952f797ed3d490624dc62Dmitry Vyukov return (u64)tv.tv_sec * 1000*1000*1000 + tv.tv_usec * 1000; 1904bebe7bab966c82f0a8952f797ed3d490624dc62Dmitry Vyukov} 1914bebe7bab966c82f0a8952f797ed3d490624dc62Dmitry Vyukov 192ed996f79710f532bf231537e44d5c8c9c9d57e8dAlexey Samsonovvoid GetThreadStackTopAndBottom(bool at_initialization, uptr *stack_top, 193e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov uptr *stack_bottom) { 194e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov static const uptr kMaxThreadStackSize = 256 * (1 << 20); // 256M 195e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov CHECK(stack_top); 196e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov CHECK(stack_bottom); 197ed996f79710f532bf231537e44d5c8c9c9d57e8dAlexey Samsonov if (at_initialization) { 198e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov // This is the main thread. Libpthread may not be initialized yet. 199e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov struct rlimit rl; 2006985085c4860bf945358f227ddba26511ae770e9Kostya Serebryany CHECK_EQ(getrlimit(RLIMIT_STACK, &rl), 0); 201e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov 202e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov // Find the mapping that contains a stack variable. 2039ae2883d88dd28b9c5dc862107e6e6d12a35926eAlexander Potapenko MemoryMappingLayout proc_maps(/*cache_enabled*/true); 204e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov uptr start, end, offset; 205e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov uptr prev_end = 0; 20645717c9d5e39a434749ae10509111f9df1b2cdf4Alexey Samsonov while (proc_maps.Next(&start, &end, &offset, 0, 0, /* protection */0)) { 207e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov if ((uptr)&rl < end) 208e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov break; 209e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov prev_end = end; 210e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov } 211e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov CHECK((uptr)&rl >= start && (uptr)&rl < end); 212e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov 213e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov // Get stacksize from rlimit, but clip it so that it does not overlap 214e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov // with other mappings. 215e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov uptr stacksize = rl.rlim_cur; 216e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov if (stacksize > end - prev_end) 217e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov stacksize = end - prev_end; 218e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov // When running with unlimited stack size, we still want to set some limit. 219e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov // The unlimited stack size is caused by 'ulimit -s unlimited'. 220e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov // Also, for some reason, GNU make spawns subprocesses with unlimited stack. 221e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov if (stacksize > kMaxThreadStackSize) 222e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov stacksize = kMaxThreadStackSize; 223e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov *stack_top = end; 224e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov *stack_bottom = end - stacksize; 225e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov return; 226e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov } 227e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov pthread_attr_t attr; 2286985085c4860bf945358f227ddba26511ae770e9Kostya Serebryany CHECK_EQ(pthread_getattr_np(pthread_self(), &attr), 0); 229e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov uptr stacksize = 0; 230e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov void *stackaddr = 0; 231e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov pthread_attr_getstack(&attr, &stackaddr, (size_t*)&stacksize); 232e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov pthread_attr_destroy(&attr); 233e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov 234e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov *stack_top = (uptr)stackaddr + stacksize; 235e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov *stack_bottom = (uptr)stackaddr; 236e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov CHECK(stacksize < kMaxThreadStackSize); // Sanity check. 237e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov} 238e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov 2393dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov// Like getenv, but reads env directly from /proc and does not use libc. 2403dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov// This function should be called first inside __asan_init. 2413dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonovconst char *GetEnv(const char *name) { 2423dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov static char *environ; 2433dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov static uptr len; 2443dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov static bool inited; 2453dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov if (!inited) { 2463dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov inited = true; 2473dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov uptr environ_size; 2483dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov len = ReadFileToBuffer("/proc/self/environ", 2493dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov &environ, &environ_size, 1 << 26); 2503dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov } 2513dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov if (!environ || len == 0) return 0; 2523dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov uptr namelen = internal_strlen(name); 2533dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov const char *p = environ; 2543dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov while (*p != '\0') { // will happen at the \0\0 that terminates the buffer 2553dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov // proc file has the format NAME=value\0NAME=value\0NAME=value\0... 2563dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov const char* endp = 2573dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov (char*)internal_memchr(p, '\0', len - (p - environ)); 2583dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov if (endp == 0) // this entry isn't NUL terminated 2593dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov return 0; 2603dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov else if (!internal_memcmp(p, name, namelen) && p[namelen] == '=') // Match. 2613dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov return p + namelen + 1; // point after = 2623dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov p = endp + 1; 2633dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov } 2643dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov return 0; // Not found. 2653dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov} 2663dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov 267b152b1f1411f47848037ab5120c142cf28a9d487Dmitry Vyukov// Does not compile for Go because dlsym() requires -ldl 268b152b1f1411f47848037ab5120c142cf28a9d487Dmitry Vyukov#ifndef SANITIZER_GO 269b152b1f1411f47848037ab5120c142cf28a9d487Dmitry Vyukovbool SetEnv(const char *name, const char *value) { 270b152b1f1411f47848037ab5120c142cf28a9d487Dmitry Vyukov void *f = dlsym(RTLD_NEXT, "setenv"); 271b152b1f1411f47848037ab5120c142cf28a9d487Dmitry Vyukov if (f == 0) 272b152b1f1411f47848037ab5120c142cf28a9d487Dmitry Vyukov return false; 273b152b1f1411f47848037ab5120c142cf28a9d487Dmitry Vyukov typedef int(*setenv_ft)(const char *name, const char *value, int overwrite); 274b152b1f1411f47848037ab5120c142cf28a9d487Dmitry Vyukov setenv_ft setenv_f; 275b152b1f1411f47848037ab5120c142cf28a9d487Dmitry Vyukov CHECK_EQ(sizeof(setenv_f), sizeof(f)); 276b152b1f1411f47848037ab5120c142cf28a9d487Dmitry Vyukov internal_memcpy(&setenv_f, &f, sizeof(f)); 277b152b1f1411f47848037ab5120c142cf28a9d487Dmitry Vyukov return setenv_f(name, value, 1) == 0; 278b152b1f1411f47848037ab5120c142cf28a9d487Dmitry Vyukov} 279b152b1f1411f47848037ab5120c142cf28a9d487Dmitry Vyukov#endif 280b152b1f1411f47848037ab5120c142cf28a9d487Dmitry Vyukov 281eab061185ec0046d447b298a1dff84f028202a3cEvgeniy Stepanov#ifdef __GLIBC__ 282eab061185ec0046d447b298a1dff84f028202a3cEvgeniy Stepanov 283eab061185ec0046d447b298a1dff84f028202a3cEvgeniy Stepanovextern "C" { 284eab061185ec0046d447b298a1dff84f028202a3cEvgeniy Stepanov extern void *__libc_stack_end; 285eab061185ec0046d447b298a1dff84f028202a3cEvgeniy Stepanov} 286eab061185ec0046d447b298a1dff84f028202a3cEvgeniy Stepanov 287eab061185ec0046d447b298a1dff84f028202a3cEvgeniy Stepanovstatic void GetArgsAndEnv(char ***argv, char ***envp) { 288eab061185ec0046d447b298a1dff84f028202a3cEvgeniy Stepanov uptr *stack_end = (uptr *)__libc_stack_end; 289eab061185ec0046d447b298a1dff84f028202a3cEvgeniy Stepanov int argc = *stack_end; 290eab061185ec0046d447b298a1dff84f028202a3cEvgeniy Stepanov *argv = (char**)(stack_end + 1); 291eab061185ec0046d447b298a1dff84f028202a3cEvgeniy Stepanov *envp = (char**)(stack_end + argc + 2); 292eab061185ec0046d447b298a1dff84f028202a3cEvgeniy Stepanov} 293eab061185ec0046d447b298a1dff84f028202a3cEvgeniy Stepanov 294eab061185ec0046d447b298a1dff84f028202a3cEvgeniy Stepanov#else // __GLIBC__ 295eab061185ec0046d447b298a1dff84f028202a3cEvgeniy Stepanov 29623709c9ad9ac7c45de288f5260403426bf932db7Peter Collingbournestatic void ReadNullSepFileToArray(const char *path, char ***arr, 29723709c9ad9ac7c45de288f5260403426bf932db7Peter Collingbourne int arr_size) { 29823709c9ad9ac7c45de288f5260403426bf932db7Peter Collingbourne char *buff; 299d7e5bb4043adf4756e6f8cfe0f5a3165b185474dAlexey Samsonov uptr buff_size = 0; 30023709c9ad9ac7c45de288f5260403426bf932db7Peter Collingbourne *arr = (char **)MmapOrDie(arr_size * sizeof(char *), "NullSepFileArray"); 30123709c9ad9ac7c45de288f5260403426bf932db7Peter Collingbourne ReadFileToBuffer(path, &buff, &buff_size, 1024 * 1024); 30223709c9ad9ac7c45de288f5260403426bf932db7Peter Collingbourne (*arr)[0] = buff; 30323709c9ad9ac7c45de288f5260403426bf932db7Peter Collingbourne int count, i; 30423709c9ad9ac7c45de288f5260403426bf932db7Peter Collingbourne for (count = 1, i = 1; ; i++) { 305d7e5bb4043adf4756e6f8cfe0f5a3165b185474dAlexey Samsonov if (buff[i] == 0) { 306d7e5bb4043adf4756e6f8cfe0f5a3165b185474dAlexey Samsonov if (buff[i+1] == 0) break; 30723709c9ad9ac7c45de288f5260403426bf932db7Peter Collingbourne (*arr)[count] = &buff[i+1]; 30823709c9ad9ac7c45de288f5260403426bf932db7Peter Collingbourne CHECK_LE(count, arr_size - 1); // FIXME: make this more flexible. 30923709c9ad9ac7c45de288f5260403426bf932db7Peter Collingbourne count++; 310d7e5bb4043adf4756e6f8cfe0f5a3165b185474dAlexey Samsonov } 311d7e5bb4043adf4756e6f8cfe0f5a3165b185474dAlexey Samsonov } 31223709c9ad9ac7c45de288f5260403426bf932db7Peter Collingbourne (*arr)[count] = 0; 31323709c9ad9ac7c45de288f5260403426bf932db7Peter Collingbourne} 31423709c9ad9ac7c45de288f5260403426bf932db7Peter Collingbourne 315eab061185ec0046d447b298a1dff84f028202a3cEvgeniy Stepanovstatic void GetArgsAndEnv(char ***argv, char ***envp) { 3167b7801d0811e7091240ddbfdcff817791973ef6fEvgeniy Stepanov static const int kMaxArgv = 2000, kMaxEnvp = 2000; 317eab061185ec0046d447b298a1dff84f028202a3cEvgeniy Stepanov ReadNullSepFileToArray("/proc/self/cmdline", argv, kMaxArgv); 318eab061185ec0046d447b298a1dff84f028202a3cEvgeniy Stepanov ReadNullSepFileToArray("/proc/self/environ", envp, kMaxEnvp); 319eab061185ec0046d447b298a1dff84f028202a3cEvgeniy Stepanov} 320eab061185ec0046d447b298a1dff84f028202a3cEvgeniy Stepanov 321eab061185ec0046d447b298a1dff84f028202a3cEvgeniy Stepanov#endif // __GLIBC__ 322eab061185ec0046d447b298a1dff84f028202a3cEvgeniy Stepanov 323eab061185ec0046d447b298a1dff84f028202a3cEvgeniy Stepanovvoid ReExec() { 32423709c9ad9ac7c45de288f5260403426bf932db7Peter Collingbourne char **argv, **envp; 325eab061185ec0046d447b298a1dff84f028202a3cEvgeniy Stepanov GetArgsAndEnv(&argv, &envp); 326f35eae83757946decb312deab3f0fe155fe5d580Evgeniy Stepanov execve("/proc/self/exe", argv, envp); 327f35eae83757946decb312deab3f0fe155fe5d580Evgeniy Stepanov Printf("execve failed, errno %d\n", errno); 328f35eae83757946decb312deab3f0fe155fe5d580Evgeniy Stepanov Die(); 329d7e5bb4043adf4756e6f8cfe0f5a3165b185474dAlexey Samsonov} 330d7e5bb4043adf4756e6f8cfe0f5a3165b185474dAlexey Samsonov 33125742574510cfb41b97e32f63f107fbb9b328d13Alexander Potapenkovoid PrepareForSandboxing() { 33225742574510cfb41b97e32f63f107fbb9b328d13Alexander Potapenko // Some kinds of sandboxes may forbid filesystem access, so we won't be able 33325742574510cfb41b97e32f63f107fbb9b328d13Alexander Potapenko // to read the file mappings from /proc/self/maps. Luckily, neither the 33425742574510cfb41b97e32f63f107fbb9b328d13Alexander Potapenko // process will be able to load additional libraries, so it's fine to use the 33525742574510cfb41b97e32f63f107fbb9b328d13Alexander Potapenko // cached mappings. 33625742574510cfb41b97e32f63f107fbb9b328d13Alexander Potapenko MemoryMappingLayout::CacheMemoryMappings(); 33725742574510cfb41b97e32f63f107fbb9b328d13Alexander Potapenko} 33825742574510cfb41b97e32f63f107fbb9b328d13Alexander Potapenko 339e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov// ----------------- sanitizer_procmaps.h 340286dd3f8afe6700e5dd9b0bdb7afd23121c98c12Dmitry Vyukov// Linker initialized. 341286dd3f8afe6700e5dd9b0bdb7afd23121c98c12Dmitry VyukovProcSelfMapsBuff MemoryMappingLayout::cached_proc_self_maps_; 342ad91267d45fef531c1082ab7974e4cc78aba5280Alexander PotapenkoStaticSpinMutex MemoryMappingLayout::cache_lock_; // Linker initialized. 34393da8b6a5e0ed2ca621897504c5d06449b3d7077Alexander Potapenko 3449ae2883d88dd28b9c5dc862107e6e6d12a35926eAlexander PotapenkoMemoryMappingLayout::MemoryMappingLayout(bool cache_enabled) { 345ad91267d45fef531c1082ab7974e4cc78aba5280Alexander Potapenko proc_self_maps_.len = 346ad91267d45fef531c1082ab7974e4cc78aba5280Alexander Potapenko ReadFileToBuffer("/proc/self/maps", &proc_self_maps_.data, 347ad91267d45fef531c1082ab7974e4cc78aba5280Alexander Potapenko &proc_self_maps_.mmaped_size, 1 << 26); 3489ae2883d88dd28b9c5dc862107e6e6d12a35926eAlexander Potapenko if (cache_enabled) { 3499ae2883d88dd28b9c5dc862107e6e6d12a35926eAlexander Potapenko if (proc_self_maps_.mmaped_size == 0) { 3509ae2883d88dd28b9c5dc862107e6e6d12a35926eAlexander Potapenko LoadFromCache(); 3519ae2883d88dd28b9c5dc862107e6e6d12a35926eAlexander Potapenko CHECK_GT(proc_self_maps_.len, 0); 3529ae2883d88dd28b9c5dc862107e6e6d12a35926eAlexander Potapenko } 3539ae2883d88dd28b9c5dc862107e6e6d12a35926eAlexander Potapenko } else { 3549ae2883d88dd28b9c5dc862107e6e6d12a35926eAlexander Potapenko CHECK_GT(proc_self_maps_.mmaped_size, 0); 35593da8b6a5e0ed2ca621897504c5d06449b3d7077Alexander Potapenko } 3566895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov Reset(); 35793da8b6a5e0ed2ca621897504c5d06449b3d7077Alexander Potapenko // FIXME: in the future we may want to cache the mappings on demand only. 3589ae2883d88dd28b9c5dc862107e6e6d12a35926eAlexander Potapenko if (cache_enabled) 3599ae2883d88dd28b9c5dc862107e6e6d12a35926eAlexander Potapenko CacheMemoryMappings(); 3606895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov} 3616895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov 362e1f5dac9296df08ff83ae5fca51ce4da995b55cfAlexey SamsonovMemoryMappingLayout::~MemoryMappingLayout() { 3637385f8b8b8723064910cf9737dc929e90aeac548Alexander Potapenko // Only unmap the buffer if it is different from the cached one. Otherwise 3647385f8b8b8723064910cf9737dc929e90aeac548Alexander Potapenko // it will be unmapped when the cache is refreshed. 3657385f8b8b8723064910cf9737dc929e90aeac548Alexander Potapenko if (proc_self_maps_.data != cached_proc_self_maps_.data) { 3667385f8b8b8723064910cf9737dc929e90aeac548Alexander Potapenko UnmapOrDie(proc_self_maps_.data, proc_self_maps_.mmaped_size); 3677385f8b8b8723064910cf9737dc929e90aeac548Alexander Potapenko } 3686895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov} 3696895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov 370e1f5dac9296df08ff83ae5fca51ce4da995b55cfAlexey Samsonovvoid MemoryMappingLayout::Reset() { 371ad91267d45fef531c1082ab7974e4cc78aba5280Alexander Potapenko current_ = proc_self_maps_.data; 3726895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov} 3736895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov 37493da8b6a5e0ed2ca621897504c5d06449b3d7077Alexander Potapenko// static 37593da8b6a5e0ed2ca621897504c5d06449b3d7077Alexander Potapenkovoid MemoryMappingLayout::CacheMemoryMappings() { 37693da8b6a5e0ed2ca621897504c5d06449b3d7077Alexander Potapenko SpinMutexLock l(&cache_lock_); 37793da8b6a5e0ed2ca621897504c5d06449b3d7077Alexander Potapenko // Don't invalidate the cache if the mappings are unavailable. 378ad91267d45fef531c1082ab7974e4cc78aba5280Alexander Potapenko ProcSelfMapsBuff old_proc_self_maps; 379ad91267d45fef531c1082ab7974e4cc78aba5280Alexander Potapenko old_proc_self_maps = cached_proc_self_maps_; 380ad91267d45fef531c1082ab7974e4cc78aba5280Alexander Potapenko cached_proc_self_maps_.len = 381ad91267d45fef531c1082ab7974e4cc78aba5280Alexander Potapenko ReadFileToBuffer("/proc/self/maps", &cached_proc_self_maps_.data, 382ad91267d45fef531c1082ab7974e4cc78aba5280Alexander Potapenko &cached_proc_self_maps_.mmaped_size, 1 << 26); 383ad91267d45fef531c1082ab7974e4cc78aba5280Alexander Potapenko if (cached_proc_self_maps_.mmaped_size == 0) { 384ad91267d45fef531c1082ab7974e4cc78aba5280Alexander Potapenko cached_proc_self_maps_ = old_proc_self_maps; 38593da8b6a5e0ed2ca621897504c5d06449b3d7077Alexander Potapenko } else { 386ad91267d45fef531c1082ab7974e4cc78aba5280Alexander Potapenko if (old_proc_self_maps.mmaped_size) { 387ad91267d45fef531c1082ab7974e4cc78aba5280Alexander Potapenko UnmapOrDie(old_proc_self_maps.data, 388ad91267d45fef531c1082ab7974e4cc78aba5280Alexander Potapenko old_proc_self_maps.mmaped_size); 38993da8b6a5e0ed2ca621897504c5d06449b3d7077Alexander Potapenko } 39093da8b6a5e0ed2ca621897504c5d06449b3d7077Alexander Potapenko } 39193da8b6a5e0ed2ca621897504c5d06449b3d7077Alexander Potapenko} 39293da8b6a5e0ed2ca621897504c5d06449b3d7077Alexander Potapenko 39393da8b6a5e0ed2ca621897504c5d06449b3d7077Alexander Potapenkovoid MemoryMappingLayout::LoadFromCache() { 39493da8b6a5e0ed2ca621897504c5d06449b3d7077Alexander Potapenko SpinMutexLock l(&cache_lock_); 395ad91267d45fef531c1082ab7974e4cc78aba5280Alexander Potapenko if (cached_proc_self_maps_.data) { 396286dd3f8afe6700e5dd9b0bdb7afd23121c98c12Dmitry Vyukov proc_self_maps_ = cached_proc_self_maps_; 39793da8b6a5e0ed2ca621897504c5d06449b3d7077Alexander Potapenko } 39893da8b6a5e0ed2ca621897504c5d06449b3d7077Alexander Potapenko} 39993da8b6a5e0ed2ca621897504c5d06449b3d7077Alexander Potapenko 400a4e4744778e6b3067f5cf223cf28bb586c1ecf67Kostya Serebryany// Parse a hex value in str and update str. 401a4e4744778e6b3067f5cf223cf28bb586c1ecf67Kostya Serebryanystatic uptr ParseHex(char **str) { 402a4e4744778e6b3067f5cf223cf28bb586c1ecf67Kostya Serebryany uptr x = 0; 403a4e4744778e6b3067f5cf223cf28bb586c1ecf67Kostya Serebryany char *s; 404a4e4744778e6b3067f5cf223cf28bb586c1ecf67Kostya Serebryany for (s = *str; ; s++) { 405a4e4744778e6b3067f5cf223cf28bb586c1ecf67Kostya Serebryany char c = *s; 406a4e4744778e6b3067f5cf223cf28bb586c1ecf67Kostya Serebryany uptr v = 0; 407a4e4744778e6b3067f5cf223cf28bb586c1ecf67Kostya Serebryany if (c >= '0' && c <= '9') 408a4e4744778e6b3067f5cf223cf28bb586c1ecf67Kostya Serebryany v = c - '0'; 409a4e4744778e6b3067f5cf223cf28bb586c1ecf67Kostya Serebryany else if (c >= 'a' && c <= 'f') 410a4e4744778e6b3067f5cf223cf28bb586c1ecf67Kostya Serebryany v = c - 'a' + 10; 411a4e4744778e6b3067f5cf223cf28bb586c1ecf67Kostya Serebryany else if (c >= 'A' && c <= 'F') 412a4e4744778e6b3067f5cf223cf28bb586c1ecf67Kostya Serebryany v = c - 'A' + 10; 413a4e4744778e6b3067f5cf223cf28bb586c1ecf67Kostya Serebryany else 414a4e4744778e6b3067f5cf223cf28bb586c1ecf67Kostya Serebryany break; 415a4e4744778e6b3067f5cf223cf28bb586c1ecf67Kostya Serebryany x = x * 16 + v; 416a4e4744778e6b3067f5cf223cf28bb586c1ecf67Kostya Serebryany } 417a4e4744778e6b3067f5cf223cf28bb586c1ecf67Kostya Serebryany *str = s; 418a4e4744778e6b3067f5cf223cf28bb586c1ecf67Kostya Serebryany return x; 419a4e4744778e6b3067f5cf223cf28bb586c1ecf67Kostya Serebryany} 420a4e4744778e6b3067f5cf223cf28bb586c1ecf67Kostya Serebryany 421ab11e0b10d077945a6e681766b41e12ac6aeb0f0Alexey Samsonovstatic bool IsOneOf(char c, char c1, char c2) { 422a4e4744778e6b3067f5cf223cf28bb586c1ecf67Kostya Serebryany return c == c1 || c == c2; 423a4e4744778e6b3067f5cf223cf28bb586c1ecf67Kostya Serebryany} 424a4e4744778e6b3067f5cf223cf28bb586c1ecf67Kostya Serebryany 425a4e4744778e6b3067f5cf223cf28bb586c1ecf67Kostya Serebryanystatic bool IsDecimal(char c) { 426a4e4744778e6b3067f5cf223cf28bb586c1ecf67Kostya Serebryany return c >= '0' && c <= '9'; 427a4e4744778e6b3067f5cf223cf28bb586c1ecf67Kostya Serebryany} 428a4e4744778e6b3067f5cf223cf28bb586c1ecf67Kostya Serebryany 429e1f5dac9296df08ff83ae5fca51ce4da995b55cfAlexey Samsonovbool MemoryMappingLayout::Next(uptr *start, uptr *end, uptr *offset, 43045717c9d5e39a434749ae10509111f9df1b2cdf4Alexey Samsonov char filename[], uptr filename_size, 43145717c9d5e39a434749ae10509111f9df1b2cdf4Alexey Samsonov uptr *protection) { 432ad91267d45fef531c1082ab7974e4cc78aba5280Alexander Potapenko char *last = proc_self_maps_.data + proc_self_maps_.len; 4336895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov if (current_ >= last) return false; 4346895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov uptr dummy; 4356895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov if (!start) start = &dummy; 4366895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov if (!end) end = &dummy; 4376895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov if (!offset) offset = &dummy; 4386895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov char *next_line = (char*)internal_memchr(current_, '\n', last - current_); 4396895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov if (next_line == 0) 4406895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov next_line = last; 441a4e4744778e6b3067f5cf223cf28bb586c1ecf67Kostya Serebryany // Example: 08048000-08056000 r-xp 00000000 03:0c 64593 /foo/bar 442a4e4744778e6b3067f5cf223cf28bb586c1ecf67Kostya Serebryany *start = ParseHex(¤t_); 443bb8a9511bc748d6a4fd601d713bda584ef7bb772Kostya Serebryany CHECK_EQ(*current_++, '-'); 444a4e4744778e6b3067f5cf223cf28bb586c1ecf67Kostya Serebryany *end = ParseHex(¤t_); 445bb8a9511bc748d6a4fd601d713bda584ef7bb772Kostya Serebryany CHECK_EQ(*current_++, ' '); 44645717c9d5e39a434749ae10509111f9df1b2cdf4Alexey Samsonov uptr local_protection = 0; 447ab11e0b10d077945a6e681766b41e12ac6aeb0f0Alexey Samsonov CHECK(IsOneOf(*current_, '-', 'r')); 44845717c9d5e39a434749ae10509111f9df1b2cdf4Alexey Samsonov if (*current_++ == 'r') 44945717c9d5e39a434749ae10509111f9df1b2cdf4Alexey Samsonov local_protection |= kProtectionRead; 450ab11e0b10d077945a6e681766b41e12ac6aeb0f0Alexey Samsonov CHECK(IsOneOf(*current_, '-', 'w')); 45145717c9d5e39a434749ae10509111f9df1b2cdf4Alexey Samsonov if (*current_++ == 'w') 45245717c9d5e39a434749ae10509111f9df1b2cdf4Alexey Samsonov local_protection |= kProtectionWrite; 453ab11e0b10d077945a6e681766b41e12ac6aeb0f0Alexey Samsonov CHECK(IsOneOf(*current_, '-', 'x')); 45445717c9d5e39a434749ae10509111f9df1b2cdf4Alexey Samsonov if (*current_++ == 'x') 45545717c9d5e39a434749ae10509111f9df1b2cdf4Alexey Samsonov local_protection |= kProtectionExecute; 456ab11e0b10d077945a6e681766b41e12ac6aeb0f0Alexey Samsonov CHECK(IsOneOf(*current_, 's', 'p')); 45745717c9d5e39a434749ae10509111f9df1b2cdf4Alexey Samsonov if (*current_++ == 's') 45845717c9d5e39a434749ae10509111f9df1b2cdf4Alexey Samsonov local_protection |= kProtectionShared; 45945717c9d5e39a434749ae10509111f9df1b2cdf4Alexey Samsonov if (protection) { 46045717c9d5e39a434749ae10509111f9df1b2cdf4Alexey Samsonov *protection = local_protection; 46145717c9d5e39a434749ae10509111f9df1b2cdf4Alexey Samsonov } 462bb8a9511bc748d6a4fd601d713bda584ef7bb772Kostya Serebryany CHECK_EQ(*current_++, ' '); 463a4e4744778e6b3067f5cf223cf28bb586c1ecf67Kostya Serebryany *offset = ParseHex(¤t_); 464bb8a9511bc748d6a4fd601d713bda584ef7bb772Kostya Serebryany CHECK_EQ(*current_++, ' '); 465a4e4744778e6b3067f5cf223cf28bb586c1ecf67Kostya Serebryany ParseHex(¤t_); 466bb8a9511bc748d6a4fd601d713bda584ef7bb772Kostya Serebryany CHECK_EQ(*current_++, ':'); 467a4e4744778e6b3067f5cf223cf28bb586c1ecf67Kostya Serebryany ParseHex(¤t_); 468bb8a9511bc748d6a4fd601d713bda584ef7bb772Kostya Serebryany CHECK_EQ(*current_++, ' '); 469a4e4744778e6b3067f5cf223cf28bb586c1ecf67Kostya Serebryany while (IsDecimal(*current_)) 470a4e4744778e6b3067f5cf223cf28bb586c1ecf67Kostya Serebryany current_++; 471bb8a9511bc748d6a4fd601d713bda584ef7bb772Kostya Serebryany CHECK_EQ(*current_++, ' '); 4726895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov // Skip spaces. 4736895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov while (current_ < next_line && *current_ == ' ') 4746895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov current_++; 4756895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov // Fill in the filename. 4766895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov uptr i = 0; 4776895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov while (current_ < next_line) { 4786895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov if (filename && i < filename_size - 1) 4796895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov filename[i++] = *current_; 4806895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov current_++; 4816895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov } 4826895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov if (filename && i < filename_size) 4836895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov filename[i] = 0; 4846895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov current_ = next_line + 1; 4856895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov return true; 4866895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov} 4876895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov 488e1f5dac9296df08ff83ae5fca51ce4da995b55cfAlexey Samsonov// Gets the object name and the offset by walking MemoryMappingLayout. 489e1f5dac9296df08ff83ae5fca51ce4da995b55cfAlexey Samsonovbool MemoryMappingLayout::GetObjectNameAndOffset(uptr addr, uptr *offset, 490e1f5dac9296df08ff83ae5fca51ce4da995b55cfAlexey Samsonov char filename[], 49145717c9d5e39a434749ae10509111f9df1b2cdf4Alexey Samsonov uptr filename_size, 49245717c9d5e39a434749ae10509111f9df1b2cdf4Alexey Samsonov uptr *protection) { 49345717c9d5e39a434749ae10509111f9df1b2cdf4Alexey Samsonov return IterateForObjectNameAndOffset(addr, offset, filename, filename_size, 49445717c9d5e39a434749ae10509111f9df1b2cdf4Alexey Samsonov protection); 4956895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov} 4966895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov 497dddb18b7be36fe1843c8b98a8d9d7614aef5ce8dKostya Serebryanybool SanitizerSetThreadName(const char *name) { 498b10a5621daa804f3a2b18fbe75d5fed2a4aeadd3Kostya Serebryany#ifdef PR_SET_NAME 4991ec519c604021162de8bdb8d433fbad1c5033200Dmitry Vyukov return 0 == prctl(PR_SET_NAME, (unsigned long)name, 0, 0, 0); // NOLINT 500b10a5621daa804f3a2b18fbe75d5fed2a4aeadd3Kostya Serebryany#else 501b10a5621daa804f3a2b18fbe75d5fed2a4aeadd3Kostya Serebryany return false; 502b10a5621daa804f3a2b18fbe75d5fed2a4aeadd3Kostya Serebryany#endif 503dddb18b7be36fe1843c8b98a8d9d7614aef5ce8dKostya Serebryany} 504dddb18b7be36fe1843c8b98a8d9d7614aef5ce8dKostya Serebryany 505dddb18b7be36fe1843c8b98a8d9d7614aef5ce8dKostya Serebryanybool SanitizerGetThreadName(char *name, int max_len) { 506b10a5621daa804f3a2b18fbe75d5fed2a4aeadd3Kostya Serebryany#ifdef PR_GET_NAME 507dddb18b7be36fe1843c8b98a8d9d7614aef5ce8dKostya Serebryany char buff[17]; 5081ec519c604021162de8bdb8d433fbad1c5033200Dmitry Vyukov if (prctl(PR_GET_NAME, (unsigned long)buff, 0, 0, 0)) // NOLINT 509dddb18b7be36fe1843c8b98a8d9d7614aef5ce8dKostya Serebryany return false; 510dddb18b7be36fe1843c8b98a8d9d7614aef5ce8dKostya Serebryany internal_strncpy(name, buff, max_len); 511dddb18b7be36fe1843c8b98a8d9d7614aef5ce8dKostya Serebryany name[max_len] = 0; 512dddb18b7be36fe1843c8b98a8d9d7614aef5ce8dKostya Serebryany return true; 513b10a5621daa804f3a2b18fbe75d5fed2a4aeadd3Kostya Serebryany#else 514b10a5621daa804f3a2b18fbe75d5fed2a4aeadd3Kostya Serebryany return false; 515b10a5621daa804f3a2b18fbe75d5fed2a4aeadd3Kostya Serebryany#endif 516dddb18b7be36fe1843c8b98a8d9d7614aef5ce8dKostya Serebryany} 517dddb18b7be36fe1843c8b98a8d9d7614aef5ce8dKostya Serebryany 5184fce4495502a3668cc4e99164ffcaea92e534d48Dmitry Vyukov#ifndef SANITIZER_GO 519a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryany//------------------------- SlowUnwindStack ----------------------------------- 520a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryany#ifdef __arm__ 521a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryany#define UNWIND_STOP _URC_END_OF_STACK 522a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryany#define UNWIND_CONTINUE _URC_NO_REASON 523a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryany#else 524a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryany#define UNWIND_STOP _URC_NORMAL_STOP 525a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryany#define UNWIND_CONTINUE _URC_NO_REASON 526a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryany#endif 527a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryany 528a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryanyuptr Unwind_GetIP(struct _Unwind_Context *ctx) { 529a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryany#ifdef __arm__ 530a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryany uptr val; 531a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryany _Unwind_VRS_Result res = _Unwind_VRS_Get(ctx, _UVRSC_CORE, 532a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryany 15 /* r15 = PC */, _UVRSD_UINT32, &val); 533a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryany CHECK(res == _UVRSR_OK && "_Unwind_VRS_Get failed"); 534a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryany // Clear the Thumb bit. 535a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryany return val & ~(uptr)1; 536a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryany#else 537a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryany return _Unwind_GetIP(ctx); 538a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryany#endif 539a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryany} 540a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryany 541a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryany_Unwind_Reason_Code Unwind_Trace(struct _Unwind_Context *ctx, void *param) { 542a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryany StackTrace *b = (StackTrace*)param; 543a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryany CHECK(b->size < b->max_size); 544a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryany uptr pc = Unwind_GetIP(ctx); 545a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryany b->trace[b->size++] = pc; 546a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryany if (b->size == b->max_size) return UNWIND_STOP; 547a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryany return UNWIND_CONTINUE; 548a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryany} 549a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryany 55049d616ec42ab420ce3ebcbe846b21e3729adf5acKostya Serebryanystatic bool MatchPc(uptr cur_pc, uptr trace_pc) { 5515e10443518154a9d68d299ef65a0a99ed42193b7Kostya Serebryany return cur_pc - trace_pc <= 64 || trace_pc - cur_pc <= 64; 55249d616ec42ab420ce3ebcbe846b21e3729adf5acKostya Serebryany} 55349d616ec42ab420ce3ebcbe846b21e3729adf5acKostya Serebryany 55449d616ec42ab420ce3ebcbe846b21e3729adf5acKostya Serebryanyvoid StackTrace::SlowUnwindStack(uptr pc, uptr max_depth) { 555a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryany this->size = 0; 556a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryany this->max_size = max_depth; 557a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryany if (max_depth > 1) { 558a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryany _Unwind_Backtrace(Unwind_Trace, this); 5595e10443518154a9d68d299ef65a0a99ed42193b7Kostya Serebryany // We need to pop a few frames so that pc is on top. 5605e10443518154a9d68d299ef65a0a99ed42193b7Kostya Serebryany // trace[0] belongs to the current function so we always pop it. 56149d616ec42ab420ce3ebcbe846b21e3729adf5acKostya Serebryany int to_pop = 1; 5625e10443518154a9d68d299ef65a0a99ed42193b7Kostya Serebryany /**/ if (size > 1 && MatchPc(pc, trace[1])) to_pop = 1; 5635e10443518154a9d68d299ef65a0a99ed42193b7Kostya Serebryany else if (size > 2 && MatchPc(pc, trace[2])) to_pop = 2; 5645e10443518154a9d68d299ef65a0a99ed42193b7Kostya Serebryany else if (size > 3 && MatchPc(pc, trace[3])) to_pop = 3; 5655e10443518154a9d68d299ef65a0a99ed42193b7Kostya Serebryany else if (size > 4 && MatchPc(pc, trace[4])) to_pop = 4; 5665e10443518154a9d68d299ef65a0a99ed42193b7Kostya Serebryany else if (size > 5 && MatchPc(pc, trace[5])) to_pop = 5; 56749d616ec42ab420ce3ebcbe846b21e3729adf5acKostya Serebryany this->PopStackFrames(to_pop); 568a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryany } 56949d616ec42ab420ce3ebcbe846b21e3729adf5acKostya Serebryany this->trace[0] = pc; 570a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryany} 571a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryany 5724fce4495502a3668cc4e99164ffcaea92e534d48Dmitry Vyukov#endif // #ifndef SANITIZER_GO 5734fce4495502a3668cc4e99164ffcaea92e534d48Dmitry Vyukov 574f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukovenum MutexState { 575f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov MtxUnlocked = 0, 576f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov MtxLocked = 1, 577f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov MtxSleeping = 2 578f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov}; 579f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov 580f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry VyukovBlockingMutex::BlockingMutex(LinkerInitialized) { 581d164ed175a61529589938b3db3cab076a19acf67Dmitry Vyukov CHECK_EQ(owner_, 0); 582f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov} 583f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov 58493af5948d3e0c5bdc396f432dd0ae782f499c449Alexey SamsonovBlockingMutex::BlockingMutex() { 58593af5948d3e0c5bdc396f432dd0ae782f499c449Alexey Samsonov internal_memset(this, 0, sizeof(*this)); 58693af5948d3e0c5bdc396f432dd0ae782f499c449Alexey Samsonov} 58793af5948d3e0c5bdc396f432dd0ae782f499c449Alexey Samsonov 588f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukovvoid BlockingMutex::Lock() { 589f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov atomic_uint32_t *m = reinterpret_cast<atomic_uint32_t *>(&opaque_storage_); 590f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov if (atomic_exchange(m, MtxLocked, memory_order_acquire) == MtxUnlocked) 591f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov return; 592f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov while (atomic_exchange(m, MtxSleeping, memory_order_acquire) != MtxUnlocked) 593c0dbb80bf0eac2771da6faefa5c22155ed4fd33bDmitry Vyukov syscall(__NR_futex, m, FUTEX_WAIT, MtxSleeping, 0, 0, 0); 594f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov} 595f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov 596f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukovvoid BlockingMutex::Unlock() { 597f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov atomic_uint32_t *m = reinterpret_cast<atomic_uint32_t *>(&opaque_storage_); 598f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov u32 v = atomic_exchange(m, MtxUnlocked, memory_order_relaxed); 59948526014de78e21f7ed027a60670016bc7f5d292Dmitry Vyukov CHECK_NE(v, MtxUnlocked); 600f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov if (v == MtxSleeping) 601c0dbb80bf0eac2771da6faefa5c22155ed4fd33bDmitry Vyukov syscall(__NR_futex, m, FUTEX_WAKE, 1, 0, 0, 0); 602f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov} 603f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov 604ce700979f644c790c2d9d80f5cc2a1ada0380284Alexey Samsonovvoid BlockingMutex::CheckLocked() { 605ce700979f644c790c2d9d80f5cc2a1ada0380284Alexey Samsonov atomic_uint32_t *m = reinterpret_cast<atomic_uint32_t *>(&opaque_storage_); 606ce700979f644c790c2d9d80f5cc2a1ada0380284Alexey Samsonov CHECK_NE(MtxUnlocked, atomic_load(m, memory_order_relaxed)); 607ce700979f644c790c2d9d80f5cc2a1ada0380284Alexey Samsonov} 608ce700979f644c790c2d9d80f5cc2a1ada0380284Alexey Samsonov 6096fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany// ----------------- sanitizer_linux.h 6106fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany// The actual size of this structure is specified by d_reclen. 6116fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany// Note that getdents64 uses a different structure format. We only provide the 6126fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany// 32-bit syscall here. 6136fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryanystruct linux_dirent { 6146fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany unsigned long d_ino; 6156fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany unsigned long d_off; 6166fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany unsigned short d_reclen; 6176fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany char d_name[256]; 6186fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany}; 6196fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany 6206fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany// Syscall wrappers. 6216fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryanylong internal_ptrace(int request, int pid, void *addr, void *data) { 6226fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany return syscall(__NR_ptrace, request, pid, addr, data); 6236fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany} 6246fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany 6256fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryanyint internal_waitpid(int pid, int *status, int options) { 6266fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany return syscall(__NR_wait4, pid, status, options, NULL /* rusage */); 6276fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany} 6286fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany 6296fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryanyint internal_getppid() { 6306fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany return syscall(__NR_getppid); 6316fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany} 6326fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany 6336fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryanyint internal_getdents(fd_t fd, struct linux_dirent *dirp, unsigned int count) { 6346fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany return syscall(__NR_getdents, fd, dirp, count); 6356fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany} 6366fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany 6376fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya SerebryanyOFF_T internal_lseek(fd_t fd, OFF_T offset, int whence) { 6386fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany return syscall(__NR_lseek, fd, offset, whence); 6396fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany} 6406fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany 6416fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryanyint internal_prctl(int option, uptr arg2, uptr arg3, uptr arg4, uptr arg5) { 6426fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany return syscall(__NR_prctl, option, arg2, arg3, arg4, arg5); 6436fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany} 6446fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany 6456fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryanyint internal_sigaltstack(const struct sigaltstack *ss, 6466fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany struct sigaltstack *oss) { 6476fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany return syscall(__NR_sigaltstack, ss, oss); 6486fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany} 6496fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany 6506fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany// ThreadLister implementation. 6516fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya SerebryanyThreadLister::ThreadLister(int pid) 6526fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany : pid_(pid), 6536fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany descriptor_(-1), 65410f3ab775088bec69dd9e7b611f9b4e152f629bcAlexey Samsonov buffer_(4096), 6556fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany error_(true), 65610f3ab775088bec69dd9e7b611f9b4e152f629bcAlexey Samsonov entry_((struct linux_dirent *)buffer_.data()), 6576fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany bytes_read_(0) { 6586fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany char task_directory_path[80]; 6596fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany internal_snprintf(task_directory_path, sizeof(task_directory_path), 6606fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany "/proc/%d/task/", pid); 6616fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany descriptor_ = internal_open(task_directory_path, O_RDONLY | O_DIRECTORY); 6626fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany if (descriptor_ < 0) { 6636fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany error_ = true; 6646fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany Report("Can't open /proc/%d/task for reading.\n", pid); 6656fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany } else { 6666fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany error_ = false; 6676fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany } 6686fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany} 6696fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany 6706fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryanyint ThreadLister::GetNextTID() { 6716fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany int tid = -1; 6726fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany do { 6736fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany if (error_) 6746fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany return -1; 6756fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany if ((char *)entry_ >= &buffer_[bytes_read_] && !GetDirectoryEntries()) 6766fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany return -1; 6776fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany if (entry_->d_ino != 0 && entry_->d_name[0] >= '0' && 6786fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany entry_->d_name[0] <= '9') { 6796fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany // Found a valid tid. 6806fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany tid = (int)internal_atoll(entry_->d_name); 6816fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany } 6826fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany entry_ = (struct linux_dirent *)(((char *)entry_) + entry_->d_reclen); 6836fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany } while (tid < 0); 6846fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany return tid; 6856fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany} 6866fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany 6876fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryanyvoid ThreadLister::Reset() { 6886fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany if (error_ || descriptor_ < 0) 6896fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany return; 6906fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany internal_lseek(descriptor_, 0, SEEK_SET); 6916fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany} 6926fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany 6936fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya SerebryanyThreadLister::~ThreadLister() { 6946fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany if (descriptor_ >= 0) 6956fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany internal_close(descriptor_); 6966fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany} 6976fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany 6986fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryanybool ThreadLister::error() { return error_; } 6996fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany 7006fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryanybool ThreadLister::GetDirectoryEntries() { 7016fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany CHECK_GE(descriptor_, 0); 7026fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany CHECK_NE(error_, true); 7036fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany bytes_read_ = internal_getdents(descriptor_, 70410f3ab775088bec69dd9e7b611f9b4e152f629bcAlexey Samsonov (struct linux_dirent *)buffer_.data(), 70510f3ab775088bec69dd9e7b611f9b4e152f629bcAlexey Samsonov buffer_.size()); 7066fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany if (bytes_read_ < 0) { 7076fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany Report("Can't read directory entries from /proc/%d/task.\n", pid_); 7086fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany error_ = true; 7096fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany return false; 7106fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany } else if (bytes_read_ == 0) { 7116fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany return false; 7126fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany } 71310f3ab775088bec69dd9e7b611f9b4e152f629bcAlexey Samsonov entry_ = (struct linux_dirent *)buffer_.data(); 7146fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany return true; 7156fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany} 7166fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany 717b114ed83859d8d4964ac2284584733bcd2acf4f6Evgeniy Stepanovstatic uptr g_tls_size; 718b114ed83859d8d4964ac2284584733bcd2acf4f6Evgeniy Stepanov 719b114ed83859d8d4964ac2284584733bcd2acf4f6Evgeniy Stepanov#ifdef __i386__ 720b114ed83859d8d4964ac2284584733bcd2acf4f6Evgeniy Stepanov# define DL_INTERNAL_FUNCTION __attribute__((regparm(3), stdcall)) 721b114ed83859d8d4964ac2284584733bcd2acf4f6Evgeniy Stepanov#else 722b114ed83859d8d4964ac2284584733bcd2acf4f6Evgeniy Stepanov# define DL_INTERNAL_FUNCTION 723b114ed83859d8d4964ac2284584733bcd2acf4f6Evgeniy Stepanov#endif 724b114ed83859d8d4964ac2284584733bcd2acf4f6Evgeniy Stepanov 725b114ed83859d8d4964ac2284584733bcd2acf4f6Evgeniy Stepanovvoid InitTlsSize() { 726b114ed83859d8d4964ac2284584733bcd2acf4f6Evgeniy Stepanov#ifndef SANITIZER_GO 727b114ed83859d8d4964ac2284584733bcd2acf4f6Evgeniy Stepanov typedef void (*get_tls_func)(size_t*, size_t*) DL_INTERNAL_FUNCTION; 728b114ed83859d8d4964ac2284584733bcd2acf4f6Evgeniy Stepanov get_tls_func get_tls; 729b114ed83859d8d4964ac2284584733bcd2acf4f6Evgeniy Stepanov void *get_tls_static_info_ptr = dlsym(RTLD_NEXT, "_dl_get_tls_static_info"); 730b114ed83859d8d4964ac2284584733bcd2acf4f6Evgeniy Stepanov CHECK_EQ(sizeof(get_tls), sizeof(get_tls_static_info_ptr)); 731b114ed83859d8d4964ac2284584733bcd2acf4f6Evgeniy Stepanov internal_memcpy(&get_tls, &get_tls_static_info_ptr, 732b114ed83859d8d4964ac2284584733bcd2acf4f6Evgeniy Stepanov sizeof(get_tls_static_info_ptr)); 733b114ed83859d8d4964ac2284584733bcd2acf4f6Evgeniy Stepanov CHECK_NE(get_tls, 0); 734b114ed83859d8d4964ac2284584733bcd2acf4f6Evgeniy Stepanov size_t tls_size = 0; 735b114ed83859d8d4964ac2284584733bcd2acf4f6Evgeniy Stepanov size_t tls_align = 0; 736b114ed83859d8d4964ac2284584733bcd2acf4f6Evgeniy Stepanov get_tls(&tls_size, &tls_align); 737b114ed83859d8d4964ac2284584733bcd2acf4f6Evgeniy Stepanov g_tls_size = tls_size; 738b114ed83859d8d4964ac2284584733bcd2acf4f6Evgeniy Stepanov#endif 739b114ed83859d8d4964ac2284584733bcd2acf4f6Evgeniy Stepanov} 740b114ed83859d8d4964ac2284584733bcd2acf4f6Evgeniy Stepanov 741b114ed83859d8d4964ac2284584733bcd2acf4f6Evgeniy Stepanovuptr GetTlsSize() { 742b114ed83859d8d4964ac2284584733bcd2acf4f6Evgeniy Stepanov return g_tls_size; 743b114ed83859d8d4964ac2284584733bcd2acf4f6Evgeniy Stepanov} 744b114ed83859d8d4964ac2284584733bcd2acf4f6Evgeniy Stepanov 745b9bf700ae7fe59e25976e0abe9636150f3a39cd2Evgeniy Stepanovvoid AdjustStackSizeLinux(void *attr_, int verbosity) { 746b9bf700ae7fe59e25976e0abe9636150f3a39cd2Evgeniy Stepanov pthread_attr_t *attr = (pthread_attr_t *)attr_; 747609a02ad07f09147e2fe7beaa257b8c607aca033Evgeniy Stepanov uptr stackaddr = 0; 748b9bf700ae7fe59e25976e0abe9636150f3a39cd2Evgeniy Stepanov size_t stacksize = 0; 749b9bf700ae7fe59e25976e0abe9636150f3a39cd2Evgeniy Stepanov pthread_attr_getstack(attr, (void**)&stackaddr, &stacksize); 750b9bf700ae7fe59e25976e0abe9636150f3a39cd2Evgeniy Stepanov // GLibC will return (0 - stacksize) as the stack address in the case when 751b9bf700ae7fe59e25976e0abe9636150f3a39cd2Evgeniy Stepanov // stacksize is set, but stackaddr is not. 752b9bf700ae7fe59e25976e0abe9636150f3a39cd2Evgeniy Stepanov bool stack_set = (stackaddr != 0) && (stackaddr + stacksize != 0); 753b9bf700ae7fe59e25976e0abe9636150f3a39cd2Evgeniy Stepanov // We place a lot of tool data into TLS, account for that. 754b9bf700ae7fe59e25976e0abe9636150f3a39cd2Evgeniy Stepanov const uptr minstacksize = GetTlsSize() + 128*1024; 755b9bf700ae7fe59e25976e0abe9636150f3a39cd2Evgeniy Stepanov if (stacksize < minstacksize) { 756b9bf700ae7fe59e25976e0abe9636150f3a39cd2Evgeniy Stepanov if (!stack_set) { 757b9bf700ae7fe59e25976e0abe9636150f3a39cd2Evgeniy Stepanov if (verbosity && stacksize != 0) 758b9bf700ae7fe59e25976e0abe9636150f3a39cd2Evgeniy Stepanov Printf("Sanitizer: increasing stacksize %zu->%zu\n", stacksize, 759b9bf700ae7fe59e25976e0abe9636150f3a39cd2Evgeniy Stepanov minstacksize); 760b9bf700ae7fe59e25976e0abe9636150f3a39cd2Evgeniy Stepanov pthread_attr_setstacksize(attr, minstacksize); 761b9bf700ae7fe59e25976e0abe9636150f3a39cd2Evgeniy Stepanov } else { 762b9bf700ae7fe59e25976e0abe9636150f3a39cd2Evgeniy Stepanov Printf("Sanitizer: pre-allocated stack size is insufficient: " 763b9bf700ae7fe59e25976e0abe9636150f3a39cd2Evgeniy Stepanov "%zu < %zu\n", stacksize, minstacksize); 764b9bf700ae7fe59e25976e0abe9636150f3a39cd2Evgeniy Stepanov Printf("Sanitizer: pthread_create is likely to fail.\n"); 765b9bf700ae7fe59e25976e0abe9636150f3a39cd2Evgeniy Stepanov } 766b9bf700ae7fe59e25976e0abe9636150f3a39cd2Evgeniy Stepanov } 767b9bf700ae7fe59e25976e0abe9636150f3a39cd2Evgeniy Stepanov} 768b9bf700ae7fe59e25976e0abe9636150f3a39cd2Evgeniy Stepanov 769ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov} // namespace __sanitizer 770ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov 77146f9395baf65e17f1a3f7a3a1deee72a1560ac53Alexey Samsonov#endif // SANITIZER_LINUX 772