| // Copyright (c) 2025, the Dart project authors. Please see the AUTHORS file |
| // for details. All rights reserved. Use of this source code is governed by a |
| // BSD-style license that can be found in the LICENSE file. |
| |
| #ifndef RUNTIME_BIN_MAPPABLE_H_ |
| #define RUNTIME_BIN_MAPPABLE_H_ |
| |
| #include "platform/globals.h" |
| |
| #include "bin/file.h" |
| #include "bin/virtual_memory.h" |
| |
| namespace dart { |
| namespace bin { |
| |
| class Mappable { |
| public: |
| static Mappable* FromPath(const char* path); |
| #if defined(DART_HOST_OS_FUCHSIA) || defined(DART_HOST_OS_LINUX) |
| static Mappable* FromFD(int fd); |
| #endif |
| static Mappable* FromMemory(const uint8_t* memory, size_t size); |
| |
| virtual MappedMemory* Map(File::MapType type, |
| uint64_t position, |
| uint64_t length, |
| void* start = nullptr) = 0; |
| |
| virtual bool SetPosition(uint64_t position) = 0; |
| virtual bool ReadFully(void* dest, int64_t length) = 0; |
| |
| virtual ~Mappable() {} |
| |
| protected: |
| Mappable() {} |
| |
| private: |
| DISALLOW_COPY_AND_ASSIGN(Mappable); |
| }; |
| |
| class FileMappable : public Mappable { |
| public: |
| explicit FileMappable(File* file) : Mappable(), file_(file) {} |
| |
| ~FileMappable() override { file_->Release(); } |
| |
| MappedMemory* Map(File::MapType type, |
| uint64_t position, |
| uint64_t length, |
| void* start = nullptr) override { |
| return file_->Map(type, position, length, start); |
| } |
| |
| bool SetPosition(uint64_t position) override { |
| return file_->SetPosition(position); |
| } |
| |
| bool ReadFully(void* dest, int64_t length) override { |
| return file_->ReadFully(dest, length); |
| } |
| |
| private: |
| File* const file_; |
| DISALLOW_COPY_AND_ASSIGN(FileMappable); |
| }; |
| |
| class MemoryMappable : public Mappable { |
| public: |
| MemoryMappable(const uint8_t* memory, size_t size) |
| : Mappable(), memory_(memory), size_(size), position_(memory) {} |
| |
| ~MemoryMappable() override {} |
| |
| MappedMemory* Map(File::MapType type, |
| uint64_t position, |
| uint64_t length, |
| void* start = nullptr) override { |
| if (position > size_) return nullptr; |
| MappedMemory* result = nullptr; |
| const uword map_size = Utils::RoundUp(length, VirtualMemory::PageSize()); |
| if (start == nullptr) { |
| auto* memory = VirtualMemory::Allocate( |
| map_size, type == File::kReadExecute, "dart-compiled-image"); |
| if (memory == nullptr) return nullptr; |
| result = new MappedMemory(memory->address(), memory->size()); |
| memory->release(); |
| delete memory; |
| } else { |
| result = new MappedMemory(start, map_size, |
| /*should_unmap=*/false); |
| } |
| |
| size_t remainder = 0; |
| if ((position + length) > size_) { |
| remainder = position + length - size_; |
| length = size_ - position; |
| } |
| memcpy(result->address(), memory_ + position, length); // NOLINT |
| memset(reinterpret_cast<uint8_t*>(result->address()) + length, 0, |
| remainder); |
| |
| auto mode = VirtualMemory::kReadOnly; |
| switch (type) { |
| case File::kReadExecute: |
| mode = VirtualMemory::kReadExecute; |
| break; |
| case File::kReadWrite: |
| mode = VirtualMemory::kReadWrite; |
| break; |
| case File::kReadOnly: |
| mode = VirtualMemory::kReadOnly; |
| break; |
| default: |
| UNREACHABLE(); |
| } |
| |
| VirtualMemory::Protect(result->address(), result->size(), mode); |
| |
| return result; |
| } |
| |
| bool SetPosition(uint64_t position) override { |
| if (position > size_) return false; |
| position_ = memory_ + position; |
| return true; |
| } |
| |
| bool ReadFully(void* dest, int64_t length) override { |
| if ((position_ + length) > (memory_ + size_)) return false; |
| memcpy(dest, position_, length); |
| return true; |
| } |
| |
| private: |
| const uint8_t* const memory_; |
| const size_t size_; |
| const uint8_t* position_; |
| DISALLOW_COPY_AND_ASSIGN(MemoryMappable); |
| }; |
| |
| } // namespace bin |
| } // namespace dart |
| |
| #endif // RUNTIME_BIN_MAPPABLE_H_ |