// Copyright (c) 2021, the Dart project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. #include "platform/globals.h" #if defined(DART_HOST_OS_FUCHSIA) #include "bin/virtual_memory.h" #include #include #include #include "platform/assert.h" #include "platform/utils.h" namespace dart { namespace bin { uword VirtualMemory::page_size_ = 0; intptr_t VirtualMemory::CalculatePageSize() { const intptr_t page_size = getpagesize(); ASSERT(page_size != 0); ASSERT(Utils::IsPowerOfTwo(page_size)); return page_size; } VirtualMemory* VirtualMemory::Allocate(intptr_t size, bool is_executable, const char* name) { ASSERT(Utils::IsAligned(size, page_size_)); zx_handle_t vmar = zx_vmar_root_self(); zx_handle_t vmo = ZX_HANDLE_INVALID; zx_status_t status = zx_vmo_create(size, 0u, &vmo); if (status != ZX_OK) { return nullptr; } if (name != nullptr) { zx_object_set_property(vmo, ZX_PROP_NAME, name, strlen(name)); } if (is_executable) { // Add ZX_RIGHT_EXECUTE permission to VMO, so it can be mapped // into memory as executable (now or later). status = zx_vmo_replace_as_executable(vmo, ZX_HANDLE_INVALID, &vmo); if (status != ZX_OK) { zx_handle_close(vmo); return nullptr; } } const zx_vm_option_t region_options = ZX_VM_PERM_READ | ZX_VM_PERM_WRITE | (is_executable ? ZX_VM_PERM_EXECUTE : 0); uword base; status = zx_vmar_map(vmar, region_options, 0, vmo, 0u, size, &base); zx_handle_close(vmo); if (status != ZX_OK) { return nullptr; } return new VirtualMemory(reinterpret_cast(base), size); } VirtualMemory::~VirtualMemory() { if (address_ != nullptr) { zx_status_t status = zx_vmar_unmap( zx_vmar_root_self(), reinterpret_cast(address_), size_); if (status != ZX_OK) { FATAL("zx_vmar_unmap failed: %s\n", zx_status_get_string(status)); } } } void VirtualMemory::Protect(void* address, intptr_t size, Protection mode) { const uword start_address = reinterpret_cast(address); const uword end_address = start_address + size; const uword page_address = Utils::RoundDown(start_address, PageSize()); uint32_t prot = 0; switch (mode) { case kNoAccess: prot = 0; break; case kReadOnly: prot = ZX_VM_PERM_READ; break; case kReadWrite: prot = ZX_VM_PERM_READ | ZX_VM_PERM_WRITE; break; case kReadExecute: prot = ZX_VM_PERM_READ | ZX_VM_PERM_EXECUTE; break; case kReadWriteExecute: prot = ZX_VM_PERM_READ | ZX_VM_PERM_WRITE | ZX_VM_PERM_EXECUTE; break; } zx_status_t status = zx_vmar_protect(zx_vmar_root_self(), prot, page_address, end_address - page_address); if (status != ZX_OK) { FATAL("zx_vmar_protect(0x%lx, 0x%lx) failed: %s\n", page_address, end_address - page_address, zx_status_get_string(status)); } } } // namespace bin } // namespace dart #endif // defined(DART_HOST_OS_FUCHSIA)