blob: 5c906c521af991fbaae73f06299d339b5f53e5e3 [file] [log] [blame]
Georgia Kouveli8b57c862017-03-02 15:18:58 +00001// Copyright 2017, VIXL authors
armvixlc68cb642014-09-25 18:49:30 +01002// All rights reserved.
3//
4// Redistribution and use in source and binary forms, with or without
5// modification, are permitted provided that the following conditions are met:
6//
7// * Redistributions of source code must retain the above copyright notice,
8// this list of conditions and the following disclaimer.
9// * Redistributions in binary form must reproduce the above copyright notice,
10// this list of conditions and the following disclaimer in the documentation
11// and/or other materials provided with the distribution.
12// * Neither the name of ARM Limited nor the names of its contributors may be
13// used to endorse or promote products derived from this software without
14// specific prior written permission.
15//
16// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS CONTRIBUTORS "AS IS" AND
17// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
20// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
22// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
23// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
25// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26
Alex Gilday31dd2ae2016-07-05 16:34:41 +010027extern "C" {
28#include <sys/mman.h>
29}
30
Alexandre Rames1f9074d2016-05-23 15:50:01 +010031#include "code-buffer-vixl.h"
32#include "utils-vixl.h"
armvixlc68cb642014-09-25 18:49:30 +010033
34namespace vixl {
35
36
Alexandre Rames7cd99a82016-08-03 13:32:02 +010037CodeBuffer::CodeBuffer(size_t capacity)
38 : buffer_(NULL),
39 managed_(true),
40 cursor_(NULL),
41 dirty_(false),
42 capacity_(capacity) {
43 if (capacity_ == 0) {
44 return;
45 }
Jacob Bramley1fa6f062016-12-19 11:40:08 +000046#ifdef VIXL_CODE_BUFFER_MALLOC
Alexandre Rames0287a6c2016-11-16 10:37:05 +000047 buffer_ = reinterpret_cast<byte*>(malloc(capacity_));
Jacob Bramley1fa6f062016-12-19 11:40:08 +000048#elif defined(VIXL_CODE_BUFFER_MMAP)
Alex Gilday31dd2ae2016-07-05 16:34:41 +010049 buffer_ = reinterpret_cast<byte*>(mmap(NULL,
50 capacity,
51 PROT_READ | PROT_WRITE,
52 MAP_PRIVATE | MAP_ANONYMOUS,
53 -1,
54 0));
Jacob Bramley1fa6f062016-12-19 11:40:08 +000055#else
56#error Unknown code buffer allocator.
Alexandre Rames0287a6c2016-11-16 10:37:05 +000057#endif
armvixlc68cb642014-09-25 18:49:30 +010058 VIXL_CHECK(buffer_ != NULL);
Alexandre Ramesd3832962016-07-04 15:03:43 +010059 // Aarch64 instructions must be word aligned, we assert the default allocator
armvixlc68cb642014-09-25 18:49:30 +010060 // always returns word align memory.
61 VIXL_ASSERT(IsWordAligned(buffer_));
62
63 cursor_ = buffer_;
armvixlc68cb642014-09-25 18:49:30 +010064}
65
66
Alexandre Rames919e3fe2016-10-14 09:07:54 +010067CodeBuffer::CodeBuffer(byte* buffer, size_t capacity)
armvixlc68cb642014-09-25 18:49:30 +010068 : buffer_(reinterpret_cast<byte*>(buffer)),
69 managed_(false),
70 cursor_(reinterpret_cast<byte*>(buffer)),
71 dirty_(false),
72 capacity_(capacity) {
73 VIXL_ASSERT(buffer_ != NULL);
74}
75
76
Pierre Langloisa5b3cef2019-01-28 11:30:38 +000077CodeBuffer::~CodeBuffer() VIXL_NEGATIVE_TESTING_ALLOW_EXCEPTION {
armvixlc68cb642014-09-25 18:49:30 +010078 VIXL_ASSERT(!IsDirty());
79 if (managed_) {
Jacob Bramley1fa6f062016-12-19 11:40:08 +000080#ifdef VIXL_CODE_BUFFER_MALLOC
Alexandre Rames0287a6c2016-11-16 10:37:05 +000081 free(buffer_);
Jacob Bramley1fa6f062016-12-19 11:40:08 +000082#elif defined(VIXL_CODE_BUFFER_MMAP)
Alex Gilday31dd2ae2016-07-05 16:34:41 +010083 munmap(buffer_, capacity_);
Jacob Bramley1fa6f062016-12-19 11:40:08 +000084#else
85#error Unknown code buffer allocator.
Alexandre Rames0287a6c2016-11-16 10:37:05 +000086#endif
armvixlc68cb642014-09-25 18:49:30 +010087 }
88}
89
90
Jacob Bramley745a8552016-12-20 09:52:30 +000091void CodeBuffer::SetExecutable() {
Jacob Bramleycff5a2e2019-03-15 09:34:56 +000092#ifdef VIXL_CODE_BUFFER_MMAP
Alex Gilday31dd2ae2016-07-05 16:34:41 +010093 int ret = mprotect(buffer_, capacity_, PROT_READ | PROT_EXEC);
94 VIXL_CHECK(ret == 0);
Jacob Bramleycff5a2e2019-03-15 09:34:56 +000095#else
96 // This requires page-aligned memory blocks, which we can only guarantee with
97 // mmap.
98 VIXL_UNIMPLEMENTED();
Jacob Bramley745a8552016-12-20 09:52:30 +000099#endif
Jacob Bramleycff5a2e2019-03-15 09:34:56 +0000100}
Alex Gilday31dd2ae2016-07-05 16:34:41 +0100101
102
Jacob Bramley745a8552016-12-20 09:52:30 +0000103void CodeBuffer::SetWritable() {
Jacob Bramleycff5a2e2019-03-15 09:34:56 +0000104#ifdef VIXL_CODE_BUFFER_MMAP
Alex Gilday31dd2ae2016-07-05 16:34:41 +0100105 int ret = mprotect(buffer_, capacity_, PROT_READ | PROT_WRITE);
106 VIXL_CHECK(ret == 0);
Jacob Bramleycff5a2e2019-03-15 09:34:56 +0000107#else
108 // This requires page-aligned memory blocks, which we can only guarantee with
109 // mmap.
110 VIXL_UNIMPLEMENTED();
Jacob Bramley745a8552016-12-20 09:52:30 +0000111#endif
Jacob Bramleycff5a2e2019-03-15 09:34:56 +0000112}
Alex Gilday31dd2ae2016-07-05 16:34:41 +0100113
114
armvixlc68cb642014-09-25 18:49:30 +0100115void CodeBuffer::EmitString(const char* string) {
Pierre Langlois88c46b82016-06-02 18:15:32 +0100116 VIXL_ASSERT(HasSpaceFor(strlen(string) + 1));
armvixlc68cb642014-09-25 18:49:30 +0100117 char* dst = reinterpret_cast<char*>(cursor_);
118 dirty_ = true;
119 char* null_char = stpcpy(dst, string);
120 cursor_ = reinterpret_cast<byte*>(null_char) + 1;
121}
122
123
Pierre Langlois88c46b82016-06-02 18:15:32 +0100124void CodeBuffer::EmitData(const void* data, size_t size) {
125 VIXL_ASSERT(HasSpaceFor(size));
126 dirty_ = true;
127 memcpy(cursor_, data, size);
128 cursor_ = cursor_ + size;
129}
130
131
Vincent Belliard3e1b8992016-07-13 16:02:19 -0700132void CodeBuffer::UpdateData(size_t offset, const void* data, size_t size) {
133 dirty_ = true;
134 byte* dst = buffer_ + offset;
135 VIXL_ASSERT(dst + size <= cursor_);
136 memcpy(dst, data, size);
137}
138
139
armvixlc68cb642014-09-25 18:49:30 +0100140void CodeBuffer::Align() {
141 byte* end = AlignUp(cursor_, 4);
armvixlc68cb642014-09-25 18:49:30 +0100142 const size_t padding_size = end - cursor_;
armvixlc68cb642014-09-25 18:49:30 +0100143 VIXL_ASSERT(padding_size <= 4);
Georgia Kouveli8b57c862017-03-02 15:18:58 +0000144 EmitZeroedBytes(static_cast<int>(padding_size));
armvixlc68cb642014-09-25 18:49:30 +0100145}
146
Georgia Kouveli8b57c862017-03-02 15:18:58 +0000147void CodeBuffer::EmitZeroedBytes(int n) {
148 EnsureSpaceFor(n);
149 dirty_ = true;
150 memset(cursor_, 0, n);
151 cursor_ += n;
152}
armvixlc68cb642014-09-25 18:49:30 +0100153
154void CodeBuffer::Reset() {
armvixl330dc712014-11-25 10:38:32 +0000155#ifdef VIXL_DEBUG
armvixlc68cb642014-09-25 18:49:30 +0100156 if (managed_) {
Pierre Langlois88c46b82016-06-02 18:15:32 +0100157 // Fill with zeros (there is no useful value common to A32 and T32).
armvixlc68cb642014-09-25 18:49:30 +0100158 memset(buffer_, 0, capacity_);
159 }
160#endif
161 cursor_ = buffer_;
162 SetClean();
163}
164
165
166void CodeBuffer::Grow(size_t new_capacity) {
167 VIXL_ASSERT(managed_);
168 VIXL_ASSERT(new_capacity > capacity_);
Pierre Langloisf5348ce2016-09-22 11:15:35 +0100169 ptrdiff_t cursor_offset = GetCursorOffset();
Jacob Bramley1fa6f062016-12-19 11:40:08 +0000170#ifdef VIXL_CODE_BUFFER_MALLOC
Alexandre Rames0287a6c2016-11-16 10:37:05 +0000171 buffer_ = static_cast<byte*>(realloc(buffer_, new_capacity));
172 VIXL_CHECK(buffer_ != NULL);
Jacob Bramley1fa6f062016-12-19 11:40:08 +0000173#elif defined(VIXL_CODE_BUFFER_MMAP)
Alex Gilday31dd2ae2016-07-05 16:34:41 +0100174 buffer_ = static_cast<byte*>(
175 mremap(buffer_, capacity_, new_capacity, MREMAP_MAYMOVE));
176 VIXL_CHECK(buffer_ != MAP_FAILED);
Jacob Bramley1fa6f062016-12-19 11:40:08 +0000177#else
178#error Unknown code buffer allocator.
179#endif
armvixlc68cb642014-09-25 18:49:30 +0100180
Pierre Langloisf5348ce2016-09-22 11:15:35 +0100181 cursor_ = buffer_ + cursor_offset;
armvixlc68cb642014-09-25 18:49:30 +0100182 capacity_ = new_capacity;
183}
184
185
186} // namespace vixl