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