1b8021494Sopenharmony_ci// Copyright 2017, VIXL authors 2b8021494Sopenharmony_ci// All rights reserved. 3b8021494Sopenharmony_ci// 4b8021494Sopenharmony_ci// Redistribution and use in source and binary forms, with or without 5b8021494Sopenharmony_ci// modification, are permitted provided that the following conditions are met: 6b8021494Sopenharmony_ci// 7b8021494Sopenharmony_ci// * Redistributions of source code must retain the above copyright notice, 8b8021494Sopenharmony_ci// this list of conditions and the following disclaimer. 9b8021494Sopenharmony_ci// * Redistributions in binary form must reproduce the above copyright notice, 10b8021494Sopenharmony_ci// this list of conditions and the following disclaimer in the documentation 11b8021494Sopenharmony_ci// and/or other materials provided with the distribution. 12b8021494Sopenharmony_ci// * Neither the name of ARM Limited nor the names of its contributors may be 13b8021494Sopenharmony_ci// used to endorse or promote products derived from this software without 14b8021494Sopenharmony_ci// specific prior written permission. 15b8021494Sopenharmony_ci// 16b8021494Sopenharmony_ci// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS CONTRIBUTORS "AS IS" AND 17b8021494Sopenharmony_ci// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18b8021494Sopenharmony_ci// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19b8021494Sopenharmony_ci// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE 20b8021494Sopenharmony_ci// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21b8021494Sopenharmony_ci// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 22b8021494Sopenharmony_ci// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 23b8021494Sopenharmony_ci// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 24b8021494Sopenharmony_ci// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 25b8021494Sopenharmony_ci// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26b8021494Sopenharmony_ci 27b8021494Sopenharmony_ci#include "code-buffer-vixl.h" 28b8021494Sopenharmony_ci#include "utils-vixl.h" 29b8021494Sopenharmony_ci 30b8021494Sopenharmony_cinamespace vixl { 31b8021494Sopenharmony_ci 32b8021494Sopenharmony_ciCodeBuffer::CodeBuffer(size_t capacity) 33b8021494Sopenharmony_ci : buffer_(NULL), 34b8021494Sopenharmony_ci managed_(true), 35b8021494Sopenharmony_ci cursor_(NULL), 36b8021494Sopenharmony_ci dirty_(false), 37b8021494Sopenharmony_ci capacity_(capacity) { 38b8021494Sopenharmony_ci if (capacity_ == 0) { 39b8021494Sopenharmony_ci return; 40b8021494Sopenharmony_ci } 41b8021494Sopenharmony_ci#ifdef VIXL_CODE_BUFFER_MALLOC 42b8021494Sopenharmony_ci buffer_ = reinterpret_cast<byte*>(malloc(capacity_)); 43b8021494Sopenharmony_ci#elif defined(VIXL_CODE_BUFFER_MMAP) 44b8021494Sopenharmony_ci buffer_ = reinterpret_cast<byte*>(mmap(NULL, 45b8021494Sopenharmony_ci capacity, 46b8021494Sopenharmony_ci PROT_READ | PROT_WRITE, 47b8021494Sopenharmony_ci MAP_PRIVATE | MAP_ANONYMOUS, 48b8021494Sopenharmony_ci -1, 49b8021494Sopenharmony_ci 0)); 50b8021494Sopenharmony_ci#else 51b8021494Sopenharmony_ci#error Unknown code buffer allocator. 52b8021494Sopenharmony_ci#endif 53b8021494Sopenharmony_ci VIXL_CHECK(buffer_ != NULL); 54b8021494Sopenharmony_ci // Aarch64 instructions must be word aligned, we assert the default allocator 55b8021494Sopenharmony_ci // always returns word align memory. 56b8021494Sopenharmony_ci if (buffer_ != MAP_FAILED) { 57b8021494Sopenharmony_ci VIXL_ASSERT(IsWordAligned(buffer_)); 58b8021494Sopenharmony_ci cursor_ = buffer_; 59b8021494Sopenharmony_ci } 60b8021494Sopenharmony_ci} 61b8021494Sopenharmony_ci 62b8021494Sopenharmony_ci 63b8021494Sopenharmony_ciCodeBuffer::CodeBuffer(byte* buffer, size_t capacity) 64b8021494Sopenharmony_ci : buffer_(reinterpret_cast<byte*>(buffer)), 65b8021494Sopenharmony_ci managed_(false), 66b8021494Sopenharmony_ci cursor_(reinterpret_cast<byte*>(buffer)), 67b8021494Sopenharmony_ci dirty_(false), 68b8021494Sopenharmony_ci capacity_(capacity) { 69b8021494Sopenharmony_ci VIXL_ASSERT(buffer_ != NULL); 70b8021494Sopenharmony_ci} 71b8021494Sopenharmony_ci 72b8021494Sopenharmony_ci 73b8021494Sopenharmony_ciCodeBuffer::~CodeBuffer() VIXL_NEGATIVE_TESTING_ALLOW_EXCEPTION { 74b8021494Sopenharmony_ci // VIXL_ASSERT(!IsDirty()); // Use own allocator - not applied 75b8021494Sopenharmony_ci if (managed_) { 76b8021494Sopenharmony_ci#ifdef VIXL_CODE_BUFFER_MALLOC 77b8021494Sopenharmony_ci free(buffer_); 78b8021494Sopenharmony_ci#elif defined(VIXL_CODE_BUFFER_MMAP) 79b8021494Sopenharmony_ci if (buffer_ != MAP_FAILED) { 80b8021494Sopenharmony_ci [[maybe_unused]] int res = munmap(buffer_, capacity_); 81b8021494Sopenharmony_ci // Success unmap position 82b8021494Sopenharmony_ci VIXL_ASSERT(res == 0); 83b8021494Sopenharmony_ci if ((mmap_max_ != 0) && (capacity_ > mmap_max_)) { 84b8021494Sopenharmony_ci // Force crash - allocated too much 85b8021494Sopenharmony_ci printf(" Allocated too much memory.\n"); 86b8021494Sopenharmony_ci VIXL_UNREACHABLE(); 87b8021494Sopenharmony_ci } 88b8021494Sopenharmony_ci } 89b8021494Sopenharmony_ci#else 90b8021494Sopenharmony_ci#error Unknown code buffer allocator. 91b8021494Sopenharmony_ci#endif 92b8021494Sopenharmony_ci } 93b8021494Sopenharmony_ci} 94b8021494Sopenharmony_ci 95b8021494Sopenharmony_ci 96b8021494Sopenharmony_civoid CodeBuffer::SetExecutable() { 97b8021494Sopenharmony_ci#ifdef VIXL_CODE_BUFFER_MMAP 98b8021494Sopenharmony_ci int ret = mprotect(buffer_, capacity_, PROT_READ | PROT_EXEC); 99b8021494Sopenharmony_ci VIXL_CHECK(ret == 0); 100b8021494Sopenharmony_ci#else 101b8021494Sopenharmony_ci // This requires page-aligned memory blocks, which we can only guarantee with 102b8021494Sopenharmony_ci // mmap. 103b8021494Sopenharmony_ci VIXL_UNIMPLEMENTED(); 104b8021494Sopenharmony_ci#endif 105b8021494Sopenharmony_ci} 106b8021494Sopenharmony_ci 107b8021494Sopenharmony_ci 108b8021494Sopenharmony_civoid CodeBuffer::SetWritable() { 109b8021494Sopenharmony_ci#ifdef VIXL_CODE_BUFFER_MMAP 110b8021494Sopenharmony_ci int ret = mprotect(buffer_, capacity_, PROT_READ | PROT_WRITE); 111b8021494Sopenharmony_ci VIXL_CHECK(ret == 0); 112b8021494Sopenharmony_ci#else 113b8021494Sopenharmony_ci // This requires page-aligned memory blocks, which we can only guarantee with 114b8021494Sopenharmony_ci // mmap. 115b8021494Sopenharmony_ci VIXL_UNIMPLEMENTED(); 116b8021494Sopenharmony_ci#endif 117b8021494Sopenharmony_ci} 118b8021494Sopenharmony_ci 119b8021494Sopenharmony_ci// For some reason OHOS toolchain doesn't have this function 120b8021494Sopenharmony_ci#ifdef PANDA_TARGET_MOBILE 121b8021494Sopenharmony_cichar* stpcpy (char *dst, const char *src) { 122b8021494Sopenharmony_ci const size_t len = strlen (src); 123b8021494Sopenharmony_ci return (char *) memcpy (dst, src, len + 1) + len; 124b8021494Sopenharmony_ci} 125b8021494Sopenharmony_ci#endif 126b8021494Sopenharmony_ci 127b8021494Sopenharmony_civoid CodeBuffer::EmitString(const char* string) { 128b8021494Sopenharmony_ci const auto len = strlen(string) + 1; 129b8021494Sopenharmony_ci VIXL_ASSERT(HasSpaceFor(len)); 130b8021494Sopenharmony_ci char* dst = reinterpret_cast<char*>(cursor_); 131b8021494Sopenharmony_ci dirty_ = true; 132b8021494Sopenharmony_ci memcpy(dst, string, len); 133b8021494Sopenharmony_ci cursor_ = reinterpret_cast<byte*>(dst + len); 134b8021494Sopenharmony_ci} 135b8021494Sopenharmony_ci 136b8021494Sopenharmony_ci 137b8021494Sopenharmony_civoid CodeBuffer::EmitData(const void* data, size_t size) { 138b8021494Sopenharmony_ci VIXL_ASSERT(HasSpaceFor(size)); 139b8021494Sopenharmony_ci dirty_ = true; 140b8021494Sopenharmony_ci memcpy(cursor_, data, size); 141b8021494Sopenharmony_ci cursor_ = cursor_ + size; 142b8021494Sopenharmony_ci} 143b8021494Sopenharmony_ci 144b8021494Sopenharmony_ci 145b8021494Sopenharmony_civoid CodeBuffer::UpdateData(size_t offset, const void* data, size_t size) { 146b8021494Sopenharmony_ci dirty_ = true; 147b8021494Sopenharmony_ci byte* dst = buffer_ + offset; 148b8021494Sopenharmony_ci VIXL_ASSERT(dst + size <= cursor_); 149b8021494Sopenharmony_ci memcpy(dst, data, size); 150b8021494Sopenharmony_ci} 151b8021494Sopenharmony_ci 152b8021494Sopenharmony_ci 153b8021494Sopenharmony_civoid CodeBuffer::Align() { 154b8021494Sopenharmony_ci byte* end = AlignUp(cursor_, 4); 155b8021494Sopenharmony_ci const size_t padding_size = end - cursor_; 156b8021494Sopenharmony_ci VIXL_ASSERT(padding_size <= 4); 157b8021494Sopenharmony_ci EmitZeroedBytes(static_cast<int>(padding_size)); 158b8021494Sopenharmony_ci} 159b8021494Sopenharmony_ci 160b8021494Sopenharmony_civoid CodeBuffer::EmitZeroedBytes(int n) { 161b8021494Sopenharmony_ci EnsureSpaceFor(n); 162b8021494Sopenharmony_ci dirty_ = true; 163b8021494Sopenharmony_ci memset(cursor_, 0, n); 164b8021494Sopenharmony_ci cursor_ += n; 165b8021494Sopenharmony_ci} 166b8021494Sopenharmony_ci 167b8021494Sopenharmony_civoid CodeBuffer::Reset() { 168b8021494Sopenharmony_ci#ifdef VIXL_DEBUG 169b8021494Sopenharmony_ci if (managed_) { 170b8021494Sopenharmony_ci // Fill with zeros (there is no useful value common to A32 and T32). 171b8021494Sopenharmony_ci memset(buffer_, 0, capacity_); 172b8021494Sopenharmony_ci } 173b8021494Sopenharmony_ci#endif 174b8021494Sopenharmony_ci cursor_ = buffer_; 175b8021494Sopenharmony_ci SetClean(); 176b8021494Sopenharmony_ci} 177b8021494Sopenharmony_ci 178b8021494Sopenharmony_ci 179b8021494Sopenharmony_civoid CodeBuffer::Grow(size_t new_capacity) { 180b8021494Sopenharmony_ci VIXL_ASSERT(managed_); 181b8021494Sopenharmony_ci VIXL_ASSERT(new_capacity > capacity_); 182b8021494Sopenharmony_ci ptrdiff_t cursor_offset = GetCursorOffset(); 183b8021494Sopenharmony_ci VIXL_ASSERT(false); 184b8021494Sopenharmony_ci // Do not support grow with our allocators 185b8021494Sopenharmony_ci#ifdef VIXL_CODE_BUFFER_MALLOC 186b8021494Sopenharmony_ci buffer_ = static_cast<byte*>(realloc(buffer_, new_capacity)); 187b8021494Sopenharmony_ci VIXL_CHECK(buffer_ != NULL); 188b8021494Sopenharmony_ci#elif defined(VIXL_CODE_BUFFER_MMAP) 189b8021494Sopenharmony_ci buffer_ = static_cast<byte*>( 190b8021494Sopenharmony_ci mremap(buffer_, capacity_, new_capacity, MREMAP_MAYMOVE)); 191b8021494Sopenharmony_ci VIXL_CHECK(buffer_ != MAP_FAILED); 192b8021494Sopenharmony_ci if ((mmap_max_ != 0) && (new_capacity > mmap_max_)) { 193b8021494Sopenharmony_ci // Force crash - allocated too much 194b8021494Sopenharmony_ci printf(" Allocated too much memory.\n"); 195b8021494Sopenharmony_ci VIXL_UNREACHABLE(); 196b8021494Sopenharmony_ci } 197b8021494Sopenharmony_ci#else 198b8021494Sopenharmony_ci#error Unknown code buffer allocator. 199b8021494Sopenharmony_ci#endif 200b8021494Sopenharmony_ci cursor_ = buffer_ + cursor_offset; 201b8021494Sopenharmony_ci capacity_ = new_capacity; 202b8021494Sopenharmony_ci} 203b8021494Sopenharmony_ci 204b8021494Sopenharmony_ci 205b8021494Sopenharmony_ci} // namespace vixl 206