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