1//===-- sanitizer_rtems.cc ------------------------------------------------===// 2// 3// This file is distributed under the University of Illinois Open Source 4// License. See LICENSE.TXT for details. 5// 6//===----------------------------------------------------------------------===// 7// 8// This file is shared between various sanitizers' runtime libraries and 9// implements RTEMS-specific functions. 10//===----------------------------------------------------------------------===// 11 12#include "sanitizer_rtems.h" 13#if SANITIZER_RTEMS 14 15#define posix_memalign __real_posix_memalign 16#define free __real_free 17#define memset __real_memset 18 19#include "sanitizer_file.h" 20#include "sanitizer_symbolizer.h" 21#include <errno.h> 22#include <fcntl.h> 23#include <pthread.h> 24#include <sched.h> 25#include <stdio.h> 26#include <stdlib.h> 27#include <string.h> 28#include <unistd.h> 29 30// There is no mmap on RTEMS. Use memalign, etc. 31#define __mmap_alloc_aligned posix_memalign 32#define __mmap_free free 33#define __mmap_memset memset 34 35namespace __sanitizer { 36 37#include "sanitizer_syscall_generic.inc" 38 39void NORETURN internal__exit(int exitcode) { 40 _exit(exitcode); 41} 42 43uptr internal_sched_yield() { 44 return sched_yield(); 45} 46 47uptr internal_getpid() { 48 return getpid(); 49} 50 51int internal_dlinfo(void *handle, int request, void *p) { 52 UNIMPLEMENTED(); 53} 54 55bool FileExists(const char *filename) { 56 struct stat st; 57 if (stat(filename, &st)) 58 return false; 59 // Sanity check: filename is a regular file. 60 return S_ISREG(st.st_mode); 61} 62 63uptr GetThreadSelf() { return static_cast<uptr>(pthread_self()); } 64 65tid_t GetTid() { return GetThreadSelf(); } 66 67void Abort() { abort(); } 68 69int Atexit(void (*function)(void)) { return atexit(function); } 70 71void SleepForSeconds(int seconds) { sleep(seconds); } 72 73void SleepForMillis(int millis) { usleep(millis * 1000); } 74 75bool SupportsColoredOutput(fd_t fd) { return false; } 76 77void GetThreadStackTopAndBottom(bool at_initialization, 78 uptr *stack_top, uptr *stack_bottom) { 79 pthread_attr_t attr; 80 pthread_attr_init(&attr); 81 CHECK_EQ(pthread_getattr_np(pthread_self(), &attr), 0); 82 void *base = nullptr; 83 size_t size = 0; 84 CHECK_EQ(pthread_attr_getstack(&attr, &base, &size), 0); 85 CHECK_EQ(pthread_attr_destroy(&attr), 0); 86 87 *stack_bottom = reinterpret_cast<uptr>(base); 88 *stack_top = *stack_bottom + size; 89} 90 91void GetThreadStackAndTls(bool main, uptr *stk_addr, uptr *stk_size, 92 uptr *tls_addr, uptr *tls_size) { 93 uptr stack_top, stack_bottom; 94 GetThreadStackTopAndBottom(main, &stack_top, &stack_bottom); 95 *stk_addr = stack_bottom; 96 *stk_size = stack_top - stack_bottom; 97 *tls_addr = *tls_size = 0; 98} 99 100void MaybeReexec() {} 101void CheckASLR() {} 102void DisableCoreDumperIfNecessary() {} 103void InstallDeadlySignalHandlers(SignalHandlerType handler) {} 104void SetAlternateSignalStack() {} 105void UnsetAlternateSignalStack() {} 106void InitTlsSize() {} 107 108void PrintModuleMap() {} 109 110void SignalContext::DumpAllRegisters(void *context) {} 111const char *DescribeSignalOrException(int signo) { UNIMPLEMENTED(); } 112 113enum MutexState { MtxUnlocked = 0, MtxLocked = 1, MtxSleeping = 2 }; 114 115BlockingMutex::BlockingMutex() { 116 internal_memset(this, 0, sizeof(*this)); 117} 118 119void 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 129void 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 135void 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 140uptr GetPageSize() { return getpagesize(); } 141 142uptr GetMmapGranularity() { return GetPageSize(); } 143 144uptr GetMaxVirtualAddress() { 145 return (1ULL << 32) - 1; // 0xffffffff 146} 147 148void *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 158void *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 171void *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 184void *MmapNoReserveOrDie(uptr size, const char *mem_type) { 185 return MmapOrDie(size, mem_type, false); 186} 187 188void UnmapOrDie(void *addr, uptr size) { 189 if (!addr || !size) return; 190 __mmap_free(addr); 191 DecreaseTotalMmap(size); 192} 193 194fd_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 207void CloseFile(fd_t fd) { 208 close(fd); 209} 210 211bool 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 221bool 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 231bool RenameFile(const char *oldpath, const char *newpath, error_t *error_p) { 232 uptr res = rename(oldpath, newpath); 233 return !internal_iserror(res, error_p); 234} 235 236void ReleaseMemoryPagesToOS(uptr beg, uptr end) {} 237void DumpProcessMap() {} 238 239// There is no page protection so everything is "accessible." 240bool IsAccessibleMemoryRange(uptr beg, uptr size) { 241 return true; 242} 243 244char **GetArgv() { return nullptr; } 245 246const char *GetEnv(const char *name) { 247 return getenv(name); 248} 249 250uptr ReadBinaryName(/*out*/char *buf, uptr buf_len) { 251 internal_strncpy(buf, "StubBinaryName", buf_len); 252 return internal_strlen(buf); 253} 254 255uptr ReadLongProcessName(/*out*/ char *buf, uptr buf_len) { 256 internal_strncpy(buf, "StubProcessName", buf_len); 257 return internal_strlen(buf); 258} 259 260bool IsPathSeparator(const char c) { 261 return c == '/'; 262} 263 264bool IsAbsolutePath(const char *path) { 265 return path != nullptr && IsPathSeparator(path[0]); 266} 267 268void ReportFile::Write(const char *buffer, uptr length) { 269 SpinMutexLock l(mu); 270 static const char *kWriteError = 271 "ReportFile::Write() can't output requested buffer!\n"; 272 ReopenIfNecessary(); 273 if (length != write(fd, buffer, length)) { 274 write(fd, kWriteError, internal_strlen(kWriteError)); 275 Die(); 276 } 277} 278 279uptr MainThreadStackBase, MainThreadStackSize; 280uptr MainThreadTlsBase, MainThreadTlsSize; 281 282} // namespace __sanitizer 283 284#endif // SANITIZER_RTEMS 285