15 #include "llvm/Support/DataTypes.h"
19 #ifdef HAVE_SYS_MMAN_H
24 #include <mach/mach.h>
28 # if defined(__OpenBSD__)
29 # include <mips64/sysarch.h>
31 # include <sys/cachectl.h>
36 extern "C" void sys_icache_invalidate(
const void *Addr,
size_t len);
38 extern "C" void __clear_cache(
void *,
void*);
43 int getPosixProtectionFlags(
unsigned Flags) {
50 return PROT_READ | PROT_WRITE;
52 return PROT_READ | PROT_EXEC;
55 return PROT_READ | PROT_WRITE | PROT_EXEC;
57 #if defined(__FreeBSD__)
65 return PROT_READ | PROT_EXEC;
83 const MemoryBlock *
const NearBlock,
85 std::error_code &EC) {
86 EC = std::error_code();
91 const size_t NumPages = (NumBytes+PageSize-1)/PageSize;
95 int MMFlags = MAP_PRIVATE |
103 int Protect = getPosixProtectionFlags(PFlags);
106 uintptr_t Start = NearBlock ?
reinterpret_cast<uintptr_t
>(NearBlock->base()) +
107 NearBlock->size() : 0;
108 if (Start && Start % PageSize)
109 Start += PageSize - Start %
PageSize;
111 void *Addr = ::mmap(reinterpret_cast<void*>(Start), PageSize*NumPages,
112 Protect, MMFlags, fd, 0);
113 if (Addr == MAP_FAILED) {
117 EC = std::error_code(errno, std::generic_category());
118 return MemoryBlock();
122 Result.Address = Addr;
133 if (M.Address ==
nullptr || M.Size == 0)
134 return std::error_code();
136 if (0 != ::munmap(M.Address, M.Size))
137 return std::error_code(errno, std::generic_category());
142 return std::error_code();
148 if (M.Address ==
nullptr || M.Size == 0)
149 return std::error_code();
152 return std::error_code(EINVAL, std::generic_category());
154 int Protect = getPosixProtectionFlags(Flags);
156 uintptr_t Start =
alignAddr((uint8_t *)M.Address - PageSize + 1, PageSize);
157 uintptr_t
End =
alignAddr((uint8_t *)M.Address + M.Size, PageSize);
158 int Result = ::mprotect((
void *)Start, End - Start, Protect);
161 return std::error_code(errno, std::generic_category());
166 return std::error_code();
176 std::string *ErrMsg) {
177 if (NumBytes == 0)
return MemoryBlock();
180 size_t NumPages = (NumBytes+PageSize-1)/PageSize;
184 int flags = MAP_PRIVATE |
192 void* start = NearBlock ? (
unsigned char*)NearBlock->base() +
193 NearBlock->size() :
nullptr;
195 #if defined(__APPLE__) && (defined(__arm__) || defined(__arm64__))
196 void *pa = ::mmap(start, PageSize*NumPages, PROT_READ|PROT_EXEC,
199 void *pa = ::mmap(start, PageSize*NumPages, PROT_READ|PROT_WRITE|PROT_EXEC,
202 if (pa == MAP_FAILED) {
206 MakeErrMsg(ErrMsg,
"Can't allocate RWX Memory");
207 return MemoryBlock();
210 #if defined(__APPLE__) && (defined(__arm__) || defined(__arm64__))
211 kern_return_t kr = vm_protect(mach_task_self(), (vm_address_t)pa,
212 (vm_size_t)(PageSize*NumPages), 0,
214 if (KERN_SUCCESS != kr) {
215 MakeErrMsg(ErrMsg,
"vm_protect max RX failed");
216 return MemoryBlock();
219 kr = vm_protect(mach_task_self(), (vm_address_t)pa,
220 (vm_size_t)(PageSize*NumPages), 0,
222 if (KERN_SUCCESS != kr) {
224 return MemoryBlock();
236 if (M.Address ==
nullptr || M.Size == 0)
return false;
237 if (0 != ::munmap(M.Address, M.Size))
238 return MakeErrMsg(ErrMsg,
"Can't release RWX Memory");
243 #if defined(__APPLE__) && (defined(__arm__) || defined(__arm64__))
244 if (M.Address == 0 || M.Size == 0)
return false;
246 kern_return_t kr = vm_protect(mach_task_self(), (vm_address_t)M.Address,
248 return KERN_SUCCESS == kr;
255 if (M.Address ==
nullptr || M.Size == 0)
return false;
257 #if defined(__APPLE__) && (defined(__arm__) || defined(__arm64__))
258 kern_return_t kr = vm_protect(mach_task_self(), (vm_address_t)M.Address,
260 return KERN_SUCCESS == kr;
267 #if defined(__APPLE__) && (defined(__arm__) || defined(__arm64__))
268 kern_return_t kr = vm_protect(mach_task_self(), (vm_address_t)Addr,
271 return KERN_SUCCESS == kr;
278 #if defined(__APPLE__) && (defined(__arm__) || defined(__arm64__))
279 kern_return_t kr = vm_protect(mach_task_self(), (vm_address_t)Addr,
282 return KERN_SUCCESS == kr;
295 #if defined(__APPLE__)
297 # if (defined(__POWERPC__) || defined (__ppc__) || \
298 defined(_POWER) || defined(_ARCH_PPC) || defined(__arm__) || \
300 sys_icache_invalidate(const_cast<void *>(Addr), Len);
305 # if (defined(__POWERPC__) || defined (__ppc__) || \
306 defined(_POWER) || defined(_ARCH_PPC)) && defined(__GNUC__)
307 const size_t LineSize = 32;
313 for (
intptr_t Line = StartLine; Line < EndLine; Line += LineSize)
314 asm volatile(
"dcbf 0, %0" : :
"r"(Line));
315 asm volatile(
"sync");
317 for (
intptr_t Line = StartLine; Line < EndLine; Line += LineSize)
318 asm volatile(
"icbi 0, %0" : :
"r"(Line));
319 asm volatile(
"isync");
320 # elif (defined(__arm__) || defined(__aarch64__) || defined(__mips__)) && \
323 const char *Start =
static_cast<const char *
>(Addr);
324 const char *End = Start + Len;
325 __clear_cache(const_cast<char *>(Start), const_cast<char *>(End));
static bool setRangeWritable(const void *Addr, size_t Size)
setRangeWritable - Mark the page containing a range of addresses as writable.
static std::error_code releaseMappedMemory(MemoryBlock &Block)
This method releases a block of memory that was allocated with the allocateMappedMemory method...
static MemoryBlock allocateMappedMemory(size_t NumBytes, const MemoryBlock *const NearBlock, unsigned Flags, std::error_code &EC)
This method allocates a block of memory that is suitable for loading dynamically generated code (e...
void ValgrindDiscardTranslations(const void *Addr, size_t Len)
struct fuzzer::@269 Flags
static void InvalidateInstructionCache(const void *Addr, size_t Len)
InvalidateInstructionCache - Before the JIT can run a block of code that has been emitted it must inv...
static cl::opt< int > PageSize("imp-null-check-page-size", cl::desc("The page size of the target in bytes"), cl::init(4096))
static bool ReleaseRWX(MemoryBlock &block, std::string *ErrMsg=nullptr)
This method releases a block of Read/Write/Execute memory that was allocated with the AllocateRWX met...
static const unsigned End
static bool setRangeExecutable(const void *Addr, size_t Size)
setRangeExecutable - Mark the page containing a range of addresses as executable. ...
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
static unsigned getPageSize()
static MemoryBlock AllocateRWX(size_t NumBytes, const MemoryBlock *NearBlock, std::string *ErrMsg=nullptr)
This method allocates a block of Read/Write/Execute memory that is suitable for executing dynamically...
bool MakeErrMsg(std::string *ErrMsg, const std::string &prefix)
uintptr_t alignAddr(const void *Addr, size_t Alignment)
Aligns Addr to Alignment bytes, rounding up.
Provides a library for accessing information about this process and other processes on the operating ...
static bool setExecutable(MemoryBlock &M, std::string *ErrMsg=nullptr)
setExecutable - Before the JIT can run a block of code, it has to be given read and executable privil...
std::underlying_type< E >::type Mask()
Get a bitmask with 1s in all places up to the high-order bit of E's largest value.
static bool setWritable(MemoryBlock &M, std::string *ErrMsg=nullptr)
setWritable - When adding to a block of code, the JIT may need to mark a block of code as RW since th...
static std::error_code protectMappedMemory(const MemoryBlock &Block, unsigned Flags)
This method sets the protection flags for a block of memory to the state specified by /p Flags...