1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
|
//===- 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 <fcntl.h>
#include <string.h>
#include <sys/errno.h>
#include <sys/mman.h>
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<char *>(Addr) + Size);
#endif
}
orc_rt::Expected<void *> 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<orc_rt::StringError>(
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<orc_rt::StringError>(
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<orc_rt::StringError>(
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<orc_rt::StringError>(
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
|