]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/compiler-rt/lib/sanitizer_common/sanitizer_rtems.cc
Merge llvm, clang, compiler-rt, libc++, libunwind, lld, lldb and openmp
[FreeBSD/FreeBSD.git] / contrib / compiler-rt / lib / sanitizer_common / sanitizer_rtems.cc
1 //===-- sanitizer_rtems.cc ------------------------------------------------===//
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