1// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
2// for details. All rights reserved. Use of this source code is governed by a
3// BSD-style license that can be found in the LICENSE file.
4
5#include "vm/virtual_memory.h"
6
7#include "platform/assert.h"
8#include "platform/utils.h"
9
10#if defined(DART_HOST_OS_MACOS)
11#include <mach/mach.h>
12#endif
13
14namespace dart {
15
16bool VirtualMemory::InSamePage(uword address0, uword address1) {
17 return (Utils::RoundDown(x: address0, alignment: PageSize()) ==
18 Utils::RoundDown(x: address1, alignment: PageSize()));
19}
20
21void VirtualMemory::Truncate(intptr_t new_size) {
22 ASSERT(Utils::IsAligned(new_size, PageSize()));
23 ASSERT(new_size <= size());
24 if (reserved_.size() ==
25 region_.size()) { // Don't create holes in reservation.
26 if (FreeSubSegment(address: reinterpret_cast<void*>(start() + new_size),
27 size: size() - new_size)) {
28 reserved_.set_size(new_size);
29 if (AliasOffset() != 0) {
30 FreeSubSegment(address: reinterpret_cast<void*>(alias_.start() + new_size),
31 size: alias_.size() - new_size);
32 }
33 }
34 }
35 region_.Subregion(from: region_, offset: 0, size: new_size);
36 alias_.Subregion(from: alias_, offset: 0, size: new_size);
37}
38
39VirtualMemory* VirtualMemory::ForImagePage(void* pointer, uword size) {
40 // Memory for precompilated instructions was allocated by the embedder, so
41 // create a VirtualMemory without allocating.
42 MemoryRegion region(pointer, size);
43 MemoryRegion reserved(nullptr, 0); // null reservation indicates VM should
44 // not attempt to free this memory.
45 VirtualMemory* memory = new VirtualMemory(region, region, reserved);
46 ASSERT(!memory->vm_owns_region());
47 return memory;
48}
49
50#if !defined(DART_TARGET_OS_FUCHSIA)
51// TODO(52579): Reenable on Fuchsia.
52
53bool VirtualMemory::DuplicateRX(VirtualMemory* target) {
54 const intptr_t aligned_size = Utils::RoundUp(x: size(), alignment: PageSize());
55 ASSERT_LESS_OR_EQUAL(aligned_size, target->size());
56
57#if defined(DART_HOST_OS_MACOS)
58 // Mac is special cased because iOS doesn't allow allocating new executable
59 // memory, so the default approach would fail. We are allowed to make new
60 // mappings of existing executable memory using vm_remap though, which is
61 // effectively the same for non-writable memory.
62 const mach_port_t task = mach_task_self();
63 const vm_address_t source_address = reinterpret_cast<vm_address_t>(address());
64 const vm_size_t mem_size = aligned_size;
65 const vm_prot_t read_execute = VM_PROT_READ | VM_PROT_EXECUTE;
66 vm_prot_t current_protection = read_execute;
67 vm_prot_t max_protection = read_execute;
68 vm_address_t target_address =
69 reinterpret_cast<vm_address_t>(target->address());
70 kern_return_t status = vm_remap(
71 task, &target_address, mem_size,
72 /*mask=*/0,
73 /*flags=*/VM_FLAGS_FIXED | VM_FLAGS_OVERWRITE, task, source_address,
74 /*copy=*/true, &current_protection, &max_protection,
75 /*inheritance=*/VM_INHERIT_NONE);
76 if (status != KERN_SUCCESS) {
77 return false;
78 }
79 ASSERT(reinterpret_cast<void*>(target_address) == target->address());
80 ASSERT_EQUAL(current_protection & read_execute, read_execute);
81 ASSERT_EQUAL(max_protection & read_execute, read_execute);
82 return true;
83
84#else // defined(DART_HOST_OS_MACOS)
85 // TODO(52497): Use dual mapping on platforms where it's supported.
86 // Check that target doesn't overlap with this.
87 ASSERT(target->start() >= end() || target->end() <= start());
88 memcpy(target->address(), address(), size()); // NOLINT
89 Protect(address: target->address(), size: aligned_size, mode: kReadExecute);
90 return true;
91#endif // defined(DART_HOST_OS_MACOS)
92}
93
94#endif // !defined(DART_TARGET_OS_FUCHSIA)
95
96} // namespace dart
97

source code of dart_sdk/runtime/vm/virtual_memory.cc