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
1418namespace dart {
@@ -20,9 +24,15 @@ namespace elf {
2024// / Dart_CreateAppAOTSnapshotAsElf.
2125class 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
379439DART_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+
399461DART_EXPORT void Dart_UnloadELF (Dart_LoadedElf* loaded) {
400462 delete reinterpret_cast <dart::bin::elf::LoadedElf*>(loaded);
401463}
0 commit comments