145
|
1 //===-- sanitizer_rtems.cpp -----------------------------------------------===//
|
|
2 //
|
|
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
4 // See https://llvm.org/LICENSE.txt for license information.
|
|
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
6 //
|
|
7 //===----------------------------------------------------------------------===//
|
|
8 //
|
|
9 // This file is shared between various sanitizers' runtime libraries and
|
|
10 // implements RTEMS-specific functions.
|
|
11 //===----------------------------------------------------------------------===//
|
|
12
|
|
13 #include "sanitizer_rtems.h"
|
|
14 #if SANITIZER_RTEMS
|
|
15
|
|
16 #define posix_memalign __real_posix_memalign
|
|
17 #define free __real_free
|
|
18 #define memset __real_memset
|
|
19
|
|
20 #include "sanitizer_file.h"
|
|
21 #include "sanitizer_symbolizer.h"
|
|
22 #include <errno.h>
|
|
23 #include <fcntl.h>
|
|
24 #include <pthread.h>
|
|
25 #include <sched.h>
|
|
26 #include <stdio.h>
|
|
27 #include <stdlib.h>
|
|
28 #include <string.h>
|
|
29 #include <unistd.h>
|
|
30
|
|
31 // There is no mmap on RTEMS. Use memalign, etc.
|
|
32 #define __mmap_alloc_aligned posix_memalign
|
|
33 #define __mmap_free free
|
|
34 #define __mmap_memset memset
|
|
35
|
|
36 namespace __sanitizer {
|
|
37
|
|
38 #include "sanitizer_syscall_generic.inc"
|
|
39
|
|
40 void NORETURN internal__exit(int exitcode) {
|
|
41 _exit(exitcode);
|
|
42 }
|
|
43
|
|
44 uptr internal_sched_yield() {
|
|
45 return sched_yield();
|
|
46 }
|
|
47
|
|
48 uptr internal_getpid() {
|
|
49 return getpid();
|
|
50 }
|
|
51
|
|
52 bool FileExists(const char *filename) {
|
|
53 struct stat st;
|
|
54 if (stat(filename, &st))
|
|
55 return false;
|
|
56 // Sanity check: filename is a regular file.
|
|
57 return S_ISREG(st.st_mode);
|
|
58 }
|
|
59
|
|
60 uptr GetThreadSelf() { return static_cast<uptr>(pthread_self()); }
|
|
61
|
|
62 tid_t GetTid() { return GetThreadSelf(); }
|
|
63
|
|
64 void Abort() { abort(); }
|
|
65
|
|
66 int Atexit(void (*function)(void)) { return atexit(function); }
|
|
67
|
|
68 void SleepForSeconds(int seconds) { sleep(seconds); }
|
|
69
|
|
70 void SleepForMillis(int millis) { usleep(millis * 1000); }
|
|
71
|
|
72 bool SupportsColoredOutput(fd_t fd) { return false; }
|
|
73
|
|
74 void GetThreadStackTopAndBottom(bool at_initialization,
|
|
75 uptr *stack_top, uptr *stack_bottom) {
|
|
76 pthread_attr_t attr;
|
|
77 pthread_attr_init(&attr);
|
|
78 CHECK_EQ(pthread_getattr_np(pthread_self(), &attr), 0);
|
|
79 void *base = nullptr;
|
|
80 size_t size = 0;
|
|
81 CHECK_EQ(pthread_attr_getstack(&attr, &base, &size), 0);
|
|
82 CHECK_EQ(pthread_attr_destroy(&attr), 0);
|
|
83
|
|
84 *stack_bottom = reinterpret_cast<uptr>(base);
|
|
85 *stack_top = *stack_bottom + size;
|
|
86 }
|
|
87
|
|
88 void GetThreadStackAndTls(bool main, uptr *stk_addr, uptr *stk_size,
|
|
89 uptr *tls_addr, uptr *tls_size) {
|
|
90 uptr stack_top, stack_bottom;
|
|
91 GetThreadStackTopAndBottom(main, &stack_top, &stack_bottom);
|
|
92 *stk_addr = stack_bottom;
|
|
93 *stk_size = stack_top - stack_bottom;
|
|
94 *tls_addr = *tls_size = 0;
|
|
95 }
|
|
96
|
|
97 void InitializePlatformEarly() {}
|
|
98 void MaybeReexec() {}
|
|
99 void CheckASLR() {}
|
|
100 void CheckMPROTECT() {}
|
|
101 void DisableCoreDumperIfNecessary() {}
|
|
102 void InstallDeadlySignalHandlers(SignalHandlerType handler) {}
|
|
103 void SetAlternateSignalStack() {}
|
|
104 void UnsetAlternateSignalStack() {}
|
|
105 void InitTlsSize() {}
|
|
106
|
|
107 void PrintModuleMap() {}
|
|
108
|
|
109 void SignalContext::DumpAllRegisters(void *context) {}
|
|
110 const char *DescribeSignalOrException(int signo) { UNIMPLEMENTED(); }
|
|
111
|
|
112 enum MutexState { MtxUnlocked = 0, MtxLocked = 1, MtxSleeping = 2 };
|
|
113
|
|
114 BlockingMutex::BlockingMutex() {
|
|
115 internal_memset(this, 0, sizeof(*this));
|
|
116 }
|
|
117
|
|
118 void BlockingMutex::Lock() {
|
|
119 CHECK_EQ(owner_, 0);
|
|
120 atomic_uint32_t *m = reinterpret_cast<atomic_uint32_t *>(&opaque_storage_);
|
|
121 if (atomic_exchange(m, MtxLocked, memory_order_acquire) == MtxUnlocked)
|
|
122 return;
|
|
123 while (atomic_exchange(m, MtxSleeping, memory_order_acquire) != MtxUnlocked) {
|
|
124 internal_sched_yield();
|
|
125 }
|
|
126 }
|
|
127
|
|
128 void BlockingMutex::Unlock() {
|
|
129 atomic_uint32_t *m = reinterpret_cast<atomic_uint32_t *>(&opaque_storage_);
|
|
130 u32 v = atomic_exchange(m, MtxUnlocked, memory_order_release);
|
|
131 CHECK_NE(v, MtxUnlocked);
|
|
132 }
|
|
133
|
|
134 void BlockingMutex::CheckLocked() {
|
|
135 atomic_uint32_t *m = reinterpret_cast<atomic_uint32_t *>(&opaque_storage_);
|
|
136 CHECK_NE(MtxUnlocked, atomic_load(m, memory_order_relaxed));
|
|
137 }
|
|
138
|
|
139 uptr GetPageSize() { return getpagesize(); }
|
|
140
|
|
141 uptr GetMmapGranularity() { return GetPageSize(); }
|
|
142
|
|
143 uptr GetMaxVirtualAddress() {
|
|
144 return (1ULL << 32) - 1; // 0xffffffff
|
|
145 }
|
|
146
|
|
147 void *MmapOrDie(uptr size, const char *mem_type, bool raw_report) {
|
|
148 void* ptr = 0;
|
|
149 int res = __mmap_alloc_aligned(&ptr, GetPageSize(), size);
|
|
150 if (UNLIKELY(res))
|
|
151 ReportMmapFailureAndDie(size, mem_type, "allocate", res, raw_report);
|
|
152 __mmap_memset(ptr, 0, size);
|
|
153 IncreaseTotalMmap(size);
|
|
154 return ptr;
|
|
155 }
|
|
156
|
|
157 void *MmapOrDieOnFatalError(uptr size, const char *mem_type) {
|
|
158 void* ptr = 0;
|
|
159 int res = __mmap_alloc_aligned(&ptr, GetPageSize(), size);
|
|
160 if (UNLIKELY(res)) {
|
|
161 if (res == ENOMEM)
|
|
162 return nullptr;
|
|
163 ReportMmapFailureAndDie(size, mem_type, "allocate", false);
|
|
164 }
|
|
165 __mmap_memset(ptr, 0, size);
|
|
166 IncreaseTotalMmap(size);
|
|
167 return ptr;
|
|
168 }
|
|
169
|
|
170 void *MmapAlignedOrDieOnFatalError(uptr size, uptr alignment,
|
|
171 const char *mem_type) {
|
|
172 CHECK(IsPowerOfTwo(size));
|
|
173 CHECK(IsPowerOfTwo(alignment));
|
|
174 void* ptr = 0;
|
|
175 int res = __mmap_alloc_aligned(&ptr, alignment, size);
|
|
176 if (res)
|
|
177 ReportMmapFailureAndDie(size, mem_type, "align allocate", res, false);
|
|
178 __mmap_memset(ptr, 0, size);
|
|
179 IncreaseTotalMmap(size);
|
|
180 return ptr;
|
|
181 }
|
|
182
|
|
183 void *MmapNoReserveOrDie(uptr size, const char *mem_type) {
|
|
184 return MmapOrDie(size, mem_type, false);
|
|
185 }
|
|
186
|
|
187 void UnmapOrDie(void *addr, uptr size) {
|
|
188 if (!addr || !size) return;
|
|
189 __mmap_free(addr);
|
|
190 DecreaseTotalMmap(size);
|
|
191 }
|
|
192
|
|
193 fd_t OpenFile(const char *filename, FileAccessMode mode, error_t *errno_p) {
|
|
194 int flags;
|
|
195 switch (mode) {
|
|
196 case RdOnly: flags = O_RDONLY; break;
|
|
197 case WrOnly: flags = O_WRONLY | O_CREAT | O_TRUNC; break;
|
|
198 case RdWr: flags = O_RDWR | O_CREAT; break;
|
|
199 }
|
|
200 fd_t res = open(filename, flags, 0660);
|
|
201 if (internal_iserror(res, errno_p))
|
|
202 return kInvalidFd;
|
|
203 return res;
|
|
204 }
|
|
205
|
|
206 void CloseFile(fd_t fd) {
|
|
207 close(fd);
|
|
208 }
|
|
209
|
|
210 bool ReadFromFile(fd_t fd, void *buff, uptr buff_size, uptr *bytes_read,
|
|
211 error_t *error_p) {
|
|
212 uptr res = read(fd, buff, buff_size);
|
|
213 if (internal_iserror(res, error_p))
|
|
214 return false;
|
|
215 if (bytes_read)
|
|
216 *bytes_read = res;
|
|
217 return true;
|
|
218 }
|
|
219
|
|
220 bool WriteToFile(fd_t fd, const void *buff, uptr buff_size, uptr *bytes_written,
|
|
221 error_t *error_p) {
|
|
222 uptr res = write(fd, buff, buff_size);
|
|
223 if (internal_iserror(res, error_p))
|
|
224 return false;
|
|
225 if (bytes_written)
|
|
226 *bytes_written = res;
|
|
227 return true;
|
|
228 }
|
|
229
|
|
230 void ReleaseMemoryPagesToOS(uptr beg, uptr end) {}
|
|
231 void DumpProcessMap() {}
|
|
232
|
|
233 // There is no page protection so everything is "accessible."
|
|
234 bool IsAccessibleMemoryRange(uptr beg, uptr size) {
|
|
235 return true;
|
|
236 }
|
|
237
|
|
238 char **GetArgv() { return nullptr; }
|
|
239 char **GetEnviron() { return nullptr; }
|
|
240
|
|
241 const char *GetEnv(const char *name) {
|
|
242 return getenv(name);
|
|
243 }
|
|
244
|
|
245 uptr ReadBinaryName(/*out*/char *buf, uptr buf_len) {
|
|
246 internal_strncpy(buf, "StubBinaryName", buf_len);
|
|
247 return internal_strlen(buf);
|
|
248 }
|
|
249
|
|
250 uptr ReadLongProcessName(/*out*/ char *buf, uptr buf_len) {
|
|
251 internal_strncpy(buf, "StubProcessName", buf_len);
|
|
252 return internal_strlen(buf);
|
|
253 }
|
|
254
|
|
255 bool IsPathSeparator(const char c) {
|
|
256 return c == '/';
|
|
257 }
|
|
258
|
|
259 bool IsAbsolutePath(const char *path) {
|
|
260 return path != nullptr && IsPathSeparator(path[0]);
|
|
261 }
|
|
262
|
|
263 void ReportFile::Write(const char *buffer, uptr length) {
|
|
264 SpinMutexLock l(mu);
|
|
265 static const char *kWriteError =
|
|
266 "ReportFile::Write() can't output requested buffer!\n";
|
|
267 ReopenIfNecessary();
|
|
268 if (length != write(fd, buffer, length)) {
|
|
269 write(fd, kWriteError, internal_strlen(kWriteError));
|
|
270 Die();
|
|
271 }
|
|
272 }
|
|
273
|
|
274 uptr MainThreadStackBase, MainThreadStackSize;
|
|
275 uptr MainThreadTlsBase, MainThreadTlsSize;
|
|
276
|
|
277 } // namespace __sanitizer
|
|
278
|
|
279 #endif // SANITIZER_RTEMS
|