mirror of
https://github.com/mirkobrombin/raven.git
synced 2026-11-05 21:56:33 +00:00
93 lines
3.7 KiB
C++
93 lines
3.7 KiB
C++
#pragma once
|
|
|
|
#include "environment.h"
|
|
|
|
#include <cstring>
|
|
#include <functional>
|
|
#include <map>
|
|
#include <optional>
|
|
#include <utility>
|
|
#include <string>
|
|
#include <string_view>
|
|
|
|
namespace raven {
|
|
|
|
// Raised by guest-memory accessors when the guest passed a pointer that cannot be read or written.
|
|
struct ApiFault {};
|
|
|
|
// One guest call of a native API: argument words, the return value and bounds-checked guest memory.
|
|
// The text a guest pointer addresses when it holds a short run of printable characters, narrow or wide; empty otherwise. For traces.
|
|
std::string describe_text(NativeProcess &process, uint64_t address);
|
|
|
|
class ApiCall {
|
|
public:
|
|
ApiCall(NativeProcess &process, NativeEnvironment &environment, std::vector<uint64_t> arguments);
|
|
uint64_t operator[](size_t index) const { return arguments.at(index); }
|
|
uint32_t u32(size_t index) const { return uint32_t(arguments.at(index)); }
|
|
int32_t i32(size_t index) const { return int32_t(arguments.at(index)); }
|
|
// Sets the value the guest receives in RAX; handlers that return nothing leave it zero.
|
|
void ret(uint64_t value) { result = value; }
|
|
// Fails the call the way Windows does: sets the last error and returns the given failure value.
|
|
void fail(uint32_t error, uint64_t value = 0);
|
|
uint32_t last_error() const;
|
|
void set_last_error(uint32_t error);
|
|
|
|
std::vector<uint8_t> read(uint64_t address, size_t size) const;
|
|
void write(uint64_t address, std::span<const uint8_t> bytes) const;
|
|
template<typename T> T load(uint64_t address) const
|
|
{
|
|
const auto bytes = read(address, sizeof(T));
|
|
T value{};
|
|
std::memcpy(&value, bytes.data(), sizeof(T));
|
|
return value;
|
|
}
|
|
template<typename T> void store(uint64_t address, T value) const
|
|
{
|
|
write(address, std::span<const uint8_t>(reinterpret_cast<const uint8_t *>(&value), sizeof(T)));
|
|
}
|
|
// A pointer-sized value for the guest: four bytes for a 32-bit program, eight for a 64-bit one.
|
|
void store_pointer(uint64_t address, uint64_t value) const;
|
|
uint64_t load_pointer(uint64_t address) const;
|
|
// The size of a pointer in the guest: four bytes for a 32-bit program, eight for a 64-bit one.
|
|
size_t pointer_width() const;
|
|
// Zero-terminated guest strings; a string longer than limit characters faults the call.
|
|
std::u16string wide(uint64_t address, size_t limit = 32768) const;
|
|
std::string narrow(uint64_t address, size_t limit = 32768) const;
|
|
// Copies text and a terminator when capacity allows; returns the characters required without the terminator.
|
|
size_t put_wide(uint64_t address, std::u16string_view text, size_t capacity) const;
|
|
size_t put_narrow(uint64_t address, std::string_view text, size_t capacity) const;
|
|
|
|
NativeProcess &process;
|
|
NativeEnvironment &environment;
|
|
uint64_t result = 0;
|
|
|
|
private:
|
|
std::vector<uint64_t> arguments;
|
|
};
|
|
|
|
// The name of the API call being served, for diagnostics.
|
|
extern const char *api_in_progress;
|
|
|
|
using ApiHandler = std::function<void(ApiCall &)>;
|
|
|
|
// Name-keyed API handlers. The argument count is the number of words the handler may read.
|
|
class ApiRegistry {
|
|
public:
|
|
void add(std::string_view name, uint32_t arguments, ApiHandler handler);
|
|
bool has(std::string_view name) const { return entries.contains(std::string(name)); }
|
|
// The handler and word count registered under a name, for adapters that reuse it.
|
|
std::optional<std::pair<uint32_t,ApiHandler>> find(std::string_view name) const;
|
|
// Runs the handler for an API trap; false when no handler is registered under this name.
|
|
// For a 32-bit caller, the pseudo handles -1 and -2 arrive sign-extended, as the handlers of a 64-bit process expect them.
|
|
bool dispatch(NativeProcess &process, NativeEnvironment &environment, std::string_view name, bool widen_handles = false) const;
|
|
|
|
private:
|
|
struct Entry {
|
|
uint32_t arguments;
|
|
ApiHandler handler;
|
|
};
|
|
std::map<std::string, Entry> entries;
|
|
};
|
|
|
|
}
|