//===- NativeMemoryAPIs.inc -------------------------------------*- C++ -*-===// // // 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 // //===----------------------------------------------------------------------===// // // Generic wrappers for unix-style memory APIs (mmap, mprotect, etc.). // //===----------------------------------------------------------------------===// #include "orc-rt/Error.h" #include "orc-rt/MemoryFlags.h" #include #include #include #include namespace { int toNativeProtFlags(orc_rt::MemProt MP) { int Prot = PROT_NONE; if ((MP & orc_rt::MemProt::Read) != orc_rt::MemProt::None) Prot |= PROT_READ; if ((MP & orc_rt::MemProt::Write) != orc_rt::MemProt::None) Prot |= PROT_WRITE; if ((MP & orc_rt::MemProt::Exec) != orc_rt::MemProt::None) Prot |= PROT_EXEC; return Prot; } #if defined(__APPLE__) extern "C" void sys_icache_invalidate(const void *Addr, size_t Size); #else extern "C" void __clear_cache(void *Start, void *End); #endif static void invalidateInstructionCache(void *Addr, size_t Size) { #if defined(__APPLE__) sys_icache_invalidate(Addr, Size); #else __clear_cache(Addr, reinterpret_cast(Addr) + Size); #endif } orc_rt::Expected hostOSMemoryReserve(size_t Size) { if (Size == 0) return nullptr; int FD = 0; int MapFlags = MAP_PRIVATE; #if defined(MAP_ANON) // If MAP_ANON is available then use it. FD = -1; MapFlags |= MAP_ANON; #else // !defined(MAP_ANON) // Fall back to /dev/zero for strict POSIX. fd = open("/dev/zero", O_RDWR); if (fd == -1) { auto ErrNum = errno; return make_error( std::string("Could not open /dev/zero for memory reserve: ") + strerror(ErrNum)); } #endif void *Addr = mmap(nullptr, Size, PROT_READ | PROT_WRITE, MapFlags, FD, 0); if (Addr == MAP_FAILED) { auto ErrNum = errno; return orc_rt::make_error( std::string("mmap for memory reserve failed: ") + strerror(ErrNum)); } return Addr; } orc_rt::Error hostOSMemoryRelease(void *Base, size_t Size) { if (munmap(Base, Size) != 0) { auto ErrNum = errno; return orc_rt::make_error( std::string("munmap for memory release failed: ") + strerror(ErrNum)); } return orc_rt::Error::success(); } orc_rt::Error hostOSMemoryProtect(void *Base, size_t Size, orc_rt::MemProt MP) { if (mprotect(Base, Size, toNativeProtFlags(MP)) != 0) { auto ErrNum = errno; return orc_rt::make_error( std::string("mprotect for memory finalize failed: ") + strerror(ErrNum)); } if ((MP & orc_rt::MemProt::Exec) != orc_rt::MemProt::None) invalidateInstructionCache(Base, Size); return orc_rt::Error::success(); } } // anonymous namespace