]>
Commit | Line | Data |
---|---|---|
b667dd70 | 1 | //===-- sanitizer_solaris.cpp ---------------------------------------------===// |
eac97531 | 2 | // |
b667dd70 ML |
3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
4 | // See https://llvm.org/LICENSE.txt for license information. | |
5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
eac97531 ML |
6 | // |
7 | //===----------------------------------------------------------------------===// | |
8 | // | |
9 | // This file is shared between various sanitizers' runtime libraries and | |
10 | // implements Solaris-specific functions. | |
11 | //===----------------------------------------------------------------------===// | |
12 | ||
13 | #include "sanitizer_platform.h" | |
14 | #if SANITIZER_SOLARIS | |
15 | ||
16 | #include <stdio.h> | |
17 | ||
18 | #include "sanitizer_common.h" | |
19 | #include "sanitizer_flags.h" | |
20 | #include "sanitizer_internal_defs.h" | |
21 | #include "sanitizer_libc.h" | |
22 | #include "sanitizer_placement_new.h" | |
23 | #include "sanitizer_platform_limits_posix.h" | |
24 | #include "sanitizer_procmaps.h" | |
25 | ||
26 | #include <fcntl.h> | |
27 | #include <pthread.h> | |
28 | #include <sched.h> | |
29 | #include <thread.h> | |
30 | #include <synch.h> | |
31 | #include <signal.h> | |
32 | #include <sys/mman.h> | |
33 | #include <sys/resource.h> | |
34 | #include <sys/stat.h> | |
35 | #include <sys/types.h> | |
36 | #include <dirent.h> | |
37 | #include <unistd.h> | |
38 | #include <errno.h> | |
39 | #include <stdlib.h> | |
40 | ||
41 | namespace __sanitizer { | |
42 | ||
43 | //#include "sanitizer_syscall_generic.inc" | |
44 | ||
45 | #define _REAL(func) _ ## func | |
46 | #define DECLARE__REAL(ret_type, func, ...) \ | |
47 | extern "C" ret_type _REAL(func)(__VA_ARGS__) | |
48 | #define DECLARE__REAL_AND_INTERNAL(ret_type, func, ...) \ | |
49 | DECLARE__REAL(ret_type, func, __VA_ARGS__); \ | |
50 | ret_type internal_ ## func(__VA_ARGS__) | |
51 | ||
0b5ccc80 RO |
52 | #if !defined(_LP64) && _FILE_OFFSET_BITS == 64 |
53 | #define _REAL64(func) _ ## func ## 64 | |
54 | #else | |
55 | #define _REAL64(func) _REAL(func) | |
56 | #endif | |
57 | #define DECLARE__REAL64(ret_type, func, ...) \ | |
58 | extern "C" ret_type _REAL64(func)(__VA_ARGS__) | |
59 | #define DECLARE__REAL_AND_INTERNAL64(ret_type, func, ...) \ | |
60 | DECLARE__REAL64(ret_type, func, __VA_ARGS__); \ | |
61 | ret_type internal_ ## func(__VA_ARGS__) | |
62 | ||
eac97531 | 63 | // ---------------------- sanitizer_libc.h |
0b5ccc80 RO |
64 | DECLARE__REAL_AND_INTERNAL64(uptr, mmap, void *addr, uptr /*size_t*/ length, |
65 | int prot, int flags, int fd, OFF_T offset) { | |
66 | return (uptr)_REAL64(mmap)(addr, length, prot, flags, fd, offset); | |
eac97531 ML |
67 | } |
68 | ||
69 | DECLARE__REAL_AND_INTERNAL(uptr, munmap, void *addr, uptr length) { | |
70 | return _REAL(munmap)(addr, length); | |
71 | } | |
72 | ||
73 | DECLARE__REAL_AND_INTERNAL(int, mprotect, void *addr, uptr length, int prot) { | |
74 | return _REAL(mprotect)(addr, length, prot); | |
75 | } | |
76 | ||
0b997f6e ML |
77 | // Illumos' declaration of madvise cannot be made visible if _XOPEN_SOURCE |
78 | // is defined as g++ does on Solaris. | |
79 | // | |
80 | // This declaration is consistent with Solaris 11.4. Both Illumos and Solaris | |
81 | // versions older than 11.4 declared madvise with a caddr_t as the first | |
82 | // argument, but we don't currently support Solaris versions older than 11.4, | |
83 | // and as mentioned above the declaration is not visible on Illumos so we can | |
84 | // use any declaration we like on Illumos. | |
85 | extern "C" int madvise(void *, size_t, int); | |
86 | ||
87 | int internal_madvise(uptr addr, uptr length, int advice) { | |
88 | return madvise((void *)addr, length, advice); | |
89 | } | |
90 | ||
eac97531 ML |
91 | DECLARE__REAL_AND_INTERNAL(uptr, close, fd_t fd) { |
92 | return _REAL(close)(fd); | |
93 | } | |
94 | ||
0b5ccc80 | 95 | extern "C" int _REAL64(open)(const char *, int, ...); |
eac97531 ML |
96 | |
97 | uptr internal_open(const char *filename, int flags) { | |
0b5ccc80 | 98 | return _REAL64(open)(filename, flags); |
eac97531 ML |
99 | } |
100 | ||
101 | uptr internal_open(const char *filename, int flags, u32 mode) { | |
0b5ccc80 | 102 | return _REAL64(open)(filename, flags, mode); |
eac97531 ML |
103 | } |
104 | ||
eac97531 ML |
105 | DECLARE__REAL_AND_INTERNAL(uptr, read, fd_t fd, void *buf, uptr count) { |
106 | return _REAL(read)(fd, buf, count); | |
107 | } | |
108 | ||
109 | DECLARE__REAL_AND_INTERNAL(uptr, write, fd_t fd, const void *buf, uptr count) { | |
110 | return _REAL(write)(fd, buf, count); | |
111 | } | |
112 | ||
113 | // FIXME: There's only _ftruncate64 beginning with Solaris 11. | |
114 | DECLARE__REAL_AND_INTERNAL(uptr, ftruncate, fd_t fd, uptr size) { | |
115 | return ftruncate(fd, size); | |
116 | } | |
117 | ||
0b5ccc80 RO |
118 | DECLARE__REAL_AND_INTERNAL64(uptr, stat, const char *path, void *buf) { |
119 | return _REAL64(stat)(path, (struct stat *)buf); | |
eac97531 ML |
120 | } |
121 | ||
0b5ccc80 RO |
122 | DECLARE__REAL_AND_INTERNAL64(uptr, lstat, const char *path, void *buf) { |
123 | return _REAL64(lstat)(path, (struct stat *)buf); | |
eac97531 ML |
124 | } |
125 | ||
0b5ccc80 RO |
126 | DECLARE__REAL_AND_INTERNAL64(uptr, fstat, fd_t fd, void *buf) { |
127 | return _REAL64(fstat)(fd, (struct stat *)buf); | |
eac97531 ML |
128 | } |
129 | ||
130 | uptr internal_filesize(fd_t fd) { | |
131 | struct stat st; | |
132 | if (internal_fstat(fd, &st)) | |
133 | return -1; | |
134 | return (uptr)st.st_size; | |
135 | } | |
136 | ||
b667dd70 ML |
137 | DECLARE__REAL_AND_INTERNAL(uptr, dup, int oldfd) { |
138 | return _REAL(dup)(oldfd); | |
139 | } | |
140 | ||
eac97531 ML |
141 | DECLARE__REAL_AND_INTERNAL(uptr, dup2, int oldfd, int newfd) { |
142 | return _REAL(dup2)(oldfd, newfd); | |
143 | } | |
144 | ||
145 | DECLARE__REAL_AND_INTERNAL(uptr, readlink, const char *path, char *buf, | |
146 | uptr bufsize) { | |
147 | return _REAL(readlink)(path, buf, bufsize); | |
148 | } | |
149 | ||
150 | DECLARE__REAL_AND_INTERNAL(uptr, unlink, const char *path) { | |
151 | return _REAL(unlink)(path); | |
152 | } | |
153 | ||
154 | DECLARE__REAL_AND_INTERNAL(uptr, rename, const char *oldpath, | |
155 | const char *newpath) { | |
156 | return _REAL(rename)(oldpath, newpath); | |
157 | } | |
158 | ||
159 | DECLARE__REAL_AND_INTERNAL(uptr, sched_yield, void) { | |
160 | return sched_yield(); | |
161 | } | |
162 | ||
90e46074 L |
163 | DECLARE__REAL_AND_INTERNAL(void, usleep, u64 useconds) { |
164 | struct timespec ts; | |
165 | ts.tv_sec = useconds / 1000000; | |
166 | ts.tv_nsec = (useconds % 1000000) * 1000; | |
167 | nanosleep(&ts, nullptr); | |
168 | } | |
169 | ||
eac97531 ML |
170 | DECLARE__REAL_AND_INTERNAL(uptr, execve, const char *filename, |
171 | char *const argv[], char *const envp[]) { | |
172 | return _REAL(execve)(filename, argv, envp); | |
173 | } | |
174 | ||
175 | DECLARE__REAL_AND_INTERNAL(uptr, waitpid, int pid, int *status, int options) { | |
176 | return _REAL(waitpid)(pid, status, options); | |
177 | } | |
178 | ||
179 | DECLARE__REAL_AND_INTERNAL(uptr, getpid, void) { | |
180 | return _REAL(getpid)(); | |
181 | } | |
182 | ||
183 | // FIXME: This might be wrong: _getdents doesn't take a struct linux_dirent *. | |
0b5ccc80 RO |
184 | DECLARE__REAL_AND_INTERNAL64(uptr, getdents, fd_t fd, struct linux_dirent *dirp, |
185 | unsigned int count) { | |
186 | return _REAL64(getdents)(fd, dirp, count); | |
eac97531 ML |
187 | } |
188 | ||
0b5ccc80 RO |
189 | DECLARE__REAL_AND_INTERNAL64(uptr, lseek, fd_t fd, OFF_T offset, int whence) { |
190 | return _REAL64(lseek)(fd, offset, whence); | |
eac97531 ML |
191 | } |
192 | ||
193 | // FIXME: This might be wrong: _sigfillset doesn't take a | |
194 | // __sanitizer_sigset_t *. | |
195 | DECLARE__REAL_AND_INTERNAL(void, sigfillset, __sanitizer_sigset_t *set) { | |
196 | _REAL(sigfillset)(set); | |
197 | } | |
198 | ||
199 | // FIXME: This might be wrong: _sigprocmask doesn't take __sanitizer_sigset_t *. | |
200 | DECLARE__REAL_AND_INTERNAL(uptr, sigprocmask, int how, | |
201 | __sanitizer_sigset_t *set, | |
202 | __sanitizer_sigset_t *oldset) { | |
203 | return _REAL(sigprocmask)(how, set, oldset); | |
204 | } | |
205 | ||
206 | DECLARE__REAL_AND_INTERNAL(int, fork, void) { | |
207 | // TODO(glider): this may call user's pthread_atfork() handlers which is bad. | |
208 | return _REAL(fork)(); | |
209 | } | |
210 | ||
211 | u64 NanoTime() { | |
212 | return gethrtime(); | |
213 | } | |
214 | ||
215 | uptr internal_clock_gettime(__sanitizer_clockid_t clk_id, void *tp) { | |
216 | // FIXME: No internal variant. | |
217 | return clock_gettime(clk_id, (timespec *)tp); | |
218 | } | |
219 | ||
220 | // ----------------- sanitizer_common.h | |
90e46074 L |
221 | void FutexWait(atomic_uint32_t *p, u32 cmp) { |
222 | // FIXME: implement actual blocking. | |
223 | sched_yield(); | |
224 | } | |
225 | ||
226 | void FutexWake(atomic_uint32_t *p, u32 count) {} | |
227 | ||
eac97531 ML |
228 | BlockingMutex::BlockingMutex() { |
229 | CHECK(sizeof(mutex_t) <= sizeof(opaque_storage_)); | |
230 | internal_memset(this, 0, sizeof(*this)); | |
231 | CHECK_EQ(mutex_init((mutex_t *)&opaque_storage_, USYNC_THREAD, NULL), 0); | |
232 | } | |
233 | ||
234 | void BlockingMutex::Lock() { | |
235 | CHECK(sizeof(mutex_t) <= sizeof(opaque_storage_)); | |
236 | CHECK_NE(owner_, (uptr)thr_self()); | |
237 | CHECK_EQ(mutex_lock((mutex_t *)&opaque_storage_), 0); | |
238 | CHECK(!owner_); | |
239 | owner_ = (uptr)thr_self(); | |
240 | } | |
241 | ||
242 | void BlockingMutex::Unlock() { | |
243 | CHECK(owner_ == (uptr)thr_self()); | |
244 | owner_ = 0; | |
245 | CHECK_EQ(mutex_unlock((mutex_t *)&opaque_storage_), 0); | |
246 | } | |
247 | ||
90e46074 | 248 | void BlockingMutex::CheckLocked() const { CHECK_EQ((uptr)thr_self(), owner_); } |
eac97531 ML |
249 | |
250 | } // namespace __sanitizer | |
251 | ||
252 | #endif // SANITIZER_SOLARIS |