10b57cec5SDimitry Andric //===-- sanitizer_linux.h ---------------------------------------*- C++ -*-===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric // 90b57cec5SDimitry Andric // Linux-specific syscall wrappers and classes. 100b57cec5SDimitry Andric // 110b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 120b57cec5SDimitry Andric #ifndef SANITIZER_LINUX_H 130b57cec5SDimitry Andric #define SANITIZER_LINUX_H 140b57cec5SDimitry Andric 150b57cec5SDimitry Andric #include "sanitizer_platform.h" 160b57cec5SDimitry Andric #if SANITIZER_FREEBSD || SANITIZER_LINUX || SANITIZER_NETBSD || \ 17e8d8bef9SDimitry Andric SANITIZER_SOLARIS 180b57cec5SDimitry Andric # include "sanitizer_common.h" 190b57cec5SDimitry Andric # include "sanitizer_internal_defs.h" 200b57cec5SDimitry Andric # include "sanitizer_platform_limits_freebsd.h" 210b57cec5SDimitry Andric # include "sanitizer_platform_limits_netbsd.h" 220b57cec5SDimitry Andric # include "sanitizer_platform_limits_posix.h" 230b57cec5SDimitry Andric # include "sanitizer_platform_limits_solaris.h" 240b57cec5SDimitry Andric # include "sanitizer_posix.h" 250b57cec5SDimitry Andric 260b57cec5SDimitry Andric struct link_map; // Opaque type returned by dlopen(). 275ffd83dbSDimitry Andric struct utsname; 280b57cec5SDimitry Andric 290b57cec5SDimitry Andric namespace __sanitizer { 300b57cec5SDimitry Andric // Dirent structure for getdents(). Note that this structure is different from 310b57cec5SDimitry Andric // the one in <dirent.h>, which is used by readdir(). 320b57cec5SDimitry Andric struct linux_dirent; 330b57cec5SDimitry Andric 340b57cec5SDimitry Andric struct ProcSelfMapsBuff { 350b57cec5SDimitry Andric char *data; 360b57cec5SDimitry Andric uptr mmaped_size; 370b57cec5SDimitry Andric uptr len; 380b57cec5SDimitry Andric }; 390b57cec5SDimitry Andric 400b57cec5SDimitry Andric struct MemoryMappingLayoutData { 410b57cec5SDimitry Andric ProcSelfMapsBuff proc_self_maps; 420b57cec5SDimitry Andric const char *current; 430b57cec5SDimitry Andric }; 440b57cec5SDimitry Andric 450b57cec5SDimitry Andric void ReadProcMaps(ProcSelfMapsBuff *proc_maps); 460b57cec5SDimitry Andric 470b57cec5SDimitry Andric // Syscall wrappers. 480b57cec5SDimitry Andric uptr internal_getdents(fd_t fd, struct linux_dirent *dirp, unsigned int count); 490b57cec5SDimitry Andric uptr internal_sigaltstack(const void *ss, void *oss); 500b57cec5SDimitry Andric uptr internal_sigprocmask(int how, __sanitizer_sigset_t *set, 510b57cec5SDimitry Andric __sanitizer_sigset_t *oldset); 52349cc55cSDimitry Andric 53349cc55cSDimitry Andric void SetSigProcMask(__sanitizer_sigset_t *set, __sanitizer_sigset_t *oldset); 5406c3fb27SDimitry Andric void BlockSignals(__sanitizer_sigset_t *oldset = nullptr); 55349cc55cSDimitry Andric struct ScopedBlockSignals { 56349cc55cSDimitry Andric explicit ScopedBlockSignals(__sanitizer_sigset_t *copy); 57349cc55cSDimitry Andric ~ScopedBlockSignals(); 58349cc55cSDimitry Andric 590eae32dcSDimitry Andric ScopedBlockSignals &operator=(const ScopedBlockSignals &) = delete; 600eae32dcSDimitry Andric ScopedBlockSignals(const ScopedBlockSignals &) = delete; 610eae32dcSDimitry Andric 62349cc55cSDimitry Andric private: 63349cc55cSDimitry Andric __sanitizer_sigset_t saved_; 64349cc55cSDimitry Andric }; 65349cc55cSDimitry Andric 66fe6060f1SDimitry Andric # if SANITIZER_GLIBC 670b57cec5SDimitry Andric uptr internal_clock_gettime(__sanitizer_clockid_t clk_id, void *tp); 68fe6060f1SDimitry Andric # endif 690b57cec5SDimitry Andric 700b57cec5SDimitry Andric // Linux-only syscalls. 710b57cec5SDimitry Andric # if SANITIZER_LINUX 720b57cec5SDimitry Andric uptr internal_prctl(int option, uptr arg2, uptr arg3, uptr arg4, uptr arg5); 73753f127fSDimitry Andric # if defined(__x86_64__) 74753f127fSDimitry Andric uptr internal_arch_prctl(int option, uptr arg2); 75753f127fSDimitry Andric # endif 760b57cec5SDimitry Andric // Used only by sanitizer_stoptheworld. Signal handlers that are actually used 770b57cec5SDimitry Andric // (like the process-wide error reporting SEGV handler) must use 780b57cec5SDimitry Andric // internal_sigaction instead. 790b57cec5SDimitry Andric int internal_sigaction_norestorer(int signum, const void *act, void *oldact); 800b57cec5SDimitry Andric void internal_sigdelset(__sanitizer_sigset_t *set, int signum); 81e8d8bef9SDimitry Andric # if defined(__x86_64__) || defined(__mips__) || defined(__aarch64__) || \ 82e8d8bef9SDimitry Andric defined(__powerpc64__) || defined(__s390__) || defined(__i386__) || \ 83bdd1243dSDimitry Andric defined(__arm__) || SANITIZER_RISCV64 || SANITIZER_LOONGARCH64 840b57cec5SDimitry Andric uptr internal_clone(int (*fn)(void *), void *child_stack, int flags, void *arg, 850b57cec5SDimitry Andric int *parent_tidptr, void *newtls, int *child_tidptr); 860b57cec5SDimitry Andric # endif 875ffd83dbSDimitry Andric int internal_uname(struct utsname *buf); 880b57cec5SDimitry Andric # elif SANITIZER_FREEBSD 8981ad6265SDimitry Andric uptr internal_procctl(int type, int id, int cmd, void *data); 900b57cec5SDimitry Andric void internal_sigdelset(__sanitizer_sigset_t *set, int signum); 910b57cec5SDimitry Andric # elif SANITIZER_NETBSD 920b57cec5SDimitry Andric void internal_sigdelset(__sanitizer_sigset_t *set, int signum); 930b57cec5SDimitry Andric uptr internal_clone(int (*fn)(void *), void *child_stack, int flags, void *arg); 940b57cec5SDimitry Andric # endif // SANITIZER_LINUX 950b57cec5SDimitry Andric 960b57cec5SDimitry Andric // This class reads thread IDs from /proc/<pid>/task using only syscalls. 970b57cec5SDimitry Andric class ThreadLister { 980b57cec5SDimitry Andric public: 990b57cec5SDimitry Andric explicit ThreadLister(pid_t pid); 1000b57cec5SDimitry Andric ~ThreadLister(); 1010b57cec5SDimitry Andric enum Result { 1020b57cec5SDimitry Andric Error, 1030b57cec5SDimitry Andric Incomplete, 1040b57cec5SDimitry Andric Ok, 1050b57cec5SDimitry Andric }; 1060b57cec5SDimitry Andric Result ListThreads(InternalMmapVector<tid_t> *threads); 1070b57cec5SDimitry Andric 1080b57cec5SDimitry Andric private: 1090b57cec5SDimitry Andric bool IsAlive(int tid); 1100b57cec5SDimitry Andric 1110b57cec5SDimitry Andric pid_t pid_; 1120b57cec5SDimitry Andric int descriptor_ = -1; 1130b57cec5SDimitry Andric InternalMmapVector<char> buffer_; 1140b57cec5SDimitry Andric }; 1150b57cec5SDimitry Andric 1160b57cec5SDimitry Andric // Exposed for testing. 1170b57cec5SDimitry Andric uptr ThreadDescriptorSize(); 1180b57cec5SDimitry Andric uptr ThreadSelf(); 1190b57cec5SDimitry Andric 1200b57cec5SDimitry Andric // Matches a library's file name against a base name (stripping path and version 1210b57cec5SDimitry Andric // information). 1220b57cec5SDimitry Andric bool LibraryNameIs(const char *full_name, const char *base_name); 1230b57cec5SDimitry Andric 1240b57cec5SDimitry Andric // Call cb for each region mapped by map. 1250b57cec5SDimitry Andric void ForEachMappedRegion(link_map *map, void (*cb)(const void *, uptr)); 1260b57cec5SDimitry Andric 1270b57cec5SDimitry Andric // Releases memory pages entirely within the [beg, end] address range. 1280b57cec5SDimitry Andric // The pages no longer count toward RSS; reads are guaranteed to return 0. 1290b57cec5SDimitry Andric // Requires (but does not verify!) that pages are MAP_PRIVATE. 130e8d8bef9SDimitry Andric inline void ReleaseMemoryPagesToOSAndZeroFill(uptr beg, uptr end) { 1310b57cec5SDimitry Andric // man madvise on Linux promises zero-fill for anonymous private pages. 1320b57cec5SDimitry Andric // Testing shows the same behaviour for private (but not anonymous) mappings 1330b57cec5SDimitry Andric // of shm_open() files, as long as the underlying file is untouched. 1340b57cec5SDimitry Andric CHECK(SANITIZER_LINUX); 1350b57cec5SDimitry Andric ReleaseMemoryPagesToOS(beg, end); 1360b57cec5SDimitry Andric } 1370b57cec5SDimitry Andric 1380b57cec5SDimitry Andric # if SANITIZER_ANDROID 1390b57cec5SDimitry Andric 1400b57cec5SDimitry Andric # if defined(__aarch64__) 1410b57cec5SDimitry Andric # define __get_tls() \ 142*5f757f3fSDimitry Andric ({ \ 143*5f757f3fSDimitry Andric void **__v; \ 144*5f757f3fSDimitry Andric __asm__("mrs %0, tpidr_el0" : "=r"(__v)); \ 145*5f757f3fSDimitry Andric __v; \ 146*5f757f3fSDimitry Andric }) 1470b57cec5SDimitry Andric # elif defined(__arm__) 1480b57cec5SDimitry Andric # define __get_tls() \ 149*5f757f3fSDimitry Andric ({ \ 150*5f757f3fSDimitry Andric void **__v; \ 151*5f757f3fSDimitry Andric __asm__("mrc p15, 0, %0, c13, c0, 3" : "=r"(__v)); \ 152*5f757f3fSDimitry Andric __v; \ 153*5f757f3fSDimitry Andric }) 1540b57cec5SDimitry Andric # elif defined(__mips__) 1550b57cec5SDimitry Andric // On mips32r1, this goes via a kernel illegal instruction trap that's 1560b57cec5SDimitry Andric // optimized for v1. 1570b57cec5SDimitry Andric # define __get_tls() \ 158*5f757f3fSDimitry Andric ({ \ 159*5f757f3fSDimitry Andric register void **__v asm("v1"); \ 160*5f757f3fSDimitry Andric __asm__( \ 161*5f757f3fSDimitry Andric ".set push\n" \ 1620b57cec5SDimitry Andric ".set mips32r2\n" \ 1630b57cec5SDimitry Andric "rdhwr %0,$29\n" \ 164*5f757f3fSDimitry Andric ".set pop\n" \ 165*5f757f3fSDimitry Andric : "=r"(__v)); \ 166*5f757f3fSDimitry Andric __v; \ 167*5f757f3fSDimitry Andric }) 16806c3fb27SDimitry Andric # elif defined(__riscv) 16906c3fb27SDimitry Andric # define __get_tls() \ 170*5f757f3fSDimitry Andric ({ \ 171*5f757f3fSDimitry Andric void **__v; \ 172*5f757f3fSDimitry Andric __asm__("mv %0, tp" : "=r"(__v)); \ 173*5f757f3fSDimitry Andric __v; \ 174*5f757f3fSDimitry Andric }) 1750b57cec5SDimitry Andric # elif defined(__i386__) 1760b57cec5SDimitry Andric # define __get_tls() \ 177*5f757f3fSDimitry Andric ({ \ 178*5f757f3fSDimitry Andric void **__v; \ 179*5f757f3fSDimitry Andric __asm__("movl %%gs:0, %0" : "=r"(__v)); \ 180*5f757f3fSDimitry Andric __v; \ 181*5f757f3fSDimitry Andric }) 1820b57cec5SDimitry Andric # elif defined(__x86_64__) 1830b57cec5SDimitry Andric # define __get_tls() \ 184*5f757f3fSDimitry Andric ({ \ 185*5f757f3fSDimitry Andric void **__v; \ 186*5f757f3fSDimitry Andric __asm__("mov %%fs:0, %0" : "=r"(__v)); \ 187*5f757f3fSDimitry Andric __v; \ 188*5f757f3fSDimitry Andric }) 1890b57cec5SDimitry Andric # else 1900b57cec5SDimitry Andric # error "Unsupported architecture." 1910b57cec5SDimitry Andric # endif 1920b57cec5SDimitry Andric 1930b57cec5SDimitry Andric // The Android Bionic team has allocated a TLS slot for sanitizers starting 1940b57cec5SDimitry Andric // with Q, given that Android currently doesn't support ELF TLS. It is used to 1950b57cec5SDimitry Andric // store sanitizer thread specific data. 1960b57cec5SDimitry Andric static const int TLS_SLOT_SANITIZER = 6; 1970b57cec5SDimitry Andric 1980b57cec5SDimitry Andric ALWAYS_INLINE uptr *get_android_tls_ptr() { 1990b57cec5SDimitry Andric return reinterpret_cast<uptr *>(&__get_tls()[TLS_SLOT_SANITIZER]); 2000b57cec5SDimitry Andric } 2010b57cec5SDimitry Andric 2020b57cec5SDimitry Andric # endif // SANITIZER_ANDROID 2030b57cec5SDimitry Andric 2040b57cec5SDimitry Andric } // namespace __sanitizer 2050b57cec5SDimitry Andric 2060b57cec5SDimitry Andric #endif 2070b57cec5SDimitry Andric #endif // SANITIZER_LINUX_H 208