1 //===-- sanitizer_rtems.cpp -----------------------------------------------===//
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
7 //===----------------------------------------------------------------------===//
9 // This file is shared between various sanitizers' runtime libraries and
10 // implements RTEMS-specific functions.
11 //===----------------------------------------------------------------------===//
13 #include "sanitizer_rtems.h"
16 #define posix_memalign __real_posix_memalign
17 #define free __real_free
18 #define memset __real_memset
20 #include "sanitizer_file.h"
21 #include "sanitizer_symbolizer.h"
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
36 namespace __sanitizer
{
38 #include "sanitizer_syscall_generic.inc"
40 void NORETURN
internal__exit(int exitcode
) {
44 uptr
internal_sched_yield() {
48 uptr
internal_getpid() {
52 int internal_dlinfo(void *handle
, int request
, void *p
) {
56 bool FileExists(const char *filename
) {
58 if (stat(filename
, &st
))
60 // Sanity check: filename is a regular file.
61 return S_ISREG(st
.st_mode
);
64 uptr
GetThreadSelf() { return static_cast<uptr
>(pthread_self()); }
66 tid_t
GetTid() { return GetThreadSelf(); }
68 void Abort() { abort(); }
70 int Atexit(void (*function
)(void)) { return atexit(function
); }
72 void SleepForSeconds(int seconds
) { sleep(seconds
); }
74 void SleepForMillis(int millis
) { usleep(millis
* 1000); }
76 bool SupportsColoredOutput(fd_t fd
) { return false; }
78 void GetThreadStackTopAndBottom(bool at_initialization
,
79 uptr
*stack_top
, uptr
*stack_bottom
) {
81 pthread_attr_init(&attr
);
82 CHECK_EQ(pthread_getattr_np(pthread_self(), &attr
), 0);
85 CHECK_EQ(pthread_attr_getstack(&attr
, &base
, &size
), 0);
86 CHECK_EQ(pthread_attr_destroy(&attr
), 0);
88 *stack_bottom
= reinterpret_cast<uptr
>(base
);
89 *stack_top
= *stack_bottom
+ size
;
92 void 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;
101 void InitializePlatformEarly() {}
102 void MaybeReexec() {}
104 void CheckMPROTECT() {}
105 void DisableCoreDumperIfNecessary() {}
106 void InstallDeadlySignalHandlers(SignalHandlerType handler
) {}
107 void SetAlternateSignalStack() {}
108 void UnsetAlternateSignalStack() {}
109 void InitTlsSize() {}
111 void PrintModuleMap() {}
113 void SignalContext::DumpAllRegisters(void *context
) {}
114 const char *DescribeSignalOrException(int signo
) { UNIMPLEMENTED(); }
116 enum MutexState
{ MtxUnlocked
= 0, MtxLocked
= 1, MtxSleeping
= 2 };
118 BlockingMutex::BlockingMutex() {
119 internal_memset(this, 0, sizeof(*this));
122 void BlockingMutex::Lock() {
124 atomic_uint32_t
*m
= reinterpret_cast<atomic_uint32_t
*>(&opaque_storage_
);
125 if (atomic_exchange(m
, MtxLocked
, memory_order_acquire
) == MtxUnlocked
)
127 while (atomic_exchange(m
, MtxSleeping
, memory_order_acquire
) != MtxUnlocked
) {
128 internal_sched_yield();
132 void 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
);
138 void BlockingMutex::CheckLocked() {
139 atomic_uint32_t
*m
= reinterpret_cast<atomic_uint32_t
*>(&opaque_storage_
);
140 CHECK_NE(MtxUnlocked
, atomic_load(m
, memory_order_relaxed
));
143 uptr
GetPageSize() { return getpagesize(); }
145 uptr
GetMmapGranularity() { return GetPageSize(); }
147 uptr
GetMaxVirtualAddress() {
148 return (1ULL << 32) - 1; // 0xffffffff
151 void *MmapOrDie(uptr size
, const char *mem_type
, bool raw_report
) {
153 int res
= __mmap_alloc_aligned(&ptr
, GetPageSize(), size
);
155 ReportMmapFailureAndDie(size
, mem_type
, "allocate", res
, raw_report
);
156 __mmap_memset(ptr
, 0, size
);
157 IncreaseTotalMmap(size
);
161 void *MmapOrDieOnFatalError(uptr size
, const char *mem_type
) {
163 int res
= __mmap_alloc_aligned(&ptr
, GetPageSize(), size
);
167 ReportMmapFailureAndDie(size
, mem_type
, "allocate", false);
169 __mmap_memset(ptr
, 0, size
);
170 IncreaseTotalMmap(size
);
174 void *MmapAlignedOrDieOnFatalError(uptr size
, uptr alignment
,
175 const char *mem_type
) {
176 CHECK(IsPowerOfTwo(size
));
177 CHECK(IsPowerOfTwo(alignment
));
179 int res
= __mmap_alloc_aligned(&ptr
, alignment
, size
);
181 ReportMmapFailureAndDie(size
, mem_type
, "align allocate", res
, false);
182 __mmap_memset(ptr
, 0, size
);
183 IncreaseTotalMmap(size
);
187 void *MmapNoReserveOrDie(uptr size
, const char *mem_type
) {
188 return MmapOrDie(size
, mem_type
, false);
191 void UnmapOrDie(void *addr
, uptr size
) {
192 if (!addr
|| !size
) return;
194 DecreaseTotalMmap(size
);
197 fd_t
OpenFile(const char *filename
, FileAccessMode mode
, error_t
*errno_p
) {
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;
204 fd_t res
= open(filename
, flags
, 0660);
205 if (internal_iserror(res
, errno_p
))
210 void CloseFile(fd_t fd
) {
214 bool ReadFromFile(fd_t fd
, void *buff
, uptr buff_size
, uptr
*bytes_read
,
216 uptr res
= read(fd
, buff
, buff_size
);
217 if (internal_iserror(res
, error_p
))
224 bool WriteToFile(fd_t fd
, const void *buff
, uptr buff_size
, uptr
*bytes_written
,
226 uptr res
= write(fd
, buff
, buff_size
);
227 if (internal_iserror(res
, error_p
))
230 *bytes_written
= res
;
234 void ReleaseMemoryPagesToOS(uptr beg
, uptr end
) {}
235 void DumpProcessMap() {}
237 // There is no page protection so everything is "accessible."
238 bool IsAccessibleMemoryRange(uptr beg
, uptr size
) {
242 char **GetArgv() { return nullptr; }
243 char **GetEnviron() { return nullptr; }
245 const char *GetEnv(const char *name
) {
249 uptr
ReadBinaryName(/*out*/char *buf
, uptr buf_len
) {
250 internal_strncpy(buf
, "StubBinaryName", buf_len
);
251 return internal_strlen(buf
);
254 uptr
ReadLongProcessName(/*out*/ char *buf
, uptr buf_len
) {
255 internal_strncpy(buf
, "StubProcessName", buf_len
);
256 return internal_strlen(buf
);
259 bool IsPathSeparator(const char c
) {
263 bool IsAbsolutePath(const char *path
) {
264 return path
!= nullptr && IsPathSeparator(path
[0]);
267 void ReportFile::Write(const char *buffer
, uptr length
) {
269 static const char *kWriteError
=
270 "ReportFile::Write() can't output requested buffer!\n";
272 if (length
!= write(fd
, buffer
, length
)) {
273 write(fd
, kWriteError
, internal_strlen(kWriteError
));
278 uptr MainThreadStackBase
, MainThreadStackSize
;
279 uptr MainThreadTlsBase
, MainThreadTlsSize
;
281 } // namespace __sanitizer
283 #endif // SANITIZER_RTEMS