code_buffer.cpp (2877B)
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