sanitizer_linux.cc revision 7b7801d0811e7091240ddbfdcff817791973ef6f
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//===----------------------------------------------------------------------===// 14ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov#ifdef __linux__ 15ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov 166895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov#include "sanitizer_common.h" 1794b5036ee6ba866e1702848855b6d687d1e70afaAlexey Samsonov#include "sanitizer_internal_defs.h" 18ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov#include "sanitizer_libc.h" 1993da8b6a5e0ed2ca621897504c5d06449b3d7077Alexander Potapenko#include "sanitizer_mutex.h" 20a68633fb76208137ccb807914df52758ee5ca6f0Alexey Samsonov#include "sanitizer_placement_new.h" 216895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov#include "sanitizer_procmaps.h" 22a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryany#include "sanitizer_stacktrace.h" 23ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov 24c5d465136b911bf925f2a631e2b79f1c03e8a1b0Alexey Samsonov#include <fcntl.h> 25e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov#include <pthread.h> 260969bcf2c936126b1f6e636b978aade8fc207437Alexey Samsonov#include <sched.h> 27ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov#include <sys/mman.h> 28e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov#include <sys/resource.h> 29c5d465136b911bf925f2a631e2b79f1c03e8a1b0Alexey Samsonov#include <sys/stat.h> 30ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov#include <sys/syscall.h> 31e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov#include <sys/time.h> 32ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov#include <sys/types.h> 33fa5c41eddf77a3614da0f62044ebf741d86aeab7Dmitry Vyukov#include <sys/prctl.h> 34ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov#include <unistd.h> 35a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryany#include <unwind.h> 363334e12d33261cb8f211f2f49f28ddfa027a40c3Evgeniy Stepanov#include <errno.h> 37fa5c41eddf77a3614da0f62044ebf741d86aeab7Dmitry Vyukov 38fa5c41eddf77a3614da0f62044ebf741d86aeab7Dmitry Vyukov// <linux/futex.h> is broken on some linux distributions. 39fa5c41eddf77a3614da0f62044ebf741d86aeab7Dmitry Vyukovconst int FUTEX_WAIT = 0; 40fa5c41eddf77a3614da0f62044ebf741d86aeab7Dmitry Vyukovconst int FUTEX_WAKE = 1; 41ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov 429d0dbbaf33e5c2fe280f141e30be497d62b703a8Kostya Serebryany// Are we using 32-bit or 64-bit syscalls? 435af39e50366f1aacbebc284f572f08ad1ad07357Kostya Serebryany// x32 (which defines __x86_64__) has SANITIZER_WORDSIZE == 32 4408bfe4988de493dd3e61d02759b3f19c42f8fb78Kostya Serebryany// but it still needs to use 64-bit syscalls. 455af39e50366f1aacbebc284f572f08ad1ad07357Kostya Serebryany#if defined(__x86_64__) || SANITIZER_WORDSIZE == 64 469d0dbbaf33e5c2fe280f141e30be497d62b703a8Kostya Serebryany# define SANITIZER_LINUX_USES_64BIT_SYSCALLS 1 479d0dbbaf33e5c2fe280f141e30be497d62b703a8Kostya Serebryany#else 489d0dbbaf33e5c2fe280f141e30be497d62b703a8Kostya Serebryany# define SANITIZER_LINUX_USES_64BIT_SYSCALLS 0 499d0dbbaf33e5c2fe280f141e30be497d62b703a8Kostya Serebryany#endif 509d0dbbaf33e5c2fe280f141e30be497d62b703a8Kostya Serebryany 51ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonovnamespace __sanitizer { 52ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov 53e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov// --------------- sanitizer_libc.h 54ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonovvoid *internal_mmap(void *addr, uptr length, int prot, int flags, 55ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov int fd, u64 offset) { 569d0dbbaf33e5c2fe280f141e30be497d62b703a8Kostya Serebryany#if SANITIZER_LINUX_USES_64BIT_SYSCALLS 57ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov return (void *)syscall(__NR_mmap, addr, length, prot, flags, fd, offset); 58ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov#else 59ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov return (void *)syscall(__NR_mmap2, addr, length, prot, flags, fd, offset); 60ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov#endif 61ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov} 62ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov 631f11d31faa5ed89b74f7d543b1182fe8de198be5Alexey Samsonovint internal_munmap(void *addr, uptr length) { 641f11d31faa5ed89b74f7d543b1182fe8de198be5Alexey Samsonov return syscall(__NR_munmap, addr, length); 651f11d31faa5ed89b74f7d543b1182fe8de198be5Alexey Samsonov} 661f11d31faa5ed89b74f7d543b1182fe8de198be5Alexey Samsonov 67a56aefd2e01940fcf88d1426f9de3d5e4b1ee203Alexey Samsonovint internal_close(fd_t fd) { 68a56aefd2e01940fcf88d1426f9de3d5e4b1ee203Alexey Samsonov return syscall(__NR_close, fd); 69a56aefd2e01940fcf88d1426f9de3d5e4b1ee203Alexey Samsonov} 70a56aefd2e01940fcf88d1426f9de3d5e4b1ee203Alexey Samsonov 71ee7cc4454421a176d23442382afd9a01d36e7ad4Alexey Samsonovfd_t internal_open(const char *filename, int flags) { 72ee7cc4454421a176d23442382afd9a01d36e7ad4Alexey Samsonov return syscall(__NR_open, filename, flags); 73ee7cc4454421a176d23442382afd9a01d36e7ad4Alexey Samsonov} 74ee7cc4454421a176d23442382afd9a01d36e7ad4Alexey Samsonov 75e85c83dcee3d35068e6670ab32545953d4330335Alexey Samsonovfd_t internal_open(const char *filename, int flags, u32 mode) { 76ee7cc4454421a176d23442382afd9a01d36e7ad4Alexey Samsonov return syscall(__NR_open, filename, flags, mode); 77ee7cc4454421a176d23442382afd9a01d36e7ad4Alexey Samsonov} 78ee7cc4454421a176d23442382afd9a01d36e7ad4Alexey Samsonov 79ee7cc4454421a176d23442382afd9a01d36e7ad4Alexey Samsonovfd_t OpenFile(const char *filename, bool write) { 80ee7cc4454421a176d23442382afd9a01d36e7ad4Alexey Samsonov return internal_open(filename, 819b8a9c1b1ce4659457178ff4c0838ac1b35ca9dcKostya Serebryany write ? O_WRONLY | O_CREAT /*| O_CLOEXEC*/ : O_RDONLY, 0660); 82c5d465136b911bf925f2a631e2b79f1c03e8a1b0Alexey Samsonov} 83c5d465136b911bf925f2a631e2b79f1c03e8a1b0Alexey Samsonov 84a56aefd2e01940fcf88d1426f9de3d5e4b1ee203Alexey Samsonovuptr internal_read(fd_t fd, void *buf, uptr count) { 853334e12d33261cb8f211f2f49f28ddfa027a40c3Evgeniy Stepanov sptr res; 863334e12d33261cb8f211f2f49f28ddfa027a40c3Evgeniy Stepanov HANDLE_EINTR(res, (sptr)syscall(__NR_read, fd, buf, count)); 873334e12d33261cb8f211f2f49f28ddfa027a40c3Evgeniy Stepanov return res; 88a56aefd2e01940fcf88d1426f9de3d5e4b1ee203Alexey Samsonov} 89a56aefd2e01940fcf88d1426f9de3d5e4b1ee203Alexey Samsonov 90a56aefd2e01940fcf88d1426f9de3d5e4b1ee203Alexey Samsonovuptr internal_write(fd_t fd, const void *buf, uptr count) { 913334e12d33261cb8f211f2f49f28ddfa027a40c3Evgeniy Stepanov sptr res; 923334e12d33261cb8f211f2f49f28ddfa027a40c3Evgeniy Stepanov HANDLE_EINTR(res, (sptr)syscall(__NR_write, fd, buf, count)); 933334e12d33261cb8f211f2f49f28ddfa027a40c3Evgeniy Stepanov return res; 94a56aefd2e01940fcf88d1426f9de3d5e4b1ee203Alexey Samsonov} 95a56aefd2e01940fcf88d1426f9de3d5e4b1ee203Alexey Samsonov 964c9317a7b61e136f832d2ede70f557963fd46bceAlexey Samsonovint internal_stat(const char *path, void *buf) { 974c9317a7b61e136f832d2ede70f557963fd46bceAlexey Samsonov#if SANITIZER_LINUX_USES_64BIT_SYSCALLS 984c9317a7b61e136f832d2ede70f557963fd46bceAlexey Samsonov return syscall(__NR_stat, path, buf); 994c9317a7b61e136f832d2ede70f557963fd46bceAlexey Samsonov#else 1004c9317a7b61e136f832d2ede70f557963fd46bceAlexey Samsonov return syscall(__NR_stat64, path, buf); 1014c9317a7b61e136f832d2ede70f557963fd46bceAlexey Samsonov#endif 1024c9317a7b61e136f832d2ede70f557963fd46bceAlexey Samsonov} 1034c9317a7b61e136f832d2ede70f557963fd46bceAlexey Samsonov 1044c9317a7b61e136f832d2ede70f557963fd46bceAlexey Samsonovint internal_lstat(const char *path, void *buf) { 1054c9317a7b61e136f832d2ede70f557963fd46bceAlexey Samsonov#if SANITIZER_LINUX_USES_64BIT_SYSCALLS 1064c9317a7b61e136f832d2ede70f557963fd46bceAlexey Samsonov return syscall(__NR_lstat, path, buf); 1074c9317a7b61e136f832d2ede70f557963fd46bceAlexey Samsonov#else 1084c9317a7b61e136f832d2ede70f557963fd46bceAlexey Samsonov return syscall(__NR_lstat64, path, buf); 1094c9317a7b61e136f832d2ede70f557963fd46bceAlexey Samsonov#endif 1104c9317a7b61e136f832d2ede70f557963fd46bceAlexey Samsonov} 1114c9317a7b61e136f832d2ede70f557963fd46bceAlexey Samsonov 1124c9317a7b61e136f832d2ede70f557963fd46bceAlexey Samsonovint internal_fstat(fd_t fd, void *buf) { 1134c9317a7b61e136f832d2ede70f557963fd46bceAlexey Samsonov#if SANITIZER_LINUX_USES_64BIT_SYSCALLS 1144c9317a7b61e136f832d2ede70f557963fd46bceAlexey Samsonov return syscall(__NR_fstat, fd, buf); 1154c9317a7b61e136f832d2ede70f557963fd46bceAlexey Samsonov#else 1164c9317a7b61e136f832d2ede70f557963fd46bceAlexey Samsonov return syscall(__NR_fstat64, fd, buf); 1174c9317a7b61e136f832d2ede70f557963fd46bceAlexey Samsonov#endif 1184c9317a7b61e136f832d2ede70f557963fd46bceAlexey Samsonov} 1194c9317a7b61e136f832d2ede70f557963fd46bceAlexey Samsonov 1208e820fcf7aafeb8101322182d742fcf99255d972Alexey Samsonovuptr internal_filesize(fd_t fd) { 1219d0dbbaf33e5c2fe280f141e30be497d62b703a8Kostya Serebryany#if SANITIZER_LINUX_USES_64BIT_SYSCALLS 122a68633fb76208137ccb807914df52758ee5ca6f0Alexey Samsonov struct stat st; 123a68633fb76208137ccb807914df52758ee5ca6f0Alexey Samsonov#else 124a68633fb76208137ccb807914df52758ee5ca6f0Alexey Samsonov struct stat64 st; 125a68633fb76208137ccb807914df52758ee5ca6f0Alexey Samsonov#endif 1264c9317a7b61e136f832d2ede70f557963fd46bceAlexey Samsonov if (internal_fstat(fd, &st)) 1274c9317a7b61e136f832d2ede70f557963fd46bceAlexey Samsonov return -1; 1288e820fcf7aafeb8101322182d742fcf99255d972Alexey Samsonov return (uptr)st.st_size; 1298e820fcf7aafeb8101322182d742fcf99255d972Alexey Samsonov} 1308e820fcf7aafeb8101322182d742fcf99255d972Alexey Samsonov 1318e820fcf7aafeb8101322182d742fcf99255d972Alexey Samsonovint internal_dup2(int oldfd, int newfd) { 1328e820fcf7aafeb8101322182d742fcf99255d972Alexey Samsonov return syscall(__NR_dup2, oldfd, newfd); 1338e820fcf7aafeb8101322182d742fcf99255d972Alexey Samsonov} 1348e820fcf7aafeb8101322182d742fcf99255d972Alexey Samsonov 135d1b8f588d6b712b6ff2b3d58c73d71614f520122Alexey Samsonovuptr internal_readlink(const char *path, char *buf, uptr bufsize) { 136d1b8f588d6b712b6ff2b3d58c73d71614f520122Alexey Samsonov return (uptr)syscall(__NR_readlink, path, buf, bufsize); 137d1b8f588d6b712b6ff2b3d58c73d71614f520122Alexey Samsonov} 138d1b8f588d6b712b6ff2b3d58c73d71614f520122Alexey Samsonov 1390969bcf2c936126b1f6e636b978aade8fc207437Alexey Samsonovint internal_sched_yield() { 1400969bcf2c936126b1f6e636b978aade8fc207437Alexey Samsonov return syscall(__NR_sched_yield); 1410969bcf2c936126b1f6e636b978aade8fc207437Alexey Samsonov} 1420969bcf2c936126b1f6e636b978aade8fc207437Alexey Samsonov 143e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov// ----------------- sanitizer_common.h 14493b4cafd631b661b4b612ccdc0938f7f1e1c86d6Alexey Samsonovbool FileExists(const char *filename) { 1459d0dbbaf33e5c2fe280f141e30be497d62b703a8Kostya Serebryany#if SANITIZER_LINUX_USES_64BIT_SYSCALLS 14693b4cafd631b661b4b612ccdc0938f7f1e1c86d6Alexey Samsonov struct stat st; 14793b4cafd631b661b4b612ccdc0938f7f1e1c86d6Alexey Samsonov if (syscall(__NR_stat, filename, &st)) 14893b4cafd631b661b4b612ccdc0938f7f1e1c86d6Alexey Samsonov return false; 14993b4cafd631b661b4b612ccdc0938f7f1e1c86d6Alexey Samsonov#else 15093b4cafd631b661b4b612ccdc0938f7f1e1c86d6Alexey Samsonov struct stat64 st; 15193b4cafd631b661b4b612ccdc0938f7f1e1c86d6Alexey Samsonov if (syscall(__NR_stat64, filename, &st)) 15293b4cafd631b661b4b612ccdc0938f7f1e1c86d6Alexey Samsonov return false; 15393b4cafd631b661b4b612ccdc0938f7f1e1c86d6Alexey Samsonov#endif 15493b4cafd631b661b4b612ccdc0938f7f1e1c86d6Alexey Samsonov // Sanity check: filename is a regular file. 15593b4cafd631b661b4b612ccdc0938f7f1e1c86d6Alexey Samsonov return S_ISREG(st.st_mode); 15693b4cafd631b661b4b612ccdc0938f7f1e1c86d6Alexey Samsonov} 15793b4cafd631b661b4b612ccdc0938f7f1e1c86d6Alexey Samsonov 158e0023f74ea88efee329f68391b70f8adc6b21617Dmitry Vyukovuptr GetTid() { 159e0023f74ea88efee329f68391b70f8adc6b21617Dmitry Vyukov return syscall(__NR_gettid); 160e0023f74ea88efee329f68391b70f8adc6b21617Dmitry Vyukov} 161e0023f74ea88efee329f68391b70f8adc6b21617Dmitry Vyukov 162ed996f79710f532bf231537e44d5c8c9c9d57e8dAlexey Samsonovvoid GetThreadStackTopAndBottom(bool at_initialization, uptr *stack_top, 163e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov uptr *stack_bottom) { 164e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov static const uptr kMaxThreadStackSize = 256 * (1 << 20); // 256M 165e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov CHECK(stack_top); 166e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov CHECK(stack_bottom); 167ed996f79710f532bf231537e44d5c8c9c9d57e8dAlexey Samsonov if (at_initialization) { 168e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov // This is the main thread. Libpthread may not be initialized yet. 169e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov struct rlimit rl; 1706985085c4860bf945358f227ddba26511ae770e9Kostya Serebryany CHECK_EQ(getrlimit(RLIMIT_STACK, &rl), 0); 171e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov 172e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov // Find the mapping that contains a stack variable. 173e1f5dac9296df08ff83ae5fca51ce4da995b55cfAlexey Samsonov MemoryMappingLayout proc_maps; 174e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov uptr start, end, offset; 175e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov uptr prev_end = 0; 176e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov while (proc_maps.Next(&start, &end, &offset, 0, 0)) { 177e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov if ((uptr)&rl < end) 178e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov break; 179e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov prev_end = end; 180e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov } 181e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov CHECK((uptr)&rl >= start && (uptr)&rl < end); 182e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov 183e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov // Get stacksize from rlimit, but clip it so that it does not overlap 184e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov // with other mappings. 185e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov uptr stacksize = rl.rlim_cur; 186e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov if (stacksize > end - prev_end) 187e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov stacksize = end - prev_end; 188e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov // When running with unlimited stack size, we still want to set some limit. 189e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov // The unlimited stack size is caused by 'ulimit -s unlimited'. 190e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov // Also, for some reason, GNU make spawns subprocesses with unlimited stack. 191e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov if (stacksize > kMaxThreadStackSize) 192e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov stacksize = kMaxThreadStackSize; 193e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov *stack_top = end; 194e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov *stack_bottom = end - stacksize; 195e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov return; 196e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov } 197e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov pthread_attr_t attr; 1986985085c4860bf945358f227ddba26511ae770e9Kostya Serebryany CHECK_EQ(pthread_getattr_np(pthread_self(), &attr), 0); 199e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov uptr stacksize = 0; 200e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov void *stackaddr = 0; 201e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov pthread_attr_getstack(&attr, &stackaddr, (size_t*)&stacksize); 202e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov pthread_attr_destroy(&attr); 203e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov 204e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov *stack_top = (uptr)stackaddr + stacksize; 205e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov *stack_bottom = (uptr)stackaddr; 206e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov CHECK(stacksize < kMaxThreadStackSize); // Sanity check. 207e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov} 208e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov 2093dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov// Like getenv, but reads env directly from /proc and does not use libc. 2103dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov// This function should be called first inside __asan_init. 2113dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonovconst char *GetEnv(const char *name) { 2123dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov static char *environ; 2133dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov static uptr len; 2143dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov static bool inited; 2153dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov if (!inited) { 2163dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov inited = true; 2173dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov uptr environ_size; 2183dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov len = ReadFileToBuffer("/proc/self/environ", 2193dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov &environ, &environ_size, 1 << 26); 2203dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov } 2213dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov if (!environ || len == 0) return 0; 2223dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov uptr namelen = internal_strlen(name); 2233dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov const char *p = environ; 2243dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov while (*p != '\0') { // will happen at the \0\0 that terminates the buffer 2253dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov // proc file has the format NAME=value\0NAME=value\0NAME=value\0... 2263dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov const char* endp = 2273dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov (char*)internal_memchr(p, '\0', len - (p - environ)); 2283dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov if (endp == 0) // this entry isn't NUL terminated 2293dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov return 0; 2303dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov else if (!internal_memcmp(p, name, namelen) && p[namelen] == '=') // Match. 2313dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov return p + namelen + 1; // point after = 2323dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov p = endp + 1; 2333dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov } 2343dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov return 0; // Not found. 2353dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov} 2363dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov 23723709c9ad9ac7c45de288f5260403426bf932db7Peter Collingbournestatic void ReadNullSepFileToArray(const char *path, char ***arr, 23823709c9ad9ac7c45de288f5260403426bf932db7Peter Collingbourne int arr_size) { 23923709c9ad9ac7c45de288f5260403426bf932db7Peter Collingbourne char *buff; 240d7e5bb4043adf4756e6f8cfe0f5a3165b185474dAlexey Samsonov uptr buff_size = 0; 24123709c9ad9ac7c45de288f5260403426bf932db7Peter Collingbourne *arr = (char **)MmapOrDie(arr_size * sizeof(char *), "NullSepFileArray"); 24223709c9ad9ac7c45de288f5260403426bf932db7Peter Collingbourne ReadFileToBuffer(path, &buff, &buff_size, 1024 * 1024); 24323709c9ad9ac7c45de288f5260403426bf932db7Peter Collingbourne (*arr)[0] = buff; 24423709c9ad9ac7c45de288f5260403426bf932db7Peter Collingbourne int count, i; 24523709c9ad9ac7c45de288f5260403426bf932db7Peter Collingbourne for (count = 1, i = 1; ; i++) { 246d7e5bb4043adf4756e6f8cfe0f5a3165b185474dAlexey Samsonov if (buff[i] == 0) { 247d7e5bb4043adf4756e6f8cfe0f5a3165b185474dAlexey Samsonov if (buff[i+1] == 0) break; 24823709c9ad9ac7c45de288f5260403426bf932db7Peter Collingbourne (*arr)[count] = &buff[i+1]; 24923709c9ad9ac7c45de288f5260403426bf932db7Peter Collingbourne CHECK_LE(count, arr_size - 1); // FIXME: make this more flexible. 25023709c9ad9ac7c45de288f5260403426bf932db7Peter Collingbourne count++; 251d7e5bb4043adf4756e6f8cfe0f5a3165b185474dAlexey Samsonov } 252d7e5bb4043adf4756e6f8cfe0f5a3165b185474dAlexey Samsonov } 25323709c9ad9ac7c45de288f5260403426bf932db7Peter Collingbourne (*arr)[count] = 0; 25423709c9ad9ac7c45de288f5260403426bf932db7Peter Collingbourne} 25523709c9ad9ac7c45de288f5260403426bf932db7Peter Collingbourne 25623709c9ad9ac7c45de288f5260403426bf932db7Peter Collingbournevoid ReExec() { 2577b7801d0811e7091240ddbfdcff817791973ef6fEvgeniy Stepanov static const int kMaxArgv = 2000, kMaxEnvp = 2000; 25823709c9ad9ac7c45de288f5260403426bf932db7Peter Collingbourne char **argv, **envp; 25923709c9ad9ac7c45de288f5260403426bf932db7Peter Collingbourne ReadNullSepFileToArray("/proc/self/cmdline", &argv, kMaxArgv); 26023709c9ad9ac7c45de288f5260403426bf932db7Peter Collingbourne ReadNullSepFileToArray("/proc/self/environ", &envp, kMaxEnvp); 26123709c9ad9ac7c45de288f5260403426bf932db7Peter Collingbourne execve(argv[0], argv, envp); 262d7e5bb4043adf4756e6f8cfe0f5a3165b185474dAlexey Samsonov} 263d7e5bb4043adf4756e6f8cfe0f5a3165b185474dAlexey Samsonov 26425742574510cfb41b97e32f63f107fbb9b328d13Alexander Potapenkovoid PrepareForSandboxing() { 26525742574510cfb41b97e32f63f107fbb9b328d13Alexander Potapenko // Some kinds of sandboxes may forbid filesystem access, so we won't be able 26625742574510cfb41b97e32f63f107fbb9b328d13Alexander Potapenko // to read the file mappings from /proc/self/maps. Luckily, neither the 26725742574510cfb41b97e32f63f107fbb9b328d13Alexander Potapenko // process will be able to load additional libraries, so it's fine to use the 26825742574510cfb41b97e32f63f107fbb9b328d13Alexander Potapenko // cached mappings. 26925742574510cfb41b97e32f63f107fbb9b328d13Alexander Potapenko MemoryMappingLayout::CacheMemoryMappings(); 27025742574510cfb41b97e32f63f107fbb9b328d13Alexander Potapenko} 27125742574510cfb41b97e32f63f107fbb9b328d13Alexander Potapenko 272e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov// ----------------- sanitizer_procmaps.h 273286dd3f8afe6700e5dd9b0bdb7afd23121c98c12Dmitry Vyukov// Linker initialized. 274286dd3f8afe6700e5dd9b0bdb7afd23121c98c12Dmitry VyukovProcSelfMapsBuff MemoryMappingLayout::cached_proc_self_maps_; 275ad91267d45fef531c1082ab7974e4cc78aba5280Alexander PotapenkoStaticSpinMutex MemoryMappingLayout::cache_lock_; // Linker initialized. 27693da8b6a5e0ed2ca621897504c5d06449b3d7077Alexander Potapenko 277e1f5dac9296df08ff83ae5fca51ce4da995b55cfAlexey SamsonovMemoryMappingLayout::MemoryMappingLayout() { 278ad91267d45fef531c1082ab7974e4cc78aba5280Alexander Potapenko proc_self_maps_.len = 279ad91267d45fef531c1082ab7974e4cc78aba5280Alexander Potapenko ReadFileToBuffer("/proc/self/maps", &proc_self_maps_.data, 280ad91267d45fef531c1082ab7974e4cc78aba5280Alexander Potapenko &proc_self_maps_.mmaped_size, 1 << 26); 281ad91267d45fef531c1082ab7974e4cc78aba5280Alexander Potapenko if (proc_self_maps_.mmaped_size == 0) { 28293da8b6a5e0ed2ca621897504c5d06449b3d7077Alexander Potapenko LoadFromCache(); 283ad91267d45fef531c1082ab7974e4cc78aba5280Alexander Potapenko CHECK_GT(proc_self_maps_.len, 0); 28493da8b6a5e0ed2ca621897504c5d06449b3d7077Alexander Potapenko } 285ad91267d45fef531c1082ab7974e4cc78aba5280Alexander Potapenko // internal_write(2, proc_self_maps_.data, proc_self_maps_.len); 2866895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov Reset(); 28793da8b6a5e0ed2ca621897504c5d06449b3d7077Alexander Potapenko // FIXME: in the future we may want to cache the mappings on demand only. 28893da8b6a5e0ed2ca621897504c5d06449b3d7077Alexander Potapenko CacheMemoryMappings(); 2896895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov} 2906895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov 291e1f5dac9296df08ff83ae5fca51ce4da995b55cfAlexey SamsonovMemoryMappingLayout::~MemoryMappingLayout() { 2927385f8b8b8723064910cf9737dc929e90aeac548Alexander Potapenko // Only unmap the buffer if it is different from the cached one. Otherwise 2937385f8b8b8723064910cf9737dc929e90aeac548Alexander Potapenko // it will be unmapped when the cache is refreshed. 2947385f8b8b8723064910cf9737dc929e90aeac548Alexander Potapenko if (proc_self_maps_.data != cached_proc_self_maps_.data) { 2957385f8b8b8723064910cf9737dc929e90aeac548Alexander Potapenko UnmapOrDie(proc_self_maps_.data, proc_self_maps_.mmaped_size); 2967385f8b8b8723064910cf9737dc929e90aeac548Alexander Potapenko } 2976895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov} 2986895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov 299e1f5dac9296df08ff83ae5fca51ce4da995b55cfAlexey Samsonovvoid MemoryMappingLayout::Reset() { 300ad91267d45fef531c1082ab7974e4cc78aba5280Alexander Potapenko current_ = proc_self_maps_.data; 3016895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov} 3026895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov 30393da8b6a5e0ed2ca621897504c5d06449b3d7077Alexander Potapenko// static 30493da8b6a5e0ed2ca621897504c5d06449b3d7077Alexander Potapenkovoid MemoryMappingLayout::CacheMemoryMappings() { 30593da8b6a5e0ed2ca621897504c5d06449b3d7077Alexander Potapenko SpinMutexLock l(&cache_lock_); 30693da8b6a5e0ed2ca621897504c5d06449b3d7077Alexander Potapenko // Don't invalidate the cache if the mappings are unavailable. 307ad91267d45fef531c1082ab7974e4cc78aba5280Alexander Potapenko ProcSelfMapsBuff old_proc_self_maps; 308ad91267d45fef531c1082ab7974e4cc78aba5280Alexander Potapenko old_proc_self_maps = cached_proc_self_maps_; 309ad91267d45fef531c1082ab7974e4cc78aba5280Alexander Potapenko cached_proc_self_maps_.len = 310ad91267d45fef531c1082ab7974e4cc78aba5280Alexander Potapenko ReadFileToBuffer("/proc/self/maps", &cached_proc_self_maps_.data, 311ad91267d45fef531c1082ab7974e4cc78aba5280Alexander Potapenko &cached_proc_self_maps_.mmaped_size, 1 << 26); 312ad91267d45fef531c1082ab7974e4cc78aba5280Alexander Potapenko if (cached_proc_self_maps_.mmaped_size == 0) { 313ad91267d45fef531c1082ab7974e4cc78aba5280Alexander Potapenko cached_proc_self_maps_ = old_proc_self_maps; 31493da8b6a5e0ed2ca621897504c5d06449b3d7077Alexander Potapenko } else { 315ad91267d45fef531c1082ab7974e4cc78aba5280Alexander Potapenko if (old_proc_self_maps.mmaped_size) { 316ad91267d45fef531c1082ab7974e4cc78aba5280Alexander Potapenko UnmapOrDie(old_proc_self_maps.data, 317ad91267d45fef531c1082ab7974e4cc78aba5280Alexander Potapenko old_proc_self_maps.mmaped_size); 31893da8b6a5e0ed2ca621897504c5d06449b3d7077Alexander Potapenko } 31993da8b6a5e0ed2ca621897504c5d06449b3d7077Alexander Potapenko } 32093da8b6a5e0ed2ca621897504c5d06449b3d7077Alexander Potapenko} 32193da8b6a5e0ed2ca621897504c5d06449b3d7077Alexander Potapenko 32293da8b6a5e0ed2ca621897504c5d06449b3d7077Alexander Potapenkovoid MemoryMappingLayout::LoadFromCache() { 32393da8b6a5e0ed2ca621897504c5d06449b3d7077Alexander Potapenko SpinMutexLock l(&cache_lock_); 324ad91267d45fef531c1082ab7974e4cc78aba5280Alexander Potapenko if (cached_proc_self_maps_.data) { 325286dd3f8afe6700e5dd9b0bdb7afd23121c98c12Dmitry Vyukov proc_self_maps_ = cached_proc_self_maps_; 32693da8b6a5e0ed2ca621897504c5d06449b3d7077Alexander Potapenko } 32793da8b6a5e0ed2ca621897504c5d06449b3d7077Alexander Potapenko} 32893da8b6a5e0ed2ca621897504c5d06449b3d7077Alexander Potapenko 329a4e4744778e6b3067f5cf223cf28bb586c1ecf67Kostya Serebryany// Parse a hex value in str and update str. 330a4e4744778e6b3067f5cf223cf28bb586c1ecf67Kostya Serebryanystatic uptr ParseHex(char **str) { 331a4e4744778e6b3067f5cf223cf28bb586c1ecf67Kostya Serebryany uptr x = 0; 332a4e4744778e6b3067f5cf223cf28bb586c1ecf67Kostya Serebryany char *s; 333a4e4744778e6b3067f5cf223cf28bb586c1ecf67Kostya Serebryany for (s = *str; ; s++) { 334a4e4744778e6b3067f5cf223cf28bb586c1ecf67Kostya Serebryany char c = *s; 335a4e4744778e6b3067f5cf223cf28bb586c1ecf67Kostya Serebryany uptr v = 0; 336a4e4744778e6b3067f5cf223cf28bb586c1ecf67Kostya Serebryany if (c >= '0' && c <= '9') 337a4e4744778e6b3067f5cf223cf28bb586c1ecf67Kostya Serebryany v = c - '0'; 338a4e4744778e6b3067f5cf223cf28bb586c1ecf67Kostya Serebryany else if (c >= 'a' && c <= 'f') 339a4e4744778e6b3067f5cf223cf28bb586c1ecf67Kostya Serebryany v = c - 'a' + 10; 340a4e4744778e6b3067f5cf223cf28bb586c1ecf67Kostya Serebryany else if (c >= 'A' && c <= 'F') 341a4e4744778e6b3067f5cf223cf28bb586c1ecf67Kostya Serebryany v = c - 'A' + 10; 342a4e4744778e6b3067f5cf223cf28bb586c1ecf67Kostya Serebryany else 343a4e4744778e6b3067f5cf223cf28bb586c1ecf67Kostya Serebryany break; 344a4e4744778e6b3067f5cf223cf28bb586c1ecf67Kostya Serebryany x = x * 16 + v; 345a4e4744778e6b3067f5cf223cf28bb586c1ecf67Kostya Serebryany } 346a4e4744778e6b3067f5cf223cf28bb586c1ecf67Kostya Serebryany *str = s; 347a4e4744778e6b3067f5cf223cf28bb586c1ecf67Kostya Serebryany return x; 348a4e4744778e6b3067f5cf223cf28bb586c1ecf67Kostya Serebryany} 349a4e4744778e6b3067f5cf223cf28bb586c1ecf67Kostya Serebryany 350a4e4744778e6b3067f5cf223cf28bb586c1ecf67Kostya Serebryanystatic bool IsOnOf(char c, char c1, char c2) { 351a4e4744778e6b3067f5cf223cf28bb586c1ecf67Kostya Serebryany return c == c1 || c == c2; 352a4e4744778e6b3067f5cf223cf28bb586c1ecf67Kostya Serebryany} 353a4e4744778e6b3067f5cf223cf28bb586c1ecf67Kostya Serebryany 354a4e4744778e6b3067f5cf223cf28bb586c1ecf67Kostya Serebryanystatic bool IsDecimal(char c) { 355a4e4744778e6b3067f5cf223cf28bb586c1ecf67Kostya Serebryany return c >= '0' && c <= '9'; 356a4e4744778e6b3067f5cf223cf28bb586c1ecf67Kostya Serebryany} 357a4e4744778e6b3067f5cf223cf28bb586c1ecf67Kostya Serebryany 358e1f5dac9296df08ff83ae5fca51ce4da995b55cfAlexey Samsonovbool MemoryMappingLayout::Next(uptr *start, uptr *end, uptr *offset, 359e1f5dac9296df08ff83ae5fca51ce4da995b55cfAlexey Samsonov char filename[], uptr filename_size) { 360ad91267d45fef531c1082ab7974e4cc78aba5280Alexander Potapenko char *last = proc_self_maps_.data + proc_self_maps_.len; 3616895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov if (current_ >= last) return false; 3626895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov uptr dummy; 3636895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov if (!start) start = &dummy; 3646895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov if (!end) end = &dummy; 3656895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov if (!offset) offset = &dummy; 3666895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov char *next_line = (char*)internal_memchr(current_, '\n', last - current_); 3676895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov if (next_line == 0) 3686895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov next_line = last; 369a4e4744778e6b3067f5cf223cf28bb586c1ecf67Kostya Serebryany // Example: 08048000-08056000 r-xp 00000000 03:0c 64593 /foo/bar 370a4e4744778e6b3067f5cf223cf28bb586c1ecf67Kostya Serebryany *start = ParseHex(¤t_); 371bb8a9511bc748d6a4fd601d713bda584ef7bb772Kostya Serebryany CHECK_EQ(*current_++, '-'); 372a4e4744778e6b3067f5cf223cf28bb586c1ecf67Kostya Serebryany *end = ParseHex(¤t_); 373bb8a9511bc748d6a4fd601d713bda584ef7bb772Kostya Serebryany CHECK_EQ(*current_++, ' '); 374a4e4744778e6b3067f5cf223cf28bb586c1ecf67Kostya Serebryany CHECK(IsOnOf(*current_++, '-', 'r')); 375a4e4744778e6b3067f5cf223cf28bb586c1ecf67Kostya Serebryany CHECK(IsOnOf(*current_++, '-', 'w')); 376a4e4744778e6b3067f5cf223cf28bb586c1ecf67Kostya Serebryany CHECK(IsOnOf(*current_++, '-', 'x')); 377a4e4744778e6b3067f5cf223cf28bb586c1ecf67Kostya Serebryany CHECK(IsOnOf(*current_++, 's', 'p')); 378bb8a9511bc748d6a4fd601d713bda584ef7bb772Kostya Serebryany CHECK_EQ(*current_++, ' '); 379a4e4744778e6b3067f5cf223cf28bb586c1ecf67Kostya Serebryany *offset = ParseHex(¤t_); 380bb8a9511bc748d6a4fd601d713bda584ef7bb772Kostya Serebryany CHECK_EQ(*current_++, ' '); 381a4e4744778e6b3067f5cf223cf28bb586c1ecf67Kostya Serebryany ParseHex(¤t_); 382bb8a9511bc748d6a4fd601d713bda584ef7bb772Kostya Serebryany CHECK_EQ(*current_++, ':'); 383a4e4744778e6b3067f5cf223cf28bb586c1ecf67Kostya Serebryany ParseHex(¤t_); 384bb8a9511bc748d6a4fd601d713bda584ef7bb772Kostya Serebryany CHECK_EQ(*current_++, ' '); 385a4e4744778e6b3067f5cf223cf28bb586c1ecf67Kostya Serebryany while (IsDecimal(*current_)) 386a4e4744778e6b3067f5cf223cf28bb586c1ecf67Kostya Serebryany current_++; 387bb8a9511bc748d6a4fd601d713bda584ef7bb772Kostya Serebryany CHECK_EQ(*current_++, ' '); 3886895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov // Skip spaces. 3896895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov while (current_ < next_line && *current_ == ' ') 3906895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov current_++; 3916895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov // Fill in the filename. 3926895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov uptr i = 0; 3936895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov while (current_ < next_line) { 3946895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov if (filename && i < filename_size - 1) 3956895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov filename[i++] = *current_; 3966895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov current_++; 3976895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov } 3986895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov if (filename && i < filename_size) 3996895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov filename[i] = 0; 4006895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov current_ = next_line + 1; 4016895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov return true; 4026895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov} 4036895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov 404e1f5dac9296df08ff83ae5fca51ce4da995b55cfAlexey Samsonov// Gets the object name and the offset by walking MemoryMappingLayout. 405e1f5dac9296df08ff83ae5fca51ce4da995b55cfAlexey Samsonovbool MemoryMappingLayout::GetObjectNameAndOffset(uptr addr, uptr *offset, 406e1f5dac9296df08ff83ae5fca51ce4da995b55cfAlexey Samsonov char filename[], 407e1f5dac9296df08ff83ae5fca51ce4da995b55cfAlexey Samsonov uptr filename_size) { 4086895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov return IterateForObjectNameAndOffset(addr, offset, filename, filename_size); 4096895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov} 4106895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov 411dddb18b7be36fe1843c8b98a8d9d7614aef5ce8dKostya Serebryanybool SanitizerSetThreadName(const char *name) { 412b10a5621daa804f3a2b18fbe75d5fed2a4aeadd3Kostya Serebryany#ifdef PR_SET_NAME 4131ec519c604021162de8bdb8d433fbad1c5033200Dmitry Vyukov return 0 == prctl(PR_SET_NAME, (unsigned long)name, 0, 0, 0); // NOLINT 414b10a5621daa804f3a2b18fbe75d5fed2a4aeadd3Kostya Serebryany#else 415b10a5621daa804f3a2b18fbe75d5fed2a4aeadd3Kostya Serebryany return false; 416b10a5621daa804f3a2b18fbe75d5fed2a4aeadd3Kostya Serebryany#endif 417dddb18b7be36fe1843c8b98a8d9d7614aef5ce8dKostya Serebryany} 418dddb18b7be36fe1843c8b98a8d9d7614aef5ce8dKostya Serebryany 419dddb18b7be36fe1843c8b98a8d9d7614aef5ce8dKostya Serebryanybool SanitizerGetThreadName(char *name, int max_len) { 420b10a5621daa804f3a2b18fbe75d5fed2a4aeadd3Kostya Serebryany#ifdef PR_GET_NAME 421dddb18b7be36fe1843c8b98a8d9d7614aef5ce8dKostya Serebryany char buff[17]; 4221ec519c604021162de8bdb8d433fbad1c5033200Dmitry Vyukov if (prctl(PR_GET_NAME, (unsigned long)buff, 0, 0, 0)) // NOLINT 423dddb18b7be36fe1843c8b98a8d9d7614aef5ce8dKostya Serebryany return false; 424dddb18b7be36fe1843c8b98a8d9d7614aef5ce8dKostya Serebryany internal_strncpy(name, buff, max_len); 425dddb18b7be36fe1843c8b98a8d9d7614aef5ce8dKostya Serebryany name[max_len] = 0; 426dddb18b7be36fe1843c8b98a8d9d7614aef5ce8dKostya Serebryany return true; 427b10a5621daa804f3a2b18fbe75d5fed2a4aeadd3Kostya Serebryany#else 428b10a5621daa804f3a2b18fbe75d5fed2a4aeadd3Kostya Serebryany return false; 429b10a5621daa804f3a2b18fbe75d5fed2a4aeadd3Kostya Serebryany#endif 430dddb18b7be36fe1843c8b98a8d9d7614aef5ce8dKostya Serebryany} 431dddb18b7be36fe1843c8b98a8d9d7614aef5ce8dKostya Serebryany 4324fce4495502a3668cc4e99164ffcaea92e534d48Dmitry Vyukov#ifndef SANITIZER_GO 433a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryany//------------------------- SlowUnwindStack ----------------------------------- 434a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryany#ifdef __arm__ 435a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryany#define UNWIND_STOP _URC_END_OF_STACK 436a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryany#define UNWIND_CONTINUE _URC_NO_REASON 437a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryany#else 438a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryany#define UNWIND_STOP _URC_NORMAL_STOP 439a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryany#define UNWIND_CONTINUE _URC_NO_REASON 440a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryany#endif 441a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryany 442a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryanyuptr Unwind_GetIP(struct _Unwind_Context *ctx) { 443a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryany#ifdef __arm__ 444a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryany uptr val; 445a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryany _Unwind_VRS_Result res = _Unwind_VRS_Get(ctx, _UVRSC_CORE, 446a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryany 15 /* r15 = PC */, _UVRSD_UINT32, &val); 447a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryany CHECK(res == _UVRSR_OK && "_Unwind_VRS_Get failed"); 448a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryany // Clear the Thumb bit. 449a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryany return val & ~(uptr)1; 450a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryany#else 451a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryany return _Unwind_GetIP(ctx); 452a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryany#endif 453a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryany} 454a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryany 455a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryany_Unwind_Reason_Code Unwind_Trace(struct _Unwind_Context *ctx, void *param) { 456a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryany StackTrace *b = (StackTrace*)param; 457a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryany CHECK(b->size < b->max_size); 458a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryany uptr pc = Unwind_GetIP(ctx); 459a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryany b->trace[b->size++] = pc; 460a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryany if (b->size == b->max_size) return UNWIND_STOP; 461a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryany return UNWIND_CONTINUE; 462a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryany} 463a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryany 46449d616ec42ab420ce3ebcbe846b21e3729adf5acKostya Serebryanystatic bool MatchPc(uptr cur_pc, uptr trace_pc) { 4655e10443518154a9d68d299ef65a0a99ed42193b7Kostya Serebryany return cur_pc - trace_pc <= 64 || trace_pc - cur_pc <= 64; 46649d616ec42ab420ce3ebcbe846b21e3729adf5acKostya Serebryany} 46749d616ec42ab420ce3ebcbe846b21e3729adf5acKostya Serebryany 46849d616ec42ab420ce3ebcbe846b21e3729adf5acKostya Serebryanyvoid StackTrace::SlowUnwindStack(uptr pc, uptr max_depth) { 469a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryany this->size = 0; 470a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryany this->max_size = max_depth; 471a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryany if (max_depth > 1) { 472a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryany _Unwind_Backtrace(Unwind_Trace, this); 4735e10443518154a9d68d299ef65a0a99ed42193b7Kostya Serebryany // We need to pop a few frames so that pc is on top. 4745e10443518154a9d68d299ef65a0a99ed42193b7Kostya Serebryany // trace[0] belongs to the current function so we always pop it. 47549d616ec42ab420ce3ebcbe846b21e3729adf5acKostya Serebryany int to_pop = 1; 4765e10443518154a9d68d299ef65a0a99ed42193b7Kostya Serebryany /**/ if (size > 1 && MatchPc(pc, trace[1])) to_pop = 1; 4775e10443518154a9d68d299ef65a0a99ed42193b7Kostya Serebryany else if (size > 2 && MatchPc(pc, trace[2])) to_pop = 2; 4785e10443518154a9d68d299ef65a0a99ed42193b7Kostya Serebryany else if (size > 3 && MatchPc(pc, trace[3])) to_pop = 3; 4795e10443518154a9d68d299ef65a0a99ed42193b7Kostya Serebryany else if (size > 4 && MatchPc(pc, trace[4])) to_pop = 4; 4805e10443518154a9d68d299ef65a0a99ed42193b7Kostya Serebryany else if (size > 5 && MatchPc(pc, trace[5])) to_pop = 5; 48149d616ec42ab420ce3ebcbe846b21e3729adf5acKostya Serebryany this->PopStackFrames(to_pop); 482a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryany } 48349d616ec42ab420ce3ebcbe846b21e3729adf5acKostya Serebryany this->trace[0] = pc; 484a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryany} 485a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryany 4864fce4495502a3668cc4e99164ffcaea92e534d48Dmitry Vyukov#endif // #ifndef SANITIZER_GO 4874fce4495502a3668cc4e99164ffcaea92e534d48Dmitry Vyukov 488f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukovenum MutexState { 489f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov MtxUnlocked = 0, 490f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov MtxLocked = 1, 491f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov MtxSleeping = 2 492f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov}; 493f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov 494f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry VyukovBlockingMutex::BlockingMutex(LinkerInitialized) { 495d164ed175a61529589938b3db3cab076a19acf67Dmitry Vyukov CHECK_EQ(owner_, 0); 496f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov} 497f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov 498f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukovvoid BlockingMutex::Lock() { 499f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov atomic_uint32_t *m = reinterpret_cast<atomic_uint32_t *>(&opaque_storage_); 500f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov if (atomic_exchange(m, MtxLocked, memory_order_acquire) == MtxUnlocked) 501f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov return; 502f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov while (atomic_exchange(m, MtxSleeping, memory_order_acquire) != MtxUnlocked) 503c0dbb80bf0eac2771da6faefa5c22155ed4fd33bDmitry Vyukov syscall(__NR_futex, m, FUTEX_WAIT, MtxSleeping, 0, 0, 0); 504f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov} 505f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov 506f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukovvoid BlockingMutex::Unlock() { 507f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov atomic_uint32_t *m = reinterpret_cast<atomic_uint32_t *>(&opaque_storage_); 508f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov u32 v = atomic_exchange(m, MtxUnlocked, memory_order_relaxed); 50948526014de78e21f7ed027a60670016bc7f5d292Dmitry Vyukov CHECK_NE(v, MtxUnlocked); 510f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov if (v == MtxSleeping) 511c0dbb80bf0eac2771da6faefa5c22155ed4fd33bDmitry Vyukov syscall(__NR_futex, m, FUTEX_WAKE, 1, 0, 0, 0); 512f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov} 513f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov 514ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov} // namespace __sanitizer 515ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov 516ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov#endif // __linux__ 517