File: | projects/compiler-rt/lib/sanitizer_common/sanitizer_linux.cc |
Warning: | line 460, column 10 The left operand of '&' is a garbage value |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | //===-- sanitizer_linux.cc ------------------------------------------------===// | |||||
2 | // | |||||
3 | // The LLVM Compiler Infrastructure | |||||
4 | // | |||||
5 | // This file is distributed under the University of Illinois Open Source | |||||
6 | // License. See LICENSE.TXT for details. | |||||
7 | // | |||||
8 | //===----------------------------------------------------------------------===// | |||||
9 | // | |||||
10 | // This file is shared between AddressSanitizer and ThreadSanitizer | |||||
11 | // run-time libraries and implements linux-specific functions from | |||||
12 | // sanitizer_libc.h. | |||||
13 | //===----------------------------------------------------------------------===// | |||||
14 | ||||||
15 | #include "sanitizer_platform.h" | |||||
16 | ||||||
17 | #if SANITIZER_FREEBSD0 || SANITIZER_LINUX1 || SANITIZER_NETBSD0 || \ | |||||
18 | SANITIZER_OPENBSD0 || SANITIZER_SOLARIS0 | |||||
19 | ||||||
20 | #include "sanitizer_common.h" | |||||
21 | #include "sanitizer_flags.h" | |||||
22 | #include "sanitizer_getauxval.h" | |||||
23 | #include "sanitizer_internal_defs.h" | |||||
24 | #include "sanitizer_libc.h" | |||||
25 | #include "sanitizer_linux.h" | |||||
26 | #include "sanitizer_mutex.h" | |||||
27 | #include "sanitizer_placement_new.h" | |||||
28 | #include "sanitizer_procmaps.h" | |||||
29 | ||||||
30 | #if SANITIZER_LINUX1 | |||||
31 | #include <asm/param.h> | |||||
32 | #endif | |||||
33 | ||||||
34 | // For mips64, syscall(__NR_stat) fills the buffer in the 'struct kernel_stat' | |||||
35 | // format. Struct kernel_stat is defined as 'struct stat' in asm/stat.h. To | |||||
36 | // access stat from asm/stat.h, without conflicting with definition in | |||||
37 | // sys/stat.h, we use this trick. | |||||
38 | #if defined(__mips64) | |||||
39 | #include <asm/unistd.h> | |||||
40 | #include <sys/types.h> | |||||
41 | #define stat kernel_stat | |||||
42 | #include <asm/stat.h> | |||||
43 | #undef stat | |||||
44 | #endif | |||||
45 | ||||||
46 | #include <dlfcn.h> | |||||
47 | #include <errno(*__errno_location ()).h> | |||||
48 | #include <fcntl.h> | |||||
49 | #include <link.h> | |||||
50 | #include <pthread.h> | |||||
51 | #include <sched.h> | |||||
52 | #include <signal.h> | |||||
53 | #include <sys/mman.h> | |||||
54 | #include <sys/param.h> | |||||
55 | #if !SANITIZER_SOLARIS0 | |||||
56 | #include <sys/ptrace.h> | |||||
57 | #endif | |||||
58 | #include <sys/resource.h> | |||||
59 | #include <sys/stat.h> | |||||
60 | #include <sys/syscall.h> | |||||
61 | #include <sys/time.h> | |||||
62 | #include <sys/types.h> | |||||
63 | #if !SANITIZER_OPENBSD0 | |||||
64 | #include <ucontext.h> | |||||
65 | #endif | |||||
66 | #if SANITIZER_OPENBSD0 | |||||
67 | #include <sys/futex.h> | |||||
68 | #include <sys/sysctl.h> | |||||
69 | #endif | |||||
70 | #include <unistd.h> | |||||
71 | ||||||
72 | #if SANITIZER_LINUX1 | |||||
73 | #include <sys/utsname.h> | |||||
74 | #endif | |||||
75 | ||||||
76 | #if SANITIZER_LINUX1 && !SANITIZER_ANDROID0 | |||||
77 | #include <sys/personality.h> | |||||
78 | #endif | |||||
79 | ||||||
80 | #if SANITIZER_FREEBSD0 | |||||
81 | #include <sys/exec.h> | |||||
82 | #include <sys/sysctl.h> | |||||
83 | #include <machine/atomic.h> | |||||
84 | extern "C" { | |||||
85 | // <sys/umtx.h> must be included after <errno.h> and <sys/types.h> on | |||||
86 | // FreeBSD 9.2 and 10.0. | |||||
87 | #include <sys/umtx.h> | |||||
88 | } | |||||
89 | #include <sys/thr.h> | |||||
90 | #endif // SANITIZER_FREEBSD | |||||
91 | ||||||
92 | #if SANITIZER_NETBSD0 | |||||
93 | #include <limits.h> // For NAME_MAX | |||||
94 | #include <sys/sysctl.h> | |||||
95 | #include <sys/exec.h> | |||||
96 | extern struct ps_strings *__ps_strings; | |||||
97 | #endif // SANITIZER_NETBSD | |||||
98 | ||||||
99 | #if SANITIZER_SOLARIS0 | |||||
100 | #include <stdlib.h> | |||||
101 | #include <thread.h> | |||||
102 | #define environ _environ | |||||
103 | #endif | |||||
104 | ||||||
105 | extern char **environ; | |||||
106 | ||||||
107 | #if SANITIZER_LINUX1 | |||||
108 | // <linux/time.h> | |||||
109 | struct kernel_timeval { | |||||
110 | long tv_sec; | |||||
111 | long tv_usec; | |||||
112 | }; | |||||
113 | ||||||
114 | // <linux/futex.h> is broken on some linux distributions. | |||||
115 | const int FUTEX_WAIT = 0; | |||||
116 | const int FUTEX_WAKE = 1; | |||||
117 | const int FUTEX_PRIVATE_FLAG = 128; | |||||
118 | const int FUTEX_WAIT_PRIVATE = FUTEX_WAIT | FUTEX_PRIVATE_FLAG; | |||||
119 | const int FUTEX_WAKE_PRIVATE = FUTEX_WAKE | FUTEX_PRIVATE_FLAG; | |||||
120 | #endif // SANITIZER_LINUX | |||||
121 | ||||||
122 | // Are we using 32-bit or 64-bit Linux syscalls? | |||||
123 | // x32 (which defines __x86_64__) has SANITIZER_WORDSIZE == 32 | |||||
124 | // but it still needs to use 64-bit syscalls. | |||||
125 | #if SANITIZER_LINUX1 && (defined(__x86_64__1) || defined(__powerpc64__) || \ | |||||
126 | SANITIZER_WORDSIZE64 == 64) | |||||
127 | # define SANITIZER_LINUX_USES_64BIT_SYSCALLS1 1 | |||||
128 | #else | |||||
129 | # define SANITIZER_LINUX_USES_64BIT_SYSCALLS1 0 | |||||
130 | #endif | |||||
131 | ||||||
132 | #if defined(__x86_64__1) || SANITIZER_MIPS640 | |||||
133 | extern "C" { | |||||
134 | extern void internal_sigreturn(); | |||||
135 | } | |||||
136 | #endif | |||||
137 | ||||||
138 | // Note : FreeBSD had implemented both | |||||
139 | // Linux and OpenBSD apis, available from | |||||
140 | // future 12.x version most likely | |||||
141 | #if SANITIZER_LINUX1 && defined(__NR_getrandom318) | |||||
142 | # if !defined(GRND_NONBLOCK1) | |||||
143 | # define GRND_NONBLOCK1 1 | |||||
144 | # endif | |||||
145 | # define SANITIZER_USE_GETRANDOM1 1 | |||||
146 | #else | |||||
147 | # define SANITIZER_USE_GETRANDOM1 0 | |||||
148 | #endif // SANITIZER_LINUX && defined(__NR_getrandom) | |||||
149 | ||||||
150 | #if SANITIZER_OPENBSD0 | |||||
151 | # define SANITIZER_USE_GETENTROPY0 1 | |||||
152 | #else | |||||
153 | # if SANITIZER_FREEBSD0 && __FreeBSD_version >= 1200000 | |||||
154 | # define SANITIZER_USE_GETENTROPY0 1 | |||||
155 | # else | |||||
156 | # define SANITIZER_USE_GETENTROPY0 0 | |||||
157 | # endif | |||||
158 | #endif // SANITIZER_USE_GETENTROPY | |||||
159 | ||||||
160 | namespace __sanitizer { | |||||
161 | ||||||
162 | #if SANITIZER_LINUX1 && defined(__x86_64__1) | |||||
163 | #include "sanitizer_syscall_linux_x86_64.inc" | |||||
164 | #elif SANITIZER_LINUX1 && defined(__aarch64__) | |||||
165 | #include "sanitizer_syscall_linux_aarch64.inc" | |||||
166 | #elif SANITIZER_LINUX1 && defined(__arm__) | |||||
167 | #include "sanitizer_syscall_linux_arm.inc" | |||||
168 | #else | |||||
169 | #include "sanitizer_syscall_generic.inc" | |||||
170 | #endif | |||||
171 | ||||||
172 | // --------------- sanitizer_libc.h | |||||
173 | #if !SANITIZER_SOLARIS0 && !SANITIZER_NETBSD0 | |||||
174 | #if !SANITIZER_S3900 && !SANITIZER_OPENBSD0 | |||||
175 | uptr internal_mmap(void *addr, uptr length, int prot, int flags, int fd, | |||||
176 | OFF_T offset) { | |||||
177 | #if SANITIZER_FREEBSD0 || SANITIZER_LINUX_USES_64BIT_SYSCALLS1 | |||||
178 | return internal_syscall(SYSCALL(mmap)9, (uptr)addr, length, prot, flags, fd, | |||||
179 | offset); | |||||
180 | #else | |||||
181 | // mmap2 specifies file offset in 4096-byte units. | |||||
182 | CHECK(IsAligned(offset, 4096))do { __sanitizer::u64 v1 = (__sanitizer::u64)((IsAligned(offset , 4096))); __sanitizer::u64 v2 = (__sanitizer::u64)(0); if (__builtin_expect (!!(!(v1 != v2)), 0)) __sanitizer::CheckFailed("/build/llvm-toolchain-snapshot-8~svn345461/projects/compiler-rt/lib/sanitizer_common/sanitizer_linux.cc" , 182, "(" "(IsAligned(offset, 4096))" ") " "!=" " (" "0" ")" , v1, v2); } while (false); | |||||
183 | return internal_syscall(SYSCALL(mmap2)__NR_mmap2, addr, length, prot, flags, fd, | |||||
184 | offset / 4096); | |||||
185 | #endif | |||||
186 | } | |||||
187 | #endif // !SANITIZER_S390 && !SANITIZER_OPENBSD | |||||
188 | ||||||
189 | #if !SANITIZER_OPENBSD0 | |||||
190 | uptr internal_munmap(void *addr, uptr length) { | |||||
191 | return internal_syscall(SYSCALL(munmap)11, (uptr)addr, length); | |||||
192 | } | |||||
193 | ||||||
194 | int internal_mprotect(void *addr, uptr length, int prot) { | |||||
195 | return internal_syscall(SYSCALL(mprotect)10, (uptr)addr, length, prot); | |||||
196 | } | |||||
197 | #endif | |||||
198 | ||||||
199 | uptr internal_close(fd_t fd) { | |||||
200 | return internal_syscall(SYSCALL(close)3, fd); | |||||
201 | } | |||||
202 | ||||||
203 | uptr internal_open(const char *filename, int flags) { | |||||
204 | #if SANITIZER_USES_CANONICAL_LINUX_SYSCALLS0 | |||||
205 | return internal_syscall(SYSCALL(openat)257, AT_FDCWD-100, (uptr)filename, flags); | |||||
206 | #else | |||||
207 | return internal_syscall(SYSCALL(open)2, (uptr)filename, flags); | |||||
208 | #endif | |||||
209 | } | |||||
210 | ||||||
211 | uptr internal_open(const char *filename, int flags, u32 mode) { | |||||
212 | #if SANITIZER_USES_CANONICAL_LINUX_SYSCALLS0 | |||||
213 | return internal_syscall(SYSCALL(openat)257, AT_FDCWD-100, (uptr)filename, flags, | |||||
214 | mode); | |||||
215 | #else | |||||
216 | return internal_syscall(SYSCALL(open)2, (uptr)filename, flags, mode); | |||||
217 | #endif | |||||
218 | } | |||||
219 | ||||||
220 | uptr internal_read(fd_t fd, void *buf, uptr count) { | |||||
221 | sptr res; | |||||
222 | HANDLE_EINTR(res,{ int rverrno; do { res = ((sptr)internal_syscall(0, fd, (uptr )buf, count)); } while (internal_iserror(res, &rverrno) && rverrno == 4); } | |||||
223 | (sptr)internal_syscall(SYSCALL(read), fd, (uptr)buf, count)){ int rverrno; do { res = ((sptr)internal_syscall(0, fd, (uptr )buf, count)); } while (internal_iserror(res, &rverrno) && rverrno == 4); }; | |||||
224 | return res; | |||||
225 | } | |||||
226 | ||||||
227 | uptr internal_write(fd_t fd, const void *buf, uptr count) { | |||||
228 | sptr res; | |||||
229 | HANDLE_EINTR(res,{ int rverrno; do { res = ((sptr)internal_syscall(1, fd, (uptr )buf, count)); } while (internal_iserror(res, &rverrno) && rverrno == 4); } | |||||
230 | (sptr)internal_syscall(SYSCALL(write), fd, (uptr)buf, count)){ int rverrno; do { res = ((sptr)internal_syscall(1, fd, (uptr )buf, count)); } while (internal_iserror(res, &rverrno) && rverrno == 4); }; | |||||
231 | return res; | |||||
232 | } | |||||
233 | ||||||
234 | uptr internal_ftruncate(fd_t fd, uptr size) { | |||||
235 | sptr res; | |||||
236 | HANDLE_EINTR(res, (sptr)internal_syscall(SYSCALL(ftruncate), fd,{ int rverrno; do { res = ((sptr)internal_syscall(77, fd, (OFF_T )size)); } while (internal_iserror(res, &rverrno) && rverrno == 4); } | |||||
237 | (OFF_T)size)){ int rverrno; do { res = ((sptr)internal_syscall(77, fd, (OFF_T )size)); } while (internal_iserror(res, &rverrno) && rverrno == 4); }; | |||||
238 | return res; | |||||
239 | } | |||||
240 | ||||||
241 | #if !SANITIZER_LINUX_USES_64BIT_SYSCALLS1 && SANITIZER_LINUX1 | |||||
242 | static void stat64_to_stat(struct stat64 *in, struct stat *out) { | |||||
243 | internal_memset(out, 0, sizeof(*out)); | |||||
244 | out->st_dev = in->st_dev; | |||||
245 | out->st_ino = in->st_ino; | |||||
246 | out->st_mode = in->st_mode; | |||||
247 | out->st_nlink = in->st_nlink; | |||||
248 | out->st_uid = in->st_uid; | |||||
249 | out->st_gid = in->st_gid; | |||||
250 | out->st_rdev = in->st_rdev; | |||||
251 | out->st_size = in->st_size; | |||||
252 | out->st_blksize = in->st_blksize; | |||||
253 | out->st_blocks = in->st_blocks; | |||||
254 | out->st_atimest_atim.tv_sec = in->st_atimest_atim.tv_sec; | |||||
255 | out->st_mtimest_mtim.tv_sec = in->st_mtimest_mtim.tv_sec; | |||||
256 | out->st_ctimest_ctim.tv_sec = in->st_ctimest_ctim.tv_sec; | |||||
257 | } | |||||
258 | #endif | |||||
259 | ||||||
260 | #if defined(__mips64) | |||||
261 | // Undefine compatibility macros from <sys/stat.h> | |||||
262 | // so that they would not clash with the kernel_stat | |||||
263 | // st_[a|m|c]time fields | |||||
264 | #undef st_atimest_atim.tv_sec | |||||
265 | #undef st_mtimest_mtim.tv_sec | |||||
266 | #undef st_ctimest_ctim.tv_sec | |||||
267 | #if defined(SANITIZER_ANDROID0) | |||||
268 | // Bionic sys/stat.h defines additional macros | |||||
269 | // for compatibility with the old NDKs and | |||||
270 | // they clash with the kernel_stat structure | |||||
271 | // st_[a|m|c]time_nsec fields. | |||||
272 | #undef st_atime_nsec | |||||
273 | #undef st_mtime_nsec | |||||
274 | #undef st_ctime_nsec | |||||
275 | #endif | |||||
276 | static void kernel_stat_to_stat(struct kernel_stat *in, struct stat *out) { | |||||
277 | internal_memset(out, 0, sizeof(*out)); | |||||
278 | out->st_dev = in->st_dev; | |||||
279 | out->st_ino = in->st_ino; | |||||
280 | out->st_mode = in->st_mode; | |||||
281 | out->st_nlink = in->st_nlink; | |||||
282 | out->st_uid = in->st_uid; | |||||
283 | out->st_gid = in->st_gid; | |||||
284 | out->st_rdev = in->st_rdev; | |||||
285 | out->st_size = in->st_size; | |||||
286 | out->st_blksize = in->st_blksize; | |||||
287 | out->st_blocks = in->st_blocks; | |||||
288 | #if defined(__USE_MISC1) || \ | |||||
289 | defined(__USE_XOPEN2K81) || \ | |||||
290 | defined(SANITIZER_ANDROID0) | |||||
291 | out->st_atim.tv_sec = in->st_atimest_atim.tv_sec; | |||||
292 | out->st_atim.tv_nsec = in->st_atime_nsec; | |||||
293 | out->st_mtim.tv_sec = in->st_mtimest_mtim.tv_sec; | |||||
294 | out->st_mtim.tv_nsec = in->st_mtime_nsec; | |||||
295 | out->st_ctim.tv_sec = in->st_ctimest_ctim.tv_sec; | |||||
296 | out->st_ctim.tv_nsec = in->st_ctime_nsec; | |||||
297 | #else | |||||
298 | out->st_atimest_atim.tv_sec = in->st_atimest_atim.tv_sec; | |||||
299 | out->st_atimensec = in->st_atime_nsec; | |||||
300 | out->st_mtimest_mtim.tv_sec = in->st_mtimest_mtim.tv_sec; | |||||
301 | out->st_mtimensec = in->st_mtime_nsec; | |||||
302 | out->st_ctimest_ctim.tv_sec = in->st_ctimest_ctim.tv_sec; | |||||
303 | out->st_atimensec = in->st_ctime_nsec; | |||||
304 | #endif | |||||
305 | } | |||||
306 | #endif | |||||
307 | ||||||
308 | uptr internal_stat(const char *path, void *buf) { | |||||
309 | #if SANITIZER_FREEBSD0 || SANITIZER_OPENBSD0 | |||||
310 | return internal_syscall(SYSCALL(fstatat)__NR_fstatat, AT_FDCWD-100, (uptr)path, (uptr)buf, 0); | |||||
311 | #elif SANITIZER_USES_CANONICAL_LINUX_SYSCALLS0 | |||||
312 | return internal_syscall(SYSCALL(newfstatat)262, AT_FDCWD-100, (uptr)path, (uptr)buf, | |||||
313 | 0); | |||||
314 | #elif SANITIZER_LINUX_USES_64BIT_SYSCALLS1 | |||||
315 | # if defined(__mips64) | |||||
316 | // For mips64, stat syscall fills buffer in the format of kernel_stat | |||||
317 | struct kernel_stat kbuf; | |||||
318 | int res = internal_syscall(SYSCALL(stat)4, path, &kbuf); | |||||
319 | kernel_stat_to_stat(&kbuf, (struct stat *)buf); | |||||
320 | return res; | |||||
321 | # else | |||||
322 | return internal_syscall(SYSCALL(stat)4, (uptr)path, (uptr)buf); | |||||
323 | # endif | |||||
324 | #else | |||||
325 | struct stat64 buf64; | |||||
326 | int res = internal_syscall(SYSCALL(stat64)__NR_stat64, path, &buf64); | |||||
327 | stat64_to_stat(&buf64, (struct stat *)buf); | |||||
328 | return res; | |||||
329 | #endif | |||||
330 | } | |||||
331 | ||||||
332 | uptr internal_lstat(const char *path, void *buf) { | |||||
333 | #if SANITIZER_FREEBSD0 || SANITIZER_OPENBSD0 | |||||
334 | return internal_syscall(SYSCALL(fstatat)__NR_fstatat, AT_FDCWD-100, (uptr)path, (uptr)buf, | |||||
335 | AT_SYMLINK_NOFOLLOW0x100); | |||||
336 | #elif SANITIZER_USES_CANONICAL_LINUX_SYSCALLS0 | |||||
337 | return internal_syscall(SYSCALL(newfstatat)262, AT_FDCWD-100, (uptr)path, (uptr)buf, | |||||
338 | AT_SYMLINK_NOFOLLOW0x100); | |||||
339 | #elif SANITIZER_LINUX_USES_64BIT_SYSCALLS1 | |||||
340 | # if SANITIZER_MIPS640 | |||||
341 | // For mips64, lstat syscall fills buffer in the format of kernel_stat | |||||
342 | struct kernel_stat kbuf; | |||||
343 | int res = internal_syscall(SYSCALL(lstat)6, path, &kbuf); | |||||
344 | kernel_stat_to_stat(&kbuf, (struct stat *)buf); | |||||
345 | return res; | |||||
346 | # else | |||||
347 | return internal_syscall(SYSCALL(lstat)6, (uptr)path, (uptr)buf); | |||||
348 | # endif | |||||
349 | #else | |||||
350 | struct stat64 buf64; | |||||
351 | int res = internal_syscall(SYSCALL(lstat64)__NR_lstat64, path, &buf64); | |||||
352 | stat64_to_stat(&buf64, (struct stat *)buf); | |||||
353 | return res; | |||||
354 | #endif | |||||
355 | } | |||||
356 | ||||||
357 | uptr internal_fstat(fd_t fd, void *buf) { | |||||
358 | #if SANITIZER_FREEBSD0 || SANITIZER_OPENBSD0 || \ | |||||
359 | SANITIZER_LINUX_USES_64BIT_SYSCALLS1 | |||||
360 | #if SANITIZER_MIPS640 && !SANITIZER_OPENBSD0 | |||||
361 | // For mips64, fstat syscall fills buffer in the format of kernel_stat | |||||
362 | struct kernel_stat kbuf; | |||||
363 | int res = internal_syscall(SYSCALL(fstat)5, fd, &kbuf); | |||||
364 | kernel_stat_to_stat(&kbuf, (struct stat *)buf); | |||||
365 | return res; | |||||
366 | # else | |||||
367 | return internal_syscall(SYSCALL(fstat)5, fd, (uptr)buf); | |||||
368 | # endif | |||||
369 | #else | |||||
370 | struct stat64 buf64; | |||||
371 | int res = internal_syscall(SYSCALL(fstat64)__NR_fstat64, fd, &buf64); | |||||
372 | stat64_to_stat(&buf64, (struct stat *)buf); | |||||
373 | return res; | |||||
374 | #endif | |||||
375 | } | |||||
376 | ||||||
377 | uptr internal_filesize(fd_t fd) { | |||||
378 | struct stat st; | |||||
379 | if (internal_fstat(fd, &st)) | |||||
380 | return -1; | |||||
381 | return (uptr)st.st_size; | |||||
382 | } | |||||
383 | ||||||
384 | uptr internal_dup2(int oldfd, int newfd) { | |||||
385 | #if SANITIZER_USES_CANONICAL_LINUX_SYSCALLS0 | |||||
386 | return internal_syscall(SYSCALL(dup3)292, oldfd, newfd, 0); | |||||
387 | #else | |||||
388 | return internal_syscall(SYSCALL(dup2)33, oldfd, newfd); | |||||
389 | #endif | |||||
390 | } | |||||
391 | ||||||
392 | uptr internal_readlink(const char *path, char *buf, uptr bufsize) { | |||||
393 | #if SANITIZER_USES_CANONICAL_LINUX_SYSCALLS0 | |||||
394 | return internal_syscall(SYSCALL(readlinkat)267, AT_FDCWD-100, (uptr)path, (uptr)buf, | |||||
395 | bufsize); | |||||
396 | #elif SANITIZER_OPENBSD0 | |||||
397 | return internal_syscall(SYSCALL(readlinkat)267, AT_FDCWD-100, (uptr)path, (uptr)buf, | |||||
398 | bufsize); | |||||
399 | #else | |||||
400 | return internal_syscall(SYSCALL(readlink)89, path, buf, bufsize); | |||||
401 | #endif | |||||
402 | } | |||||
403 | ||||||
404 | uptr internal_unlink(const char *path) { | |||||
405 | #if SANITIZER_USES_CANONICAL_LINUX_SYSCALLS0 || SANITIZER_OPENBSD0 | |||||
406 | return internal_syscall(SYSCALL(unlinkat)263, AT_FDCWD-100, (uptr)path, 0); | |||||
407 | #else | |||||
408 | return internal_syscall(SYSCALL(unlink)87, (uptr)path); | |||||
409 | #endif | |||||
410 | } | |||||
411 | ||||||
412 | uptr internal_rename(const char *oldpath, const char *newpath) { | |||||
413 | #if SANITIZER_USES_CANONICAL_LINUX_SYSCALLS0 || SANITIZER_OPENBSD0 | |||||
414 | return internal_syscall(SYSCALL(renameat)264, AT_FDCWD-100, (uptr)oldpath, AT_FDCWD-100, | |||||
415 | (uptr)newpath); | |||||
416 | #else | |||||
417 | return internal_syscall(SYSCALL(rename)82, (uptr)oldpath, (uptr)newpath); | |||||
418 | #endif | |||||
419 | } | |||||
420 | ||||||
421 | uptr internal_sched_yield() { | |||||
422 | return internal_syscall(SYSCALL(sched_yield)24); | |||||
423 | } | |||||
424 | ||||||
425 | void internal__exit(int exitcode) { | |||||
426 | #if SANITIZER_FREEBSD0 || SANITIZER_OPENBSD0 | |||||
427 | internal_syscall(SYSCALL(exit)60, exitcode); | |||||
428 | #else | |||||
429 | internal_syscall(SYSCALL(exit_group)231, exitcode); | |||||
430 | #endif | |||||
431 | Die(); // Unreachable. | |||||
432 | } | |||||
433 | ||||||
434 | unsigned int internal_sleep(unsigned int seconds) { | |||||
435 | struct timespec ts; | |||||
436 | ts.tv_sec = 1; | |||||
437 | ts.tv_nsec = 0; | |||||
438 | int res = internal_syscall(SYSCALL(nanosleep)35, &ts, &ts); | |||||
439 | if (res) return ts.tv_sec; | |||||
440 | return 0; | |||||
441 | } | |||||
442 | ||||||
443 | uptr internal_execve(const char *filename, char *const argv[], | |||||
444 | char *const envp[]) { | |||||
445 | return internal_syscall(SYSCALL(execve)59, (uptr)filename, (uptr)argv, | |||||
446 | (uptr)envp); | |||||
447 | } | |||||
448 | #endif // !SANITIZER_SOLARIS && !SANITIZER_NETBSD | |||||
449 | ||||||
450 | // ----------------- sanitizer_common.h | |||||
451 | bool FileExists(const char *filename) { | |||||
452 | struct stat st; | |||||
453 | #if SANITIZER_USES_CANONICAL_LINUX_SYSCALLS0 | |||||
454 | if (internal_syscall(SYSCALL(newfstatat)262, AT_FDCWD-100, filename, &st, 0)) | |||||
455 | #else | |||||
456 | if (internal_stat(filename, &st)) | |||||
| ||||||
457 | #endif | |||||
458 | return false; | |||||
459 | // Sanity check: filename is a regular file. | |||||
460 | return S_ISREG(st.st_mode)((((st.st_mode)) & 0170000) == (0100000)); | |||||
| ||||||
461 | } | |||||
462 | ||||||
463 | #if !SANITIZER_NETBSD0 | |||||
464 | tid_t GetTid() { | |||||
465 | #if SANITIZER_FREEBSD0 | |||||
466 | long Tid; | |||||
467 | thr_self(&Tid); | |||||
468 | return Tid; | |||||
469 | #elif SANITIZER_OPENBSD0 | |||||
470 | return internal_syscall(SYSCALL(getthrid)__NR_getthrid); | |||||
471 | #elif SANITIZER_SOLARIS0 | |||||
472 | return thr_self(); | |||||
473 | #else | |||||
474 | return internal_syscall(SYSCALL(gettid)186); | |||||
475 | #endif | |||||
476 | } | |||||
477 | ||||||
478 | int TgKill(pid_t pid, tid_t tid, int sig) { | |||||
479 | #if SANITIZER_LINUX1 | |||||
480 | return internal_syscall(SYSCALL(tgkill)234, pid, tid, sig); | |||||
481 | #elif SANITIZER_FREEBSD0 | |||||
482 | return internal_syscall(SYSCALL(thr_kill2)__NR_thr_kill2, pid, tid, sig); | |||||
483 | #elif SANITIZER_OPENBSD0 | |||||
484 | (void)pid; | |||||
485 | return internal_syscall(SYSCALL(thrkill)__NR_thrkill, tid, sig, nullptr); | |||||
486 | #elif SANITIZER_SOLARIS0 | |||||
487 | (void)pid; | |||||
488 | return thr_kill(tid, sig); | |||||
489 | #endif | |||||
490 | } | |||||
491 | #endif | |||||
492 | ||||||
493 | #if !SANITIZER_SOLARIS0 && !SANITIZER_NETBSD0 | |||||
494 | u64 NanoTime() { | |||||
495 | #if SANITIZER_FREEBSD0 || SANITIZER_OPENBSD0 | |||||
496 | timeval tv; | |||||
497 | #else | |||||
498 | kernel_timeval tv; | |||||
499 | #endif | |||||
500 | internal_memset(&tv, 0, sizeof(tv)); | |||||
501 | internal_syscall(SYSCALL(gettimeofday)96, &tv, 0); | |||||
502 | return (u64)tv.tv_sec * 1000*1000*1000 + tv.tv_usec * 1000; | |||||
503 | } | |||||
504 | ||||||
505 | uptr internal_clock_gettime(__sanitizer_clockid_t clk_id, void *tp) { | |||||
506 | return internal_syscall(SYSCALL(clock_gettime)228, clk_id, tp); | |||||
507 | } | |||||
508 | #endif // !SANITIZER_SOLARIS && !SANITIZER_NETBSD | |||||
509 | ||||||
510 | // Like getenv, but reads env directly from /proc (on Linux) or parses the | |||||
511 | // 'environ' array (on some others) and does not use libc. This function | |||||
512 | // should be called first inside __asan_init. | |||||
513 | const char *GetEnv(const char *name) { | |||||
514 | #if SANITIZER_FREEBSD0 || SANITIZER_NETBSD0 || SANITIZER_OPENBSD0 || \ | |||||
515 | SANITIZER_SOLARIS0 | |||||
516 | if (::environ != 0) { | |||||
517 | uptr NameLen = internal_strlen(name); | |||||
518 | for (char **Env = ::environ; *Env != 0; Env++) { | |||||
519 | if (internal_strncmp(*Env, name, NameLen) == 0 && (*Env)[NameLen] == '=') | |||||
520 | return (*Env) + NameLen + 1; | |||||
521 | } | |||||
522 | } | |||||
523 | return 0; // Not found. | |||||
524 | #elif SANITIZER_LINUX1 | |||||
525 | static char *environ; | |||||
526 | static uptr len; | |||||
527 | static bool inited; | |||||
528 | if (!inited) { | |||||
529 | inited = true; | |||||
530 | uptr environ_size; | |||||
531 | if (!ReadFileToBuffer("/proc/self/environ", &environ, &environ_size, &len)) | |||||
532 | environ = nullptr; | |||||
533 | } | |||||
534 | if (!environ || len == 0) return nullptr; | |||||
535 | uptr namelen = internal_strlen(name); | |||||
536 | const char *p = environ; | |||||
537 | while (*p != '\0') { // will happen at the \0\0 that terminates the buffer | |||||
538 | // proc file has the format NAME=value\0NAME=value\0NAME=value\0... | |||||
539 | const char* endp = | |||||
540 | (char*)internal_memchr(p, '\0', len - (p - environ)); | |||||
541 | if (!endp) // this entry isn't NUL terminated | |||||
542 | return nullptr; | |||||
543 | else if (!internal_memcmp(p, name, namelen) && p[namelen] == '=') // Match. | |||||
544 | return p + namelen + 1; // point after = | |||||
545 | p = endp + 1; | |||||
546 | } | |||||
547 | return nullptr; // Not found. | |||||
548 | #else | |||||
549 | #error "Unsupported platform" | |||||
550 | #endif | |||||
551 | } | |||||
552 | ||||||
553 | #if !SANITIZER_FREEBSD0 && !SANITIZER_NETBSD0 && !SANITIZER_OPENBSD0 | |||||
554 | extern "C" { | |||||
555 | SANITIZER_WEAK_ATTRIBUTE__attribute__((weak)) extern void *__libc_stack_end; | |||||
556 | } | |||||
557 | #endif | |||||
558 | ||||||
559 | #if !SANITIZER_GO0 && !SANITIZER_FREEBSD0 && !SANITIZER_NETBSD0 && \ | |||||
560 | !SANITIZER_OPENBSD0 | |||||
561 | static void ReadNullSepFileToArray(const char *path, char ***arr, | |||||
562 | int arr_size) { | |||||
563 | char *buff; | |||||
564 | uptr buff_size; | |||||
565 | uptr buff_len; | |||||
566 | *arr = (char **)MmapOrDie(arr_size * sizeof(char *), "NullSepFileArray"); | |||||
567 | if (!ReadFileToBuffer(path, &buff, &buff_size, &buff_len, 1024 * 1024)) { | |||||
568 | (*arr)[0] = nullptr; | |||||
569 | return; | |||||
570 | } | |||||
571 | (*arr)[0] = buff; | |||||
572 | int count, i; | |||||
573 | for (count = 1, i = 1; ; i++) { | |||||
574 | if (buff[i] == 0) { | |||||
575 | if (buff[i+1] == 0) break; | |||||
576 | (*arr)[count] = &buff[i+1]; | |||||
577 | CHECK_LE(count, arr_size - 1)do { __sanitizer::u64 v1 = (__sanitizer::u64)((count)); __sanitizer ::u64 v2 = (__sanitizer::u64)((arr_size - 1)); if (__builtin_expect (!!(!(v1 <= v2)), 0)) __sanitizer::CheckFailed("/build/llvm-toolchain-snapshot-8~svn345461/projects/compiler-rt/lib/sanitizer_common/sanitizer_linux.cc" , 577, "(" "(count)" ") " "<=" " (" "(arr_size - 1)" ")", v1 , v2); } while (false); // FIXME: make this more flexible. | |||||
578 | count++; | |||||
579 | } | |||||
580 | } | |||||
581 | (*arr)[count] = nullptr; | |||||
582 | } | |||||
583 | #endif | |||||
584 | ||||||
585 | #if !SANITIZER_OPENBSD0 | |||||
586 | static void GetArgsAndEnv(char ***argv, char ***envp) { | |||||
587 | #if SANITIZER_FREEBSD0 | |||||
588 | // On FreeBSD, retrieving the argument and environment arrays is done via the | |||||
589 | // kern.ps_strings sysctl, which returns a pointer to a structure containing | |||||
590 | // this information. See also <sys/exec.h>. | |||||
591 | ps_strings *pss; | |||||
592 | uptr sz = sizeof(pss); | |||||
593 | if (internal_sysctlbyname("kern.ps_strings", &pss, &sz, NULL__null, 0) == -1) { | |||||
594 | Printf("sysctl kern.ps_strings failed\n"); | |||||
595 | Die(); | |||||
596 | } | |||||
597 | *argv = pss->ps_argvstr; | |||||
598 | *envp = pss->ps_envstr; | |||||
599 | #elif SANITIZER_NETBSD0 | |||||
600 | *argv = __ps_strings->ps_argvstr; | |||||
601 | *envp = __ps_strings->ps_envstr; | |||||
602 | #else // SANITIZER_FREEBSD | |||||
603 | #if !SANITIZER_GO0 | |||||
604 | if (&__libc_stack_end) { | |||||
605 | #endif // !SANITIZER_GO | |||||
606 | uptr* stack_end = (uptr*)__libc_stack_end; | |||||
607 | int argc = *stack_end; | |||||
608 | *argv = (char**)(stack_end + 1); | |||||
609 | *envp = (char**)(stack_end + argc + 2); | |||||
610 | #if !SANITIZER_GO0 | |||||
611 | } else { | |||||
612 | static const int kMaxArgv = 2000, kMaxEnvp = 2000; | |||||
613 | ReadNullSepFileToArray("/proc/self/cmdline", argv, kMaxArgv); | |||||
614 | ReadNullSepFileToArray("/proc/self/environ", envp, kMaxEnvp); | |||||
615 | } | |||||
616 | #endif // !SANITIZER_GO | |||||
617 | #endif // SANITIZER_FREEBSD | |||||
618 | } | |||||
619 | ||||||
620 | char **GetArgv() { | |||||
621 | char **argv, **envp; | |||||
622 | GetArgsAndEnv(&argv, &envp); | |||||
623 | return argv; | |||||
624 | } | |||||
625 | ||||||
626 | void ReExec() { | |||||
627 | char **argv, **envp; | |||||
628 | const char *pathname = "/proc/self/exe"; | |||||
629 | ||||||
630 | #if SANITIZER_NETBSD0 | |||||
631 | static const int name[] = { | |||||
632 | CTL_KERN, KERN_PROC_ARGS, -1, KERN_PROC_PATHNAME, | |||||
633 | }; | |||||
634 | char path[400]; | |||||
635 | uptr len; | |||||
636 | ||||||
637 | len = sizeof(path); | |||||
638 | if (internal_sysctl(name, ARRAY_SIZE(name)(sizeof(name)/sizeof((name)[0])), path, &len, NULL__null, 0) != -1) | |||||
639 | pathname = path; | |||||
640 | #elif SANITIZER_SOLARIS0 | |||||
641 | pathname = getexecname(); | |||||
642 | CHECK_NE(pathname, NULL)do { __sanitizer::u64 v1 = (__sanitizer::u64)((pathname)); __sanitizer ::u64 v2 = (__sanitizer::u64)((__null)); if (__builtin_expect (!!(!(v1 != v2)), 0)) __sanitizer::CheckFailed("/build/llvm-toolchain-snapshot-8~svn345461/projects/compiler-rt/lib/sanitizer_common/sanitizer_linux.cc" , 642, "(" "(pathname)" ") " "!=" " (" "(__null)" ")", v1, v2 ); } while (false); | |||||
643 | #endif | |||||
644 | ||||||
645 | GetArgsAndEnv(&argv, &envp); | |||||
646 | uptr rv = internal_execve(pathname, argv, envp); | |||||
647 | int rverrno; | |||||
648 | CHECK_EQ(internal_iserror(rv, &rverrno), true)do { __sanitizer::u64 v1 = (__sanitizer::u64)((internal_iserror (rv, &rverrno))); __sanitizer::u64 v2 = (__sanitizer::u64 )((true)); if (__builtin_expect(!!(!(v1 == v2)), 0)) __sanitizer ::CheckFailed("/build/llvm-toolchain-snapshot-8~svn345461/projects/compiler-rt/lib/sanitizer_common/sanitizer_linux.cc" , 648, "(" "(internal_iserror(rv, &rverrno))" ") " "==" " (" "(true)" ")", v1, v2); } while (false); | |||||
649 | Printf("execve failed, errno %d\n", rverrno); | |||||
650 | Die(); | |||||
651 | } | |||||
652 | #endif | |||||
653 | ||||||
654 | #if !SANITIZER_SOLARIS0 | |||||
655 | enum MutexState { | |||||
656 | MtxUnlocked = 0, | |||||
657 | MtxLocked = 1, | |||||
658 | MtxSleeping = 2 | |||||
659 | }; | |||||
660 | ||||||
661 | BlockingMutex::BlockingMutex() { | |||||
662 | internal_memset(this, 0, sizeof(*this)); | |||||
663 | } | |||||
664 | ||||||
665 | void BlockingMutex::Lock() { | |||||
666 | CHECK_EQ(owner_, 0)do { __sanitizer::u64 v1 = (__sanitizer::u64)((owner_)); __sanitizer ::u64 v2 = (__sanitizer::u64)((0)); if (__builtin_expect(!!(! (v1 == v2)), 0)) __sanitizer::CheckFailed("/build/llvm-toolchain-snapshot-8~svn345461/projects/compiler-rt/lib/sanitizer_common/sanitizer_linux.cc" , 666, "(" "(owner_)" ") " "==" " (" "(0)" ")", v1, v2); } while (false); | |||||
667 | atomic_uint32_t *m = reinterpret_cast<atomic_uint32_t *>(&opaque_storage_); | |||||
668 | if (atomic_exchange(m, MtxLocked, memory_order_acquire) == MtxUnlocked) | |||||
669 | return; | |||||
670 | while (atomic_exchange(m, MtxSleeping, memory_order_acquire) != MtxUnlocked) { | |||||
671 | #if SANITIZER_FREEBSD0 | |||||
672 | _umtx_op(m, UMTX_OP_WAIT_UINT, MtxSleeping, 0, 0); | |||||
673 | #elif SANITIZER_NETBSD0 | |||||
674 | sched_yield(); /* No userspace futex-like synchronization */ | |||||
675 | #else | |||||
676 | internal_syscall(SYSCALL(futex)202, (uptr)m, FUTEX_WAIT_PRIVATE, MtxSleeping, | |||||
677 | 0, 0, 0); | |||||
678 | #endif | |||||
679 | } | |||||
680 | } | |||||
681 | ||||||
682 | void BlockingMutex::Unlock() { | |||||
683 | atomic_uint32_t *m = reinterpret_cast<atomic_uint32_t *>(&opaque_storage_); | |||||
684 | u32 v = atomic_exchange(m, MtxUnlocked, memory_order_release); | |||||
685 | CHECK_NE(v, MtxUnlocked)do { __sanitizer::u64 v1 = (__sanitizer::u64)((v)); __sanitizer ::u64 v2 = (__sanitizer::u64)((MtxUnlocked)); if (__builtin_expect (!!(!(v1 != v2)), 0)) __sanitizer::CheckFailed("/build/llvm-toolchain-snapshot-8~svn345461/projects/compiler-rt/lib/sanitizer_common/sanitizer_linux.cc" , 685, "(" "(v)" ") " "!=" " (" "(MtxUnlocked)" ")", v1, v2); } while (false); | |||||
686 | if (v == MtxSleeping) { | |||||
687 | #if SANITIZER_FREEBSD0 | |||||
688 | _umtx_op(m, UMTX_OP_WAKE, 1, 0, 0); | |||||
689 | #elif SANITIZER_NETBSD0 | |||||
690 | /* No userspace futex-like synchronization */ | |||||
691 | #else | |||||
692 | internal_syscall(SYSCALL(futex)202, (uptr)m, FUTEX_WAKE_PRIVATE, 1, 0, 0, 0); | |||||
693 | #endif | |||||
694 | } | |||||
695 | } | |||||
696 | ||||||
697 | void BlockingMutex::CheckLocked() { | |||||
698 | atomic_uint32_t *m = reinterpret_cast<atomic_uint32_t *>(&opaque_storage_); | |||||
699 | CHECK_NE(MtxUnlocked, atomic_load(m, memory_order_relaxed))do { __sanitizer::u64 v1 = (__sanitizer::u64)((MtxUnlocked)); __sanitizer::u64 v2 = (__sanitizer::u64)((atomic_load(m, memory_order_relaxed ))); if (__builtin_expect(!!(!(v1 != v2)), 0)) __sanitizer::CheckFailed ("/build/llvm-toolchain-snapshot-8~svn345461/projects/compiler-rt/lib/sanitizer_common/sanitizer_linux.cc" , 699, "(" "(MtxUnlocked)" ") " "!=" " (" "(atomic_load(m, memory_order_relaxed))" ")", v1, v2); } while (false); | |||||
700 | } | |||||
701 | #endif // !SANITIZER_SOLARIS | |||||
702 | ||||||
703 | // ----------------- sanitizer_linux.h | |||||
704 | // The actual size of this structure is specified by d_reclen. | |||||
705 | // Note that getdents64 uses a different structure format. We only provide the | |||||
706 | // 32-bit syscall here. | |||||
707 | #if SANITIZER_NETBSD0 | |||||
708 | // Not used | |||||
709 | #elif SANITIZER_OPENBSD0 | |||||
710 | // struct dirent is different for Linux and us. At this moment, we use only | |||||
711 | // d_fileno (Linux call this d_ino), d_reclen, and d_name. | |||||
712 | struct linux_dirent { | |||||
713 | u64 d_ino; // d_fileno | |||||
714 | u16 d_reclen; | |||||
715 | u16 d_namlen; // not used | |||||
716 | u8 d_type; // not used | |||||
717 | char d_name[NAME_MAX255 + 1]; | |||||
718 | }; | |||||
719 | #else | |||||
720 | struct linux_dirent { | |||||
721 | #if SANITIZER_X320 || defined(__aarch64__) | |||||
722 | u64 d_ino; | |||||
723 | u64 d_off; | |||||
724 | #else | |||||
725 | unsigned long d_ino; | |||||
726 | unsigned long d_off; | |||||
727 | #endif | |||||
728 | unsigned short d_reclen; | |||||
729 | #ifdef __aarch64__ | |||||
730 | unsigned char d_type; | |||||
731 | #endif | |||||
732 | char d_name[256]; | |||||
733 | }; | |||||
734 | #endif | |||||
735 | ||||||
736 | #if !SANITIZER_SOLARIS0 && !SANITIZER_NETBSD0 | |||||
737 | // Syscall wrappers. | |||||
738 | uptr internal_ptrace(int request, int pid, void *addr, void *data) { | |||||
739 | return internal_syscall(SYSCALL(ptrace)101, request, pid, (uptr)addr, | |||||
740 | (uptr)data); | |||||
741 | } | |||||
742 | ||||||
743 | uptr internal_waitpid(int pid, int *status, int options) { | |||||
744 | return internal_syscall(SYSCALL(wait4)61, pid, (uptr)status, options, | |||||
745 | 0 /* rusage */); | |||||
746 | } | |||||
747 | ||||||
748 | uptr internal_getpid() { | |||||
749 | return internal_syscall(SYSCALL(getpid)39); | |||||
750 | } | |||||
751 | ||||||
752 | uptr internal_getppid() { | |||||
753 | return internal_syscall(SYSCALL(getppid)110); | |||||
754 | } | |||||
755 | ||||||
756 | uptr internal_getdents(fd_t fd, struct linux_dirent *dirp, unsigned int count) { | |||||
757 | #if SANITIZER_FREEBSD0 | |||||
758 | return internal_syscall(SYSCALL(getdirentries)__NR_getdirentries, fd, (uptr)dirp, count, NULL__null); | |||||
759 | #elif SANITIZER_USES_CANONICAL_LINUX_SYSCALLS0 | |||||
760 | return internal_syscall(SYSCALL(getdents64)217, fd, (uptr)dirp, count); | |||||
761 | #else | |||||
762 | return internal_syscall(SYSCALL(getdents)78, fd, (uptr)dirp, count); | |||||
763 | #endif | |||||
764 | } | |||||
765 | ||||||
766 | uptr internal_lseek(fd_t fd, OFF_T offset, int whence) { | |||||
767 | return internal_syscall(SYSCALL(lseek)8, fd, offset, whence); | |||||
768 | } | |||||
769 | ||||||
770 | #if SANITIZER_LINUX1 | |||||
771 | uptr internal_prctl(int option, uptr arg2, uptr arg3, uptr arg4, uptr arg5) { | |||||
772 | return internal_syscall(SYSCALL(prctl)157, option, arg2, arg3, arg4, arg5); | |||||
773 | } | |||||
774 | #endif | |||||
775 | ||||||
776 | uptr internal_sigaltstack(const void *ss, void *oss) { | |||||
777 | return internal_syscall(SYSCALL(sigaltstack)131, (uptr)ss, (uptr)oss); | |||||
778 | } | |||||
779 | ||||||
780 | int internal_fork() { | |||||
781 | #if SANITIZER_USES_CANONICAL_LINUX_SYSCALLS0 | |||||
782 | return internal_syscall(SYSCALL(clone)56, SIGCHLD17, 0); | |||||
783 | #else | |||||
784 | return internal_syscall(SYSCALL(fork)57); | |||||
785 | #endif | |||||
786 | } | |||||
787 | ||||||
788 | #if SANITIZER_FREEBSD0 || SANITIZER_OPENBSD0 | |||||
789 | int internal_sysctl(const int *name, unsigned int namelen, void *oldp, | |||||
790 | uptr *oldlenp, const void *newp, uptr newlen) { | |||||
791 | #if SANITIZER_OPENBSD0 | |||||
792 | return sysctl(name, namelen, oldp, (size_t *)oldlenp, (void *)newp, | |||||
793 | (size_t)newlen); | |||||
794 | #else | |||||
795 | return sysctl(name, namelen, oldp, (size_t *)oldlenp, newp, (size_t)newlen); | |||||
796 | #endif | |||||
797 | } | |||||
798 | ||||||
799 | #if SANITIZER_FREEBSD0 | |||||
800 | int internal_sysctlbyname(const char *sname, void *oldp, uptr *oldlenp, | |||||
801 | const void *newp, uptr newlen) { | |||||
802 | return sysctlbyname(sname, oldp, (size_t *)oldlenp, newp, (size_t)newlen); | |||||
803 | } | |||||
804 | #endif | |||||
805 | #endif | |||||
806 | ||||||
807 | #if SANITIZER_LINUX1 | |||||
808 | #define SA_RESTORER0x04000000 0x04000000 | |||||
809 | // Doesn't set sa_restorer if the caller did not set it, so use with caution | |||||
810 | //(see below). | |||||
811 | int internal_sigaction_norestorer(int signum, const void *act, void *oldact) { | |||||
812 | __sanitizer_kernel_sigaction_t k_act, k_oldact; | |||||
813 | internal_memset(&k_act, 0, sizeof(__sanitizer_kernel_sigaction_t)); | |||||
814 | internal_memset(&k_oldact, 0, sizeof(__sanitizer_kernel_sigaction_t)); | |||||
815 | const __sanitizer_sigaction *u_act = (const __sanitizer_sigaction *)act; | |||||
816 | __sanitizer_sigaction *u_oldact = (__sanitizer_sigaction *)oldact; | |||||
817 | if (u_act) { | |||||
818 | k_act.handler = u_act->handler; | |||||
819 | k_act.sigaction = u_act->sigaction; | |||||
820 | internal_memcpy(&k_act.sa_mask, &u_act->sa_mask, | |||||
821 | sizeof(__sanitizer_kernel_sigset_t)); | |||||
822 | // Without SA_RESTORER kernel ignores the calls (probably returns EINVAL). | |||||
823 | k_act.sa_flags = u_act->sa_flags | SA_RESTORER0x04000000; | |||||
824 | // FIXME: most often sa_restorer is unset, however the kernel requires it | |||||
825 | // to point to a valid signal restorer that calls the rt_sigreturn syscall. | |||||
826 | // If sa_restorer passed to the kernel is NULL, the program may crash upon | |||||
827 | // signal delivery or fail to unwind the stack in the signal handler. | |||||
828 | // libc implementation of sigaction() passes its own restorer to | |||||
829 | // rt_sigaction, so we need to do the same (we'll need to reimplement the | |||||
830 | // restorers; for x86_64 the restorer address can be obtained from | |||||
831 | // oldact->sa_restorer upon a call to sigaction(xxx, NULL, oldact). | |||||
832 | #if !SANITIZER_ANDROID0 || !SANITIZER_MIPS320 | |||||
833 | k_act.sa_restorer = u_act->sa_restorer; | |||||
834 | #endif | |||||
835 | } | |||||
836 | ||||||
837 | uptr result = internal_syscall(SYSCALL(rt_sigaction)13, (uptr)signum, | |||||
838 | (uptr)(u_act ? &k_act : nullptr), | |||||
839 | (uptr)(u_oldact ? &k_oldact : nullptr), | |||||
840 | (uptr)sizeof(__sanitizer_kernel_sigset_t)); | |||||
841 | ||||||
842 | if ((result == 0) && u_oldact) { | |||||
843 | u_oldact->handler = k_oldact.handler; | |||||
844 | u_oldact->sigaction = k_oldact.sigaction; | |||||
845 | internal_memcpy(&u_oldact->sa_mask, &k_oldact.sa_mask, | |||||
846 | sizeof(__sanitizer_kernel_sigset_t)); | |||||
847 | u_oldact->sa_flags = k_oldact.sa_flags; | |||||
848 | #if !SANITIZER_ANDROID0 || !SANITIZER_MIPS320 | |||||
849 | u_oldact->sa_restorer = k_oldact.sa_restorer; | |||||
850 | #endif | |||||
851 | } | |||||
852 | return result; | |||||
853 | } | |||||
854 | ||||||
855 | // Invokes sigaction via a raw syscall with a restorer, but does not support | |||||
856 | // all platforms yet. | |||||
857 | // We disable for Go simply because we have not yet added to buildgo.sh. | |||||
858 | #if (defined(__x86_64__1) || SANITIZER_MIPS640) && !SANITIZER_GO0 | |||||
859 | int internal_sigaction_syscall(int signum, const void *act, void *oldact) { | |||||
860 | if (act == nullptr) | |||||
861 | return internal_sigaction_norestorer(signum, act, oldact); | |||||
862 | __sanitizer_sigaction u_adjust; | |||||
863 | internal_memcpy(&u_adjust, act, sizeof(u_adjust)); | |||||
864 | #if !SANITIZER_ANDROID0 || !SANITIZER_MIPS320 | |||||
865 | if (u_adjust.sa_restorer == nullptr) { | |||||
866 | u_adjust.sa_restorer = internal_sigreturn; | |||||
867 | } | |||||
868 | #endif | |||||
869 | return internal_sigaction_norestorer(signum, (const void *)&u_adjust, oldact); | |||||
870 | } | |||||
871 | #endif // defined(__x86_64__) && !SANITIZER_GO | |||||
872 | #endif // SANITIZER_LINUX | |||||
873 | ||||||
874 | uptr internal_sigprocmask(int how, __sanitizer_sigset_t *set, | |||||
875 | __sanitizer_sigset_t *oldset) { | |||||
876 | #if SANITIZER_FREEBSD0 || SANITIZER_OPENBSD0 | |||||
877 | return internal_syscall(SYSCALL(sigprocmask)__NR_sigprocmask, how, set, oldset); | |||||
878 | #else | |||||
879 | __sanitizer_kernel_sigset_t *k_set = (__sanitizer_kernel_sigset_t *)set; | |||||
880 | __sanitizer_kernel_sigset_t *k_oldset = (__sanitizer_kernel_sigset_t *)oldset; | |||||
881 | return internal_syscall(SYSCALL(rt_sigprocmask)14, (uptr)how, | |||||
882 | (uptr)&k_set->sig[0], (uptr)&k_oldset->sig[0], | |||||
883 | sizeof(__sanitizer_kernel_sigset_t)); | |||||
884 | #endif | |||||
885 | } | |||||
886 | ||||||
887 | void internal_sigfillset(__sanitizer_sigset_t *set) { | |||||
888 | internal_memset(set, 0xff, sizeof(*set)); | |||||
889 | } | |||||
890 | ||||||
891 | void internal_sigemptyset(__sanitizer_sigset_t *set) { | |||||
892 | internal_memset(set, 0, sizeof(*set)); | |||||
893 | } | |||||
894 | ||||||
895 | #if SANITIZER_LINUX1 | |||||
896 | void internal_sigdelset(__sanitizer_sigset_t *set, int signum) { | |||||
897 | signum -= 1; | |||||
898 | CHECK_GE(signum, 0)do { __sanitizer::u64 v1 = (__sanitizer::u64)((signum)); __sanitizer ::u64 v2 = (__sanitizer::u64)((0)); if (__builtin_expect(!!(! (v1 >= v2)), 0)) __sanitizer::CheckFailed("/build/llvm-toolchain-snapshot-8~svn345461/projects/compiler-rt/lib/sanitizer_common/sanitizer_linux.cc" , 898, "(" "(signum)" ") " ">=" " (" "(0)" ")", v1, v2); } while (false); | |||||
899 | CHECK_LT(signum, sizeof(*set) * 8)do { __sanitizer::u64 v1 = (__sanitizer::u64)((signum)); __sanitizer ::u64 v2 = (__sanitizer::u64)((sizeof(*set) * 8)); if (__builtin_expect (!!(!(v1 < v2)), 0)) __sanitizer::CheckFailed("/build/llvm-toolchain-snapshot-8~svn345461/projects/compiler-rt/lib/sanitizer_common/sanitizer_linux.cc" , 899, "(" "(signum)" ") " "<" " (" "(sizeof(*set) * 8)" ")" , v1, v2); } while (false); | |||||
900 | __sanitizer_kernel_sigset_t *k_set = (__sanitizer_kernel_sigset_t *)set; | |||||
901 | const uptr idx = signum / (sizeof(k_set->sig[0]) * 8); | |||||
902 | const uptr bit = signum % (sizeof(k_set->sig[0]) * 8); | |||||
903 | k_set->sig[idx] &= ~(1 << bit); | |||||
904 | } | |||||
905 | ||||||
906 | bool internal_sigismember(__sanitizer_sigset_t *set, int signum) { | |||||
907 | signum -= 1; | |||||
908 | CHECK_GE(signum, 0)do { __sanitizer::u64 v1 = (__sanitizer::u64)((signum)); __sanitizer ::u64 v2 = (__sanitizer::u64)((0)); if (__builtin_expect(!!(! (v1 >= v2)), 0)) __sanitizer::CheckFailed("/build/llvm-toolchain-snapshot-8~svn345461/projects/compiler-rt/lib/sanitizer_common/sanitizer_linux.cc" , 908, "(" "(signum)" ") " ">=" " (" "(0)" ")", v1, v2); } while (false); | |||||
909 | CHECK_LT(signum, sizeof(*set) * 8)do { __sanitizer::u64 v1 = (__sanitizer::u64)((signum)); __sanitizer ::u64 v2 = (__sanitizer::u64)((sizeof(*set) * 8)); if (__builtin_expect (!!(!(v1 < v2)), 0)) __sanitizer::CheckFailed("/build/llvm-toolchain-snapshot-8~svn345461/projects/compiler-rt/lib/sanitizer_common/sanitizer_linux.cc" , 909, "(" "(signum)" ") " "<" " (" "(sizeof(*set) * 8)" ")" , v1, v2); } while (false); | |||||
910 | __sanitizer_kernel_sigset_t *k_set = (__sanitizer_kernel_sigset_t *)set; | |||||
911 | const uptr idx = signum / (sizeof(k_set->sig[0]) * 8); | |||||
912 | const uptr bit = signum % (sizeof(k_set->sig[0]) * 8); | |||||
913 | return k_set->sig[idx] & (1 << bit); | |||||
914 | } | |||||
915 | #elif SANITIZER_FREEBSD0 | |||||
916 | void internal_sigdelset(__sanitizer_sigset_t *set, int signum) { | |||||
917 | sigset_t *rset = reinterpret_cast<sigset_t *>(set); | |||||
918 | sigdelset(rset, signum); | |||||
919 | } | |||||
920 | ||||||
921 | bool internal_sigismember(__sanitizer_sigset_t *set, int signum) { | |||||
922 | sigset_t *rset = reinterpret_cast<sigset_t *>(set); | |||||
923 | return sigismember(rset, signum); | |||||
924 | } | |||||
925 | #endif | |||||
926 | #endif // !SANITIZER_SOLARIS | |||||
927 | ||||||
928 | #if !SANITIZER_NETBSD0 | |||||
929 | // ThreadLister implementation. | |||||
930 | ThreadLister::ThreadLister(pid_t pid) : pid_(pid), buffer_(4096) { | |||||
931 | char task_directory_path[80]; | |||||
932 | internal_snprintf(task_directory_path, sizeof(task_directory_path), | |||||
933 | "/proc/%d/task/", pid); | |||||
934 | descriptor_ = internal_open(task_directory_path, O_RDONLY00 | O_DIRECTORY0200000); | |||||
935 | if (internal_iserror(descriptor_)) { | |||||
936 | Report("Can't open /proc/%d/task for reading.\n", pid); | |||||
937 | } | |||||
938 | } | |||||
939 | ||||||
940 | ThreadLister::Result ThreadLister::ListThreads( | |||||
941 | InternalMmapVector<tid_t> *threads) { | |||||
942 | if (internal_iserror(descriptor_)) | |||||
943 | return Error; | |||||
944 | internal_lseek(descriptor_, 0, SEEK_SET0); | |||||
945 | threads->clear(); | |||||
946 | ||||||
947 | Result result = Ok; | |||||
948 | for (bool first_read = true;; first_read = false) { | |||||
949 | // Resize to max capacity if it was downsized by IsAlive. | |||||
950 | buffer_.resize(buffer_.capacity()); | |||||
951 | CHECK_GE(buffer_.size(), 4096)do { __sanitizer::u64 v1 = (__sanitizer::u64)((buffer_.size() )); __sanitizer::u64 v2 = (__sanitizer::u64)((4096)); if (__builtin_expect (!!(!(v1 >= v2)), 0)) __sanitizer::CheckFailed("/build/llvm-toolchain-snapshot-8~svn345461/projects/compiler-rt/lib/sanitizer_common/sanitizer_linux.cc" , 951, "(" "(buffer_.size())" ") " ">=" " (" "(4096)" ")", v1, v2); } while (false); | |||||
952 | uptr read = internal_getdents( | |||||
953 | descriptor_, (struct linux_dirent *)buffer_.data(), buffer_.size()); | |||||
954 | if (!read) | |||||
955 | return result; | |||||
956 | if (internal_iserror(read)) { | |||||
957 | Report("Can't read directory entries from /proc/%d/task.\n", pid_); | |||||
958 | return Error; | |||||
959 | } | |||||
960 | ||||||
961 | for (uptr begin = (uptr)buffer_.data(), end = begin + read; begin < end;) { | |||||
962 | struct linux_dirent *entry = (struct linux_dirent *)begin; | |||||
963 | begin += entry->d_reclen; | |||||
964 | if (entry->d_ino == 1) { | |||||
965 | // Inode 1 is for bad blocks and also can be a reason for early return. | |||||
966 | // Should be emitted if kernel tried to output terminating thread. | |||||
967 | // See proc_task_readdir implementation in Linux. | |||||
968 | result = Incomplete; | |||||
969 | } | |||||
970 | if (entry->d_ino && *entry->d_name >= '0' && *entry->d_name <= '9') | |||||
971 | threads->push_back(internal_atoll(entry->d_name)); | |||||
972 | } | |||||
973 | ||||||
974 | // Now we are going to detect short-read or early EOF. In such cases Linux | |||||
975 | // can return inconsistent list with missing alive threads. | |||||
976 | // Code will just remember that the list can be incomplete but it will | |||||
977 | // continue reads to return as much as possible. | |||||
978 | if (!first_read) { | |||||
979 | // The first one was a short-read by definition. | |||||
980 | result = Incomplete; | |||||
981 | } else if (read > buffer_.size() - 1024) { | |||||
982 | // Read was close to the buffer size. So double the size and assume the | |||||
983 | // worst. | |||||
984 | buffer_.resize(buffer_.size() * 2); | |||||
985 | result = Incomplete; | |||||
986 | } else if (!threads->empty() && !IsAlive(threads->back())) { | |||||
987 | // Maybe Linux early returned from read on terminated thread (!pid_alive) | |||||
988 | // and failed to restore read position. | |||||
989 | // See next_tid and proc_task_instantiate in Linux. | |||||
990 | result = Incomplete; | |||||
991 | } | |||||
992 | } | |||||
993 | } | |||||
994 | ||||||
995 | bool ThreadLister::IsAlive(int tid) { | |||||
996 | // /proc/%d/task/%d/status uses same call to detect alive threads as | |||||
997 | // proc_task_readdir. See task_state implementation in Linux. | |||||
998 | char path[80]; | |||||
999 | internal_snprintf(path, sizeof(path), "/proc/%d/task/%d/status", pid_, tid); | |||||
1000 | if (!ReadFileToVector(path, &buffer_) || buffer_.empty()) | |||||
1001 | return false; | |||||
1002 | buffer_.push_back(0); | |||||
1003 | static const char kPrefix[] = "\nPPid:"; | |||||
1004 | const char *field = internal_strstr(buffer_.data(), kPrefix); | |||||
1005 | if (!field) | |||||
1006 | return false; | |||||
1007 | field += internal_strlen(kPrefix); | |||||
1008 | return (int)internal_atoll(field) != 0; | |||||
1009 | } | |||||
1010 | ||||||
1011 | ThreadLister::~ThreadLister() { | |||||
1012 | if (!internal_iserror(descriptor_)) | |||||
1013 | internal_close(descriptor_); | |||||
1014 | } | |||||
1015 | #endif | |||||
1016 | ||||||
1017 | #if SANITIZER_WORDSIZE64 == 32 | |||||
1018 | // Take care of unusable kernel area in top gigabyte. | |||||
1019 | static uptr GetKernelAreaSize() { | |||||
1020 | #if SANITIZER_LINUX1 && !SANITIZER_X320 | |||||
1021 | const uptr gbyte = 1UL << 30; | |||||
1022 | ||||||
1023 | // Firstly check if there are writable segments | |||||
1024 | // mapped to top gigabyte (e.g. stack). | |||||
1025 | MemoryMappingLayout proc_maps(/*cache_enabled*/true); | |||||
1026 | MemoryMappedSegment segment; | |||||
1027 | while (proc_maps.Next(&segment)) { | |||||
1028 | if ((segment.end >= 3 * gbyte) && segment.IsWritable()) return 0; | |||||
1029 | } | |||||
1030 | ||||||
1031 | #if !SANITIZER_ANDROID0 | |||||
1032 | // Even if nothing is mapped, top Gb may still be accessible | |||||
1033 | // if we are running on 64-bit kernel. | |||||
1034 | // Uname may report misleading results if personality type | |||||
1035 | // is modified (e.g. under schroot) so check this as well. | |||||
1036 | struct utsname uname_info; | |||||
1037 | int pers = personality(0xffffffffUL); | |||||
1038 | if (!(pers & PER_MASK) | |||||
1039 | && uname(&uname_info) == 0 | |||||
1040 | && internal_strstr(uname_info.machine, "64")) | |||||
1041 | return 0; | |||||
1042 | #endif // SANITIZER_ANDROID | |||||
1043 | ||||||
1044 | // Top gigabyte is reserved for kernel. | |||||
1045 | return gbyte; | |||||
1046 | #else | |||||
1047 | return 0; | |||||
1048 | #endif // SANITIZER_LINUX && !SANITIZER_X32 | |||||
1049 | } | |||||
1050 | #endif // SANITIZER_WORDSIZE == 32 | |||||
1051 | ||||||
1052 | uptr GetMaxVirtualAddress() { | |||||
1053 | #if (SANITIZER_NETBSD0 || SANITIZER_OPENBSD0) && defined(__x86_64__1) | |||||
1054 | return 0x7f7ffffff000ULL; // (0x00007f8000000000 - PAGE_SIZE) | |||||
1055 | #elif SANITIZER_WORDSIZE64 == 64 | |||||
1056 | # if defined(__powerpc64__) || defined(__aarch64__) | |||||
1057 | // On PowerPC64 we have two different address space layouts: 44- and 46-bit. | |||||
1058 | // We somehow need to figure out which one we are using now and choose | |||||
1059 | // one of 0x00000fffffffffffUL and 0x00003fffffffffffUL. | |||||
1060 | // Note that with 'ulimit -s unlimited' the stack is moved away from the top | |||||
1061 | // of the address space, so simply checking the stack address is not enough. | |||||
1062 | // This should (does) work for both PowerPC64 Endian modes. | |||||
1063 | // Similarly, aarch64 has multiple address space layouts: 39, 42 and 47-bit. | |||||
1064 | return (1ULL << (MostSignificantSetBitIndex(GET_CURRENT_FRAME()(__sanitizer::uptr) __builtin_frame_address(0)) + 1)) - 1; | |||||
1065 | # elif defined(__mips64) | |||||
1066 | return (1ULL << 40) - 1; // 0x000000ffffffffffUL; | |||||
1067 | # elif defined(__s390x__) | |||||
1068 | return (1ULL << 53) - 1; // 0x001fffffffffffffUL; | |||||
1069 | # else | |||||
1070 | return (1ULL << 47) - 1; // 0x00007fffffffffffUL; | |||||
1071 | # endif | |||||
1072 | #else // SANITIZER_WORDSIZE == 32 | |||||
1073 | # if defined(__s390__) | |||||
1074 | return (1ULL << 31) - 1; // 0x7fffffff; | |||||
1075 | # else | |||||
1076 | return (1ULL << 32) - 1; // 0xffffffff; | |||||
1077 | # endif | |||||
1078 | #endif // SANITIZER_WORDSIZE | |||||
1079 | } | |||||
1080 | ||||||
1081 | uptr GetMaxUserVirtualAddress() { | |||||
1082 | uptr addr = GetMaxVirtualAddress(); | |||||
1083 | #if SANITIZER_WORDSIZE64 == 32 && !defined(__s390__) | |||||
1084 | if (!common_flags()->full_address_space) | |||||
1085 | addr -= GetKernelAreaSize(); | |||||
1086 | CHECK_LT(reinterpret_cast<uptr>(&addr), addr)do { __sanitizer::u64 v1 = (__sanitizer::u64)((reinterpret_cast <uptr>(&addr))); __sanitizer::u64 v2 = (__sanitizer ::u64)((addr)); if (__builtin_expect(!!(!(v1 < v2)), 0)) __sanitizer ::CheckFailed("/build/llvm-toolchain-snapshot-8~svn345461/projects/compiler-rt/lib/sanitizer_common/sanitizer_linux.cc" , 1086, "(" "(reinterpret_cast<uptr>(&addr))" ") " "<" " (" "(addr)" ")", v1, v2); } while (false); | |||||
1087 | #endif | |||||
1088 | return addr; | |||||
1089 | } | |||||
1090 | ||||||
1091 | uptr GetPageSize() { | |||||
1092 | // Android post-M sysconf(_SC_PAGESIZE) crashes if called from .preinit_array. | |||||
1093 | #if SANITIZER_ANDROID0 | |||||
1094 | return 4096; | |||||
1095 | #elif SANITIZER_LINUX1 && (defined(__x86_64__1) || defined(__i386__)) | |||||
1096 | return EXEC_PAGESIZE4096; | |||||
1097 | #elif SANITIZER_USE_GETAUXVAL1 | |||||
1098 | return getauxval(AT_PAGESZ6); | |||||
1099 | #else | |||||
1100 | return sysconf(_SC_PAGESIZE_SC_PAGESIZE); // EXEC_PAGESIZE may not be trustworthy. | |||||
1101 | #endif | |||||
1102 | } | |||||
1103 | ||||||
1104 | #if !SANITIZER_OPENBSD0 | |||||
1105 | uptr ReadBinaryName(/*out*/char *buf, uptr buf_len) { | |||||
1106 | #if SANITIZER_SOLARIS0 | |||||
1107 | const char *default_module_name = getexecname(); | |||||
1108 | CHECK_NE(default_module_name, NULL)do { __sanitizer::u64 v1 = (__sanitizer::u64)((default_module_name )); __sanitizer::u64 v2 = (__sanitizer::u64)((__null)); if (__builtin_expect (!!(!(v1 != v2)), 0)) __sanitizer::CheckFailed("/build/llvm-toolchain-snapshot-8~svn345461/projects/compiler-rt/lib/sanitizer_common/sanitizer_linux.cc" , 1108, "(" "(default_module_name)" ") " "!=" " (" "(__null)" ")", v1, v2); } while (false); | |||||
1109 | return internal_snprintf(buf, buf_len, "%s", default_module_name); | |||||
1110 | #else | |||||
1111 | #if SANITIZER_FREEBSD0 || SANITIZER_NETBSD0 | |||||
1112 | #if SANITIZER_FREEBSD0 | |||||
1113 | const int Mib[4] = {CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, -1}; | |||||
1114 | #else | |||||
1115 | const int Mib[4] = {CTL_KERN, KERN_PROC_ARGS, -1, KERN_PROC_PATHNAME}; | |||||
1116 | #endif | |||||
1117 | const char *default_module_name = "kern.proc.pathname"; | |||||
1118 | uptr Size = buf_len; | |||||
1119 | bool IsErr = | |||||
1120 | (internal_sysctl(Mib, ARRAY_SIZE(Mib)(sizeof(Mib)/sizeof((Mib)[0])), buf, &Size, NULL__null, 0) != 0); | |||||
1121 | int readlink_error = IsErr ? errno(*__errno_location ()) : 0; | |||||
1122 | uptr module_name_len = Size; | |||||
1123 | #else | |||||
1124 | const char *default_module_name = "/proc/self/exe"; | |||||
1125 | uptr module_name_len = internal_readlink( | |||||
1126 | default_module_name, buf, buf_len); | |||||
1127 | int readlink_error; | |||||
1128 | bool IsErr = internal_iserror(module_name_len, &readlink_error); | |||||
1129 | #endif // SANITIZER_SOLARIS | |||||
1130 | if (IsErr) { | |||||
1131 | // We can't read binary name for some reason, assume it's unknown. | |||||
1132 | Report("WARNING: reading executable name failed with errno %d, " | |||||
1133 | "some stack frames may not be symbolized\n", readlink_error); | |||||
1134 | module_name_len = internal_snprintf(buf, buf_len, "%s", | |||||
1135 | default_module_name); | |||||
1136 | CHECK_LT(module_name_len, buf_len)do { __sanitizer::u64 v1 = (__sanitizer::u64)((module_name_len )); __sanitizer::u64 v2 = (__sanitizer::u64)((buf_len)); if ( __builtin_expect(!!(!(v1 < v2)), 0)) __sanitizer::CheckFailed ("/build/llvm-toolchain-snapshot-8~svn345461/projects/compiler-rt/lib/sanitizer_common/sanitizer_linux.cc" , 1136, "(" "(module_name_len)" ") " "<" " (" "(buf_len)" ")" , v1, v2); } while (false); | |||||
1137 | } | |||||
1138 | return module_name_len; | |||||
1139 | #endif | |||||
1140 | } | |||||
1141 | #endif // !SANITIZER_OPENBSD | |||||
1142 | ||||||
1143 | uptr ReadLongProcessName(/*out*/ char *buf, uptr buf_len) { | |||||
1144 | #if SANITIZER_LINUX1 | |||||
1145 | char *tmpbuf; | |||||
1146 | uptr tmpsize; | |||||
1147 | uptr tmplen; | |||||
1148 | if (ReadFileToBuffer("/proc/self/cmdline", &tmpbuf, &tmpsize, &tmplen, | |||||
1149 | 1024 * 1024)) { | |||||
1150 | internal_strncpy(buf, tmpbuf, buf_len); | |||||
1151 | UnmapOrDie(tmpbuf, tmpsize); | |||||
1152 | return internal_strlen(buf); | |||||
1153 | } | |||||
1154 | #endif | |||||
1155 | return ReadBinaryName(buf, buf_len); | |||||
1156 | } | |||||
1157 | ||||||
1158 | // Match full names of the form /path/to/base_name{-,.}* | |||||
1159 | bool LibraryNameIs(const char *full_name, const char *base_name) { | |||||
1160 | const char *name = full_name; | |||||
1161 | // Strip path. | |||||
1162 | while (*name != '\0') name++; | |||||
1163 | while (name > full_name && *name != '/') name--; | |||||
1164 | if (*name == '/') name++; | |||||
1165 | uptr base_name_length = internal_strlen(base_name); | |||||
1166 | if (internal_strncmp(name, base_name, base_name_length)) return false; | |||||
1167 | return (name[base_name_length] == '-' || name[base_name_length] == '.'); | |||||
1168 | } | |||||
1169 | ||||||
1170 | #if !SANITIZER_ANDROID0 | |||||
1171 | // Call cb for each region mapped by map. | |||||
1172 | void ForEachMappedRegion(link_map *map, void (*cb)(const void *, uptr)) { | |||||
1173 | CHECK_NE(map, nullptr)do { __sanitizer::u64 v1 = (__sanitizer::u64)((map)); __sanitizer ::u64 v2 = (__sanitizer::u64)((nullptr)); if (__builtin_expect (!!(!(v1 != v2)), 0)) __sanitizer::CheckFailed("/build/llvm-toolchain-snapshot-8~svn345461/projects/compiler-rt/lib/sanitizer_common/sanitizer_linux.cc" , 1173, "(" "(map)" ") " "!=" " (" "(nullptr)" ")", v1, v2); } while (false); | |||||
1174 | #if !SANITIZER_FREEBSD0 && !SANITIZER_OPENBSD0 | |||||
1175 | typedef ElfW(Phdr)Elf64_Phdr Elf_Phdr; | |||||
1176 | typedef ElfW(Ehdr)Elf64_Ehdr Elf_Ehdr; | |||||
1177 | #endif // !SANITIZER_FREEBSD && !SANITIZER_OPENBSD | |||||
1178 | char *base = (char *)map->l_addr; | |||||
1179 | Elf_Ehdr *ehdr = (Elf_Ehdr *)base; | |||||
1180 | char *phdrs = base + ehdr->e_phoff; | |||||
1181 | char *phdrs_end = phdrs + ehdr->e_phnum * ehdr->e_phentsize; | |||||
1182 | ||||||
1183 | // Find the segment with the minimum base so we can "relocate" the p_vaddr | |||||
1184 | // fields. Typically ET_DYN objects (DSOs) have base of zero and ET_EXEC | |||||
1185 | // objects have a non-zero base. | |||||
1186 | uptr preferred_base = (uptr)-1; | |||||
1187 | for (char *iter = phdrs; iter != phdrs_end; iter += ehdr->e_phentsize) { | |||||
1188 | Elf_Phdr *phdr = (Elf_Phdr *)iter; | |||||
1189 | if (phdr->p_type == PT_LOAD1 && preferred_base > (uptr)phdr->p_vaddr) | |||||
1190 | preferred_base = (uptr)phdr->p_vaddr; | |||||
1191 | } | |||||
1192 | ||||||
1193 | // Compute the delta from the real base to get a relocation delta. | |||||
1194 | sptr delta = (uptr)base - preferred_base; | |||||
1195 | // Now we can figure out what the loader really mapped. | |||||
1196 | for (char *iter = phdrs; iter != phdrs_end; iter += ehdr->e_phentsize) { | |||||
1197 | Elf_Phdr *phdr = (Elf_Phdr *)iter; | |||||
1198 | if (phdr->p_type == PT_LOAD1) { | |||||
1199 | uptr seg_start = phdr->p_vaddr + delta; | |||||
1200 | uptr seg_end = seg_start + phdr->p_memsz; | |||||
1201 | // None of these values are aligned. We consider the ragged edges of the | |||||
1202 | // load command as defined, since they are mapped from the file. | |||||
1203 | seg_start = RoundDownTo(seg_start, GetPageSizeCached()); | |||||
1204 | seg_end = RoundUpTo(seg_end, GetPageSizeCached()); | |||||
1205 | cb((void *)seg_start, seg_end - seg_start); | |||||
1206 | } | |||||
1207 | } | |||||
1208 | } | |||||
1209 | #endif | |||||
1210 | ||||||
1211 | #if defined(__x86_64__1) && SANITIZER_LINUX1 | |||||
1212 | // We cannot use glibc's clone wrapper, because it messes with the child | |||||
1213 | // task's TLS. It writes the PID and TID of the child task to its thread | |||||
1214 | // descriptor, but in our case the child task shares the thread descriptor with | |||||
1215 | // the parent (because we don't know how to allocate a new thread | |||||
1216 | // descriptor to keep glibc happy). So the stock version of clone(), when | |||||
1217 | // used with CLONE_VM, would end up corrupting the parent's thread descriptor. | |||||
1218 | uptr internal_clone(int (*fn)(void *), void *child_stack, int flags, void *arg, | |||||
1219 | int *parent_tidptr, void *newtls, int *child_tidptr) { | |||||
1220 | long long res; | |||||
1221 | if (!fn || !child_stack) | |||||
1222 | return -EINVAL22; | |||||
1223 | CHECK_EQ(0, (uptr)child_stack % 16)do { __sanitizer::u64 v1 = (__sanitizer::u64)((0)); __sanitizer ::u64 v2 = (__sanitizer::u64)(((uptr)child_stack % 16)); if ( __builtin_expect(!!(!(v1 == v2)), 0)) __sanitizer::CheckFailed ("/build/llvm-toolchain-snapshot-8~svn345461/projects/compiler-rt/lib/sanitizer_common/sanitizer_linux.cc" , 1223, "(" "(0)" ") " "==" " (" "((uptr)child_stack % 16)" ")" , v1, v2); } while (false); | |||||
1224 | child_stack = (char *)child_stack - 2 * sizeof(unsigned long long); | |||||
1225 | ((unsigned long long *)child_stack)[0] = (uptr)fn; | |||||
1226 | ((unsigned long long *)child_stack)[1] = (uptr)arg; | |||||
1227 | register void *r8 __asm__("r8") = newtls; | |||||
1228 | register int *r10 __asm__("r10") = child_tidptr; | |||||
1229 | __asm__ __volatile__( | |||||
1230 | /* %rax = syscall(%rax = SYSCALL(clone), | |||||
1231 | * %rdi = flags, | |||||
1232 | * %rsi = child_stack, | |||||
1233 | * %rdx = parent_tidptr, | |||||
1234 | * %r8 = new_tls, | |||||
1235 | * %r10 = child_tidptr) | |||||
1236 | */ | |||||
1237 | "syscall\n" | |||||
1238 | ||||||
1239 | /* if (%rax != 0) | |||||
1240 | * return; | |||||
1241 | */ | |||||
1242 | "testq %%rax,%%rax\n" | |||||
1243 | "jnz 1f\n" | |||||
1244 | ||||||
1245 | /* In the child. Terminate unwind chain. */ | |||||
1246 | // XXX: We should also terminate the CFI unwind chain | |||||
1247 | // here. Unfortunately clang 3.2 doesn't support the | |||||
1248 | // necessary CFI directives, so we skip that part. | |||||
1249 | "xorq %%rbp,%%rbp\n" | |||||
1250 | ||||||
1251 | /* Call "fn(arg)". */ | |||||
1252 | "popq %%rax\n" | |||||
1253 | "popq %%rdi\n" | |||||
1254 | "call *%%rax\n" | |||||
1255 | ||||||
1256 | /* Call _exit(%rax). */ | |||||
1257 | "movq %%rax,%%rdi\n" | |||||
1258 | "movq %2,%%rax\n" | |||||
1259 | "syscall\n" | |||||
1260 | ||||||
1261 | /* Return to parent. */ | |||||
1262 | "1:\n" | |||||
1263 | : "=a" (res) | |||||
1264 | : "a"(SYSCALL(clone)56), "i"(SYSCALL(exit)60), | |||||
1265 | "S"(child_stack), | |||||
1266 | "D"(flags), | |||||
1267 | "d"(parent_tidptr), | |||||
1268 | "r"(r8), | |||||
1269 | "r"(r10) | |||||
1270 | : "memory", "r11", "rcx"); | |||||
1271 | return res; | |||||
1272 | } | |||||
1273 | #elif defined(__mips__) | |||||
1274 | uptr internal_clone(int (*fn)(void *), void *child_stack, int flags, void *arg, | |||||
1275 | int *parent_tidptr, void *newtls, int *child_tidptr) { | |||||
1276 | long long res; | |||||
1277 | if (!fn || !child_stack) | |||||
1278 | return -EINVAL22; | |||||
1279 | CHECK_EQ(0, (uptr)child_stack % 16)do { __sanitizer::u64 v1 = (__sanitizer::u64)((0)); __sanitizer ::u64 v2 = (__sanitizer::u64)(((uptr)child_stack % 16)); if ( __builtin_expect(!!(!(v1 == v2)), 0)) __sanitizer::CheckFailed ("/build/llvm-toolchain-snapshot-8~svn345461/projects/compiler-rt/lib/sanitizer_common/sanitizer_linux.cc" , 1279, "(" "(0)" ") " "==" " (" "((uptr)child_stack % 16)" ")" , v1, v2); } while (false); | |||||
1280 | child_stack = (char *)child_stack - 2 * sizeof(unsigned long long); | |||||
1281 | ((unsigned long long *)child_stack)[0] = (uptr)fn; | |||||
1282 | ((unsigned long long *)child_stack)[1] = (uptr)arg; | |||||
1283 | register void *a3 __asm__("$7") = newtls; | |||||
1284 | register int *a4 __asm__("$8") = child_tidptr; | |||||
1285 | // We don't have proper CFI directives here because it requires alot of code | |||||
1286 | // for very marginal benefits. | |||||
1287 | __asm__ __volatile__( | |||||
1288 | /* $v0 = syscall($v0 = __NR_clone, | |||||
1289 | * $a0 = flags, | |||||
1290 | * $a1 = child_stack, | |||||
1291 | * $a2 = parent_tidptr, | |||||
1292 | * $a3 = new_tls, | |||||
1293 | * $a4 = child_tidptr) | |||||
1294 | */ | |||||
1295 | ".cprestore 16;\n" | |||||
1296 | "move $4,%1;\n" | |||||
1297 | "move $5,%2;\n" | |||||
1298 | "move $6,%3;\n" | |||||
1299 | "move $7,%4;\n" | |||||
1300 | /* Store the fifth argument on stack | |||||
1301 | * if we are using 32-bit abi. | |||||
1302 | */ | |||||
1303 | #if SANITIZER_WORDSIZE64 == 32 | |||||
1304 | "lw %5,16($29);\n" | |||||
1305 | #else | |||||
1306 | "move $8,%5;\n" | |||||
1307 | #endif | |||||
1308 | "li $2,%6;\n" | |||||
1309 | "syscall;\n" | |||||
1310 | ||||||
1311 | /* if ($v0 != 0) | |||||
1312 | * return; | |||||
1313 | */ | |||||
1314 | "bnez $2,1f;\n" | |||||
1315 | ||||||
1316 | /* Call "fn(arg)". */ | |||||
1317 | #if SANITIZER_WORDSIZE64 == 32 | |||||
1318 | #ifdef __BIG_ENDIAN__ | |||||
1319 | "lw $25,4($29);\n" | |||||
1320 | "lw $4,12($29);\n" | |||||
1321 | #else | |||||
1322 | "lw $25,0($29);\n" | |||||
1323 | "lw $4,8($29);\n" | |||||
1324 | #endif | |||||
1325 | #else | |||||
1326 | "ld $25,0($29);\n" | |||||
1327 | "ld $4,8($29);\n" | |||||
1328 | #endif | |||||
1329 | "jal $25;\n" | |||||
1330 | ||||||
1331 | /* Call _exit($v0). */ | |||||
1332 | "move $4,$2;\n" | |||||
1333 | "li $2,%7;\n" | |||||
1334 | "syscall;\n" | |||||
1335 | ||||||
1336 | /* Return to parent. */ | |||||
1337 | "1:\n" | |||||
1338 | : "=r" (res) | |||||
1339 | : "r"(flags), | |||||
1340 | "r"(child_stack), | |||||
1341 | "r"(parent_tidptr), | |||||
1342 | "r"(a3), | |||||
1343 | "r"(a4), | |||||
1344 | "i"(__NR_clone56), | |||||
1345 | "i"(__NR_exit60) | |||||
1346 | : "memory", "$29" ); | |||||
1347 | return res; | |||||
1348 | } | |||||
1349 | #elif defined(__aarch64__) | |||||
1350 | uptr internal_clone(int (*fn)(void *), void *child_stack, int flags, void *arg, | |||||
1351 | int *parent_tidptr, void *newtls, int *child_tidptr) { | |||||
1352 | long long res; | |||||
1353 | if (!fn || !child_stack) | |||||
1354 | return -EINVAL22; | |||||
1355 | CHECK_EQ(0, (uptr)child_stack % 16)do { __sanitizer::u64 v1 = (__sanitizer::u64)((0)); __sanitizer ::u64 v2 = (__sanitizer::u64)(((uptr)child_stack % 16)); if ( __builtin_expect(!!(!(v1 == v2)), 0)) __sanitizer::CheckFailed ("/build/llvm-toolchain-snapshot-8~svn345461/projects/compiler-rt/lib/sanitizer_common/sanitizer_linux.cc" , 1355, "(" "(0)" ") " "==" " (" "((uptr)child_stack % 16)" ")" , v1, v2); } while (false); | |||||
1356 | child_stack = (char *)child_stack - 2 * sizeof(unsigned long long); | |||||
1357 | ((unsigned long long *)child_stack)[0] = (uptr)fn; | |||||
1358 | ((unsigned long long *)child_stack)[1] = (uptr)arg; | |||||
1359 | ||||||
1360 | register int (*__fn)(void *) __asm__("x0") = fn; | |||||
1361 | register void *__stack __asm__("x1") = child_stack; | |||||
1362 | register int __flags __asm__("x2") = flags; | |||||
1363 | register void *__arg __asm__("x3") = arg; | |||||
1364 | register int *__ptid __asm__("x4") = parent_tidptr; | |||||
1365 | register void *__tls __asm__("x5") = newtls; | |||||
1366 | register int *__ctid __asm__("x6") = child_tidptr; | |||||
1367 | ||||||
1368 | __asm__ __volatile__( | |||||
1369 | "mov x0,x2\n" /* flags */ | |||||
1370 | "mov x2,x4\n" /* ptid */ | |||||
1371 | "mov x3,x5\n" /* tls */ | |||||
1372 | "mov x4,x6\n" /* ctid */ | |||||
1373 | "mov x8,%9\n" /* clone */ | |||||
1374 | ||||||
1375 | "svc 0x0\n" | |||||
1376 | ||||||
1377 | /* if (%r0 != 0) | |||||
1378 | * return %r0; | |||||
1379 | */ | |||||
1380 | "cmp x0, #0\n" | |||||
1381 | "bne 1f\n" | |||||
1382 | ||||||
1383 | /* In the child, now. Call "fn(arg)". */ | |||||
1384 | "ldp x1, x0, [sp], #16\n" | |||||
1385 | "blr x1\n" | |||||
1386 | ||||||
1387 | /* Call _exit(%r0). */ | |||||
1388 | "mov x8, %10\n" | |||||
1389 | "svc 0x0\n" | |||||
1390 | "1:\n" | |||||
1391 | ||||||
1392 | : "=r" (res) | |||||
1393 | : "i"(-EINVAL22), | |||||
1394 | "r"(__fn), "r"(__stack), "r"(__flags), "r"(__arg), | |||||
1395 | "r"(__ptid), "r"(__tls), "r"(__ctid), | |||||
1396 | "i"(__NR_clone56), "i"(__NR_exit60) | |||||
1397 | : "x30", "memory"); | |||||
1398 | return res; | |||||
1399 | } | |||||
1400 | #elif defined(__powerpc64__) | |||||
1401 | uptr internal_clone(int (*fn)(void *), void *child_stack, int flags, void *arg, | |||||
1402 | int *parent_tidptr, void *newtls, int *child_tidptr) { | |||||
1403 | long long res; | |||||
1404 | // Stack frame structure. | |||||
1405 | #if SANITIZER_PPC64V10 | |||||
1406 | // Back chain == 0 (SP + 112) | |||||
1407 | // Frame (112 bytes): | |||||
1408 | // Parameter save area (SP + 48), 8 doublewords | |||||
1409 | // TOC save area (SP + 40) | |||||
1410 | // Link editor doubleword (SP + 32) | |||||
1411 | // Compiler doubleword (SP + 24) | |||||
1412 | // LR save area (SP + 16) | |||||
1413 | // CR save area (SP + 8) | |||||
1414 | // Back chain (SP + 0) | |||||
1415 | # define FRAME_SIZE 112 | |||||
1416 | # define FRAME_TOC_SAVE_OFFSET 40 | |||||
1417 | #elif SANITIZER_PPC64V20 | |||||
1418 | // Back chain == 0 (SP + 32) | |||||
1419 | // Frame (32 bytes): | |||||
1420 | // TOC save area (SP + 24) | |||||
1421 | // LR save area (SP + 16) | |||||
1422 | // CR save area (SP + 8) | |||||
1423 | // Back chain (SP + 0) | |||||
1424 | # define FRAME_SIZE 32 | |||||
1425 | # define FRAME_TOC_SAVE_OFFSET 24 | |||||
1426 | #else | |||||
1427 | # error "Unsupported PPC64 ABI" | |||||
1428 | #endif | |||||
1429 | if (!fn || !child_stack) | |||||
1430 | return -EINVAL22; | |||||
1431 | CHECK_EQ(0, (uptr)child_stack % 16)do { __sanitizer::u64 v1 = (__sanitizer::u64)((0)); __sanitizer ::u64 v2 = (__sanitizer::u64)(((uptr)child_stack % 16)); if ( __builtin_expect(!!(!(v1 == v2)), 0)) __sanitizer::CheckFailed ("/build/llvm-toolchain-snapshot-8~svn345461/projects/compiler-rt/lib/sanitizer_common/sanitizer_linux.cc" , 1431, "(" "(0)" ") " "==" " (" "((uptr)child_stack % 16)" ")" , v1, v2); } while (false); | |||||
1432 | ||||||
1433 | register int (*__fn)(void *) __asm__("r3") = fn; | |||||
1434 | register void *__cstack __asm__("r4") = child_stack; | |||||
1435 | register int __flags __asm__("r5") = flags; | |||||
1436 | register void *__arg __asm__("r6") = arg; | |||||
1437 | register int *__ptidptr __asm__("r7") = parent_tidptr; | |||||
1438 | register void *__newtls __asm__("r8") = newtls; | |||||
1439 | register int *__ctidptr __asm__("r9") = child_tidptr; | |||||
1440 | ||||||
1441 | __asm__ __volatile__( | |||||
1442 | /* fn and arg are saved across the syscall */ | |||||
1443 | "mr 28, %5\n\t" | |||||
1444 | "mr 27, %8\n\t" | |||||
1445 | ||||||
1446 | /* syscall | |||||
1447 | r0 == __NR_clone | |||||
1448 | r3 == flags | |||||
1449 | r4 == child_stack | |||||
1450 | r5 == parent_tidptr | |||||
1451 | r6 == newtls | |||||
1452 | r7 == child_tidptr */ | |||||
1453 | "mr 3, %7\n\t" | |||||
1454 | "mr 5, %9\n\t" | |||||
1455 | "mr 6, %10\n\t" | |||||
1456 | "mr 7, %11\n\t" | |||||
1457 | "li 0, %3\n\t" | |||||
1458 | "sc\n\t" | |||||
1459 | ||||||
1460 | /* Test if syscall was successful */ | |||||
1461 | "cmpdi cr1, 3, 0\n\t" | |||||
1462 | "crandc cr1*4+eq, cr1*4+eq, cr0*4+so\n\t" | |||||
1463 | "bne- cr1, 1f\n\t" | |||||
1464 | ||||||
1465 | /* Set up stack frame */ | |||||
1466 | "li 29, 0\n\t" | |||||
1467 | "stdu 29, -8(1)\n\t" | |||||
1468 | "stdu 1, -%12(1)\n\t" | |||||
1469 | /* Do the function call */ | |||||
1470 | "std 2, %13(1)\n\t" | |||||
1471 | #if SANITIZER_PPC64V10 | |||||
1472 | "ld 0, 0(28)\n\t" | |||||
1473 | "ld 2, 8(28)\n\t" | |||||
1474 | "mtctr 0\n\t" | |||||
1475 | #elif SANITIZER_PPC64V20 | |||||
1476 | "mr 12, 28\n\t" | |||||
1477 | "mtctr 12\n\t" | |||||
1478 | #else | |||||
1479 | # error "Unsupported PPC64 ABI" | |||||
1480 | #endif | |||||
1481 | "mr 3, 27\n\t" | |||||
1482 | "bctrl\n\t" | |||||
1483 | "ld 2, %13(1)\n\t" | |||||
1484 | ||||||
1485 | /* Call _exit(r3) */ | |||||
1486 | "li 0, %4\n\t" | |||||
1487 | "sc\n\t" | |||||
1488 | ||||||
1489 | /* Return to parent */ | |||||
1490 | "1:\n\t" | |||||
1491 | "mr %0, 3\n\t" | |||||
1492 | : "=r" (res) | |||||
1493 | : "0" (-1), | |||||
1494 | "i" (EINVAL22), | |||||
1495 | "i" (__NR_clone56), | |||||
1496 | "i" (__NR_exit60), | |||||
1497 | "r" (__fn), | |||||
1498 | "r" (__cstack), | |||||
1499 | "r" (__flags), | |||||
1500 | "r" (__arg), | |||||
1501 | "r" (__ptidptr), | |||||
1502 | "r" (__newtls), | |||||
1503 | "r" (__ctidptr), | |||||
1504 | "i" (FRAME_SIZE), | |||||
1505 | "i" (FRAME_TOC_SAVE_OFFSET) | |||||
1506 | : "cr0", "cr1", "memory", "ctr", "r0", "r27", "r28", "r29"); | |||||
1507 | return res; | |||||
1508 | } | |||||
1509 | #elif defined(__i386__) && SANITIZER_LINUX1 | |||||
1510 | uptr internal_clone(int (*fn)(void *), void *child_stack, int flags, void *arg, | |||||
1511 | int *parent_tidptr, void *newtls, int *child_tidptr) { | |||||
1512 | int res; | |||||
1513 | if (!fn || !child_stack) | |||||
1514 | return -EINVAL22; | |||||
1515 | CHECK_EQ(0, (uptr)child_stack % 16)do { __sanitizer::u64 v1 = (__sanitizer::u64)((0)); __sanitizer ::u64 v2 = (__sanitizer::u64)(((uptr)child_stack % 16)); if ( __builtin_expect(!!(!(v1 == v2)), 0)) __sanitizer::CheckFailed ("/build/llvm-toolchain-snapshot-8~svn345461/projects/compiler-rt/lib/sanitizer_common/sanitizer_linux.cc" , 1515, "(" "(0)" ") " "==" " (" "((uptr)child_stack % 16)" ")" , v1, v2); } while (false); | |||||
1516 | child_stack = (char *)child_stack - 7 * sizeof(unsigned int); | |||||
1517 | ((unsigned int *)child_stack)[0] = (uptr)flags; | |||||
1518 | ((unsigned int *)child_stack)[1] = (uptr)0; | |||||
1519 | ((unsigned int *)child_stack)[2] = (uptr)fn; | |||||
1520 | ((unsigned int *)child_stack)[3] = (uptr)arg; | |||||
1521 | __asm__ __volatile__( | |||||
1522 | /* %eax = syscall(%eax = SYSCALL(clone), | |||||
1523 | * %ebx = flags, | |||||
1524 | * %ecx = child_stack, | |||||
1525 | * %edx = parent_tidptr, | |||||
1526 | * %esi = new_tls, | |||||
1527 | * %edi = child_tidptr) | |||||
1528 | */ | |||||
1529 | ||||||
1530 | /* Obtain flags */ | |||||
1531 | "movl (%%ecx), %%ebx\n" | |||||
1532 | /* Do the system call */ | |||||
1533 | "pushl %%ebx\n" | |||||
1534 | "pushl %%esi\n" | |||||
1535 | "pushl %%edi\n" | |||||
1536 | /* Remember the flag value. */ | |||||
1537 | "movl %%ebx, (%%ecx)\n" | |||||
1538 | "int $0x80\n" | |||||
1539 | "popl %%edi\n" | |||||
1540 | "popl %%esi\n" | |||||
1541 | "popl %%ebx\n" | |||||
1542 | ||||||
1543 | /* if (%eax != 0) | |||||
1544 | * return; | |||||
1545 | */ | |||||
1546 | ||||||
1547 | "test %%eax,%%eax\n" | |||||
1548 | "jnz 1f\n" | |||||
1549 | ||||||
1550 | /* terminate the stack frame */ | |||||
1551 | "xorl %%ebp,%%ebp\n" | |||||
1552 | /* Call FN. */ | |||||
1553 | "call *%%ebx\n" | |||||
1554 | #ifdef PIC | |||||
1555 | "call here\n" | |||||
1556 | "here:\n" | |||||
1557 | "popl %%ebx\n" | |||||
1558 | "addl $_GLOBAL_OFFSET_TABLE_+[.-here], %%ebx\n" | |||||
1559 | #endif | |||||
1560 | /* Call exit */ | |||||
1561 | "movl %%eax, %%ebx\n" | |||||
1562 | "movl %2, %%eax\n" | |||||
1563 | "int $0x80\n" | |||||
1564 | "1:\n" | |||||
1565 | : "=a" (res) | |||||
1566 | : "a"(SYSCALL(clone)56), "i"(SYSCALL(exit)60), | |||||
1567 | "c"(child_stack), | |||||
1568 | "d"(parent_tidptr), | |||||
1569 | "S"(newtls), | |||||
1570 | "D"(child_tidptr) | |||||
1571 | : "memory"); | |||||
1572 | return res; | |||||
1573 | } | |||||
1574 | #elif defined(__arm__) && SANITIZER_LINUX1 | |||||
1575 | uptr internal_clone(int (*fn)(void *), void *child_stack, int flags, void *arg, | |||||
1576 | int *parent_tidptr, void *newtls, int *child_tidptr) { | |||||
1577 | unsigned int res; | |||||
1578 | if (!fn || !child_stack) | |||||
1579 | return -EINVAL22; | |||||
1580 | child_stack = (char *)child_stack - 2 * sizeof(unsigned int); | |||||
1581 | ((unsigned int *)child_stack)[0] = (uptr)fn; | |||||
1582 | ((unsigned int *)child_stack)[1] = (uptr)arg; | |||||
1583 | register int r0 __asm__("r0") = flags; | |||||
1584 | register void *r1 __asm__("r1") = child_stack; | |||||
1585 | register int *r2 __asm__("r2") = parent_tidptr; | |||||
1586 | register void *r3 __asm__("r3") = newtls; | |||||
1587 | register int *r4 __asm__("r4") = child_tidptr; | |||||
1588 | register int r7 __asm__("r7") = __NR_clone56; | |||||
1589 | ||||||
1590 | #if __ARM_ARCH > 4 || defined (__ARM_ARCH_4T__) | |||||
1591 | # define ARCH_HAS_BX | |||||
1592 | #endif | |||||
1593 | #if __ARM_ARCH > 4 | |||||
1594 | # define ARCH_HAS_BLX | |||||
1595 | #endif | |||||
1596 | ||||||
1597 | #ifdef ARCH_HAS_BX | |||||
1598 | # ifdef ARCH_HAS_BLX | |||||
1599 | # define BLX(R) "blx " #R "\n" | |||||
1600 | # else | |||||
1601 | # define BLX(R) "mov lr, pc; bx " #R "\n" | |||||
1602 | # endif | |||||
1603 | #else | |||||
1604 | # define BLX(R) "mov lr, pc; mov pc," #R "\n" | |||||
1605 | #endif | |||||
1606 | ||||||
1607 | __asm__ __volatile__( | |||||
1608 | /* %r0 = syscall(%r7 = SYSCALL(clone), | |||||
1609 | * %r0 = flags, | |||||
1610 | * %r1 = child_stack, | |||||
1611 | * %r2 = parent_tidptr, | |||||
1612 | * %r3 = new_tls, | |||||
1613 | * %r4 = child_tidptr) | |||||
1614 | */ | |||||
1615 | ||||||
1616 | /* Do the system call */ | |||||
1617 | "swi 0x0\n" | |||||
1618 | ||||||
1619 | /* if (%r0 != 0) | |||||
1620 | * return %r0; | |||||
1621 | */ | |||||
1622 | "cmp r0, #0\n" | |||||
1623 | "bne 1f\n" | |||||
1624 | ||||||
1625 | /* In the child, now. Call "fn(arg)". */ | |||||
1626 | "ldr r0, [sp, #4]\n" | |||||
1627 | "ldr ip, [sp], #8\n" | |||||
1628 | BLX(ip) | |||||
1629 | /* Call _exit(%r0). */ | |||||
1630 | "mov r7, %7\n" | |||||
1631 | "swi 0x0\n" | |||||
1632 | "1:\n" | |||||
1633 | "mov %0, r0\n" | |||||
1634 | : "=r"(res) | |||||
1635 | : "r"(r0), "r"(r1), "r"(r2), "r"(r3), "r"(r4), "r"(r7), | |||||
1636 | "i"(__NR_exit60) | |||||
1637 | : "memory"); | |||||
1638 | return res; | |||||
1639 | } | |||||
1640 | #endif // defined(__x86_64__) && SANITIZER_LINUX | |||||
1641 | ||||||
1642 | #if SANITIZER_ANDROID0 | |||||
1643 | #if __ANDROID_API__ < 21 | |||||
1644 | extern "C" __attribute__((weak)) int dl_iterate_phdr( | |||||
1645 | int (*)(struct dl_phdr_info *, size_t, void *), void *); | |||||
1646 | #endif | |||||
1647 | ||||||
1648 | static int dl_iterate_phdr_test_cb(struct dl_phdr_info *info, size_t size, | |||||
1649 | void *data) { | |||||
1650 | // Any name starting with "lib" indicates a bug in L where library base names | |||||
1651 | // are returned instead of paths. | |||||
1652 | if (info->dlpi_name && info->dlpi_name[0] == 'l' && | |||||
1653 | info->dlpi_name[1] == 'i' && info->dlpi_name[2] == 'b') { | |||||
1654 | *(bool *)data = true; | |||||
1655 | return 1; | |||||
1656 | } | |||||
1657 | return 0; | |||||
1658 | } | |||||
1659 | ||||||
1660 | static atomic_uint32_t android_api_level; | |||||
1661 | ||||||
1662 | static AndroidApiLevel AndroidDetectApiLevelStatic() { | |||||
1663 | #if __ANDROID_API__ <= 19 | |||||
1664 | return ANDROID_KITKAT; | |||||
1665 | #elif __ANDROID_API__ <= 22 | |||||
1666 | return ANDROID_LOLLIPOP_MR1; | |||||
1667 | #else | |||||
1668 | return ANDROID_POST_LOLLIPOP; | |||||
1669 | #endif | |||||
1670 | } | |||||
1671 | ||||||
1672 | static AndroidApiLevel AndroidDetectApiLevel() { | |||||
1673 | if (!&dl_iterate_phdr) | |||||
1674 | return ANDROID_KITKAT; // K or lower | |||||
1675 | bool base_name_seen = false; | |||||
1676 | dl_iterate_phdr(dl_iterate_phdr_test_cb, &base_name_seen); | |||||
1677 | if (base_name_seen) | |||||
1678 | return ANDROID_LOLLIPOP_MR1; // L MR1 | |||||
1679 | return ANDROID_POST_LOLLIPOP; // post-L | |||||
1680 | // Plain L (API level 21) is completely broken wrt ASan and not very | |||||
1681 | // interesting to detect. | |||||
1682 | } | |||||
1683 | ||||||
1684 | extern "C" __attribute__((weak)) void* _DYNAMIC; | |||||
1685 | ||||||
1686 | AndroidApiLevel AndroidGetApiLevel() { | |||||
1687 | AndroidApiLevel level = | |||||
1688 | (AndroidApiLevel)atomic_load(&android_api_level, memory_order_relaxed); | |||||
1689 | if (level) return level; | |||||
1690 | level = &_DYNAMIC == nullptr ? AndroidDetectApiLevelStatic() | |||||
1691 | : AndroidDetectApiLevel(); | |||||
1692 | atomic_store(&android_api_level, level, memory_order_relaxed); | |||||
1693 | return level; | |||||
1694 | } | |||||
1695 | ||||||
1696 | #endif | |||||
1697 | ||||||
1698 | static HandleSignalMode GetHandleSignalModeImpl(int signum) { | |||||
1699 | switch (signum) { | |||||
1700 | case SIGABRT6: | |||||
1701 | return common_flags()->handle_abort; | |||||
1702 | case SIGILL4: | |||||
1703 | return common_flags()->handle_sigill; | |||||
1704 | case SIGTRAP5: | |||||
1705 | return common_flags()->handle_sigtrap; | |||||
1706 | case SIGFPE8: | |||||
1707 | return common_flags()->handle_sigfpe; | |||||
1708 | case SIGSEGV11: | |||||
1709 | return common_flags()->handle_segv; | |||||
1710 | case SIGBUS7: | |||||
1711 | return common_flags()->handle_sigbus; | |||||
1712 | } | |||||
1713 | return kHandleSignalNo; | |||||
1714 | } | |||||
1715 | ||||||
1716 | HandleSignalMode GetHandleSignalMode(int signum) { | |||||
1717 | HandleSignalMode result = GetHandleSignalModeImpl(signum); | |||||
1718 | if (result == kHandleSignalYes && !common_flags()->allow_user_segv_handler) | |||||
1719 | return kHandleSignalExclusive; | |||||
1720 | return result; | |||||
1721 | } | |||||
1722 | ||||||
1723 | #if !SANITIZER_GO0 | |||||
1724 | void *internal_start_thread(void(*func)(void *arg), void *arg) { | |||||
1725 | // Start the thread with signals blocked, otherwise it can steal user signals. | |||||
1726 | __sanitizer_sigset_t set, old; | |||||
1727 | internal_sigfillset(&set); | |||||
1728 | #if SANITIZER_LINUX1 && !SANITIZER_ANDROID0 | |||||
1729 | // Glibc uses SIGSETXID signal during setuid call. If this signal is blocked | |||||
1730 | // on any thread, setuid call hangs (see test/tsan/setuid.c). | |||||
1731 | internal_sigdelset(&set, 33); | |||||
1732 | #endif | |||||
1733 | internal_sigprocmask(SIG_SETMASK2, &set, &old); | |||||
1734 | void *th; | |||||
1735 | real_pthread_create(&th, nullptr, (void*(*)(void *arg))func, arg); | |||||
1736 | internal_sigprocmask(SIG_SETMASK2, &old, nullptr); | |||||
1737 | return th; | |||||
1738 | } | |||||
1739 | ||||||
1740 | void internal_join_thread(void *th) { | |||||
1741 | real_pthread_join(th, nullptr); | |||||
1742 | } | |||||
1743 | #else | |||||
1744 | void *internal_start_thread(void (*func)(void *), void *arg) { return 0; } | |||||
1745 | ||||||
1746 | void internal_join_thread(void *th) {} | |||||
1747 | #endif | |||||
1748 | ||||||
1749 | #if defined(__aarch64__) | |||||
1750 | // Android headers in the older NDK releases miss this definition. | |||||
1751 | struct __sanitizer_esr_context { | |||||
1752 | struct _aarch64_ctx head; | |||||
1753 | uint64_t esr; | |||||
1754 | }; | |||||
1755 | ||||||
1756 | static bool Aarch64GetESR(ucontext_t *ucontext, u64 *esr) { | |||||
1757 | static const u32 kEsrMagic = 0x45535201; | |||||
1758 | u8 *aux = ucontext->uc_mcontext.__reserved; | |||||
1759 | while (true) { | |||||
1760 | _aarch64_ctx *ctx = (_aarch64_ctx *)aux; | |||||
1761 | if (ctx->size == 0) break; | |||||
1762 | if (ctx->magic == kEsrMagic) { | |||||
1763 | *esr = ((__sanitizer_esr_context *)ctx)->esr; | |||||
1764 | return true; | |||||
1765 | } | |||||
1766 | aux += ctx->size; | |||||
1767 | } | |||||
1768 | return false; | |||||
1769 | } | |||||
1770 | #endif | |||||
1771 | ||||||
1772 | #if SANITIZER_OPENBSD0 | |||||
1773 | using Context = sigcontext; | |||||
1774 | #else | |||||
1775 | using Context = ucontext_t; | |||||
1776 | #endif | |||||
1777 | ||||||
1778 | SignalContext::WriteFlag SignalContext::GetWriteFlag() const { | |||||
1779 | Context *ucontext = (Context *)context; | |||||
1780 | #if defined(__x86_64__1) || defined(__i386__) | |||||
1781 | static const uptr PF_WRITE = 1U << 1; | |||||
1782 | #if SANITIZER_FREEBSD0 | |||||
1783 | uptr err = ucontext->uc_mcontext.mc_err; | |||||
1784 | #elif SANITIZER_NETBSD0 | |||||
1785 | uptr err = ucontext->uc_mcontext.__gregs[_REG_ERR]; | |||||
1786 | #elif SANITIZER_OPENBSD0 | |||||
1787 | uptr err = ucontext->sc_err; | |||||
1788 | #elif SANITIZER_SOLARIS0 && defined(__i386__) | |||||
1789 | const int Err = 13; | |||||
1790 | uptr err = ucontext->uc_mcontext.gregs[Err]; | |||||
1791 | #else | |||||
1792 | uptr err = ucontext->uc_mcontext.gregs[REG_ERRREG_ERR]; | |||||
1793 | #endif // SANITIZER_FREEBSD | |||||
1794 | return err & PF_WRITE ? WRITE : READ; | |||||
1795 | #elif defined(__mips__) | |||||
1796 | uint32_t *exception_source; | |||||
1797 | uint32_t faulty_instruction; | |||||
1798 | uint32_t op_code; | |||||
1799 | ||||||
1800 | exception_source = (uint32_t *)ucontext->uc_mcontext.pc; | |||||
1801 | faulty_instruction = (uint32_t)(*exception_source); | |||||
1802 | ||||||
1803 | op_code = (faulty_instruction >> 26) & 0x3f; | |||||
1804 | ||||||
1805 | // FIXME: Add support for FPU, microMIPS, DSP, MSA memory instructions. | |||||
1806 | switch (op_code) { | |||||
1807 | case 0x28: // sb | |||||
1808 | case 0x29: // sh | |||||
1809 | case 0x2b: // sw | |||||
1810 | case 0x3f: // sd | |||||
1811 | #if __mips_isa_rev < 6 | |||||
1812 | case 0x2c: // sdl | |||||
1813 | case 0x2d: // sdr | |||||
1814 | case 0x2a: // swl | |||||
1815 | case 0x2e: // swr | |||||
1816 | #endif | |||||
1817 | return SignalContext::WRITE; | |||||
1818 | ||||||
1819 | case 0x20: // lb | |||||
1820 | case 0x24: // lbu | |||||
1821 | case 0x21: // lh | |||||
1822 | case 0x25: // lhu | |||||
1823 | case 0x23: // lw | |||||
1824 | case 0x27: // lwu | |||||
1825 | case 0x37: // ld | |||||
1826 | #if __mips_isa_rev < 6 | |||||
1827 | case 0x1a: // ldl | |||||
1828 | case 0x1b: // ldr | |||||
1829 | case 0x22: // lwl | |||||
1830 | case 0x26: // lwr | |||||
1831 | #endif | |||||
1832 | return SignalContext::READ; | |||||
1833 | #if __mips_isa_rev == 6 | |||||
1834 | case 0x3b: // pcrel | |||||
1835 | op_code = (faulty_instruction >> 19) & 0x3; | |||||
1836 | switch (op_code) { | |||||
1837 | case 0x1: // lwpc | |||||
1838 | case 0x2: // lwupc | |||||
1839 | return SignalContext::READ; | |||||
1840 | } | |||||
1841 | #endif | |||||
1842 | } | |||||
1843 | return SignalContext::UNKNOWN; | |||||
1844 | #elif defined(__arm__) | |||||
1845 | static const uptr FSR_WRITE = 1U << 11; | |||||
1846 | uptr fsr = ucontext->uc_mcontext.error_code; | |||||
1847 | return fsr & FSR_WRITE ? WRITE : READ; | |||||
1848 | #elif defined(__aarch64__) | |||||
1849 | static const u64 ESR_ELx_WNR = 1U << 6; | |||||
1850 | u64 esr; | |||||
1851 | if (!Aarch64GetESR(ucontext, &esr)) return UNKNOWN; | |||||
1852 | return esr & ESR_ELx_WNR ? WRITE : READ; | |||||
1853 | #elif SANITIZER_SOLARIS0 && defined(__sparc__) | |||||
1854 | // Decode the instruction to determine the access type. | |||||
1855 | // From OpenSolaris $SRC/uts/sun4/os/trap.c (get_accesstype). | |||||
1856 | uptr pc = ucontext->uc_mcontext.gregs[REG_PC]; | |||||
1857 | u32 instr = *(u32 *)pc; | |||||
1858 | return (instr >> 21) & 1 ? WRITE: READ; | |||||
1859 | #else | |||||
1860 | (void)ucontext; | |||||
1861 | return UNKNOWN; // FIXME: Implement. | |||||
1862 | #endif | |||||
1863 | } | |||||
1864 | ||||||
1865 | void SignalContext::DumpAllRegisters(void *context) { | |||||
1866 | // FIXME: Implement this. | |||||
1867 | } | |||||
1868 | ||||||
1869 | static void GetPcSpBp(void *context, uptr *pc, uptr *sp, uptr *bp) { | |||||
1870 | #if SANITIZER_NETBSD0 | |||||
1871 | // This covers all NetBSD architectures | |||||
1872 | ucontext_t *ucontext = (ucontext_t *)context; | |||||
1873 | *pc = _UC_MACHINE_PC(ucontext); | |||||
1874 | *bp = _UC_MACHINE_FP(ucontext); | |||||
1875 | *sp = _UC_MACHINE_SP(ucontext); | |||||
1876 | #elif defined(__arm__) | |||||
1877 | ucontext_t *ucontext = (ucontext_t*)context; | |||||
1878 | *pc = ucontext->uc_mcontext.arm_pc; | |||||
1879 | *bp = ucontext->uc_mcontext.arm_fp; | |||||
1880 | *sp = ucontext->uc_mcontext.arm_sp; | |||||
1881 | #elif defined(__aarch64__) | |||||
1882 | ucontext_t *ucontext = (ucontext_t*)context; | |||||
1883 | *pc = ucontext->uc_mcontext.pc; | |||||
1884 | *bp = ucontext->uc_mcontext.regs[29]; | |||||
1885 | *sp = ucontext->uc_mcontext.sp; | |||||
1886 | #elif defined(__hppa__) | |||||
1887 | ucontext_t *ucontext = (ucontext_t*)context; | |||||
1888 | *pc = ucontext->uc_mcontext.sc_iaoq[0]; | |||||
1889 | /* GCC uses %r3 whenever a frame pointer is needed. */ | |||||
1890 | *bp = ucontext->uc_mcontext.sc_gr[3]; | |||||
1891 | *sp = ucontext->uc_mcontext.sc_gr[30]; | |||||
1892 | #elif defined(__x86_64__1) | |||||
1893 | # if SANITIZER_FREEBSD0 | |||||
1894 | ucontext_t *ucontext = (ucontext_t*)context; | |||||
1895 | *pc = ucontext->uc_mcontext.mc_rip; | |||||
1896 | *bp = ucontext->uc_mcontext.mc_rbp; | |||||
1897 | *sp = ucontext->uc_mcontext.mc_rsp; | |||||
1898 | #elif SANITIZER_OPENBSD0 | |||||
1899 | sigcontext *ucontext = (sigcontext *)context; | |||||
1900 | *pc = ucontext->sc_rip; | |||||
1901 | *bp = ucontext->sc_rbp; | |||||
1902 | *sp = ucontext->sc_rsp; | |||||
1903 | # else | |||||
1904 | ucontext_t *ucontext = (ucontext_t*)context; | |||||
1905 | *pc = ucontext->uc_mcontext.gregs[REG_RIPREG_RIP]; | |||||
1906 | *bp = ucontext->uc_mcontext.gregs[REG_RBPREG_RBP]; | |||||
1907 | *sp = ucontext->uc_mcontext.gregs[REG_RSPREG_RSP]; | |||||
1908 | # endif | |||||
1909 | #elif defined(__i386__) | |||||
1910 | # if SANITIZER_FREEBSD0 | |||||
1911 | ucontext_t *ucontext = (ucontext_t*)context; | |||||
1912 | *pc = ucontext->uc_mcontext.mc_eip; | |||||
1913 | *bp = ucontext->uc_mcontext.mc_ebp; | |||||
1914 | *sp = ucontext->uc_mcontext.mc_esp; | |||||
1915 | #elif SANITIZER_OPENBSD0 | |||||
1916 | sigcontext *ucontext = (sigcontext *)context; | |||||
1917 | *pc = ucontext->sc_eip; | |||||
1918 | *bp = ucontext->sc_ebp; | |||||
1919 | *sp = ucontext->sc_esp; | |||||
1920 | # else | |||||
1921 | ucontext_t *ucontext = (ucontext_t*)context; | |||||
1922 | # if SANITIZER_SOLARIS0 | |||||
1923 | /* Use the numeric values: the symbolic ones are undefined by llvm | |||||
1924 | include/llvm/Support/Solaris.h. */ | |||||
1925 | # ifndef REG_EIP | |||||
1926 | # define REG_EIP 14 // REG_PC | |||||
1927 | # endif | |||||
1928 | # ifndef REG_EBP | |||||
1929 | # define REG_EBP 6 // REG_FP | |||||
1930 | # endif | |||||
1931 | # ifndef REG_ESP | |||||
1932 | # define REG_ESP 17 // REG_SP | |||||
1933 | # endif | |||||
1934 | # endif | |||||
1935 | *pc = ucontext->uc_mcontext.gregs[REG_EIP]; | |||||
1936 | *bp = ucontext->uc_mcontext.gregs[REG_EBP]; | |||||
1937 | *sp = ucontext->uc_mcontext.gregs[REG_ESP]; | |||||
1938 | # endif | |||||
1939 | #elif defined(__powerpc__) || defined(__powerpc64__) | |||||
1940 | ucontext_t *ucontext = (ucontext_t*)context; | |||||
1941 | *pc = ucontext->uc_mcontext.regs->nip; | |||||
1942 | *sp = ucontext->uc_mcontext.regs->gpr[PT_R1]; | |||||
1943 | // The powerpc{,64}-linux ABIs do not specify r31 as the frame | |||||
1944 | // pointer, but GCC always uses r31 when we need a frame pointer. | |||||
1945 | *bp = ucontext->uc_mcontext.regs->gpr[PT_R31]; | |||||
1946 | #elif defined(__sparc__) | |||||
1947 | ucontext_t *ucontext = (ucontext_t*)context; | |||||
1948 | uptr *stk_ptr; | |||||
1949 | # if defined (__sparcv9) | |||||
1950 | # ifndef MC_PC | |||||
1951 | # define MC_PC REG_PC | |||||
1952 | # endif | |||||
1953 | # ifndef MC_O6 | |||||
1954 | # define MC_O6 REG_O6 | |||||
1955 | # endif | |||||
1956 | # ifdef SANITIZER_SOLARIS0 | |||||
1957 | # define mc_gregs gregs | |||||
1958 | # endif | |||||
1959 | *pc = ucontext->uc_mcontext.mc_gregs[MC_PC]; | |||||
1960 | *sp = ucontext->uc_mcontext.mc_gregs[MC_O6]; | |||||
1961 | stk_ptr = (uptr *) (*sp + 2047); | |||||
1962 | *bp = stk_ptr[15]; | |||||
1963 | # else | |||||
1964 | *pc = ucontext->uc_mcontext.gregs[REG_PC]; | |||||
1965 | *sp = ucontext->uc_mcontext.gregs[REG_O6]; | |||||
1966 | stk_ptr = (uptr *) *sp; | |||||
1967 | *bp = stk_ptr[15]; | |||||
1968 | # endif | |||||
1969 | #elif defined(__mips__) | |||||
1970 | ucontext_t *ucontext = (ucontext_t*)context; | |||||
1971 | *pc = ucontext->uc_mcontext.pc; | |||||
1972 | *bp = ucontext->uc_mcontext.gregs[30]; | |||||
1973 | *sp = ucontext->uc_mcontext.gregs[29]; | |||||
1974 | #elif defined(__s390__) | |||||
1975 | ucontext_t *ucontext = (ucontext_t*)context; | |||||
1976 | # if defined(__s390x__) | |||||
1977 | *pc = ucontext->uc_mcontext.psw.addr; | |||||
1978 | # else | |||||
1979 | *pc = ucontext->uc_mcontext.psw.addr & 0x7fffffff; | |||||
1980 | # endif | |||||
1981 | *bp = ucontext->uc_mcontext.gregs[11]; | |||||
1982 | *sp = ucontext->uc_mcontext.gregs[15]; | |||||
1983 | #else | |||||
1984 | # error "Unsupported arch" | |||||
1985 | #endif | |||||
1986 | } | |||||
1987 | ||||||
1988 | void SignalContext::InitPcSpBp() { GetPcSpBp(context, &pc, &sp, &bp); } | |||||
1989 | ||||||
1990 | void MaybeReexec() { | |||||
1991 | // No need to re-exec on Linux. | |||||
1992 | } | |||||
1993 | ||||||
1994 | void CheckASLR() { | |||||
1995 | #if SANITIZER_NETBSD0 | |||||
1996 | int mib[3]; | |||||
1997 | int paxflags; | |||||
1998 | uptr len = sizeof(paxflags); | |||||
1999 | ||||||
2000 | mib[0] = CTL_PROC; | |||||
2001 | mib[1] = internal_getpid(); | |||||
2002 | mib[2] = PROC_PID_PAXFLAGS; | |||||
2003 | ||||||
2004 | if (UNLIKELY(internal_sysctl(mib, 3, &paxflags, &len, NULL, 0) == -1)__builtin_expect(!!(internal_sysctl(mib, 3, &paxflags, & len, __null, 0) == -1), 0)) { | |||||
2005 | Printf("sysctl failed\n"); | |||||
2006 | Die(); | |||||
2007 | } | |||||
2008 | ||||||
2009 | if (UNLIKELY(paxflags & CTL_PROC_PAXFLAGS_ASLR)__builtin_expect(!!(paxflags & CTL_PROC_PAXFLAGS_ASLR), 0 )) { | |||||
2010 | Printf("This sanitizer is not compatible with enabled ASLR\n"); | |||||
2011 | Die(); | |||||
2012 | } | |||||
2013 | #else | |||||
2014 | // Do nothing | |||||
2015 | #endif | |||||
2016 | } | |||||
2017 | ||||||
2018 | void PrintModuleMap() { } | |||||
2019 | ||||||
2020 | void CheckNoDeepBind(const char *filename, int flag) { | |||||
2021 | #ifdef RTLD_DEEPBIND0x00008 | |||||
2022 | if (flag & RTLD_DEEPBIND0x00008) { | |||||
2023 | Report( | |||||
2024 | "You are trying to dlopen a %s shared library with RTLD_DEEPBIND flag" | |||||
2025 | " which is incompatibe with sanitizer runtime " | |||||
2026 | "(see https://github.com/google/sanitizers/issues/611 for details" | |||||
2027 | "). If you want to run %s library under sanitizers please remove " | |||||
2028 | "RTLD_DEEPBIND from dlopen flags.\n", | |||||
2029 | filename, filename); | |||||
2030 | Die(); | |||||
2031 | } | |||||
2032 | #endif | |||||
2033 | } | |||||
2034 | ||||||
2035 | uptr FindAvailableMemoryRange(uptr size, uptr alignment, uptr left_padding, | |||||
2036 | uptr *largest_gap_found, | |||||
2037 | uptr *max_occupied_addr) { | |||||
2038 | UNREACHABLE("FindAvailableMemoryRange is not available")do { do { __sanitizer::u64 v1 = (__sanitizer::u64)((0 && "FindAvailableMemoryRange is not available")); __sanitizer:: u64 v2 = (__sanitizer::u64)(0); if (__builtin_expect(!!(!(v1 != v2)), 0)) __sanitizer::CheckFailed("/build/llvm-toolchain-snapshot-8~svn345461/projects/compiler-rt/lib/sanitizer_common/sanitizer_linux.cc" , 2038, "(" "(0 && \"FindAvailableMemoryRange is not available\")" ") " "!=" " (" "0" ")", v1, v2); } while (false); Die(); } while (0); | |||||
2039 | return 0; | |||||
2040 | } | |||||
2041 | ||||||
2042 | bool GetRandom(void *buffer, uptr length, bool blocking) { | |||||
2043 | if (!buffer || !length || length > 256) | |||||
2044 | return false; | |||||
2045 | #if SANITIZER_USE_GETENTROPY0 | |||||
2046 | uptr rnd = getentropy(buffer, length); | |||||
2047 | int rverrno = 0; | |||||
2048 | if (internal_iserror(rnd, &rverrno) && rverrno == EFAULT14) | |||||
2049 | return false; | |||||
2050 | else if (rnd == 0) | |||||
2051 | return true; | |||||
2052 | #endif // SANITIZER_USE_GETENTROPY | |||||
2053 | ||||||
2054 | #if SANITIZER_USE_GETRANDOM1 | |||||
2055 | static atomic_uint8_t skip_getrandom_syscall; | |||||
2056 | if (!atomic_load_relaxed(&skip_getrandom_syscall)) { | |||||
2057 | // Up to 256 bytes, getrandom will not be interrupted. | |||||
2058 | uptr res = internal_syscall(SYSCALL(getrandom)318, buffer, length, | |||||
2059 | blocking ? 0 : GRND_NONBLOCK1); | |||||
2060 | int rverrno = 0; | |||||
2061 | if (internal_iserror(res, &rverrno) && rverrno == ENOSYS38) | |||||
2062 | atomic_store_relaxed(&skip_getrandom_syscall, 1); | |||||
2063 | else if (res == length) | |||||
2064 | return true; | |||||
2065 | } | |||||
2066 | #endif // SANITIZER_USE_GETRANDOM | |||||
2067 | // Up to 256 bytes, a read off /dev/urandom will not be interrupted. | |||||
2068 | // blocking is moot here, O_NONBLOCK has no effect when opening /dev/urandom. | |||||
2069 | uptr fd = internal_open("/dev/urandom", O_RDONLY00); | |||||
2070 | if (internal_iserror(fd)) | |||||
2071 | return false; | |||||
2072 | uptr res = internal_read(fd, buffer, length); | |||||
2073 | if (internal_iserror(res)) | |||||
2074 | return false; | |||||
2075 | internal_close(fd); | |||||
2076 | return true; | |||||
2077 | } | |||||
2078 | ||||||
2079 | } // namespace __sanitizer | |||||
2080 | ||||||
2081 | #endif |
1 | //===-- sanitizer_syscall_linux_x86_64.inc ----------------------*- C++ -*-===// |
2 | // |
3 | // The LLVM Compiler Infrastructure |
4 | // |
5 | // This file is distributed under the University of Illinois Open Source |
6 | // License. See LICENSE.TXT for details. |
7 | // |
8 | //===----------------------------------------------------------------------===// |
9 | // |
10 | // Implementations of internal_syscall and internal_iserror for Linux/x86_64. |
11 | // |
12 | //===----------------------------------------------------------------------===// |
13 | |
14 | #define SYSCALL(name)__NR_name __NR_ ## name |
15 | |
16 | static uptr internal_syscall(u64 nr) { |
17 | u64 retval; |
18 | asm volatile("syscall" : "=a"(retval) : "a"(nr) : "rcx", "r11", |
19 | "memory", "cc"); |
20 | return retval; |
21 | } |
22 | |
23 | template <typename T1> |
24 | static uptr internal_syscall(u64 nr, T1 arg1) { |
25 | u64 retval; |
26 | asm volatile("syscall" : "=a"(retval) : "a"(nr), "D"((u64)arg1) : |
27 | "rcx", "r11", "memory", "cc"); |
28 | return retval; |
29 | } |
30 | |
31 | template <typename T1, typename T2> |
32 | static uptr internal_syscall(u64 nr, T1 arg1, T2 arg2) { |
33 | u64 retval; |
34 | asm volatile("syscall" : "=a"(retval) : "a"(nr), "D"((u64)arg1), |
35 | "S"((u64)arg2) : "rcx", "r11", "memory", "cc"); |
36 | return retval; |
37 | } |
38 | |
39 | template <typename T1, typename T2, typename T3> |
40 | static uptr internal_syscall(u64 nr, T1 arg1, T2 arg2, T3 arg3) { |
41 | u64 retval; |
42 | asm volatile("syscall" : "=a"(retval) : "a"(nr), "D"((u64)arg1), |
43 | "S"((u64)arg2), "d"((u64)arg3) : "rcx", "r11", "memory", "cc"); |
44 | return retval; |
45 | } |
46 | |
47 | template <typename T1, typename T2, typename T3, typename T4> |
48 | static uptr internal_syscall(u64 nr, T1 arg1, T2 arg2, T3 arg3, T4 arg4) { |
49 | u64 retval; |
50 | asm volatile("mov %5, %%r10;" |
51 | "syscall" : "=a"(retval) : "a"(nr), "D"((u64)arg1), |
52 | "S"((u64)arg2), "d"((u64)arg3), "r"((u64)arg4) : |
53 | "rcx", "r11", "r10", "memory", "cc"); |
54 | return retval; |
55 | } |
56 | |
57 | template <typename T1, typename T2, typename T3, typename T4, typename T5> |
58 | static uptr internal_syscall(u64 nr, T1 arg1, T2 arg2, T3 arg3, T4 arg4, |
59 | T5 arg5) { |
60 | u64 retval; |
61 | asm volatile("mov %5, %%r10;" |
62 | "mov %6, %%r8;" |
63 | "syscall" : "=a"(retval) : "a"(nr), "D"((u64)arg1), |
64 | "S"((u64)arg2), "d"((u64)arg3), "r"((u64)arg4), "r"((u64)arg5) : |
65 | "rcx", "r11", "r10", "r8", "memory", "cc"); |
66 | return retval; |
67 | } |
68 | |
69 | template <typename T1, typename T2, typename T3, typename T4, typename T5, |
70 | typename T6> |
71 | static uptr internal_syscall(u64 nr, T1 arg1, T2 arg2, T3 arg3, T4 arg4, |
72 | T5 arg5, T6 arg6) { |
73 | u64 retval; |
74 | asm volatile("mov %5, %%r10;" |
75 | "mov %6, %%r8;" |
76 | "mov %7, %%r9;" |
77 | "syscall" : "=a"(retval) : "a"(nr), "D"((u64)arg1), |
78 | "S"((u64)arg2), "d"((u64)arg3), "r"((u64)arg4), "r"((u64)arg5), |
79 | "r"((u64)arg6) : "rcx", "r11", "r10", "r8", "r9", |
80 | "memory", "cc"); |
81 | return retval; |
82 | } |
83 | |
84 | bool internal_iserror(uptr retval, int *rverrno) { |
85 | if (retval >= (uptr)-4095) { |
86 | if (rverrno) |
87 | *rverrno = -retval; |
88 | return true; |
89 | } |
90 | return false; |
91 | } |