Skip to content

Commit f769974

Browse files
sstricklCommit Queue
authored andcommitted
[vm] Allow manual loading of Mach-O dynamic library snapshots.
Adds a Mach-O loader, similar to the existing ELF loader, that can be used on platforms that do not support loading Mach-O dynamic libraries via dlopen(). Other changes: * Renames the --force-load-elf-from-memory command line argument to --force-load-from-memory. * Use CPU_TYPE_ANY and CPU_SUBTYPE_ANY for architectures that do not have specific constants in <mach/machine.h> (e.g., RISCV), as the snapshot header check after loading also catches architecture mismatches. * Emit the unwinding information at the end of the text segment for Windows Mach-O snapshots as is done for ELF ones. TEST=vm/dart/unobfuscated_static_symbols_test vm/dart/use_dwarf_stack_traces_flag_test Issue: #60307 Change-Id: I34a2a334f47d18d5c4f4a712956e71fd0ac94024 Cq-Include-Trybots: luci.dart.try:vm-aot-linux-debug-x64-try,vm-mac-release-arm64-try,vm-aot-mac-release-arm64-try,vm-aot-mac-release-x64-try,vm-aot-dwarf-linux-product-x64-try,vm-linux-debug-x64-try,vm-mac-debug-arm64-try,vm-fuchsia-release-x64-try,vm-fuchsia-release-arm64-try,vm-linux-debug-ia32-try,vm-aot-linux-debug-simarm_x64-try,vm-aot-linux-debug-simriscv32-try,vm-aot-linux-debug-simriscv64-try,vm-aot-linux-release-simarm_x64-try,vm-gcc-linux-try,vm-ubsan-linux-release-arm64-try,vm-aot-win-release-arm64-try,vm-aot-win-release-x64-try,vm-win-release-x64-try,vm-win-release-arm64-try,vm-aot-win-debug-arm64-try,vm-win-debug-arm64-try Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/430100 Reviewed-by: Slava Egorov <[email protected]> Reviewed-by: Ryan Macnak <[email protected]>
1 parent b246cad commit f769974

16 files changed

+1143
-274
lines changed

runtime/bin/BUILD.gn

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -162,7 +162,7 @@ static_library("crashpad") {
162162
}
163163
}
164164

