Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/llvm-project/compiler-rt/lib/scudo/standalone/mem_map_linux.cpp
35292 views
1
//===-- mem_map_linux.cpp ---------------------------------------*- 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-exception
6
//
7
//===----------------------------------------------------------------------===//
8
9
#include "platform.h"
10
11
#if SCUDO_LINUX
12
13
#include "mem_map_linux.h"
14
15
#include "common.h"
16
#include "internal_defs.h"
17
#include "linux.h"
18
#include "mutex.h"
19
#include "report_linux.h"
20
#include "string_utils.h"
21
22
#include <errno.h>
23
#include <fcntl.h>
24
#include <linux/futex.h>
25
#include <sched.h>
26
#include <stdio.h>
27
#include <stdlib.h>
28
#include <string.h>
29
#include <sys/mman.h>
30
#include <sys/stat.h>
31
#include <sys/syscall.h>
32
#include <sys/time.h>
33
#include <time.h>
34
#include <unistd.h>
35
36
#if SCUDO_ANDROID
37
// TODO(chiahungduan): Review if we still need the followings macros.
38
#include <sys/prctl.h>
39
// Definitions of prctl arguments to set a vma name in Android kernels.
40
#define ANDROID_PR_SET_VMA 0x53564d41
41
#define ANDROID_PR_SET_VMA_ANON_NAME 0
42
#endif
43
44
namespace scudo {
45
46
static void *mmapWrapper(uptr Addr, uptr Size, const char *Name, uptr Flags) {
47
int MmapFlags = MAP_PRIVATE | MAP_ANONYMOUS;
48
int MmapProt;
49
if (Flags & MAP_NOACCESS) {
50
MmapFlags |= MAP_NORESERVE;
51
MmapProt = PROT_NONE;
52
} else {
53
MmapProt = PROT_READ | PROT_WRITE;
54
}
55
#if defined(__aarch64__)
56
#ifndef PROT_MTE
57
#define PROT_MTE 0x20
58
#endif
59
if (Flags & MAP_MEMTAG)
60
MmapProt |= PROT_MTE;
61
#endif
62
if (Addr)
63
MmapFlags |= MAP_FIXED;
64
void *P =
65
mmap(reinterpret_cast<void *>(Addr), Size, MmapProt, MmapFlags, -1, 0);
66
if (P == MAP_FAILED) {
67
if (!(Flags & MAP_ALLOWNOMEM) || errno != ENOMEM)
68
reportMapError(errno == ENOMEM ? Size : 0);
69
return nullptr;
70
}
71
#if SCUDO_ANDROID
72
if (Name)
73
prctl(ANDROID_PR_SET_VMA, ANDROID_PR_SET_VMA_ANON_NAME, P, Size, Name);
74
#else
75
(void)Name;
76
#endif
77
78
return P;
79
}
80
81
bool MemMapLinux::mapImpl(uptr Addr, uptr Size, const char *Name, uptr Flags) {
82
void *P = mmapWrapper(Addr, Size, Name, Flags);
83
if (P == nullptr)
84
return false;
85
86
MapBase = reinterpret_cast<uptr>(P);
87
MapCapacity = Size;
88
return true;
89
}
90
91
void MemMapLinux::unmapImpl(uptr Addr, uptr Size) {
92
// If we unmap all the pages, also mark `MapBase` to 0 to indicate invalid
93
// status.
94
if (Size == MapCapacity) {
95
MapBase = MapCapacity = 0;
96
} else {
97
// This is partial unmap and is unmapping the pages from the beginning,
98
// shift `MapBase` to the new base.
99
if (MapBase == Addr)
100
MapBase = Addr + Size;
101
MapCapacity -= Size;
102
}
103
104
if (munmap(reinterpret_cast<void *>(Addr), Size) != 0)
105
reportUnmapError(Addr, Size);
106
}
107
108
bool MemMapLinux::remapImpl(uptr Addr, uptr Size, const char *Name,
109
uptr Flags) {
110
void *P = mmapWrapper(Addr, Size, Name, Flags);
111
if (reinterpret_cast<uptr>(P) != Addr)
112
reportMapError();
113
return true;
114
}
115
116
void MemMapLinux::setMemoryPermissionImpl(uptr Addr, uptr Size, uptr Flags) {
117
int Prot = (Flags & MAP_NOACCESS) ? PROT_NONE : (PROT_READ | PROT_WRITE);
118
if (mprotect(reinterpret_cast<void *>(Addr), Size, Prot) != 0)
119
reportProtectError(Addr, Size, Prot);
120
}
121
122
void MemMapLinux::releaseAndZeroPagesToOSImpl(uptr From, uptr Size) {
123
void *Addr = reinterpret_cast<void *>(From);
124
125
while (madvise(Addr, Size, MADV_DONTNEED) == -1 && errno == EAGAIN) {
126
}
127
}
128
129
bool ReservedMemoryLinux::createImpl(uptr Addr, uptr Size, const char *Name,
130
uptr Flags) {
131
ReservedMemoryLinux::MemMapT MemMap;
132
if (!MemMap.map(Addr, Size, Name, Flags | MAP_NOACCESS))
133
return false;
134
135
MapBase = MemMap.getBase();
136
MapCapacity = MemMap.getCapacity();
137
138
return true;
139
}
140
141
void ReservedMemoryLinux::releaseImpl() {
142
if (munmap(reinterpret_cast<void *>(getBase()), getCapacity()) != 0)
143
reportUnmapError(getBase(), getCapacity());
144
}
145
146
ReservedMemoryLinux::MemMapT ReservedMemoryLinux::dispatchImpl(uptr Addr,
147
uptr Size) {
148
return ReservedMemoryLinux::MemMapT(Addr, Size);
149
}
150
151
} // namespace scudo
152
153
#endif // SCUDO_LINUX
154
155