]> git.ipfire.org Git - thirdparty/gcc.git/blob - libsanitizer/sanitizer_common/sanitizer_rtems.cpp
Libsanitizer: merge from master.
[thirdparty/gcc.git] / libsanitizer / sanitizer_common / sanitizer_rtems.cpp
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 int internal_dlinfo(void *handle, int request, void *p) {
53 UNIMPLEMENTED();
54 }
55
56 bool FileExists(const char *filename) {
57 struct stat st;
58 if (stat(filename, &st))
59 return false;
60 // Sanity check: filename is a regular file.
61 return S_ISREG(st.st_mode);
62 }
63
64 uptr GetThreadSelf() { return static_cast<uptr>(pthread_self()); }
65
66 tid_t GetTid() { return GetThreadSelf(); }
67
68 void Abort() { abort(); }
69
70 int Atexit(void (*function)(void)) { return atexit(function); }
71
72 void SleepForSeconds(int seconds) { sleep(seconds); }
73
74 void SleepForMillis(int millis) { usleep(millis * 1000); }
75
76 bool SupportsColoredOutput(fd_t fd) { return false; }
77
78 void GetThreadStackTopAndBottom(bool at_initialization,
79 uptr *stack_top, uptr *stack_bottom) {
80 pthread_attr_t attr;
81 pthread_attr_init(&attr);
82 CHECK_EQ(pthread_getattr_np(pthread_self(), &attr), 0);
83 void *base = nullptr;
84 size_t size = 0;
85 CHECK_EQ(pthread_attr_getstack(&attr, &base, &size), 0);
86 CHECK_EQ(pthread_attr_destroy(&attr), 0);
87
88 *stack_bottom = reinterpret_cast<uptr>(base);
89 *stack_top = *stack_bottom + size;
90 }
91
92 void GetThreadStackAndTls(bool main, uptr *stk_addr, uptr *stk_size,
93 uptr *tls_addr, uptr *tls_size) {
94 uptr stack_top, stack_bottom;
95 GetThreadStackTopAndBottom(main, &stack_top, &stack_bottom);
96 *stk_addr = stack_bottom;
97 *stk_size = stack_top - stack_bottom;
98 *tls_addr = *tls_size = 0;
99 }
100
101 void InitializePlatformEarly() {}
102 void MaybeReexec() {}
103 void CheckASLR() {}
104 void CheckMPROTECT() {}
105 void DisableCoreDumperIfNecessary() {}
106 void InstallDeadlySignalHandlers(SignalHandlerType handler) {}
107 void SetAlternateSignalStack() {}
108 void UnsetAlternateSignalStack() {}
109 void InitTlsSize() {}
110
111 void PrintModuleMap() {}
112
113 void SignalContext::DumpAllRegisters(void *context) {}
114 const char *DescribeSignalOrException(int signo) { UNIMPLEMENTED(); }
115
116 enum MutexState { MtxUnlocked = 0, MtxLocked = 1, MtxSleeping = 2 };
117
118 BlockingMutex::BlockingMutex() {
119 internal_memset(this, 0, sizeof(*this));
120 }
121
122 void BlockingMutex::Lock() {
123 CHECK_EQ(owner_, 0);
124 atomic_uint32_t *m = reinterpret_cast<atomic_uint32_t *>(&opaque_storage_);
125 if (atomic_exchange(m, MtxLocked, memory_order_acquire) == MtxUnlocked)
126 return;
127 while (atomic_exchange(m, MtxSleeping, memory_order_acquire) != MtxUnlocked) {
128 internal_sched_yield();
129 }
130 }
131
132 void BlockingMutex::Unlock() {
133 atomic_uint32_t *m = reinterpret_cast<atomic_uint32_t *>(&opaque_storage_);
134 u32 v = atomic_exchange(m, MtxUnlocked, memory_order_release);
135 CHECK_NE(v, MtxUnlocked);
136 }
137
138 void BlockingMutex::CheckLocked() {
139 atomic_uint32_t *m = reinterpret_cast<atomic_uint32_t *>(&opaque_storage_);
140 CHECK_NE(MtxUnlocked, atomic_load(m, memory_order_relaxed));
141 }
142
143 uptr GetPageSize() { return getpagesize(); }
144
145 uptr GetMmapGranularity() { return GetPageSize(); }
146
147 uptr GetMaxVirtualAddress() {
148 return (1ULL << 32) - 1; // 0xffffffff
149 }
150
151 void *MmapOrDie(uptr size, const char *mem_type, bool raw_report) {
152 void* ptr = 0;
153 int res = __mmap_alloc_aligned(&ptr, GetPageSize(), size);
154 if (UNLIKELY(res))
155 ReportMmapFailureAndDie(size, mem_type, "allocate", res, raw_report);
156 __mmap_memset(ptr, 0, size);
157 IncreaseTotalMmap(size);
158 return ptr;
159 }
160
161 void *MmapOrDieOnFatalError(uptr size, const char *mem_type) {
162 void* ptr = 0;
163 int res = __mmap_alloc_aligned(&ptr, GetPageSize(), size);
164 if (UNLIKELY(res)) {
165 if (res == ENOMEM)
166 return nullptr;
167 ReportMmapFailureAndDie(size, mem_type, "allocate", false);
168 }
169 __mmap_memset(ptr, 0, size);
170 IncreaseTotalMmap(size);
171 return ptr;
172 }
173
174 void *MmapAlignedOrDieOnFatalError(uptr size, uptr alignment,
175 const char *mem_type) {
176 CHECK(IsPowerOfTwo(size));
177 CHECK(IsPowerOfTwo(alignment));
178 void* ptr = 0;
179 int res = __mmap_alloc_aligned(&ptr, alignment, size);
180 if (res)
181 ReportMmapFailureAndDie(size, mem_type, "align allocate", res, false);
182 __mmap_memset(ptr, 0, size);
183 IncreaseTotalMmap(size);
184 return ptr;
185 }
186
187 void *MmapNoReserveOrDie(uptr size, const char *mem_type) {
188 return MmapOrDie(size, mem_type, false);
189 }
190
191 void UnmapOrDie(void *addr, uptr size) {
192 if (!addr || !size) return;
193 __mmap_free(addr);
194 DecreaseTotalMmap(size);
195 }
196
197 fd_t OpenFile(const char *filename, FileAccessMode mode, error_t *errno_p) {
198 int flags;
199 switch (mode) {
200 case RdOnly: flags = O_RDONLY; break;
201 case WrOnly: flags = O_WRONLY | O_CREAT | O_TRUNC; break;
202 case RdWr: flags = O_RDWR | O_CREAT; break;
203 }
204 fd_t res = open(filename, flags, 0660);
205 if (internal_iserror(res, errno_p))
206 return kInvalidFd;
207 return res;
208 }
209
210 void CloseFile(fd_t fd) {
211 close(fd);
212 }
213
214 bool ReadFromFile(fd_t fd, void *buff, uptr buff_size, uptr *bytes_read,
215 error_t *error_p) {
216 uptr res = read(fd, buff, buff_size);
217 if (internal_iserror(res, error_p))
218 return false;
219 if (bytes_read)
220 *bytes_read = res;
221 return true;
222 }
223
224 bool WriteToFile(fd_t fd, const void *buff, uptr buff_size, uptr *bytes_written,
225 error_t *error_p) {
226 uptr res = write(fd, buff, buff_size);
227 if (internal_iserror(res, error_p))
228 return false;
229 if (bytes_written)
230 *bytes_written = res;
231 return true;
232 }
233
234 void ReleaseMemoryPagesToOS(uptr beg, uptr end) {}
235 void DumpProcessMap() {}
236
237 // There is no page protection so everything is "accessible."
238 bool IsAccessibleMemoryRange(uptr beg, uptr size) {
239 return true;
240 }
241
242 char **GetArgv() { return nullptr; }
243 char **GetEnviron() { return nullptr; }
244
245 const char *GetEnv(const char *name) {
246 return getenv(name);
247 }
248
249 uptr ReadBinaryName(/*out*/char *buf, uptr buf_len) {
250 internal_strncpy(buf, "StubBinaryName", buf_len);
251 return internal_strlen(buf);
252 }
253
254 uptr ReadLongProcessName(/*out*/ char *buf, uptr buf_len) {
255 internal_strncpy(buf, "StubProcessName", buf_len);
256 return internal_strlen(buf);
257 }
258
259 bool IsPathSeparator(const char c) {
260 return c == '/';
261 }
262
263 bool IsAbsolutePath(const char *path) {
264 return path != nullptr && IsPathSeparator(path[0]);
265 }
266
267 void ReportFile::Write(const char *buffer, uptr length) {
268 SpinMutexLock l(mu);
269 static const char *kWriteError =
270 "ReportFile::Write() can't output requested buffer!\n";
271 ReopenIfNecessary();
272 if (length != write(fd, buffer, length)) {
273 write(fd, kWriteError, internal_strlen(kWriteError));
274 Die();
275 }
276 }
277
278 uptr MainThreadStackBase, MainThreadStackSize;
279 uptr MainThreadTlsBase, MainThreadTlsSize;
280
281 } // namespace __sanitizer
282
283 #endif // SANITIZER_RTEMS