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