Home | History | Annotate | Line # | Download | only in sanitizer_common
      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 InitializePlatformEarly() {}
     99 void MaybeReexec() {}
    100 void CheckASLR() {}
    101 void CheckMPROTECT() {}
    102 void DisableCoreDumperIfNecessary() {}
    103 void InstallDeadlySignalHandlers(SignalHandlerType handler) {}
    104 void SetAlternateSignalStack() {}
    105 void UnsetAlternateSignalStack() {}
    106 void InitTlsSize() {}
    107 
    108 void PrintModuleMap() {}
    109 
    110 void SignalContext::DumpAllRegisters(void *context) {}
    111 const char *DescribeSignalOrException(int signo) { UNIMPLEMENTED(); }
    112 
    113 enum MutexState { MtxUnlocked = 0, MtxLocked = 1, MtxSleeping = 2 };
    114 
    115 BlockingMutex::BlockingMutex() {
    116   internal_memset(this, 0, sizeof(*this));
    117 }
    118 
    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 
    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 
    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 
    140 uptr GetPageSize() { return getpagesize(); }
    141 
    142 uptr GetMmapGranularity() { return GetPageSize(); }
    143 
    144 uptr GetMaxVirtualAddress() {
    145   return (1ULL << 32) - 1;  // 0xffffffff
    146 }
    147 
    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 
    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 
    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 
    184 void *MmapNoReserveOrDie(uptr size, const char *mem_type) {
    185   return MmapOrDie(size, mem_type, false);
    186 }
    187 
    188 void UnmapOrDie(void *addr, uptr size) {
    189   if (!addr || !size) return;
    190   __mmap_free(addr);
    191   DecreaseTotalMmap(size);
    192 }
    193 
    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 
    207 void CloseFile(fd_t fd) {
    208   close(fd);
    209 }
    210 
    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 
    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 
    231 void ReleaseMemoryPagesToOS(uptr beg, uptr end) {}
    232 void DumpProcessMap() {}
    233 
    234 // There is no page protection so everything is "accessible."
    235 bool IsAccessibleMemoryRange(uptr beg, uptr size) {
    236   return true;
    237 }
    238 
    239 char **GetArgv() { return nullptr; }
    240 char **GetEnviron() { return nullptr; }
    241 
    242 const char *GetEnv(const char *name) {
    243   return getenv(name);
    244 }
    245 
    246 uptr ReadBinaryName(/*out*/char *buf, uptr buf_len) {
    247   internal_strncpy(buf, "StubBinaryName", buf_len);
    248   return internal_strlen(buf);
    249 }
    250 
    251 uptr ReadLongProcessName(/*out*/ char *buf, uptr buf_len) {
    252   internal_strncpy(buf, "StubProcessName", buf_len);
    253   return internal_strlen(buf);
    254 }
    255 
    256 bool IsPathSeparator(const char c) {
    257   return c == '/';
    258 }
    259 
    260 bool IsAbsolutePath(const char *path) {
    261   return path != nullptr && IsPathSeparator(path[0]);
    262 }
    263 
    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