165-
template("build_elf_loader") {
165+
template("build_shared_object_loaders") {
166166
source_set(target_name) {
167167
configs += [
168168
"..:dart_arch_config",
@@ -175,6 +175,10 @@ template("build_elf_loader") {
175175
sources = [
176176
"elf_loader.cc",
177177
"elf_loader.h",
178+
"macho_loader.cc",
179+
"macho_loader.h",
180+
"mappable.cc",
181+
"mappable.h",
178182
"virtual_memory.h",
179183
"virtual_memory_fuchsia.cc",
180184
"virtual_memory_posix.cc",
@@ -184,11 +188,11 @@ template("build_elf_loader") {
184188
}
185189
}
186190

187-
build_elf_loader("elf_loader") {
191+
build_shared_object_loaders("shared_object_loaders") {
188192
deps = [ ":libdart_builtin" ]
189193
}
190194

191-
build_elf_loader("elf_loader_product") {
195+
build_shared_object_loaders("shared_object_loaders_product") {
192196
deps = [ ":libdart_builtin_product" ]
193197
}
194198

@@ -928,13 +932,13 @@ dart_executable("dartaotruntime") {
928932

929933
if (dart_runtime_mode == "release") {
930934
extra_deps += [
931-
":elf_loader_product",
932935
":native_assets_api_product",
936+
":shared_object_loaders_product",
933937
]
934938
} else {
935939
extra_deps += [
936-
":elf_loader",
937940
":native_assets_api",
941+
":shared_object_loaders",
938942
]
939943
}
940944

@@ -966,8 +970,8 @@ dart_executable("dartaotruntime_product") {
966970
]
967971

968972
extra_deps += [
969-
":elf_loader_product",
970973
":native_assets_api_product",
974+
":shared_object_loaders_product",
971975
]
972976
}
973977

@@ -999,9 +1003,9 @@ if (build_analyze_snapshot) {
9991003
]
10001004

10011005
if (use_product_mode) {
1002-
extra_deps += [ ":elf_loader_product" ]
1006+
extra_deps += [ ":shared_object_loaders_product" ]
10031007
} else {
1004-
extra_deps += [ ":elf_loader" ]
1008+
extra_deps += [ ":shared_object_loaders" ]
10051009
}
10061010
}
10071011
}

runtime/bin/elf_loader.cc

Lines changed: 8 additions & 145 deletions
Original file line numberDiff line numberDiff line change
@@ -4,165 +4,27 @@
44

55
#include "bin/elf_loader.h"
66

7+
#include <memory>
8+
#include <utility>
9+
710
#include "platform/globals.h"
11+
812
#if defined(DART_HOST_OS_FUCHSIA)
913
#include <sys/mman.h>
1014
#endif
1115

12-
#include <memory>
13-
#include <utility>
16+
#include "platform/elf.h"
17+
#include "platform/unwinding_records.h"
1418

1519
#include "bin/file.h"
20+
#include "bin/mappable.h"
1621
#include "bin/virtual_memory.h"
17-
#include "platform/elf.h"
18-
19-
#include "platform/unwinding_records.h"
2022

2123
namespace dart {
2224
namespace bin {
2325

2426
namespace elf {
2527

26-
class Mappable {
27-
public:
28-
static Mappable* FromPath(const char* path);
29-
#if defined(DART_HOST_OS_FUCHSIA) || defined(DART_HOST_OS_LINUX)
30-
static Mappable* FromFD(int fd);
31-
#endif
32-
static Mappable* FromMemory(const uint8_t* memory, size_t size);
33-
34-
virtual MappedMemory* Map(File::MapType type,
35-
uint64_t position,
36-
uint64_t length,
37-
void* start = nullptr) = 0;
38-
39-
virtual bool SetPosition(uint64_t position) = 0;
40-
virtual bool ReadFully(void* dest, int64_t length) = 0;
41-
42-
virtual ~Mappable() {}
43-
44-
protected:
45-
Mappable() {}
46-
47-
private:
48-
DISALLOW_COPY_AND_ASSIGN(Mappable);
49-
};
50-
51-
class FileMappable : public Mappable {
52-
public:
53-
explicit FileMappable(File* file) : Mappable(), file_(file) {}
54-
55-
~FileMappable() override { file_->Release(); }
56-
57-
MappedMemory* Map(File::MapType type,
58-
uint64_t position,
59-
uint64_t length,
60-
void* start = nullptr) override {
61-
return file_->Map(type, position, length, start);
62-
}
63-
64-
bool SetPosition(uint64_t position) override {
65-
return file_->SetPosition(position);
66-
}
67-
68-
bool ReadFully(void* dest, int64_t length) override {
69-
return file_->ReadFully(dest, length);
70-
}
71-
72-
private:
73-
File* const file_;
74-
DISALLOW_COPY_AND_ASSIGN(FileMappable);
75-
};
76-
77-
class MemoryMappable : public Mappable {
78-
public:
79-
MemoryMappable(const uint8_t* memory, size_t size)
80-
: Mappable(), memory_(memory), size_(size), position_(memory) {}
81-
82-
~MemoryMappable() override {}
83-
84-
MappedMemory* Map(File::MapType type,
85-
uint64_t position,
86-
uint64_t length,
87-
void* start = nullptr) override {
88-
if (position > size_) return nullptr;
89-
MappedMemory* result = nullptr;
90-
const uword map_size = Utils::RoundUp(length, VirtualMemory::PageSize());
91-
if (start == nullptr) {
92-
auto* memory = VirtualMemory::Allocate(
93-
map_size, type == File::kReadExecute, "dart-compiled-image");
94-
if (memory == nullptr) return nullptr;
95-
result = new MappedMemory(memory->address(), memory->size());
96-
memory->release();
97-
delete memory;
98-
} else {
99-
result = new MappedMemory(start, map_size,
100-
/*should_unmap=*/false);
101-
}
102-
103-
size_t remainder = 0;
104-
if ((position + length) > size_) {
105-
remainder = position + length - size_;
106-
length = size_ - position;
107-
}
108-
memcpy(result->address(), memory_ + position, length); // NOLINT
109-
memset(reinterpret_cast<uint8_t*>(result->address()) + length, 0,
110-
remainder);
111-
112-
auto mode = VirtualMemory::kReadOnly;
113-
switch (type) {
114-
case File::kReadExecute:
115-
mode = VirtualMemory::kReadExecute;
116-
break;
117-
case File::kReadWrite:
118-
mode = VirtualMemory::kReadWrite;
119-
break;
120-
case File::kReadOnly:
121-
mode = VirtualMemory::kReadOnly;
122-
break;
123-
default:
124-
UNREACHABLE();
125-
}
126-
127-
VirtualMemory::Protect(result->address(), result->size(), mode);
128-
129-
return result;
130-
}
131-
132-
bool SetPosition(uint64_t position) override {
133-
if (position > size_) return false;
134-
position_ = memory_ + position;
135-
return true;
136-
}
137-
138-
bool ReadFully(void* dest, int64_t length) override {
139-
if ((position_ + length) > (memory_ + size_)) return false;
140-
memcpy(dest, position_, length);
141-
return true;
142-
}
143-
144-
private:
145-
const uint8_t* const memory_;
146-
const size_t size_;
147-
const uint8_t* position_;
148-
DISALLOW_COPY_AND_ASSIGN(MemoryMappable);
149-
};
150-
151-
Mappable* Mappable::FromPath(const char* path) {
152-
return new FileMappable(File::Open(/*namespc=*/nullptr, path, File::kRead,
153-
/*executable=*/true));
154-
}
155-
156-
#if defined(DART_HOST_OS_FUCHSIA) || defined(DART_HOST_OS_LINUX)
157-
Mappable* Mappable::FromFD(int fd) {
158-
return new FileMappable(File::OpenFD(fd));
159-
}
160-
#endif
161-
162-
Mappable* Mappable::FromMemory(const uint8_t* memory, size_t size) {
163-
return new MemoryMappable(memory, size);
164-
}
165-
16628
/// A loader for a subset of ELF which may be used to load objects produced by
16729
/// Dart_CreateAppAOTSnapshotAsElf.
16830
class LoadedElf {
@@ -560,6 +422,7 @@ MappedMemory* LoadedElf::MapFilePiece(uword file_start,
560422
} // namespace dart
561423

562424
using namespace dart::bin::elf; // NOLINT
425+
using Mappable = dart::bin::Mappable;
563426

564427
#if defined(DART_HOST_OS_FUCHSIA) || defined(DART_HOST_OS_LINUX)
565428
DART_EXPORT Dart_LoadedElf* Dart_LoadELF_Fd(int fd,

0 commit comments

Comments
 (0)