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