104 lines · plain
1//===- NativeMemoryAPIs.inc -------------------------------------*- C++ -*-===//2//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-exception6//7//===----------------------------------------------------------------------===//8//9// Generic wrappers for unix-style memory APIs (mmap, mprotect, etc.).10//11//===----------------------------------------------------------------------===//12 13#include "orc-rt/Error.h"14#include "orc-rt/MemoryFlags.h"15 16#include <fcntl.h>17#include <string.h>18#include <sys/errno.h>19#include <sys/mman.h>20 21namespace {22 23int toNativeProtFlags(orc_rt::MemProt MP) {24 int Prot = PROT_NONE;25 if ((MP & orc_rt::MemProt::Read) != orc_rt::MemProt::None)26 Prot |= PROT_READ;27 if ((MP & orc_rt::MemProt::Write) != orc_rt::MemProt::None)28 Prot |= PROT_WRITE;29 if ((MP & orc_rt::MemProt::Exec) != orc_rt::MemProt::None)30 Prot |= PROT_EXEC;31 return Prot;32}33 34#if defined(__APPLE__)35extern "C" void sys_icache_invalidate(const void *Addr, size_t Size);36#else37extern "C" void __clear_cache(void *Start, void *End);38#endif39 40static void invalidateInstructionCache(void *Addr, size_t Size) {41#if defined(__APPLE__)42 sys_icache_invalidate(Addr, Size);43#else44 __clear_cache(Addr, reinterpret_cast<char *>(Addr) + Size);45#endif46}47 48orc_rt::Expected<void *> hostOSMemoryReserve(size_t Size) {49 if (Size == 0)50 return nullptr;51 52 int FD = 0;53 int MapFlags = MAP_PRIVATE;54 55#if defined(MAP_ANON)56 // If MAP_ANON is available then use it.57 FD = -1;58 MapFlags |= MAP_ANON;59#else // !defined(MAP_ANON)60 // Fall back to /dev/zero for strict POSIX.61 fd = open("/dev/zero", O_RDWR);62 if (fd == -1) {63 auto ErrNum = errno;64 return make_error<orc_rt::StringError>(65 std::string("Could not open /dev/zero for memory reserve: ") +66 strerror(ErrNum));67 }68#endif69 70 void *Addr = mmap(nullptr, Size, PROT_READ | PROT_WRITE, MapFlags, FD, 0);71 if (Addr == MAP_FAILED) {72 auto ErrNum = errno;73 return orc_rt::make_error<orc_rt::StringError>(74 std::string("mmap for memory reserve failed: ") + strerror(ErrNum));75 }76 77 return Addr;78}79 80orc_rt::Error hostOSMemoryRelease(void *Base, size_t Size) {81 if (munmap(Base, Size) != 0) {82 auto ErrNum = errno;83 return orc_rt::make_error<orc_rt::StringError>(84 std::string("munmap for memory release failed: ") + strerror(ErrNum));85 }86 return orc_rt::Error::success();87}88 89orc_rt::Error hostOSMemoryProtect(void *Base, size_t Size, orc_rt::MemProt MP) {90 if (mprotect(Base, Size, toNativeProtFlags(MP)) != 0) {91 auto ErrNum = errno;92 return orc_rt::make_error<orc_rt::StringError>(93 std::string("mprotect for memory finalize failed: ") +94 strerror(ErrNum));95 }96 97 if ((MP & orc_rt::MemProt::Exec) != orc_rt::MemProt::None)98 invalidateInstructionCache(Base, Size);99 100 return orc_rt::Error::success();101}102 103} // anonymous namespace104