Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
stenzek
GitHub Repository: stenzek/duckstation
Path: blob/master/dep/biscuit/src/code_buffer.cpp
4253 views
1
#include <biscuit/assert.hpp>
2
#include <biscuit/code_buffer.hpp>
3
4
#include <cstring>
5
#include <utility>
6
7
#ifdef BISCUIT_CODE_BUFFER_MMAP
8
#include <sys/mman.h>
9
#endif
10
11
namespace biscuit {
12
13
CodeBuffer::CodeBuffer(size_t capacity)
14
: m_capacity{capacity}, m_is_managed{true} {
15
if (capacity == 0) {
16
return;
17
}
18
19
#ifdef BISCUIT_CODE_BUFFER_MMAP
20
m_buffer = static_cast<uint8_t*>(mmap(nullptr, capacity,
21
PROT_READ | PROT_WRITE,
22
MAP_PRIVATE | MAP_ANONYMOUS,
23
-1, 0));
24
BISCUIT_ASSERT(m_buffer != nullptr);
25
#else
26
m_buffer = new uint8_t[capacity]();
27
#endif
28
29
m_cursor = m_buffer;
30
}
31
32
CodeBuffer::CodeBuffer(uint8_t* buffer, size_t capacity)
33
: m_buffer{buffer}, m_cursor{buffer}, m_capacity{capacity} {
34
BISCUIT_ASSERT(buffer != nullptr);
35
}
36
37
CodeBuffer::CodeBuffer(CodeBuffer&& other) noexcept
38
: m_buffer{std::exchange(other.m_buffer, nullptr)}
39
, m_cursor{std::exchange(other.m_cursor, nullptr)}
40
, m_capacity{std::exchange(other.m_capacity, size_t{0})}
41
, m_is_managed{std::exchange(other.m_is_managed, false)} {}
42
43
CodeBuffer& CodeBuffer::operator=(CodeBuffer&& other) noexcept {
44
if (this == &other) {
45
return *this;
46
}
47
48
std::swap(m_buffer, other.m_buffer);
49
std::swap(m_cursor, other.m_cursor);
50
std::swap(m_capacity, other.m_capacity);
51
std::swap(m_is_managed, other.m_is_managed);
52
return *this;
53
}
54
55
CodeBuffer::~CodeBuffer() noexcept {
56
if (!m_is_managed) {
57
return;
58
}
59
60
#ifdef BISCUIT_CODE_BUFFER_MMAP
61
munmap(m_buffer, m_capacity);
62
#else
63
delete[] m_buffer;
64
#endif
65
}
66
67
void CodeBuffer::Grow(size_t new_capacity) {
68
BISCUIT_ASSERT(IsManaged());
69
70
// No-op, just return.
71
if (new_capacity <= m_capacity) {
72
return;
73
}
74
75
const auto cursor_offset = GetCursorOffset();
76
77
#ifdef BISCUIT_CODE_BUFFER_MMAP
78
auto* new_buffer = static_cast<uint8_t*>(mremap(m_buffer, m_capacity, new_capacity, MREMAP_MAYMOVE));
79
BISCUIT_ASSERT(new_buffer != nullptr);
80
#else
81
auto* new_buffer = new uint8_t[new_capacity]();
82
std::memcpy(new_buffer, m_buffer, m_capacity);
83
delete[] m_buffer;
84
#endif
85
86
m_buffer = new_buffer;
87
m_capacity = new_capacity;
88
m_cursor = m_buffer + cursor_offset;
89
}
90
91
void CodeBuffer::SetExecutable() {
92
#ifdef BISCUIT_CODE_BUFFER_MMAP
93
const auto result = mprotect(m_buffer, m_capacity, PROT_READ | PROT_EXEC);
94
BISCUIT_ASSERT(result == 0);
95
#else
96
// Unimplemented/Unnecessary for new
97
BISCUIT_ASSERT(false);
98
#endif
99
}
100
101
void CodeBuffer::SetWritable() {
102
#ifdef BISCUIT_CODE_BUFFER_MMAP
103
const auto result = mprotect(m_buffer, m_capacity, PROT_READ | PROT_WRITE);
104
BISCUIT_ASSERT(result == 0);
105
#else
106
// Unimplemented/Unnecessary for new
107
BISCUIT_ASSERT(false);
108
#endif
109
}
110
111
} // namespace biscuit
112
113