blob: 607348392af98a6fd357f6e6e43dc240afbbd731 [file] [log] [blame] [edit]
// 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_