mirror of
https://github.com/mirkobrombin/raven.git
synced 2026-11-05 21:56:33 +00:00
83 lines
3.5 KiB
C++
83 lines
3.5 KiB
C++
#pragma once
|
|
|
|
#include "loaded_image.h"
|
|
|
|
#include <filesystem>
|
|
#include <functional>
|
|
#include <map>
|
|
#include <memory>
|
|
#include <optional>
|
|
#include <set>
|
|
#include <unordered_map>
|
|
|
|
namespace raven {
|
|
|
|
// The file a module comes from: bytes held in memory, or a read-only mapping of the host file. A mapping shares its pages with every
|
|
// process that loads the same library, where reading a library of hundreds of megabytes into each of them cost seconds.
|
|
class ModuleBytes {
|
|
public:
|
|
ModuleBytes(std::vector<uint8_t> bytes) : owned(std::move(bytes)), view(owned) {}
|
|
// A move keeps the vector's buffer, which the view names; a copy would not.
|
|
ModuleBytes(ModuleBytes &&) = default;
|
|
ModuleBytes &operator=(ModuleBytes &&) = default;
|
|
ModuleBytes(const ModuleBytes &) = delete;
|
|
ModuleBytes &operator=(const ModuleBytes &) = delete;
|
|
static std::optional<ModuleBytes> map(const std::filesystem::path &path);
|
|
operator std::span<const uint8_t>() const { return view; }
|
|
|
|
private:
|
|
ModuleBytes() = default;
|
|
std::vector<uint8_t> owned;
|
|
std::shared_ptr<const void> mapping;
|
|
std::span<const uint8_t> view;
|
|
};
|
|
|
|
struct PEModule {
|
|
PEModule(std::string name, ModuleBytes bytes, uint64_t base, bool relocated = true);
|
|
std::string name;
|
|
ModuleBytes bytes;
|
|
PEImage image;
|
|
LoadedImage loaded;
|
|
std::vector<PEImport> imports;
|
|
std::vector<PEExport> exports;
|
|
// The first export that carries each name: imports are resolved by name, thousands of them for a large library.
|
|
std::unordered_map<std::string, size_t> export_names;
|
|
// The exports by ordinal, and how many exports both indexes cover: a lookup that misses them scans only when exports came after.
|
|
std::unordered_map<uint32_t, size_t> export_ordinals;
|
|
size_t indexed_exports = 0;
|
|
bool runtime_api = false;
|
|
// The host file a library loaded from a folder of the program's came from; empty for the runtime's own and for libraries found by name.
|
|
std::filesystem::path file;
|
|
};
|
|
|
|
// Owns module bytes and shared images. Resolves only explicitly supplied modules.
|
|
class ModuleSet {
|
|
public:
|
|
// Keep a free preferred base; relocate colliding images into graph-owned space.
|
|
// A process loader also excludes its allocations through available.
|
|
PEModule &add(std::string name, ModuleBytes bytes, std::function<bool(uint64_t, uint64_t)> available = {});
|
|
PEModule &add(std::string name, ModuleBytes bytes, uint64_t base);
|
|
// The process loader must release guest mappings and references before erasing an image.
|
|
void remove(const PEModule &module);
|
|
// An image mapped only to be read, as a data file or for its resources: it may have the other width, and nothing resolves through it.
|
|
PEModule &add_data(std::string name, ModuleBytes bytes, std::function<bool(uint64_t, uint64_t)> available = {});
|
|
const std::map<std::string, std::unique_ptr<PEModule>> &all() const;
|
|
uint64_t resolve(const PEImport &symbol) const;
|
|
std::vector<const PEModule *> resolution_path(const PEImport &symbol) const;
|
|
size_t bind_imports();
|
|
// Lets imports that name an API set contract resolve through the module that implements it.
|
|
void add_alias(std::string name, std::string target);
|
|
|
|
private:
|
|
std::map<std::string, std::unique_ptr<PEModule>> modules;
|
|
std::map<std::string, std::string> aliases;
|
|
std::set<std::string> data_names;
|
|
std::set<std::string> movable_names;
|
|
bool adding_data = false;
|
|
bool bound_any = false;
|
|
uint64_t resolve(std::string module, std::string name, uint32_t ordinal, bool by_ordinal,
|
|
std::set<std::pair<std::string, uint32_t>> &chain, std::vector<const PEModule *> *path = nullptr) const;
|
|
};
|
|
|
|
}
|