diff options
Diffstat (limited to 'lib/sanitizer_common/sanitizer_rtems.cpp')
-rw-r--r-- | lib/sanitizer_common/sanitizer_rtems.cpp | 279 |
1 files changed, 279 insertions, 0 deletions
diff --git a/lib/sanitizer_common/sanitizer_rtems.cpp b/lib/sanitizer_common/sanitizer_rtems.cpp new file mode 100644 index 000000000000..0d2576c00ab3 --- /dev/null +++ b/lib/sanitizer_common/sanitizer_rtems.cpp @@ -0,0 +1,279 @@ +//===-- sanitizer_rtems.cpp -----------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file is shared between various sanitizers' runtime libraries and +// implements RTEMS-specific functions. +//===----------------------------------------------------------------------===// + +#include "sanitizer_rtems.h" +#if SANITIZER_RTEMS + +#define posix_memalign __real_posix_memalign +#define free __real_free +#define memset __real_memset + +#include "sanitizer_file.h" +#include "sanitizer_symbolizer.h" +#include <errno.h> +#include <fcntl.h> +#include <pthread.h> +#include <sched.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +// There is no mmap on RTEMS. Use memalign, etc. +#define __mmap_alloc_aligned posix_memalign +#define __mmap_free free +#define __mmap_memset memset + +namespace __sanitizer { + +#include "sanitizer_syscall_generic.inc" + +void NORETURN internal__exit(int exitcode) { + _exit(exitcode); +} + +uptr internal_sched_yield() { + return sched_yield(); +} + +uptr internal_getpid() { + return getpid(); +} + +bool FileExists(const char *filename) { + struct stat st; + if (stat(filename, &st)) + return false; + // Sanity check: filename is a regular file. + return S_ISREG(st.st_mode); +} + +uptr GetThreadSelf() { return static_cast<uptr>(pthread_self()); } + +tid_t GetTid() { return GetThreadSelf(); } + +void Abort() { abort(); } + +int Atexit(void (*function)(void)) { return atexit(function); } + +void SleepForSeconds(int seconds) { sleep(seconds); } + +void SleepForMillis(int millis) { usleep(millis * 1000); } + +bool SupportsColoredOutput(fd_t fd) { return false; } + +void GetThreadStackTopAndBottom(bool at_initialization, + uptr *stack_top, uptr *stack_bottom) { + pthread_attr_t attr; + pthread_attr_init(&attr); + CHECK_EQ(pthread_getattr_np(pthread_self(), &attr), 0); + void *base = nullptr; + size_t size = 0; + CHECK_EQ(pthread_attr_getstack(&attr, &base, &size), 0); + CHECK_EQ(pthread_attr_destroy(&attr), 0); + + *stack_bottom = reinterpret_cast<uptr>(base); + *stack_top = *stack_bottom + size; +} + +void GetThreadStackAndTls(bool main, uptr *stk_addr, uptr *stk_size, + uptr *tls_addr, uptr *tls_size) { + uptr stack_top, stack_bottom; + GetThreadStackTopAndBottom(main, &stack_top, &stack_bottom); + *stk_addr = stack_bottom; + *stk_size = stack_top - stack_bottom; + *tls_addr = *tls_size = 0; +} + +void InitializePlatformEarly() {} +void MaybeReexec() {} +void CheckASLR() {} +void CheckMPROTECT() {} +void DisableCoreDumperIfNecessary() {} +void InstallDeadlySignalHandlers(SignalHandlerType handler) {} +void SetAlternateSignalStack() {} +void UnsetAlternateSignalStack() {} +void InitTlsSize() {} + +void PrintModuleMap() {} + +void SignalContext::DumpAllRegisters(void *context) {} +const char *DescribeSignalOrException(int signo) { UNIMPLEMENTED(); } + +enum MutexState { MtxUnlocked = 0, MtxLocked = 1, MtxSleeping = 2 }; + +BlockingMutex::BlockingMutex() { + internal_memset(this, 0, sizeof(*this)); +} + +void BlockingMutex::Lock() { + CHECK_EQ(owner_, 0); + atomic_uint32_t *m = reinterpret_cast<atomic_uint32_t *>(&opaque_storage_); + if (atomic_exchange(m, MtxLocked, memory_order_acquire) == MtxUnlocked) + return; + while (atomic_exchange(m, MtxSleeping, memory_order_acquire) != MtxUnlocked) { + internal_sched_yield(); + } +} + +void BlockingMutex::Unlock() { + atomic_uint32_t *m = reinterpret_cast<atomic_uint32_t *>(&opaque_storage_); + u32 v = atomic_exchange(m, MtxUnlocked, memory_order_release); + CHECK_NE(v, MtxUnlocked); +} + +void BlockingMutex::CheckLocked() { + atomic_uint32_t *m = reinterpret_cast<atomic_uint32_t *>(&opaque_storage_); + CHECK_NE(MtxUnlocked, atomic_load(m, memory_order_relaxed)); +} + +uptr GetPageSize() { return getpagesize(); } + +uptr GetMmapGranularity() { return GetPageSize(); } + +uptr GetMaxVirtualAddress() { + return (1ULL << 32) - 1; // 0xffffffff +} + +void *MmapOrDie(uptr size, const char *mem_type, bool raw_report) { + void* ptr = 0; + int res = __mmap_alloc_aligned(&ptr, GetPageSize(), size); + if (UNLIKELY(res)) + ReportMmapFailureAndDie(size, mem_type, "allocate", res, raw_report); + __mmap_memset(ptr, 0, size); + IncreaseTotalMmap(size); + return ptr; +} + +void *MmapOrDieOnFatalError(uptr size, const char *mem_type) { + void* ptr = 0; + int res = __mmap_alloc_aligned(&ptr, GetPageSize(), size); + if (UNLIKELY(res)) { + if (res == ENOMEM) + return nullptr; + ReportMmapFailureAndDie(size, mem_type, "allocate", false); + } + __mmap_memset(ptr, 0, size); + IncreaseTotalMmap(size); + return ptr; +} + +void *MmapAlignedOrDieOnFatalError(uptr size, uptr alignment, + const char *mem_type) { + CHECK(IsPowerOfTwo(size)); + CHECK(IsPowerOfTwo(alignment)); + void* ptr = 0; + int res = __mmap_alloc_aligned(&ptr, alignment, size); + if (res) + ReportMmapFailureAndDie(size, mem_type, "align allocate", res, false); + __mmap_memset(ptr, 0, size); + IncreaseTotalMmap(size); + return ptr; +} + +void *MmapNoReserveOrDie(uptr size, const char *mem_type) { + return MmapOrDie(size, mem_type, false); +} + +void UnmapOrDie(void *addr, uptr size) { + if (!addr || !size) return; + __mmap_free(addr); + DecreaseTotalMmap(size); +} + +fd_t OpenFile(const char *filename, FileAccessMode mode, error_t *errno_p) { + int flags; + switch (mode) { + case RdOnly: flags = O_RDONLY; break; + case WrOnly: flags = O_WRONLY | O_CREAT | O_TRUNC; break; + case RdWr: flags = O_RDWR | O_CREAT; break; + } + fd_t res = open(filename, flags, 0660); + if (internal_iserror(res, errno_p)) + return kInvalidFd; + return res; +} + +void CloseFile(fd_t fd) { + close(fd); +} + +bool ReadFromFile(fd_t fd, void *buff, uptr buff_size, uptr *bytes_read, + error_t *error_p) { + uptr res = read(fd, buff, buff_size); + if (internal_iserror(res, error_p)) + return false; + if (bytes_read) + *bytes_read = res; + return true; +} + +bool WriteToFile(fd_t fd, const void *buff, uptr buff_size, uptr *bytes_written, + error_t *error_p) { + uptr res = write(fd, buff, buff_size); + if (internal_iserror(res, error_p)) + return false; + if (bytes_written) + *bytes_written = res; + return true; +} + +void ReleaseMemoryPagesToOS(uptr beg, uptr end) {} +void DumpProcessMap() {} + +// There is no page protection so everything is "accessible." +bool IsAccessibleMemoryRange(uptr beg, uptr size) { + return true; +} + +char **GetArgv() { return nullptr; } +char **GetEnviron() { return nullptr; } + +const char *GetEnv(const char *name) { + return getenv(name); +} + +uptr ReadBinaryName(/*out*/char *buf, uptr buf_len) { + internal_strncpy(buf, "StubBinaryName", buf_len); + return internal_strlen(buf); +} + +uptr ReadLongProcessName(/*out*/ char *buf, uptr buf_len) { + internal_strncpy(buf, "StubProcessName", buf_len); + return internal_strlen(buf); +} + +bool IsPathSeparator(const char c) { + return c == '/'; +} + +bool IsAbsolutePath(const char *path) { + return path != nullptr && IsPathSeparator(path[0]); +} + +void ReportFile::Write(const char *buffer, uptr length) { + SpinMutexLock l(mu); + static const char *kWriteError = + "ReportFile::Write() can't output requested buffer!\n"; + ReopenIfNecessary(); + if (length != write(fd, buffer, length)) { + write(fd, kWriteError, internal_strlen(kWriteError)); + Die(); + } +} + +uptr MainThreadStackBase, MainThreadStackSize; +uptr MainThreadTlsBase, MainThreadTlsSize; + +} // namespace __sanitizer + +#endif // SANITIZER_RTEMS |