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