1353944Sdim//===-- sanitizer_rtems.cpp -----------------------------------------------===// 2353944Sdim// 3353944Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4353944Sdim// See https://llvm.org/LICENSE.txt for license information. 5353944Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6353944Sdim// 7353944Sdim//===----------------------------------------------------------------------===// 8353944Sdim// 9353944Sdim// This file is shared between various sanitizers' runtime libraries and 10353944Sdim// implements RTEMS-specific functions. 11353944Sdim//===----------------------------------------------------------------------===// 12353944Sdim 13353944Sdim#include "sanitizer_rtems.h" 14353944Sdim#if SANITIZER_RTEMS 15353944Sdim 16353944Sdim#define posix_memalign __real_posix_memalign 17353944Sdim#define free __real_free 18353944Sdim#define memset __real_memset 19353944Sdim 20353944Sdim#include "sanitizer_file.h" 21353944Sdim#include "sanitizer_symbolizer.h" 22353944Sdim#include <errno.h> 23353944Sdim#include <fcntl.h> 24353944Sdim#include <pthread.h> 25353944Sdim#include <sched.h> 26353944Sdim#include <stdio.h> 27353944Sdim#include <stdlib.h> 28353944Sdim#include <string.h> 29353944Sdim#include <unistd.h> 30353944Sdim 31353944Sdim// There is no mmap on RTEMS. Use memalign, etc. 32353944Sdim#define __mmap_alloc_aligned posix_memalign 33353944Sdim#define __mmap_free free 34353944Sdim#define __mmap_memset memset 35353944Sdim 36353944Sdimnamespace __sanitizer { 37353944Sdim 38353944Sdim#include "sanitizer_syscall_generic.inc" 39353944Sdim 40353944Sdimvoid NORETURN internal__exit(int exitcode) { 41353944Sdim _exit(exitcode); 42353944Sdim} 43353944Sdim 44353944Sdimuptr internal_sched_yield() { 45353944Sdim return sched_yield(); 46353944Sdim} 47353944Sdim 48353944Sdimuptr internal_getpid() { 49353944Sdim return getpid(); 50353944Sdim} 51353944Sdim 52353944Sdimbool FileExists(const char *filename) { 53353944Sdim struct stat st; 54353944Sdim if (stat(filename, &st)) 55353944Sdim return false; 56353944Sdim // Sanity check: filename is a regular file. 57353944Sdim return S_ISREG(st.st_mode); 58353944Sdim} 59353944Sdim 60353944Sdimuptr GetThreadSelf() { return static_cast<uptr>(pthread_self()); } 61353944Sdim 62353944Sdimtid_t GetTid() { return GetThreadSelf(); } 63353944Sdim 64353944Sdimvoid Abort() { abort(); } 65353944Sdim 66353944Sdimint Atexit(void (*function)(void)) { return atexit(function); } 67353944Sdim 68353944Sdimvoid SleepForSeconds(int seconds) { sleep(seconds); } 69353944Sdim 70353944Sdimvoid SleepForMillis(int millis) { usleep(millis * 1000); } 71353944Sdim 72353944Sdimbool SupportsColoredOutput(fd_t fd) { return false; } 73353944Sdim 74353944Sdimvoid GetThreadStackTopAndBottom(bool at_initialization, 75353944Sdim uptr *stack_top, uptr *stack_bottom) { 76353944Sdim pthread_attr_t attr; 77353944Sdim pthread_attr_init(&attr); 78353944Sdim CHECK_EQ(pthread_getattr_np(pthread_self(), &attr), 0); 79353944Sdim void *base = nullptr; 80353944Sdim size_t size = 0; 81353944Sdim CHECK_EQ(pthread_attr_getstack(&attr, &base, &size), 0); 82353944Sdim CHECK_EQ(pthread_attr_destroy(&attr), 0); 83353944Sdim 84353944Sdim *stack_bottom = reinterpret_cast<uptr>(base); 85353944Sdim *stack_top = *stack_bottom + size; 86353944Sdim} 87353944Sdim 88353944Sdimvoid GetThreadStackAndTls(bool main, uptr *stk_addr, uptr *stk_size, 89353944Sdim uptr *tls_addr, uptr *tls_size) { 90353944Sdim uptr stack_top, stack_bottom; 91353944Sdim GetThreadStackTopAndBottom(main, &stack_top, &stack_bottom); 92353944Sdim *stk_addr = stack_bottom; 93353944Sdim *stk_size = stack_top - stack_bottom; 94353944Sdim *tls_addr = *tls_size = 0; 95353944Sdim} 96353944Sdim 97353944Sdimvoid InitializePlatformEarly() {} 98353944Sdimvoid MaybeReexec() {} 99353944Sdimvoid CheckASLR() {} 100353944Sdimvoid CheckMPROTECT() {} 101353944Sdimvoid DisableCoreDumperIfNecessary() {} 102353944Sdimvoid InstallDeadlySignalHandlers(SignalHandlerType handler) {} 103353944Sdimvoid SetAlternateSignalStack() {} 104353944Sdimvoid UnsetAlternateSignalStack() {} 105353944Sdimvoid InitTlsSize() {} 106353944Sdim 107353944Sdimvoid PrintModuleMap() {} 108353944Sdim 109353944Sdimvoid SignalContext::DumpAllRegisters(void *context) {} 110353944Sdimconst char *DescribeSignalOrException(int signo) { UNIMPLEMENTED(); } 111353944Sdim 112353944Sdimenum MutexState { MtxUnlocked = 0, MtxLocked = 1, MtxSleeping = 2 }; 113353944Sdim 114353944SdimBlockingMutex::BlockingMutex() { 115353944Sdim internal_memset(this, 0, sizeof(*this)); 116353944Sdim} 117353944Sdim 118353944Sdimvoid BlockingMutex::Lock() { 119353944Sdim CHECK_EQ(owner_, 0); 120353944Sdim atomic_uint32_t *m = reinterpret_cast<atomic_uint32_t *>(&opaque_storage_); 121353944Sdim if (atomic_exchange(m, MtxLocked, memory_order_acquire) == MtxUnlocked) 122353944Sdim return; 123353944Sdim while (atomic_exchange(m, MtxSleeping, memory_order_acquire) != MtxUnlocked) { 124353944Sdim internal_sched_yield(); 125353944Sdim } 126353944Sdim} 127353944Sdim 128353944Sdimvoid BlockingMutex::Unlock() { 129353944Sdim atomic_uint32_t *m = reinterpret_cast<atomic_uint32_t *>(&opaque_storage_); 130353944Sdim u32 v = atomic_exchange(m, MtxUnlocked, memory_order_release); 131353944Sdim CHECK_NE(v, MtxUnlocked); 132353944Sdim} 133353944Sdim 134353944Sdimvoid BlockingMutex::CheckLocked() { 135353944Sdim atomic_uint32_t *m = reinterpret_cast<atomic_uint32_t *>(&opaque_storage_); 136353944Sdim CHECK_NE(MtxUnlocked, atomic_load(m, memory_order_relaxed)); 137353944Sdim} 138353944Sdim 139353944Sdimuptr GetPageSize() { return getpagesize(); } 140353944Sdim 141353944Sdimuptr GetMmapGranularity() { return GetPageSize(); } 142353944Sdim 143353944Sdimuptr GetMaxVirtualAddress() { 144353944Sdim return (1ULL << 32) - 1; // 0xffffffff 145353944Sdim} 146353944Sdim 147353944Sdimvoid *MmapOrDie(uptr size, const char *mem_type, bool raw_report) { 148353944Sdim void* ptr = 0; 149353944Sdim int res = __mmap_alloc_aligned(&ptr, GetPageSize(), size); 150353944Sdim if (UNLIKELY(res)) 151353944Sdim ReportMmapFailureAndDie(size, mem_type, "allocate", res, raw_report); 152353944Sdim __mmap_memset(ptr, 0, size); 153353944Sdim IncreaseTotalMmap(size); 154353944Sdim return ptr; 155353944Sdim} 156353944Sdim 157353944Sdimvoid *MmapOrDieOnFatalError(uptr size, const char *mem_type) { 158353944Sdim void* ptr = 0; 159353944Sdim int res = __mmap_alloc_aligned(&ptr, GetPageSize(), size); 160353944Sdim if (UNLIKELY(res)) { 161353944Sdim if (res == ENOMEM) 162353944Sdim return nullptr; 163353944Sdim ReportMmapFailureAndDie(size, mem_type, "allocate", false); 164353944Sdim } 165353944Sdim __mmap_memset(ptr, 0, size); 166353944Sdim IncreaseTotalMmap(size); 167353944Sdim return ptr; 168353944Sdim} 169353944Sdim 170353944Sdimvoid *MmapAlignedOrDieOnFatalError(uptr size, uptr alignment, 171353944Sdim const char *mem_type) { 172353944Sdim CHECK(IsPowerOfTwo(size)); 173353944Sdim CHECK(IsPowerOfTwo(alignment)); 174353944Sdim void* ptr = 0; 175353944Sdim int res = __mmap_alloc_aligned(&ptr, alignment, size); 176353944Sdim if (res) 177353944Sdim ReportMmapFailureAndDie(size, mem_type, "align allocate", res, false); 178353944Sdim __mmap_memset(ptr, 0, size); 179353944Sdim IncreaseTotalMmap(size); 180353944Sdim return ptr; 181353944Sdim} 182353944Sdim 183353944Sdimvoid *MmapNoReserveOrDie(uptr size, const char *mem_type) { 184353944Sdim return MmapOrDie(size, mem_type, false); 185353944Sdim} 186353944Sdim 187353944Sdimvoid UnmapOrDie(void *addr, uptr size) { 188353944Sdim if (!addr || !size) return; 189353944Sdim __mmap_free(addr); 190353944Sdim DecreaseTotalMmap(size); 191353944Sdim} 192353944Sdim 193353944Sdimfd_t OpenFile(const char *filename, FileAccessMode mode, error_t *errno_p) { 194353944Sdim int flags; 195353944Sdim switch (mode) { 196353944Sdim case RdOnly: flags = O_RDONLY; break; 197353944Sdim case WrOnly: flags = O_WRONLY | O_CREAT | O_TRUNC; break; 198353944Sdim case RdWr: flags = O_RDWR | O_CREAT; break; 199353944Sdim } 200353944Sdim fd_t res = open(filename, flags, 0660); 201353944Sdim if (internal_iserror(res, errno_p)) 202353944Sdim return kInvalidFd; 203353944Sdim return res; 204353944Sdim} 205353944Sdim 206353944Sdimvoid CloseFile(fd_t fd) { 207353944Sdim close(fd); 208353944Sdim} 209353944Sdim 210353944Sdimbool ReadFromFile(fd_t fd, void *buff, uptr buff_size, uptr *bytes_read, 211353944Sdim error_t *error_p) { 212353944Sdim uptr res = read(fd, buff, buff_size); 213353944Sdim if (internal_iserror(res, error_p)) 214353944Sdim return false; 215353944Sdim if (bytes_read) 216353944Sdim *bytes_read = res; 217353944Sdim return true; 218353944Sdim} 219353944Sdim 220353944Sdimbool WriteToFile(fd_t fd, const void *buff, uptr buff_size, uptr *bytes_written, 221353944Sdim error_t *error_p) { 222353944Sdim uptr res = write(fd, buff, buff_size); 223353944Sdim if (internal_iserror(res, error_p)) 224353944Sdim return false; 225353944Sdim if (bytes_written) 226353944Sdim *bytes_written = res; 227353944Sdim return true; 228353944Sdim} 229353944Sdim 230353944Sdimvoid ReleaseMemoryPagesToOS(uptr beg, uptr end) {} 231353944Sdimvoid DumpProcessMap() {} 232353944Sdim 233353944Sdim// There is no page protection so everything is "accessible." 234353944Sdimbool IsAccessibleMemoryRange(uptr beg, uptr size) { 235353944Sdim return true; 236353944Sdim} 237353944Sdim 238353944Sdimchar **GetArgv() { return nullptr; } 239353944Sdimchar **GetEnviron() { return nullptr; } 240353944Sdim 241353944Sdimconst char *GetEnv(const char *name) { 242353944Sdim return getenv(name); 243353944Sdim} 244353944Sdim 245353944Sdimuptr ReadBinaryName(/*out*/char *buf, uptr buf_len) { 246353944Sdim internal_strncpy(buf, "StubBinaryName", buf_len); 247353944Sdim return internal_strlen(buf); 248353944Sdim} 249353944Sdim 250353944Sdimuptr ReadLongProcessName(/*out*/ char *buf, uptr buf_len) { 251353944Sdim internal_strncpy(buf, "StubProcessName", buf_len); 252353944Sdim return internal_strlen(buf); 253353944Sdim} 254353944Sdim 255353944Sdimbool IsPathSeparator(const char c) { 256353944Sdim return c == '/'; 257353944Sdim} 258353944Sdim 259353944Sdimbool IsAbsolutePath(const char *path) { 260353944Sdim return path != nullptr && IsPathSeparator(path[0]); 261353944Sdim} 262353944Sdim 263353944Sdimvoid ReportFile::Write(const char *buffer, uptr length) { 264353944Sdim SpinMutexLock l(mu); 265353944Sdim static const char *kWriteError = 266353944Sdim "ReportFile::Write() can't output requested buffer!\n"; 267353944Sdim ReopenIfNecessary(); 268353944Sdim if (length != write(fd, buffer, length)) { 269353944Sdim write(fd, kWriteError, internal_strlen(kWriteError)); 270353944Sdim Die(); 271353944Sdim } 272353944Sdim} 273353944Sdim 274353944Sdimuptr MainThreadStackBase, MainThreadStackSize; 275353944Sdimuptr MainThreadTlsBase, MainThreadTlsSize; 276353944Sdim 277353944Sdim} // namespace __sanitizer 278353944Sdim 279353944Sdim#endif // SANITIZER_RTEMS 280