8#if defined(DART_HOST_OS_FUCHSIA)
29#if defined(DART_HOST_OS_FUCHSIA) || defined(DART_HOST_OS_LINUX)
37 void*
start =
nullptr) = 0;
60 void*
start =
nullptr)
override {
80 :
Mappable(), memory_(memory), size_(size), position_(memory) {}
87 void*
start =
nullptr)
override {
88 if (position > size_)
return nullptr;
91 if (
start ==
nullptr) {
94 if (memory ==
nullptr)
return nullptr;
103 size_t remainder = 0;
104 if ((position +
length) > size_) {
105 remainder = position +
length - size_;
106 length = size_ - position;
109 memset(
reinterpret_cast<uint8_t*
>(
result->address()) +
length, 0,
133 if (position > size_)
return false;
134 position_ = memory_ + position;
139 if ((position_ +
length) > (memory_ + size_))
return false;
140 memcpy(dest, position_,
length);
145 const uint8_t*
const memory_;
147 const uint8_t* position_;
155#if defined(DART_HOST_OS_FUCHSIA) || defined(DART_HOST_OS_LINUX)
170 uint64_t elf_data_offset)
171 : mappable_(
std::move(mappable)), elf_data_offset_(elf_data_offset) {}
193 const uint8_t** vm_instrs,
194 const uint8_t** isolate_data,
195 const uint8_t** isolate_instrs);
197 const char*
error() {
return error_; }
201 bool ReadProgramTable();
203 bool ReadSectionTable();
204 bool ReadSectionStringTable();
212 const void** mapping_start);
215 std::unique_ptr<Mappable> mappable_;
216 const uint64_t elf_data_offset_;
219 const char* error_ =
nullptr;
225 std::unique_ptr<MappedMemory> program_table_mapping_;
229 std::unique_ptr<VirtualMemory> base_;
232 std::unique_ptr<MappedMemory> section_table_mapping_;
236 std::unique_ptr<MappedMemory> section_string_table_mapping_;
237 const char* section_string_table_ =
nullptr;
240 const char* dynamic_string_table_ =
nullptr;
242 uword dynamic_symbol_count_ = 0;
244#if defined(DART_HOST_OS_WINDOWS) && \
245 (defined(HOST_ARCH_X64) || defined(HOST_ARCH_ARM64))
254#define CHECK(value) \
256 ASSERT(error_ != nullptr); \
260#define ERROR(message) \
262 error_ = (message); \
266#define CHECK_ERROR(value, message) \
268 error_ = (message); \
275 if (error_ !=
nullptr) {
280 "File offset must be page-aligned.");
282 ASSERT(mappable_ !=
nullptr);
283 CHECK_ERROR(mappable_->SetPosition(elf_data_offset_),
"Invalid file offset.");
286 CHECK(ReadProgramTable());
287 CHECK(LoadSegments());
288 CHECK(ReadSectionTable());
289 CHECK(ReadSectionStringTable());
290 CHECK(ReadSections());
298#if defined(DART_HOST_OS_WINDOWS) && \
299 (defined(HOST_ARCH_X64) || defined(HOST_ARCH_ARM64))
300 for (intptr_t i = 0; i < dynamic_runtime_function_tables_.length(); i++) {
302 dynamic_runtime_function_tables_[i]);
310 program_table_mapping_.reset();
311 section_table_mapping_.reset();
312 section_string_table_mapping_.reset();
315bool LoadedElf::ReadHeader() {
317 "Could not read ELF file.");
320 "Expected little-endian ELF object.");
323 "Can only load dynamic libraries.");
325#if defined(TARGET_ARCH_IA32)
327#elif defined(TARGET_ARCH_X64)
329 "Architecture mismatch.");
330#elif defined(TARGET_ARCH_ARM)
332#elif defined(TARGET_ARCH_ARM64)
334 "Architecture mismatch.");
335#elif defined(TARGET_ARCH_RISCV32) || defined(TARGET_ARCH_RISCV64)
338#error Unsupported architecture architecture.
342 "Unexpected ELF version.");
344 "Unexpected header size.");
347 "Unexpected program header size.");
350 "Unexpected section header size.");
355bool LoadedElf::ReadProgramTable() {
357 const uword file_length =
359 program_table_mapping_.reset(
360 MapFilePiece(file_start, file_length,
361 reinterpret_cast<const void**
>(&program_table_)));
363 "Could not mmap the program table.");
367bool LoadedElf::ReadSectionTable() {
369 const uword file_length =
371 section_table_mapping_.reset(
372 MapFilePiece(file_start, file_length,
373 reinterpret_cast<const void**
>(§ion_table_)));
375 "Could not mmap the section table.");
379bool LoadedElf::ReadSectionStringTable() {
382 section_string_table_mapping_.reset(
384 reinterpret_cast<const void**
>(§ion_string_table_)));
385 CHECK_ERROR(section_string_table_mapping_ !=
nullptr,
386 "Could not mmap the section string table.");
390bool LoadedElf::LoadSegments() {
392 uword total_memory = 0;
403 "Alignment must be a power of two.");
409 "dart-compiled-image"));
410 CHECK_ERROR(base_ !=
nullptr,
"Could not reserve virtual memory.");
419 file_offset =
header.file_offset;
421 (memory_offset % PageSize()) == (file_offset % PageSize()),
422 "Difference between file and memory offset must be page-aligned.");
424 const intptr_t adjustment =
header.memory_offset % PageSize();
426 void*
const memory_start =
427 static_cast<char*
>(base_->address()) + memory_offset - adjustment;
428 const uword file_start = elf_data_offset_ + file_offset - adjustment;
439 ERROR(
"Unsupported segment flag set.");
442#if defined(DART_HOST_OS_FUCHSIA)
453 "Could not advance file position.");
455 "Could not read file.");
460 "Could not unmap reservation.");
463 std::unique_ptr<MappedMemory> memory(
464 mappable_->Map(map_type, file_start,
length, memory_start));
465 CHECK_ERROR(memory !=
nullptr,
"Could not map segment.");
467 "Mapping not at requested address.");
468#if defined(DART_HOST_OS_WINDOWS) && \
469 (defined(HOST_ARCH_X64) || defined(HOST_ARCH_ARM64))
473 void* ptable =
nullptr;
476 dynamic_runtime_function_tables_.Add(ptable);
484bool LoadedElf::ReadSections() {
487 const char*
const name = section_string_table_ +
header.name;
488 if (strcmp(
name,
".dynstr") == 0) {
490 dynamic_string_table_ =
491 static_cast<const char*
>(base_->address()) +
header.memory_offset;
492 }
else if (strcmp(
name,
".dynsym") == 0) {
495 base_->start() +
header.memory_offset);
500 CHECK_ERROR(dynamic_string_table_ !=
nullptr,
"Couldn't find .dynstr.");
501 CHECK_ERROR(dynamic_symbol_table_ !=
nullptr,
"Couldn't find .dynsym.");
506 const uint8_t** vm_instrs,
507 const uint8_t** isolate_data,
508 const uint8_t** isolate_instrs) {
509 if (error_ !=
nullptr) {
514 for (
uword i = 1; i < dynamic_symbol_count_; ++i) {
516 const char*
name = dynamic_string_table_ + sym.name;
517 const uint8_t** output =
nullptr;
524 output = isolate_data;
526 output = isolate_instrs;
529 if (output !=
nullptr) {
530 *output =
reinterpret_cast<const uint8_t*
>(base_->start() + sym.value);
534 CHECK_ERROR(isolate_data ==
nullptr || *isolate_data !=
nullptr,
535 "Could not find isolate snapshot data.");
536 CHECK_ERROR(isolate_instrs ==
nullptr || *isolate_instrs !=
nullptr,
537 "Could not find isolate instructions.");
543 const void** mem_start) {
544 const uword adjustment = (elf_data_offset_ + file_start) % PageSize();
545 const uword mapping_offset = elf_data_offset_ + file_start - adjustment;
546 const uword mapping_length =
547 Utils::RoundUp(elf_data_offset_ + file_start + file_length, PageSize()) -
552 if (mapping !=
nullptr) {
553 *mem_start =
reinterpret_cast<uint8_t*
>(mapping->
start() +
554 (file_start % PageSize()));
566#if defined(DART_HOST_OS_FUCHSIA) || defined(DART_HOST_OS_LINUX)
568 uint64_t file_offset,
570 const uint8_t** vm_snapshot_data,
571 const uint8_t** vm_snapshot_instrs,
572 const uint8_t** vm_isolate_data,
573 const uint8_t** vm_isolate_instrs) {
574 std::unique_ptr<Mappable> mappable(Mappable::FromFD(fd));
575 std::unique_ptr<LoadedElf> elf(
576 new LoadedElf(std::move(mappable), file_offset));
579 !elf->ResolveSymbols(vm_snapshot_data, vm_snapshot_instrs,
580 vm_isolate_data, vm_isolate_instrs)) {
581 *
error = elf->error();
589#if !defined(DART_HOST_OS_FUCHSIA)
591 uint64_t file_offset,
593 const uint8_t** vm_snapshot_data,
594 const uint8_t** vm_snapshot_instrs,
595 const uint8_t** vm_isolate_data,
596 const uint8_t** vm_isolate_instrs) {
598 if (mappable ==
nullptr) {
599 *
error =
"Couldn't open file.";
602 std::unique_ptr<LoadedElf> elf(
603 new LoadedElf(std::move(mappable), file_offset));
606 !elf->ResolveSymbols(vm_snapshot_data, vm_snapshot_instrs,
607 vm_isolate_data, vm_isolate_instrs)) {
608 *
error = elf->error();
617 const uint8_t* snapshot,
618 uint64_t snapshot_size,
620 const uint8_t** vm_snapshot_data,
621 const uint8_t** vm_snapshot_instrs,
622 const uint8_t** vm_isolate_data,
623 const uint8_t** vm_isolate_instrs) {
624 std::unique_ptr<Mappable> mappable(
626 if (mappable ==
nullptr) {
627 *
error =
"Couldn't open file.";
630 std::unique_ptr<LoadedElf> elf(
634 !elf->ResolveSymbols(vm_snapshot_data, vm_snapshot_instrs,
635 vm_isolate_data, vm_isolate_instrs)) {
636 *
error = elf->error();
644 delete reinterpret_cast<LoadedElf*
>(loaded);
static constexpr T Maximum(T x, T y)
static constexpr T RoundUp(T x, uintptr_t alignment, uintptr_t offset=0)
static constexpr bool IsAligned(T x, uintptr_t alignment, uintptr_t offset=0)
static constexpr bool IsPowerOfTwo(T x)
MappedMemory * Map(MapType type, int64_t position, int64_t length, void *start=nullptr)
bool ReadFully(void *buffer, int64_t num_bytes)
static File * Open(Namespace *namespc, const char *path, FileOpenMode mode)
bool SetPosition(int64_t position)
static File * OpenFD(int fd)
static VirtualMemory * Allocate(intptr_t size, bool is_executable, const char *name)
static void Protect(void *address, intptr_t size, Protection mode)
static intptr_t PageSize()
bool SetPosition(uint64_t position) override
bool ReadFully(void *dest, int64_t length) override
MappedMemory * Map(File::MapType type, uint64_t position, uint64_t length, void *start=nullptr) override
LoadedElf(std::unique_ptr< Mappable > mappable, uint64_t elf_data_offset)
bool ResolveSymbols(const uint8_t **vm_data, const uint8_t **vm_instrs, const uint8_t **isolate_data, const uint8_t **isolate_instrs)
static Mappable * FromMemory(const uint8_t *memory, size_t size)
virtual bool ReadFully(void *dest, int64_t length)=0
virtual bool SetPosition(uint64_t position)=0
virtual MappedMemory * Map(File::MapType type, uint64_t position, uint64_t length, void *start=nullptr)=0
static Mappable * FromPath(const char *path)
~MemoryMappable() override
MemoryMappable(const uint8_t *memory, size_t size)
MappedMemory * Map(File::MapType type, uint64_t position, uint64_t length, void *start=nullptr) override
bool ReadFully(void *dest, int64_t length) override
bool SetPosition(uint64_t position) override
#define kIsolateSnapshotDataAsmSymbol
#define kIsolateSnapshotInstructionsAsmSymbol
#define kVmSnapshotDataAsmSymbol
#define kVmSnapshotInstructionsAsmSymbol
const uint8_t uint32_t uint32_t GError ** error
static constexpr intptr_t PF_R
static constexpr intptr_t PF_X
static constexpr intptr_t ET_DYN
static constexpr intptr_t EM_X86_64
static constexpr intptr_t EM_386
static constexpr intptr_t EM_RISCV
static constexpr intptr_t EM_AARCH64
static constexpr intptr_t PF_W
static constexpr intptr_t ELFDATA2LSB
static constexpr intptr_t EI_DATA
static constexpr intptr_t EM_ARM
static constexpr intptr_t EV_CURRENT
static const char header[]
#define CHECK_ERROR(value, message)
DART_EXPORT Dart_LoadedElf * Dart_LoadELF_Memory(const uint8_t *snapshot, uint64_t snapshot_size, const char **error, const uint8_t **vm_snapshot_data, const uint8_t **vm_snapshot_instrs, const uint8_t **vm_isolate_data, const uint8_t **vm_isolate_instrs)
Please see documentation for Dart_LoadElf_Fd.
DART_EXPORT Dart_LoadedElf * Dart_LoadELF(const char *filename, uint64_t file_offset, const char **error, const uint8_t **vm_snapshot_data, const uint8_t **vm_snapshot_instrs, const uint8_t **vm_isolate_data, const uint8_t **vm_isolate_instrs)
Please see documentation for Dart_LoadElf_Fd.
DART_EXPORT void Dart_UnloadELF(Dart_LoadedElf *loaded)