1 | //===-- sanitizer_linux.h ---------------------------------------*- C++ -*-===// |
2 | // |
3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
4 | // See https://llvm.org/LICENSE.txt for license information. |
5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
6 | // |
7 | //===----------------------------------------------------------------------===// |
8 | // |
9 | // Linux-specific syscall wrappers and classes. |
10 | // |
11 | //===----------------------------------------------------------------------===// |
12 | #ifndef SANITIZER_LINUX_H |
13 | #define SANITIZER_LINUX_H |
14 | |
15 | #include "sanitizer_platform.h" |
16 | #if SANITIZER_FREEBSD || SANITIZER_LINUX || SANITIZER_NETBSD || \ |
17 | SANITIZER_SOLARIS |
18 | #include "sanitizer_common.h" |
19 | #include "sanitizer_internal_defs.h" |
20 | #include "sanitizer_platform_limits_freebsd.h" |
21 | #include "sanitizer_platform_limits_netbsd.h" |
22 | #include "sanitizer_platform_limits_posix.h" |
23 | #include "sanitizer_platform_limits_solaris.h" |
24 | #include "sanitizer_posix.h" |
25 | |
26 | struct link_map; // Opaque type returned by dlopen(). |
27 | struct utsname; |
28 | |
29 | namespace __sanitizer { |
30 | // Dirent structure for getdents(). Note that this structure is different from |
31 | // the one in <dirent.h>, which is used by readdir(). |
32 | struct linux_dirent; |
33 | |
34 | struct ProcSelfMapsBuff { |
35 | char *data; |
36 | uptr mmaped_size; |
37 | uptr len; |
38 | }; |
39 | |
40 | struct MemoryMappingLayoutData { |
41 | ProcSelfMapsBuff proc_self_maps; |
42 | const char *current; |
43 | }; |
44 | |
45 | void ReadProcMaps(ProcSelfMapsBuff *proc_maps); |
46 | |
47 | // Syscall wrappers. |
48 | uptr internal_getdents(fd_t fd, struct linux_dirent *dirp, unsigned int count); |
49 | uptr internal_sigaltstack(const void* ss, void* oss); |
50 | uptr internal_sigprocmask(int how, __sanitizer_sigset_t *set, |
51 | __sanitizer_sigset_t *oldset); |
52 | #if SANITIZER_GLIBC |
53 | uptr internal_clock_gettime(__sanitizer_clockid_t clk_id, void *tp); |
54 | #endif |
55 | |
56 | // Linux-only syscalls. |
57 | #if SANITIZER_LINUX |
58 | uptr internal_prctl(int option, uptr arg2, uptr arg3, uptr arg4, uptr arg5); |
59 | // Used only by sanitizer_stoptheworld. Signal handlers that are actually used |
60 | // (like the process-wide error reporting SEGV handler) must use |
61 | // internal_sigaction instead. |
62 | int internal_sigaction_norestorer(int signum, const void *act, void *oldact); |
63 | void internal_sigdelset(__sanitizer_sigset_t *set, int signum); |
64 | #if defined(__x86_64__) || defined(__mips__) || defined(__aarch64__) || \ |
65 | defined(__powerpc64__) || defined(__s390__) || defined(__i386__) || \ |
66 | defined(__arm__) || SANITIZER_RISCV64 |
67 | uptr internal_clone(int (*fn)(void *), void *child_stack, int flags, void *arg, |
68 | int *parent_tidptr, void *newtls, int *child_tidptr); |
69 | #endif |
70 | int internal_uname(struct utsname *buf); |
71 | #elif SANITIZER_FREEBSD |
72 | void internal_sigdelset(__sanitizer_sigset_t *set, int signum); |
73 | #elif SANITIZER_NETBSD |
74 | void internal_sigdelset(__sanitizer_sigset_t *set, int signum); |
75 | uptr internal_clone(int (*fn)(void *), void *child_stack, int flags, void *arg); |
76 | #endif // SANITIZER_LINUX |
77 | |
78 | // This class reads thread IDs from /proc/<pid>/task using only syscalls. |
79 | class ThreadLister { |
80 | public: |
81 | explicit ThreadLister(pid_t pid); |
82 | ~ThreadLister(); |
83 | enum Result { |
84 | Error, |
85 | Incomplete, |
86 | Ok, |
87 | }; |
88 | Result ListThreads(InternalMmapVector<tid_t> *threads); |
89 | |
90 | private: |
91 | bool IsAlive(int tid); |
92 | |
93 | pid_t pid_; |
94 | int descriptor_ = -1; |
95 | InternalMmapVector<char> buffer_; |
96 | }; |
97 | |
98 | // Exposed for testing. |
99 | uptr ThreadDescriptorSize(); |
100 | uptr ThreadSelf(); |
101 | |
102 | // Matches a library's file name against a base name (stripping path and version |
103 | // information). |
104 | bool LibraryNameIs(const char *full_name, const char *base_name); |
105 | |
106 | // Call cb for each region mapped by map. |
107 | void ForEachMappedRegion(link_map *map, void (*cb)(const void *, uptr)); |
108 | |
109 | // Releases memory pages entirely within the [beg, end] address range. |
110 | // The pages no longer count toward RSS; reads are guaranteed to return 0. |
111 | // Requires (but does not verify!) that pages are MAP_PRIVATE. |
112 | inline void ReleaseMemoryPagesToOSAndZeroFill(uptr beg, uptr end) { |
113 | // man madvise on Linux promises zero-fill for anonymous private pages. |
114 | // Testing shows the same behaviour for private (but not anonymous) mappings |
115 | // of shm_open() files, as long as the underlying file is untouched. |
116 | CHECK(SANITIZER_LINUX); |
117 | ReleaseMemoryPagesToOS(beg, end); |
118 | } |
119 | |
120 | #if SANITIZER_ANDROID |
121 | |
122 | #if defined(__aarch64__) |
123 | # define __get_tls() \ |
124 | ({ void** __v; __asm__("mrs %0, tpidr_el0" : "=r"(__v)); __v; }) |
125 | #elif defined(__arm__) |
126 | # define __get_tls() \ |
127 | ({ void** __v; __asm__("mrc p15, 0, %0, c13, c0, 3" : "=r"(__v)); __v; }) |
128 | #elif defined(__mips__) |
129 | // On mips32r1, this goes via a kernel illegal instruction trap that's |
130 | // optimized for v1. |
131 | # define __get_tls() \ |
132 | ({ register void** __v asm("v1"); \ |
133 | __asm__(".set push\n" \ |
134 | ".set mips32r2\n" \ |
135 | "rdhwr %0,$29\n" \ |
136 | ".set pop\n" : "=r"(__v)); \ |
137 | __v; }) |
138 | #elif defined(__i386__) |
139 | # define __get_tls() \ |
140 | ({ void** __v; __asm__("movl %%gs:0, %0" : "=r"(__v)); __v; }) |
141 | #elif defined(__x86_64__) |
142 | # define __get_tls() \ |
143 | ({ void** __v; __asm__("mov %%fs:0, %0" : "=r"(__v)); __v; }) |
144 | #else |
145 | #error "Unsupported architecture." |
146 | #endif |
147 | |
148 | // The Android Bionic team has allocated a TLS slot for sanitizers starting |
149 | // with Q, given that Android currently doesn't support ELF TLS. It is used to |
150 | // store sanitizer thread specific data. |
151 | static const int TLS_SLOT_SANITIZER = 6; |
152 | |
153 | ALWAYS_INLINE uptr *get_android_tls_ptr() { |
154 | return reinterpret_cast<uptr *>(&__get_tls()[TLS_SLOT_SANITIZER]); |
155 | } |
156 | |
157 | #endif // SANITIZER_ANDROID |
158 | |
159 | } // namespace __sanitizer |
160 | |
161 | #endif |
162 | #endif // SANITIZER_LINUX_H |
163 | |