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 | |
53 | void SetSigProcMask(__sanitizer_sigset_t *set, __sanitizer_sigset_t *oldset); |
54 | void BlockSignals(__sanitizer_sigset_t *oldset = nullptr); |
55 | struct ScopedBlockSignals { |
56 | explicit ScopedBlockSignals(__sanitizer_sigset_t *copy); |
57 | ~ScopedBlockSignals(); |
58 | |
59 | ScopedBlockSignals &operator=(const ScopedBlockSignals &) = delete; |
60 | ScopedBlockSignals(const ScopedBlockSignals &) = delete; |
61 | |
62 | private: |
63 | __sanitizer_sigset_t saved_; |
64 | }; |
65 | |
66 | # if SANITIZER_GLIBC |
67 | uptr internal_clock_gettime(__sanitizer_clockid_t clk_id, void *tp); |
68 | # endif |
69 | |
70 | // Linux-only syscalls. |
71 | # if SANITIZER_LINUX |
72 | uptr internal_prctl(int option, uptr arg2, uptr arg3, uptr arg4, uptr arg5); |
73 | # if defined(__x86_64__) |
74 | uptr internal_arch_prctl(int option, uptr arg2); |
75 | # endif |
76 | // Used only by sanitizer_stoptheworld. Signal handlers that are actually used |
77 | // (like the process-wide error reporting SEGV handler) must use |
78 | // internal_sigaction instead. |
79 | int internal_sigaction_norestorer(int signum, const void *act, void *oldact); |
80 | void internal_sigdelset(__sanitizer_sigset_t *set, int signum); |
81 | # if defined(__x86_64__) || defined(__mips__) || defined(__aarch64__) || \ |
82 | defined(__powerpc64__) || defined(__s390__) || defined(__i386__) || \ |
83 | defined(__arm__) || SANITIZER_RISCV64 || SANITIZER_LOONGARCH64 |
84 | uptr internal_clone(int (*fn)(void *), void *child_stack, int flags, void *arg, |
85 | int *parent_tidptr, void *newtls, int *child_tidptr); |
86 | # endif |
87 | int internal_uname(struct utsname *buf); |
88 | # elif SANITIZER_FREEBSD |
89 | uptr internal_procctl(int type, int id, int cmd, void *data); |
90 | void internal_sigdelset(__sanitizer_sigset_t *set, int signum); |
91 | # elif SANITIZER_NETBSD |
92 | void internal_sigdelset(__sanitizer_sigset_t *set, int signum); |
93 | uptr internal_clone(int (*fn)(void *), void *child_stack, int flags, void *arg); |
94 | # endif // SANITIZER_LINUX |
95 | |
96 | // This class reads thread IDs from /proc/<pid>/task using only syscalls. |
97 | class ThreadLister { |
98 | public: |
99 | explicit ThreadLister(pid_t pid); |
100 | ~ThreadLister(); |
101 | enum Result { |
102 | Error, |
103 | Incomplete, |
104 | Ok, |
105 | }; |
106 | Result ListThreads(InternalMmapVector<tid_t> *threads); |
107 | |
108 | private: |
109 | bool IsAlive(int tid); |
110 | |
111 | pid_t pid_; |
112 | int descriptor_ = -1; |
113 | InternalMmapVector<char> buffer_; |
114 | }; |
115 | |
116 | // Exposed for testing. |
117 | uptr ThreadDescriptorSize(); |
118 | uptr ThreadSelf(); |
119 | |
120 | // Matches a library's file name against a base name (stripping path and version |
121 | // information). |
122 | bool LibraryNameIs(const char *full_name, const char *base_name); |
123 | |
124 | // Call cb for each region mapped by map. |
125 | void ForEachMappedRegion(link_map *map, void (*cb)(const void *, uptr)); |
126 | |
127 | // Releases memory pages entirely within the [beg, end] address range. |
128 | // The pages no longer count toward RSS; reads are guaranteed to return 0. |
129 | // Requires (but does not verify!) that pages are MAP_PRIVATE. |
130 | inline void ReleaseMemoryPagesToOSAndZeroFill(uptr beg, uptr end) { |
131 | // man madvise on Linux promises zero-fill for anonymous private pages. |
132 | // Testing shows the same behaviour for private (but not anonymous) mappings |
133 | // of shm_open() files, as long as the underlying file is untouched. |
134 | CHECK(SANITIZER_LINUX); |
135 | ReleaseMemoryPagesToOS(beg, end); |
136 | } |
137 | |
138 | # if SANITIZER_ANDROID |
139 | |
140 | # if defined(__aarch64__) |
141 | # define __get_tls() \ |
142 | ({ \ |
143 | void **__v; \ |
144 | __asm__("mrs %0, tpidr_el0" : "=r"(__v)); \ |
145 | __v; \ |
146 | }) |
147 | # elif defined(__arm__) |
148 | # define __get_tls() \ |
149 | ({ \ |
150 | void **__v; \ |
151 | __asm__("mrc p15, 0, %0, c13, c0, 3" : "=r"(__v)); \ |
152 | __v; \ |
153 | }) |
154 | # elif defined(__mips__) |
155 | // On mips32r1, this goes via a kernel illegal instruction trap that's |
156 | // optimized for v1. |
157 | # define __get_tls() \ |
158 | ({ \ |
159 | register void **__v asm("v1"); \ |
160 | __asm__( \ |
161 | ".set push\n" \ |
162 | ".set mips32r2\n" \ |
163 | "rdhwr %0,$29\n" \ |
164 | ".set pop\n" \ |
165 | : "=r"(__v)); \ |
166 | __v; \ |
167 | }) |
168 | # elif defined(__riscv) |
169 | # define __get_tls() \ |
170 | ({ \ |
171 | void **__v; \ |
172 | __asm__("mv %0, tp" : "=r"(__v)); \ |
173 | __v; \ |
174 | }) |
175 | # elif defined(__i386__) |
176 | # define __get_tls() \ |
177 | ({ \ |
178 | void **__v; \ |
179 | __asm__("movl %%gs:0, %0" : "=r"(__v)); \ |
180 | __v; \ |
181 | }) |
182 | # elif defined(__x86_64__) |
183 | # define __get_tls() \ |
184 | ({ \ |
185 | void **__v; \ |
186 | __asm__("mov %%fs:0, %0" : "=r"(__v)); \ |
187 | __v; \ |
188 | }) |
189 | # else |
190 | # error "Unsupported architecture." |
191 | # endif |
192 | |
193 | // The Android Bionic team has allocated a TLS slot for sanitizers starting |
194 | // with Q, given that Android currently doesn't support ELF TLS. It is used to |
195 | // store sanitizer thread specific data. |
196 | static const int TLS_SLOT_SANITIZER = 6; |
197 | |
198 | ALWAYS_INLINE uptr *get_android_tls_ptr() { |
199 | return reinterpret_cast<uptr *>(&__get_tls()[TLS_SLOT_SANITIZER]); |
200 | } |
201 | |
202 | # endif // SANITIZER_ANDROID |
203 | |
204 | } // namespace __sanitizer |
205 | |
206 | #endif |
207 | #endif // SANITIZER_LINUX_H |
208 | |