Skip to content

Commit 168cf90

Browse files
sjindel-googlecommit-bot@chromium.org
authored andcommitted
[vm] Make ELF loader Fuchsia compatible.
Change-Id: I519fb04c6bf1fbef53a833957c714f3a1e394f21 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/127641 Commit-Queue: Samir Jindel <sjindel@google.com> Reviewed-by: Martin Kustermann <kustermann@google.com>
1 parent db525fe commit 168cf90

File tree

5 files changed

+111
-17
lines changed

5 files changed

+111
-17
lines changed

runtime/bin/BUILD.gn

Lines changed: 24 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -124,23 +124,35 @@ static_library("crashpad") {
124124
}
125125
}
126126

127-
static_library("elf_loader") {
128-
configs += [
129-
"..:dart_arch_config",
130-
"..:dart_config",
131-
"..:dart_product_config",
132-
"..:dart_os_fuchsia_config",
133-
]
134-
include_dirs = [ ".." ]
135-
sources = [
136-
"elf_loader.cc",
137-
"elf_loader.h",
138-
]
127+
template("build_elf_loader") {
128+
source_set(target_name) {
129+
configs += [
130+
"..:dart_arch_config",
131+
"..:dart_config",
132+
"..:dart_product_config",
133+
"..:dart_os_fuchsia_config",
134+
]
135+
include_dirs = [ ".." ]
136+
sources = [
137+
"elf_loader.cc",
138+
"elf_loader.h",
139+
]
140+
deps = invoker.deps
141+
}
142+
}
143+
144+
build_elf_loader("elf_loader") {
139145
deps = [
140146
":libdart_builtin",
141147
]
142148
}
143149

150+
build_elf_loader("elf_loader_product") {
151+
deps = [
152+
":libdart_builtin_product",
153+
]
154+
}
155+
144156
template("build_gen_snapshot") {
145157
extra_configs = []
146158
if (defined(invoker.extra_configs)) {

runtime/bin/elf_loader.cc

Lines changed: 63 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,10 @@
99
#include <vm/cpu.h>
1010
#include <vm/virtual_memory.h>
1111

12+
#if defined(HOST_OS_FUCHSIA)
13+
#include <sys/mman.h>
14+
#endif
15+
1216
#include <memory>
1317

1418
namespace dart {
@@ -20,9 +24,15 @@ namespace elf {
2024
/// Dart_CreateAppAOTSnapshotAsElf.
2125
class LoadedElf {
2226
public:
27+
#if defined(HOST_OS_FUCHSIA)
28+
explicit LoadedElf(int fd, uint64_t elf_data_offset)
29+
: fd_(fd), elf_data_offset_(elf_data_offset) {}
30+
#else
2331
explicit LoadedElf(const char* filename, uint64_t elf_data_offset)
2432
: filename_(strdup(filename), std::free),
2533
elf_data_offset_(elf_data_offset) {}
34+
#endif
35+
2636
~LoadedElf();
2737

2838
/// Loads the ELF object into memory. Returns whether the load was successful.
@@ -61,7 +71,11 @@ class LoadedElf {
6171
uword length,
6272
const void** mapping_start);
6373

74+
#if defined(HOST_OS_FUCHSIA)
75+
int fd_ = -1;
76+
#else
6477
std::unique_ptr<char, decltype(std::free)*> filename_;
78+
#endif
6579
const uint64_t elf_data_offset_;
6680

6781
// Initialized on a successful Load().
@@ -124,8 +138,12 @@ bool LoadedElf::Load() {
124138
CHECK_ERROR(Utils::IsAligned(elf_data_offset_, PageSize()),
125139
"File offset must be page-aligned.");
126140

141+
#if defined(HOST_OS_FUCHSIA)
142+
file_ = File::OpenFD(fd_);
143+
#else
127144
file_ = File::Open(/*namespc=*/nullptr, filename_.get(),
128145
bin::File::FileOpenMode::kRead);
146+
#endif
129147
CHECK_ERROR(file_ != nullptr, "Cannot open ELF object file.");
130148
CHECK_ERROR(file_->SetPosition(elf_data_offset_), "Invalid file offset.");
131149

@@ -249,7 +267,7 @@ bool LoadedElf::LoadSegments() {
249267

250268
base_.reset(VirtualMemory::AllocateAligned(
251269
total_memory, /*alignment=*/maximum_alignment,
252-
/*is_executable=*/false, /*mapping name=*/filename_.get()));
270+
/*is_executable=*/false, /*mapping name=*/nullptr));
253271
CHECK_ERROR(base_ != nullptr, "Could not reserve virtual memory.");
254272

255273
for (uword i = 0; i < header_.num_program_headers; ++i) {
@@ -282,6 +300,27 @@ bool LoadedElf::LoadSegments() {
282300
ERROR("Unsupported segment flag set.");
283301
}
284302

303+
#if defined(HOST_OS_FUCHSIA)
304+
// mmap is less flexible on Fuchsia than on Linux and Darwin, in (at least)
305+
// two important ways:
306+
//
307+
// 1. We cannot map a file opened as RX into an RW mapping, even if the
308+
// mode is MAP_PRIVATE (which implies copy-on-write).
309+
// 2. We cannot atomically replace an existing anonymous mapping with a
310+
// file mapping: we must first unmap the existing mapping.
311+
312+
if (map_type == File::kReadWrite) {
313+
CHECK_ERROR(file_->SetPosition(file_start),
314+
"Could not advance file position.");
315+
CHECK_ERROR(file_->ReadFully(memory_start, length),
316+
"Could not read file.");
317+
continue;
318+
}
319+
320+
CHECK_ERROR(munmap(memory_start, length) == 0,
321+
"Could not unmap reservation.");
322+
#endif
323+
285324
std::unique_ptr<MappedMemory> memory(
286325
file_->Map(map_type, file_start, length, memory_start));
287326
CHECK_ERROR(memory != nullptr, "Could not map segment.");
@@ -376,6 +415,27 @@ MappedMemory* LoadedElf::MapFilePiece(uword file_start,
376415
} // namespace bin
377416
} // namespace dart
378417

418+
#if defined(HOST_OS_FUCHSIA)
419+
DART_EXPORT Dart_LoadedElf* Dart_LoadELF_Fd(int fd,
420+
uint64_t file_offset,
421+
const char** error,
422+
const uint8_t** vm_snapshot_data,
423+
const uint8_t** vm_snapshot_instrs,
424+
const uint8_t** vm_isolate_data,
425+
const uint8_t** vm_isolate_instrs) {
426+
std::unique_ptr<dart::bin::elf::LoadedElf> elf(
427+
new dart::bin::elf::LoadedElf(fd, file_offset));
428+
429+
if (!elf->Load() ||
430+
!elf->ResolveSymbols(vm_snapshot_data, vm_snapshot_instrs,
431+
vm_isolate_data, vm_isolate_instrs)) {
432+
*error = elf->error();
433+
return nullptr;
434+
}
435+
436+
return reinterpret_cast<Dart_LoadedElf*>(elf.release());
437+
}
438+
#else
379439
DART_EXPORT Dart_LoadedElf* Dart_LoadELF(const char* filename,
380440
uint64_t file_offset,
381441
const char** error,
@@ -396,6 +456,8 @@ DART_EXPORT Dart_LoadedElf* Dart_LoadELF(const char* filename,
396456
return reinterpret_cast<Dart_LoadedElf*>(elf.release());
397457
}
398458

459+
#endif
460+
399461
DART_EXPORT void Dart_UnloadELF(Dart_LoadedElf* loaded) {
400462
delete reinterpret_cast<dart::bin::elf::LoadedElf*>(loaded);
401463
}

runtime/bin/elf_loader.h

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,25 +10,37 @@
1010
typedef struct {
1111
} Dart_LoadedElf;
1212

13-
/// Loads an ELF object in 'filename'.
13+
/// Load an ELF object from a file.
1414
///
15-
/// On success, returns a handle to the library which may be used to close it
15+
/// On success, return a handle to the library which may be used to close it
1616
/// in Dart_UnloadELF. On error, returns 'nullptr' and sets 'error'. The error
1717
/// string should not be 'free'-d.
1818
///
1919
/// `file_offset` may be non-zero to read an ELF object embedded inside another
2020
/// type of file.
2121
///
22-
/// Looks up the Dart snapshot symbols "_kVmSnapshotData",
22+
/// Look up the Dart snapshot symbols "_kVmSnapshotData",
2323
/// "_kVmSnapshotInstructions", "_kVmIsolateData" and "_kVmIsolateInstructions"
2424
/// into the respectively named out-parameters.
25+
///
26+
/// On Fuchsia, Dart_LoadELF_Fd takes ownership of the file descriptor.
27+
#if defined(__Fuchsia__)
28+
DART_EXPORT Dart_LoadedElf* Dart_LoadELF_Fd(int fd,
29+
uint64_t file_offset,
30+
const char** error,
31+
const uint8_t** vm_snapshot_data,
32+
const uint8_t** vm_snapshot_instrs,
33+
const uint8_t** vm_isolate_data,
34+
const uint8_t** vm_isolate_instrs);
35+
#else
2536
DART_EXPORT Dart_LoadedElf* Dart_LoadELF(const char* filename,
2637
uint64_t file_offset,
2738
const char** error,
2839
const uint8_t** vm_snapshot_data,
2940
const uint8_t** vm_snapshot_instrs,
3041
const uint8_t** vm_isolate_data,
3142
const uint8_t** vm_isolate_instrs);
43+
#endif
3244

3345
DART_EXPORT void Dart_UnloadELF(Dart_LoadedElf* loaded);
3446

runtime/bin/file.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -213,6 +213,10 @@ class File : public ReferenceCounted<File> {
213213
// (stdin, stout or stderr).
214214
static File* OpenStdio(int fd);
215215

216+
#if defined(HOST_OS_FUCHSIA)
217+
static File* OpenFD(int fd);
218+
#endif
219+
216220
static bool Exists(Namespace* namespc, const char* path);
217221
static bool Create(Namespace* namespc, const char* path);
218222
static bool CreateLink(Namespace* namespc,

runtime/bin/file_fuchsia.cc

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -202,6 +202,10 @@ File* File::FileOpenW(const wchar_t* system_name, FileOpenMode mode) {
202202
return NULL;
203203
}
204204

205+
File* File::OpenFD(int fd) {
206+
return new File(new FileHandle(fd));
207+
}
208+
205209
File* File::Open(Namespace* namespc, const char* name, FileOpenMode mode) {
206210
NamespaceScope ns(namespc, name);
207211
// Report errors for non-regular files.
@@ -236,7 +240,7 @@ File* File::Open(Namespace* namespc, const char* name, FileOpenMode mode) {
236240
return NULL;
237241
}
238242
}
239-
return new File(new FileHandle(fd));
243+
return OpenFD(fd);
240244
}
241245

242246
File* File::OpenUri(Namespace* namespc, const char* uri, FileOpenMode mode) {

0 commit comments

Comments
 (0)