You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
3809 lines
123 KiB
C++
3809 lines
123 KiB
C++
8 months ago
|
#ifndef MEMFLOW_H
|
||
|
#define MEMFLOW_H
|
||
|
|
||
|
#include <cstdarg>
|
||
|
#include <cstring>
|
||
|
#include <cstdint>
|
||
|
#include <cstdlib>
|
||
|
#include <ostream>
|
||
|
#include <new>
|
||
|
typedef void *Library;
|
||
|
|
||
|
/**
|
||
|
* Identifies the byte order of a architecture
|
||
|
*
|
||
|
* This enum is used when reading/writing to/from the memory of a target system.
|
||
|
* The memory will be automatically converted to the endianess memflow is currently running on.
|
||
|
*
|
||
|
* See the [wikipedia article](https://en.wikipedia.org/wiki/Endianness) for more information on the subject.
|
||
|
*/
|
||
|
enum class Endianess : uint8_t {
|
||
|
/**
|
||
|
* Little Endianess
|
||
|
*/
|
||
|
Endianess_LittleEndian,
|
||
|
/**
|
||
|
* Big Endianess
|
||
|
*/
|
||
|
Endianess_BigEndian,
|
||
|
};
|
||
|
|
||
|
/**
|
||
|
* An enum representing the available verbosity levels of the logger.
|
||
|
*
|
||
|
* Typical usage includes: checking if a certain `Level` is enabled with
|
||
|
* [`log_enabled!`](macro.log_enabled.html), specifying the `Level` of
|
||
|
* [`log!`](macro.log.html), and comparing a `Level` directly to a
|
||
|
* [`LevelFilter`](enum.LevelFilter.html).
|
||
|
*/
|
||
|
enum class Level : uintptr_t {
|
||
|
/**
|
||
|
* The "error" level.
|
||
|
*
|
||
|
* Designates very serious errors.
|
||
|
*/
|
||
|
Level_Error = 1,
|
||
|
/**
|
||
|
* The "warn" level.
|
||
|
*
|
||
|
* Designates hazardous situations.
|
||
|
*/
|
||
|
Level_Warn,
|
||
|
/**
|
||
|
* The "info" level.
|
||
|
*
|
||
|
* Designates useful information.
|
||
|
*/
|
||
|
Level_Info,
|
||
|
/**
|
||
|
* The "debug" level.
|
||
|
*
|
||
|
* Designates lower priority information.
|
||
|
*/
|
||
|
Level_Debug,
|
||
|
/**
|
||
|
* The "trace" level.
|
||
|
*
|
||
|
* Designates very low priority, often extremely verbose, information.
|
||
|
*/
|
||
|
Level_Trace,
|
||
|
};
|
||
|
|
||
|
/**
|
||
|
* An enum representing the available verbosity level filters of the logger.
|
||
|
*
|
||
|
* A `LevelFilter` may be compared directly to a [`Level`]. Use this type
|
||
|
* to get and set the maximum log level with [`max_level()`] and [`set_max_level`].
|
||
|
*
|
||
|
* [`Level`]: enum.Level.html
|
||
|
* [`max_level()`]: fn.max_level.html
|
||
|
* [`set_max_level`]: fn.set_max_level.html
|
||
|
*/
|
||
|
enum class LevelFilter : uintptr_t {
|
||
|
/**
|
||
|
* A level lower than all log levels.
|
||
|
*/
|
||
|
LevelFilter_Off,
|
||
|
/**
|
||
|
* Corresponds to the `Error` log level.
|
||
|
*/
|
||
|
LevelFilter_Error,
|
||
|
/**
|
||
|
* Corresponds to the `Warn` log level.
|
||
|
*/
|
||
|
LevelFilter_Warn,
|
||
|
/**
|
||
|
* Corresponds to the `Info` log level.
|
||
|
*/
|
||
|
LevelFilter_Info,
|
||
|
/**
|
||
|
* Corresponds to the `Debug` log level.
|
||
|
*/
|
||
|
LevelFilter_Debug,
|
||
|
/**
|
||
|
* Corresponds to the `Trace` log level.
|
||
|
*/
|
||
|
LevelFilter_Trace,
|
||
|
};
|
||
|
|
||
|
struct ArchitectureObj;
|
||
|
|
||
|
|
||
|
/** Destruct the object. */
|
||
|
template<typename T>
|
||
|
inline typename std::enable_if<!std::is_pointer<T>::value>::type mem_drop(T &&self) noexcept {
|
||
|
std::move(self).drop();
|
||
|
}
|
||
|
|
||
|
template<typename T>
|
||
|
inline typename std::enable_if<std::is_pointer<T>::value>::type mem_drop(T &&self) noexcept {}
|
||
|
|
||
|
/** Forget the object's resources (null them out). */
|
||
|
template<typename T>
|
||
|
inline typename std::enable_if<!std::is_pointer<T>::value>::type mem_forget(T &self) noexcept {
|
||
|
self.forget();
|
||
|
}
|
||
|
|
||
|
template<typename T>
|
||
|
inline typename std::enable_if<std::is_pointer<T>::value>::type mem_forget(T &self) noexcept {}
|
||
|
|
||
|
/** Defer mem_forget call when object goes out of scope. */
|
||
|
template<typename T>
|
||
|
struct DeferedForget {
|
||
|
T &val;
|
||
|
|
||
|
DeferedForget(T &val) : val(val) {}
|
||
|
|
||
|
~DeferedForget() {
|
||
|
mem_forget(val);
|
||
|
}
|
||
|
};
|
||
|
|
||
|
/** Workaround for void types in generic functions. */
|
||
|
struct StoreAll {
|
||
|
constexpr bool operator[](StoreAll) const {
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
template <class T>
|
||
|
constexpr T && operator[](T &&t) const {
|
||
|
return std::forward<T>(t);
|
||
|
}
|
||
|
|
||
|
template <class T>
|
||
|
friend T && operator,(T &&t, StoreAll) {
|
||
|
return std::forward<T>(t);
|
||
|
}
|
||
|
};
|
||
|
|
||
|
template<typename CGlueCtx = void>
|
||
|
using CloneRetTmp = void;
|
||
|
|
||
|
template<typename CGlueCtx = void>
|
||
|
using ConnectorCpuStateRetTmp = void;
|
||
|
|
||
|
template<typename CGlueCtx = void>
|
||
|
using CpuStateRetTmp = void;
|
||
|
|
||
|
/**
|
||
|
* The core of the plugin system
|
||
|
*
|
||
|
* It scans system directories and collects valid memflow plugins. They can then be instantiated
|
||
|
* easily. The reason the libraries are collected is to allow for reuse, and save performance
|
||
|
*
|
||
|
* # Examples
|
||
|
*
|
||
|
* Creating a OS instance, the recommended way:
|
||
|
*
|
||
|
* ```no_run
|
||
|
* use memflow::plugins::Inventory;
|
||
|
* # use memflow::plugins::OsInstanceArcBox;
|
||
|
* # use memflow::error::Result;
|
||
|
* # fn test() -> Result<OsInstanceArcBox<'static>> {
|
||
|
* let inventory = Inventory::scan();
|
||
|
* inventory
|
||
|
* .builder()
|
||
|
* .connector("qemu")
|
||
|
* .os("win32")
|
||
|
* .build()
|
||
|
* # }
|
||
|
* # test().ok();
|
||
|
* ```
|
||
|
*
|
||
|
* Nesting connectors and os plugins:
|
||
|
* ```no_run
|
||
|
* use memflow::plugins::{Inventory, Args};
|
||
|
* # use memflow::error::Result;
|
||
|
* # fn test() -> Result<()> {
|
||
|
* let inventory = Inventory::scan();
|
||
|
* let os = inventory
|
||
|
* .builder()
|
||
|
* .connector("qemu")
|
||
|
* .os("linux")
|
||
|
* .connector("qemu")
|
||
|
* .os("win32")
|
||
|
* .build();
|
||
|
* # Ok(())
|
||
|
* # }
|
||
|
* # test().ok();
|
||
|
* ```
|
||
|
*/
|
||
|
struct Inventory;
|
||
|
|
||
|
template<typename CGlueCtx = void>
|
||
|
using KeyboardRetTmp = void;
|
||
|
|
||
|
template<typename CGlueCtx = void>
|
||
|
using KeyboardStateRetTmp = void;
|
||
|
|
||
|
template<typename T = void>
|
||
|
struct alignas(alignof(T)) RustMaybeUninit {
|
||
|
char pad[sizeof(T)];
|
||
|
inline T &assume_init() {
|
||
|
return *(T *)this;
|
||
|
}
|
||
|
constexpr const T &assume_init() const {
|
||
|
return *(const T *)this;
|
||
|
}
|
||
|
};
|
||
|
|
||
|
template<typename CGlueCtx = void>
|
||
|
using MemoryViewRetTmp = void;
|
||
|
|
||
|
template<typename CGlueCtx = void>
|
||
|
using OsKeyboardRetTmp = void;
|
||
|
|
||
|
template<typename CGlueCtx = void>
|
||
|
using OsRetTmp = void;
|
||
|
|
||
|
template<typename CGlueCtx = void>
|
||
|
using PhysicalMemoryRetTmp = void;
|
||
|
|
||
|
template<typename CGlueCtx = void>
|
||
|
using ProcessRetTmp = void;
|
||
|
|
||
|
template<typename CGlueCtx = void>
|
||
|
using VirtualTranslateRetTmp = void;
|
||
|
|
||
|
/**
|
||
|
* The largest target memory type
|
||
|
* The following core rule is defined for these memory types:
|
||
|
*
|
||
|
* `PAGE_SIZE < usize <= umem`
|
||
|
*
|
||
|
* Where `PAGE_SIZE` is any lowest granularity page size, `usize` is the standard size type, and
|
||
|
* `umem` is memflow's memory size type.
|
||
|
*
|
||
|
* This means that `usize` can always be safely cast to `umem`, while anything to do with page
|
||
|
* sizes can be cast to `umem` safely,
|
||
|
*
|
||
|
*/
|
||
|
using umem = uint64_t;
|
||
|
|
||
|
/**
|
||
|
* This type represents a address on the target system.
|
||
|
* It internally holds a `umem` value but can also be used
|
||
|
* when working in 32-bit environments.
|
||
|
*
|
||
|
* This type will not handle overflow for 32-bit or 64-bit addresses / lengths.
|
||
|
*/
|
||
|
using Address = umem;
|
||
|
/**
|
||
|
* A address with the value of zero.
|
||
|
*
|
||
|
* # Examples
|
||
|
*
|
||
|
* ```
|
||
|
* use memflow::types::Address;
|
||
|
*
|
||
|
* println!("address: {}", Address::NULL);
|
||
|
* ```
|
||
|
*/
|
||
|
constexpr static const Address Address_NULL = 0;
|
||
|
/**
|
||
|
* A address with an invalid value.
|
||
|
*
|
||
|
* # Examples
|
||
|
*
|
||
|
* ```
|
||
|
* use memflow::types::Address;
|
||
|
*
|
||
|
* println!("address: {}", Address::INVALID);
|
||
|
* ```
|
||
|
*/
|
||
|
constexpr static const Address Address_INVALID = ~0;
|
||
|
|
||
|
/**
|
||
|
* Describes the type of a page using a bitflag.
|
||
|
*/
|
||
|
using PageType = uint8_t;
|
||
|
/**
|
||
|
* The page explicitly has no flags.
|
||
|
*/
|
||
|
constexpr static const PageType PageType_NONE = 0;
|
||
|
/**
|
||
|
* The page type is not known.
|
||
|
*/
|
||
|
constexpr static const PageType PageType_UNKNOWN = 1;
|
||
|
/**
|
||
|
* The page contains page table entries.
|
||
|
*/
|
||
|
constexpr static const PageType PageType_PAGE_TABLE = 2;
|
||
|
/**
|
||
|
* The page is a writeable page.
|
||
|
*/
|
||
|
constexpr static const PageType PageType_WRITEABLE = 4;
|
||
|
/**
|
||
|
* The page is read only.
|
||
|
*/
|
||
|
constexpr static const PageType PageType_READ_ONLY = 8;
|
||
|
/**
|
||
|
* The page is not executable.
|
||
|
*/
|
||
|
constexpr static const PageType PageType_NOEXEC = 16;
|
||
|
|
||
|
/**
|
||
|
* This type represents a wrapper over a [address](address/index.html)
|
||
|
* with additional information about the containing page in the physical memory domain.
|
||
|
*
|
||
|
* This type will mostly be used by the [virtual to physical address translation](todo.html).
|
||
|
* When a physical address is translated from a virtual address the additional information
|
||
|
* about the allocated page the virtual address points to can be obtained from this structure.
|
||
|
*
|
||
|
* Most architectures have support multiple page sizes (see [huge pages](todo.html))
|
||
|
* which will be represented by the containing `page` of the `PhysicalAddress` struct.
|
||
|
*/
|
||
|
struct PhysicalAddress {
|
||
|
Address address;
|
||
|
PageType page_type;
|
||
|
uint8_t page_size_log2;
|
||
|
};
|
||
|
/**
|
||
|
* A physical address with an invalid value.
|
||
|
*/
|
||
|
constexpr static const PhysicalAddress PhysicalAddress_INVALID = PhysicalAddress{ /* .address = */ Address_INVALID, /* .page_type = */ PageType_UNKNOWN, /* .page_size_log2 = */ 0 };
|
||
|
|
||
|
/**
|
||
|
* FFI-Safe Arc
|
||
|
*
|
||
|
* This is an FFI-Safe equivalent of Arc<T> and Option<Arc<T>>.
|
||
|
*/
|
||
|
template<typename T>
|
||
|
struct CArc {
|
||
|
const T *instance;
|
||
|
const T *(*clone_fn)(const T*);
|
||
|
void (*drop_fn)(const T*);
|
||
|
|
||
|
inline CArc clone() const noexcept {
|
||
|
CArc ret;
|
||
|
ret.instance = clone_fn(instance);
|
||
|
ret.clone_fn = clone_fn;
|
||
|
ret.drop_fn = drop_fn;
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
inline void drop() && noexcept {
|
||
|
if (drop_fn)
|
||
|
drop_fn(instance);
|
||
|
forget();
|
||
|
}
|
||
|
|
||
|
inline void forget() noexcept {
|
||
|
instance = nullptr;
|
||
|
clone_fn = nullptr;
|
||
|
drop_fn = nullptr;
|
||
|
}
|
||
|
};
|
||
|
|
||
|
/**
|
||
|
* FFI-safe box
|
||
|
*
|
||
|
* This box has a static self reference, alongside a custom drop function.
|
||
|
*
|
||
|
* The drop function can be called from anywhere, it will free on correct allocator internally.
|
||
|
*/
|
||
|
template<typename T>
|
||
|
struct CBox {
|
||
|
T *instance;
|
||
|
void (*drop_fn)(T*);
|
||
|
|
||
|
CBox() = default;
|
||
|
CBox(T *instance) : instance(instance), drop_fn(nullptr) {}
|
||
|
CBox(T *instance, void (*drop_fn)(T *)) : instance(instance), drop_fn(drop_fn) {}
|
||
|
template<typename U = T, class = typename std::enable_if<std::is_same<U, T>::value>::type, class = typename std::enable_if<!std::is_same<U, void>::value>::type>
|
||
|
CBox(U &&instance) : instance(new U(instance)), drop_fn(&CBox::delete_fn) {}
|
||
|
|
||
|
static void delete_fn(T *v) {
|
||
|
delete v;
|
||
|
}
|
||
|
|
||
|
inline operator CBox<void> () const {
|
||
|
CBox<void> ret;
|
||
|
ret.instance = (void*)instance;
|
||
|
ret.drop_fn = (void(*)(void *))drop_fn;
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
static inline CBox new_box() {
|
||
|
CBox ret;
|
||
|
ret.instance = new T;
|
||
|
ret.drop_fn = &CBox::delete_fn;
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
inline void drop() && noexcept {
|
||
|
if (drop_fn && instance)
|
||
|
drop_fn(instance);
|
||
|
forget();
|
||
|
}
|
||
|
|
||
|
inline void forget() noexcept {
|
||
|
instance = nullptr;
|
||
|
drop_fn = nullptr;
|
||
|
}
|
||
|
|
||
|
inline T *operator->() {
|
||
|
return instance;
|
||
|
}
|
||
|
|
||
|
inline const T *operator->() const {
|
||
|
return instance;
|
||
|
}
|
||
|
};
|
||
|
|
||
|
template<typename CGlueInst = CBox<void>, typename CGlueCtx = CArc<void>>
|
||
|
struct ConnectorInstanceContainer {
|
||
|
typedef CGlueCtx Context;
|
||
|
CGlueInst instance;
|
||
|
CGlueCtx context;
|
||
|
|
||
|
inline Context clone_context() noexcept {
|
||
|
return context.clone();
|
||
|
}
|
||
|
|
||
|
inline void drop() && noexcept {
|
||
|
mem_drop(std::move(instance));
|
||
|
mem_drop(std::move(context));
|
||
|
}
|
||
|
|
||
|
inline void forget() noexcept {
|
||
|
mem_forget(instance);
|
||
|
mem_forget(context);
|
||
|
}
|
||
|
};
|
||
|
|
||
|
template<typename CGlueInst>
|
||
|
struct ConnectorInstanceContainer<CGlueInst, void> {
|
||
|
typedef void Context;
|
||
|
CGlueInst instance;
|
||
|
|
||
|
inline Context clone_context() noexcept {}
|
||
|
|
||
|
inline void drop() && noexcept {
|
||
|
mem_drop(std::move(instance));
|
||
|
}
|
||
|
|
||
|
inline void forget() noexcept {
|
||
|
mem_forget(instance);
|
||
|
}
|
||
|
};
|
||
|
|
||
|
/**
|
||
|
* CGlue vtable for trait Clone.
|
||
|
*
|
||
|
* This virtual function table contains ABI-safe interface for the given trait.
|
||
|
*/
|
||
|
template<typename CGlueC>
|
||
|
struct CloneVtbl {
|
||
|
typedef typename CGlueC::Context Context;
|
||
|
CGlueC (*clone)(const CGlueC *cont);
|
||
|
};
|
||
|
|
||
|
template<typename Impl>
|
||
|
struct CloneVtblImpl : CloneVtbl<typename Impl::Parent> {
|
||
|
constexpr CloneVtblImpl() :
|
||
|
CloneVtbl<typename Impl::Parent> {
|
||
|
&Impl::clone
|
||
|
} {}
|
||
|
};
|
||
|
|
||
|
/**
|
||
|
* Wrapper around mutable slices.
|
||
|
*
|
||
|
* This is meant as a safe type to pass across the FFI boundary with similar semantics as regular
|
||
|
* slice. However, not all functionality is present, use the slice conversion functions.
|
||
|
*/
|
||
|
template<typename T>
|
||
|
struct CSliceMut {
|
||
|
T *data;
|
||
|
uintptr_t len;
|
||
|
|
||
|
CSliceMut () = default;
|
||
|
|
||
|
template<typename Cont, class = typename std::enable_if<
|
||
|
std::is_same<decltype((*(Cont *)nullptr).data()), T *>::value
|
||
|
&& std::is_same<decltype((*(Cont *)nullptr).size()), size_t>::value
|
||
|
>::type>
|
||
|
CSliceMut (Cont &data) : data(data.data()), len(data.size()) {}
|
||
|
|
||
|
template<typename U = T, class = typename std::enable_if<
|
||
|
(std::is_same<T, char>::value || std::is_same<T, unsigned char>::value)
|
||
|
&& std::is_same<T, U>::value
|
||
|
>::type>
|
||
|
CSliceMut (char *value) : data((T *)value), len(strlen(value)) {}
|
||
|
|
||
|
template<typename U = T, class = typename std::enable_if<
|
||
|
(std::is_same<T, char>::value || std::is_same<T, unsigned char>::value)
|
||
|
&& std::is_same<T, U>::value
|
||
|
>::type>
|
||
|
CSliceMut (char *value, uintptr_t len) : data((T *)value), len(len) {}
|
||
|
|
||
|
template<typename U = T, class = typename std::enable_if<
|
||
|
(std::is_same<T, char>::value || std::is_same<T, unsigned char>::value)
|
||
|
&& std::is_same<T, U>::value
|
||
|
>::type>
|
||
|
CSliceMut (std::string &value) : data((T *)value.data()), len(value.length()) {}
|
||
|
|
||
|
template<typename U = T, class = typename std::enable_if<
|
||
|
(std::is_same<T, char>::value || std::is_same<T, unsigned char>::value)
|
||
|
&& std::is_same<T, U>::value
|
||
|
>::type>
|
||
|
inline operator std::string() const {
|
||
|
return std::string((char *)data, len);
|
||
|
}
|
||
|
};
|
||
|
|
||
|
/**
|
||
|
* FFI-safe 3 element tuple.
|
||
|
*/
|
||
|
template<typename A, typename B, typename C>
|
||
|
struct CTup3 {
|
||
|
A _0;
|
||
|
B _1;
|
||
|
C _2;
|
||
|
};
|
||
|
|
||
|
/**
|
||
|
* MemData type for physical memory reads.
|
||
|
*/
|
||
|
using PhysicalReadData = CTup3<PhysicalAddress, Address, CSliceMut<uint8_t>>;
|
||
|
|
||
|
/**
|
||
|
* FFI-safe 2 element tuple.
|
||
|
*/
|
||
|
template<typename A, typename B>
|
||
|
struct CTup2 {
|
||
|
A _0;
|
||
|
B _1;
|
||
|
};
|
||
|
|
||
|
using ReadData = CTup2<Address, CSliceMut<uint8_t>>;
|
||
|
|
||
|
/**
|
||
|
* FFI compatible iterator.
|
||
|
*
|
||
|
* Any mutable reference to an iterator can be converted to a `CIterator`.
|
||
|
*
|
||
|
* `CIterator<T>` implements `Iterator<Item = T>`.
|
||
|
*
|
||
|
* # Examples
|
||
|
*
|
||
|
* Using [`AsCIterator`](AsCIterator) helper:
|
||
|
*
|
||
|
* ```
|
||
|
* use cglue::iter::{CIterator, AsCIterator};
|
||
|
*
|
||
|
* extern "C" fn sum_all(iter: CIterator<usize>) -> usize {
|
||
|
* iter.sum()
|
||
|
* }
|
||
|
*
|
||
|
* let mut iter = (0..10).map(|v| v * v);
|
||
|
*
|
||
|
* assert_eq!(sum_all(iter.as_citer()), 285);
|
||
|
* ```
|
||
|
*
|
||
|
* Converting with `Into` trait:
|
||
|
*
|
||
|
* ```
|
||
|
* use cglue::iter::{CIterator, AsCIterator};
|
||
|
*
|
||
|
* extern "C" fn sum_all(iter: CIterator<usize>) -> usize {
|
||
|
* iter.sum()
|
||
|
* }
|
||
|
*
|
||
|
* let mut iter = (0..=10).map(|v| v * v);
|
||
|
*
|
||
|
* assert_eq!(sum_all((&mut iter).into()), 385);
|
||
|
* ```
|
||
|
*/
|
||
|
template<typename T>
|
||
|
struct CIterator {
|
||
|
void *iter;
|
||
|
int32_t (*func)(void*, T *out);
|
||
|
|
||
|
class iterator : std::iterator<std::input_iterator_tag, T> {
|
||
|
CIterator<T> *iter;
|
||
|
RustMaybeUninit<T> data;
|
||
|
bool initialized = false;
|
||
|
bool end = false;
|
||
|
|
||
|
public:
|
||
|
explicit iterator() : end(true) {}
|
||
|
|
||
|
explicit iterator(CIterator<T> *iter) : iter(iter) {
|
||
|
end = iter->func(iter->iter, &data.assume_init());
|
||
|
}
|
||
|
|
||
|
iterator &operator++() {
|
||
|
if (!iter || end) {
|
||
|
return *this;
|
||
|
}
|
||
|
|
||
|
end = iter->func(iter->iter, &data.assume_init());
|
||
|
|
||
|
return *this;
|
||
|
}
|
||
|
|
||
|
constexpr bool operator==(const iterator &other) const {
|
||
|
return (end && other.end)
|
||
|
|| (!end && !other.end && data.assume_init() == other.data.assume_init());
|
||
|
}
|
||
|
|
||
|
constexpr bool operator!=(const iterator &other) const {
|
||
|
return !(*this == other);
|
||
|
}
|
||
|
|
||
|
inline T &operator*() {
|
||
|
return data.assume_init();
|
||
|
}
|
||
|
|
||
|
constexpr const T &operator*() const {
|
||
|
return data.assume_init();
|
||
|
}
|
||
|
};
|
||
|
|
||
|
constexpr iterator begin() {
|
||
|
return iterator(this);
|
||
|
}
|
||
|
|
||
|
constexpr iterator end() {
|
||
|
return iterator();
|
||
|
}
|
||
|
};
|
||
|
|
||
|
template<typename Container>
|
||
|
struct CPPIterator {
|
||
|
|
||
|
typedef typename Container::iterator::value_type T;
|
||
|
|
||
|
CIterator<T> iter;
|
||
|
typename Container::iterator cur, end;
|
||
|
|
||
|
static int32_t next(void *data, T *out) {
|
||
|
CPPIterator *i = (CPPIterator *)data;
|
||
|
|
||
|
if (i->cur == i->end) {
|
||
|
return 1;
|
||
|
} else {
|
||
|
*out = *i->cur;
|
||
|
i->cur++;
|
||
|
return 0;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
CPPIterator(Container &cont)
|
||
|
: cur(cont.begin()), end(cont.end())
|
||
|
{
|
||
|
iter.iter = &iter - offsetof(CPPIterator<Container>, iter);
|
||
|
iter.func = &CPPIterator::next;
|
||
|
}
|
||
|
|
||
|
CPPIterator(CPPIterator &&o) {
|
||
|
iter = o.iter;
|
||
|
iter.iter = &this;
|
||
|
cur = o.cur;
|
||
|
end = o.end;
|
||
|
}
|
||
|
|
||
|
CPPIterator(CPPIterator &o) {
|
||
|
iter = o.iter;
|
||
|
iter.iter = &this;
|
||
|
cur = o.cur;
|
||
|
end = o.end;
|
||
|
}
|
||
|
|
||
|
inline operator CIterator<T> &() {
|
||
|
return iter;
|
||
|
}
|
||
|
};
|
||
|
|
||
|
template<typename T, typename F>
|
||
|
struct Callback {
|
||
|
T *context;
|
||
|
bool (*func)(T*, F);
|
||
|
|
||
|
template<typename Container>
|
||
|
static bool push_back(Container *context, F data) {
|
||
|
context->push_back(data);
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
template<typename Function>
|
||
|
static bool functional(Function *function, F data) {
|
||
|
return (*function)(data);
|
||
|
}
|
||
|
|
||
|
Callback() = default;
|
||
|
|
||
|
template<typename OT, typename = decltype(std::declval<OT>().push_back(std::declval<F>()))>
|
||
|
Callback(OT *cont) :
|
||
|
context((T *)cont),
|
||
|
func((decltype(func))(&Callback::push_back<OT>)) {}
|
||
|
|
||
|
template<typename Function, typename = decltype(std::declval<Function>()(std::declval<F>()))>
|
||
|
Callback(const Function &function) :
|
||
|
context((T *)&function),
|
||
|
func((decltype(func))(&Callback::functional<Function>)) {}
|
||
|
|
||
|
constexpr operator Callback<void, F> &() {
|
||
|
return *((Callback<void, F> *)this);
|
||
|
}
|
||
|
};
|
||
|
|
||
|
template<typename T>
|
||
|
using OpaqueCallback = Callback<void, T>;
|
||
|
|
||
|
/**
|
||
|
* Data needed to perform memory operations.
|
||
|
*
|
||
|
* `inp` is an iterator containing
|
||
|
*/
|
||
|
template<typename T, typename P>
|
||
|
struct MemOps {
|
||
|
CIterator<T> inp;
|
||
|
OpaqueCallback<P> *out;
|
||
|
OpaqueCallback<P> *out_fail;
|
||
|
};
|
||
|
|
||
|
using PhysicalReadMemOps = MemOps<PhysicalReadData, ReadData>;
|
||
|
|
||
|
/**
|
||
|
* Wrapper around const slices.
|
||
|
*
|
||
|
* This is meant as a safe type to pass across the FFI boundary with similar semantics as regular
|
||
|
* slice. However, not all functionality is present, use the slice conversion functions.
|
||
|
*
|
||
|
* # Examples
|
||
|
*
|
||
|
* Simple conversion:
|
||
|
*
|
||
|
* ```
|
||
|
* use cglue::slice::CSliceRef;
|
||
|
*
|
||
|
* let arr = [0, 5, 3, 2];
|
||
|
*
|
||
|
* let cslice = CSliceRef::from(&arr[..]);
|
||
|
*
|
||
|
* let slice = cslice.as_slice();
|
||
|
*
|
||
|
* assert_eq!(&arr, slice);
|
||
|
* ```
|
||
|
*/
|
||
|
template<typename T>
|
||
|
struct CSliceRef {
|
||
|
const T *data;
|
||
|
uintptr_t len;
|
||
|
|
||
|
CSliceRef () = default;
|
||
|
|
||
|
template<typename Cont, class = typename std::enable_if<
|
||
|
std::is_same<decltype((*(const Cont *)nullptr).data()), const T *>::value
|
||
|
&& std::is_same<decltype((*(const Cont *)nullptr).size()), size_t>::value
|
||
|
>::type>
|
||
|
CSliceRef (const Cont &data) : data(data.data()), len(data.size()) {}
|
||
|
|
||
|
template<typename U = T, class = typename std::enable_if<
|
||
|
(std::is_same<T, char>::value || std::is_same<T, unsigned char>::value)
|
||
|
&& std::is_same<T, U>::value
|
||
|
>::type>
|
||
|
CSliceRef (const char *value) : data((const T *)value), len(strlen(value)) {}
|
||
|
|
||
|
template<typename U = T, class = typename std::enable_if<
|
||
|
(std::is_same<T, char>::value || std::is_same<T, unsigned char>::value)
|
||
|
&& std::is_same<T, U>::value
|
||
|
>::type>
|
||
|
CSliceRef (const char *value, uintptr_t len) : data((const T *)value), len(len) {}
|
||
|
|
||
|
template<typename U = T, class = typename std::enable_if<
|
||
|
(std::is_same<T, char>::value || std::is_same<T, unsigned char>::value)
|
||
|
&& std::is_same<T, U>::value
|
||
|
>::type>
|
||
|
CSliceRef (const std::string &value) : data((const T *)value.data()), len(value.length()) {}
|
||
|
|
||
|
template<typename U = T, class = typename std::enable_if<
|
||
|
(std::is_same<T, char>::value || std::is_same<T, unsigned char>::value)
|
||
|
&& std::is_same<T, U>::value
|
||
|
>::type>
|
||
|
inline operator std::string() const {
|
||
|
return std::string((char *)data, len);
|
||
|
}
|
||
|
};
|
||
|
|
||
|
/**
|
||
|
* MemData type for physical memory writes.
|
||
|
*/
|
||
|
using PhysicalWriteData = CTup3<PhysicalAddress, Address, CSliceRef<uint8_t>>;
|
||
|
|
||
|
using WriteData = CTup2<Address, CSliceRef<uint8_t>>;
|
||
|
|
||
|
using PhysicalWriteMemOps = MemOps<PhysicalWriteData, WriteData>;
|
||
|
|
||
|
struct PhysicalMemoryMetadata {
|
||
|
Address max_address;
|
||
|
umem real_size;
|
||
|
bool readonly;
|
||
|
uint32_t ideal_batch_size;
|
||
|
};
|
||
|
|
||
|
struct PhysicalMemoryMapping {
|
||
|
Address base;
|
||
|
umem size;
|
||
|
Address real_base;
|
||
|
};
|
||
|
|
||
|
/**
|
||
|
* Simple CGlue trait object container.
|
||
|
*
|
||
|
* This is the simplest form of container, represented by an instance, clone context, and
|
||
|
* temporary return context.
|
||
|
*
|
||
|
* `instance` value usually is either a reference, or a mutable reference, or a `CBox`, which
|
||
|
* contains static reference to the instance, and a dedicated drop function for freeing resources.
|
||
|
*
|
||
|
* `context` is either `PhantomData` representing nothing, or typically a `CArc` that can be
|
||
|
* cloned at will, reference counting some resource, like a `Library` for automatic unloading.
|
||
|
*
|
||
|
* `ret_tmp` is usually `PhantomData` representing nothing, unless the trait has functions that
|
||
|
* return references to associated types, in which case space is reserved for wrapping structures.
|
||
|
*/
|
||
|
template<typename T, typename C, typename R>
|
||
|
struct CGlueObjContainer {
|
||
|
typedef C Context;
|
||
|
T instance;
|
||
|
C context;
|
||
|
RustMaybeUninit<R> ret_tmp;
|
||
|
|
||
|
inline Context clone_context() noexcept {
|
||
|
return context.clone();
|
||
|
}
|
||
|
|
||
|
inline void drop() && noexcept {
|
||
|
mem_drop(std::move(instance));
|
||
|
mem_drop(std::move(context));
|
||
|
}
|
||
|
|
||
|
inline void forget() noexcept {
|
||
|
mem_forget(instance);
|
||
|
mem_forget(context);
|
||
|
}
|
||
|
};
|
||
|
|
||
|
template<typename T, typename R>
|
||
|
struct CGlueObjContainer<T, void, R> {
|
||
|
typedef void Context;
|
||
|
T instance;
|
||
|
RustMaybeUninit<R> ret_tmp;
|
||
|
|
||
|
inline Context clone_context() noexcept {}
|
||
|
|
||
|
inline void drop() && noexcept {
|
||
|
mem_drop(std::move(instance));
|
||
|
}
|
||
|
|
||
|
inline void forget() noexcept {
|
||
|
mem_forget(instance);
|
||
|
}
|
||
|
};
|
||
|
|
||
|
template<typename T, typename C>
|
||
|
struct CGlueObjContainer<T, C, void> {
|
||
|
typedef C Context;
|
||
|
T instance;
|
||
|
C context;
|
||
|
|
||
|
inline Context clone_context() noexcept {
|
||
|
return context.clone();
|
||
|
}
|
||
|
|
||
|
void drop() && noexcept {
|
||
|
mem_drop(std::move(instance));
|
||
|
mem_drop(std::move(context));
|
||
|
}
|
||
|
|
||
|
void forget() noexcept {
|
||
|
mem_forget(instance);
|
||
|
mem_forget(context);
|
||
|
}
|
||
|
};
|
||
|
|
||
|
template<typename T>
|
||
|
struct CGlueObjContainer<T, void, void> {
|
||
|
typedef void Context;
|
||
|
T instance;
|
||
|
|
||
|
inline Context clone_context() noexcept {}
|
||
|
|
||
|
inline void drop() && noexcept {
|
||
|
mem_drop(std::move(instance));
|
||
|
}
|
||
|
|
||
|
inline void forget() noexcept {
|
||
|
mem_forget(instance);
|
||
|
}
|
||
|
};
|
||
|
|
||
|
/**
|
||
|
* MemData type for regular memory reads.
|
||
|
*/
|
||
|
using ReadDataRaw = CTup3<Address, Address, CSliceMut<uint8_t>>;
|
||
|
|
||
|
using ReadRawMemOps = MemOps<ReadDataRaw, ReadData>;
|
||
|
|
||
|
/**
|
||
|
* MemData type for regular memory writes.
|
||
|
*/
|
||
|
using WriteDataRaw = CTup3<Address, Address, CSliceRef<uint8_t>>;
|
||
|
|
||
|
using WriteRawMemOps = MemOps<WriteDataRaw, WriteData>;
|
||
|
|
||
|
struct MemoryViewMetadata {
|
||
|
Address max_address;
|
||
|
umem real_size;
|
||
|
bool readonly;
|
||
|
bool little_endian;
|
||
|
uint8_t arch_bits;
|
||
|
};
|
||
|
|
||
|
using ReadCallback = OpaqueCallback<ReadData>;
|
||
|
|
||
|
using WriteCallback = OpaqueCallback<WriteData>;
|
||
|
|
||
|
/**
|
||
|
* CGlue vtable for trait MemoryView.
|
||
|
*
|
||
|
* This virtual function table contains ABI-safe interface for the given trait.
|
||
|
*/
|
||
|
template<typename CGlueC>
|
||
|
struct MemoryViewVtbl {
|
||
|
typedef typename CGlueC::Context Context;
|
||
|
int32_t (*read_raw_iter)(CGlueC *cont, ReadRawMemOps data);
|
||
|
int32_t (*write_raw_iter)(CGlueC *cont, WriteRawMemOps data);
|
||
|
MemoryViewMetadata (*metadata)(const CGlueC *cont);
|
||
|
int32_t (*read_iter)(CGlueC *cont,
|
||
|
CIterator<ReadData> inp,
|
||
|
ReadCallback *out,
|
||
|
ReadCallback *out_fail);
|
||
|
int32_t (*read_raw_list)(CGlueC *cont, CSliceMut<ReadData> data);
|
||
|
int32_t (*read_raw_into)(CGlueC *cont, Address addr, CSliceMut<uint8_t> out);
|
||
|
int32_t (*write_iter)(CGlueC *cont,
|
||
|
CIterator<WriteData> inp,
|
||
|
WriteCallback *out,
|
||
|
WriteCallback *out_fail);
|
||
|
int32_t (*write_raw_list)(CGlueC *cont, CSliceRef<WriteData> data);
|
||
|
int32_t (*write_raw)(CGlueC *cont, Address addr, CSliceRef<uint8_t> data);
|
||
|
};
|
||
|
|
||
|
template<typename Impl>
|
||
|
struct MemoryViewVtblImpl : MemoryViewVtbl<typename Impl::Parent> {
|
||
|
constexpr MemoryViewVtblImpl() :
|
||
|
MemoryViewVtbl<typename Impl::Parent> {
|
||
|
&Impl::read_raw_iter,
|
||
|
&Impl::write_raw_iter,
|
||
|
&Impl::metadata,
|
||
|
&Impl::read_iter,
|
||
|
&Impl::read_raw_list,
|
||
|
&Impl::read_raw_into,
|
||
|
&Impl::write_iter,
|
||
|
&Impl::write_raw_list,
|
||
|
&Impl::write_raw
|
||
|
} {}
|
||
|
};
|
||
|
|
||
|
/**
|
||
|
* Simple CGlue trait object.
|
||
|
*
|
||
|
* This is the simplest form of CGlue object, represented by a container and vtable for a single
|
||
|
* trait.
|
||
|
*
|
||
|
* Container merely is a this pointer with some optional temporary return reference context.
|
||
|
*/
|
||
|
template<typename T, typename V, typename C, typename R>
|
||
|
struct CGlueTraitObj {
|
||
|
const V *vtbl;
|
||
|
CGlueObjContainer<T, C, R> container;
|
||
|
};
|
||
|
|
||
|
/**
|
||
|
* Base CGlue trait object for trait MemoryView.
|
||
|
*/
|
||
|
template<typename CGlueInst = CBox<void>, typename CGlueCtx = CArc<void>>
|
||
|
using MemoryViewBase = CGlueTraitObj<CGlueInst, MemoryViewVtbl<CGlueObjContainer<CGlueInst, CGlueCtx, MemoryViewRetTmp<CGlueCtx>>>, CGlueCtx, MemoryViewRetTmp<CGlueCtx>>;
|
||
|
|
||
|
/**
|
||
|
* CGlue vtable for trait PhysicalMemory.
|
||
|
*
|
||
|
* This virtual function table contains ABI-safe interface for the given trait.
|
||
|
*/
|
||
|
template<typename CGlueC>
|
||
|
struct PhysicalMemoryVtbl {
|
||
|
typedef typename CGlueC::Context Context;
|
||
|
int32_t (*phys_read_raw_iter)(CGlueC *cont, PhysicalReadMemOps data);
|
||
|
int32_t (*phys_write_raw_iter)(CGlueC *cont, PhysicalWriteMemOps data);
|
||
|
PhysicalMemoryMetadata (*metadata)(const CGlueC *cont);
|
||
|
void (*set_mem_map)(CGlueC *cont, CSliceRef<PhysicalMemoryMapping> _mem_map);
|
||
|
MemoryViewBase<CBox<void>, Context> (*into_phys_view)(CGlueC cont);
|
||
|
MemoryViewBase<CBox<void>, Context> (*phys_view)(CGlueC *cont);
|
||
|
};
|
||
|
|
||
|
template<typename Impl>
|
||
|
struct PhysicalMemoryVtblImpl : PhysicalMemoryVtbl<typename Impl::Parent> {
|
||
|
constexpr PhysicalMemoryVtblImpl() :
|
||
|
PhysicalMemoryVtbl<typename Impl::Parent> {
|
||
|
&Impl::phys_read_raw_iter,
|
||
|
&Impl::phys_write_raw_iter,
|
||
|
&Impl::metadata,
|
||
|
&Impl::set_mem_map,
|
||
|
&Impl::into_phys_view,
|
||
|
&Impl::phys_view
|
||
|
} {}
|
||
|
};
|
||
|
|
||
|
/**
|
||
|
* CGlue vtable for trait CpuState.
|
||
|
*
|
||
|
* This virtual function table contains ABI-safe interface for the given trait.
|
||
|
*/
|
||
|
template<typename CGlueC>
|
||
|
struct CpuStateVtbl {
|
||
|
typedef typename CGlueC::Context Context;
|
||
|
void (*pause)(CGlueC *cont);
|
||
|
void (*resume)(CGlueC *cont);
|
||
|
};
|
||
|
|
||
|
template<typename Impl>
|
||
|
struct CpuStateVtblImpl : CpuStateVtbl<typename Impl::Parent> {
|
||
|
constexpr CpuStateVtblImpl() :
|
||
|
CpuStateVtbl<typename Impl::Parent> {
|
||
|
&Impl::pause,
|
||
|
&Impl::resume
|
||
|
} {}
|
||
|
};
|
||
|
|
||
|
/**
|
||
|
* Base CGlue trait object for trait CpuState.
|
||
|
*/
|
||
|
template<typename CGlueInst = CBox<void>, typename CGlueCtx = CArc<void>>
|
||
|
using CpuStateBase = CGlueTraitObj<CGlueInst, CpuStateVtbl<CGlueObjContainer<CGlueInst, CGlueCtx, CpuStateRetTmp<CGlueCtx>>>, CGlueCtx, CpuStateRetTmp<CGlueCtx>>;
|
||
|
|
||
|
template<typename CGlueInst = CBox<void>, typename CGlueCtx = CArc<void>>
|
||
|
struct IntoCpuStateContainer {
|
||
|
typedef CGlueCtx Context;
|
||
|
CGlueInst instance;
|
||
|
CGlueCtx context;
|
||
|
|
||
|
inline Context clone_context() noexcept {
|
||
|
return context.clone();
|
||
|
}
|
||
|
|
||
|
inline void drop() && noexcept {
|
||
|
mem_drop(std::move(instance));
|
||
|
mem_drop(std::move(context));
|
||
|
}
|
||
|
|
||
|
inline void forget() noexcept {
|
||
|
mem_forget(instance);
|
||
|
mem_forget(context);
|
||
|
}
|
||
|
};
|
||
|
|
||
|
template<typename CGlueInst>
|
||
|
struct IntoCpuStateContainer<CGlueInst, void> {
|
||
|
typedef void Context;
|
||
|
CGlueInst instance;
|
||
|
|
||
|
inline Context clone_context() noexcept {}
|
||
|
|
||
|
inline void drop() && noexcept {
|
||
|
mem_drop(std::move(instance));
|
||
|
}
|
||
|
|
||
|
inline void forget() noexcept {
|
||
|
mem_forget(instance);
|
||
|
}
|
||
|
};
|
||
|
|
||
|
/**
|
||
|
* Trait group potentially implementing `:: cglue :: ext :: core :: clone :: Clone < > + CpuState < >` traits.
|
||
|
*
|
||
|
* Optional traits are not implemented here, however. There are numerous conversion
|
||
|
* functions available for safely retrieving a concrete collection of traits.
|
||
|
*
|
||
|
* `check_impl_` functions allow to check if the object implements the wanted traits.
|
||
|
*
|
||
|
* `into_impl_` functions consume the object and produce a new final structure that
|
||
|
* keeps only the required information.
|
||
|
*
|
||
|
* `cast_impl_` functions merely check and transform the object into a type that can
|
||
|
*be transformed back into `IntoCpuState` without losing data.
|
||
|
*
|
||
|
* `as_ref_`, and `as_mut_` functions obtain references to safe objects, but do not
|
||
|
* perform any memory transformations either. They are the safest to use, because
|
||
|
* there is no risk of accidentally consuming the whole object.
|
||
|
*/
|
||
|
template<typename CGlueInst = CBox<void>, typename CGlueCtx = CArc<void>>
|
||
|
struct IntoCpuState {
|
||
|
const CloneVtbl<IntoCpuStateContainer<CGlueInst, CGlueCtx>> *vtbl_clone;
|
||
|
const CpuStateVtbl<IntoCpuStateContainer<CGlueInst, CGlueCtx>> *vtbl_cpustate;
|
||
|
IntoCpuStateContainer<CGlueInst, CGlueCtx> container;
|
||
|
|
||
|
IntoCpuState() : container{} , vtbl_clone{}, vtbl_cpustate{} {}
|
||
|
|
||
|
~IntoCpuState() noexcept {
|
||
|
mem_drop(std::move(container));
|
||
|
}
|
||
|
|
||
|
typedef CGlueCtx Context;
|
||
|
|
||
|
inline IntoCpuState clone() const noexcept {
|
||
|
IntoCpuState __ret;
|
||
|
__ret.vtbl_clone = this->vtbl_clone;
|
||
|
__ret.vtbl_cpustate = this->vtbl_cpustate;
|
||
|
__ret.container = (this->vtbl_clone)->clone(&this->container);
|
||
|
return __ret;
|
||
|
}
|
||
|
|
||
|
inline void pause() noexcept {
|
||
|
(this->vtbl_cpustate)->pause(&this->container);
|
||
|
|
||
|
}
|
||
|
|
||
|
inline void resume() noexcept {
|
||
|
(this->vtbl_cpustate)->resume(&this->container);
|
||
|
|
||
|
}
|
||
|
|
||
|
};
|
||
|
|
||
|
/**
|
||
|
* CGlue vtable for trait ConnectorCpuState.
|
||
|
*
|
||
|
* This virtual function table contains ABI-safe interface for the given trait.
|
||
|
*/
|
||
|
template<typename CGlueC>
|
||
|
struct ConnectorCpuStateVtbl {
|
||
|
typedef typename CGlueC::Context Context;
|
||
|
int32_t (*cpu_state)(CGlueC *cont, CpuStateBase<CBox<void>, Context> *ok_out);
|
||
|
int32_t (*into_cpu_state)(CGlueC cont, IntoCpuState<CBox<void>, Context> *ok_out);
|
||
|
};
|
||
|
|
||
|
template<typename Impl>
|
||
|
struct ConnectorCpuStateVtblImpl : ConnectorCpuStateVtbl<typename Impl::Parent> {
|
||
|
constexpr ConnectorCpuStateVtblImpl() :
|
||
|
ConnectorCpuStateVtbl<typename Impl::Parent> {
|
||
|
&Impl::cpu_state,
|
||
|
&Impl::into_cpu_state
|
||
|
} {}
|
||
|
};
|
||
|
|
||
|
/**
|
||
|
* Trait group potentially implementing `:: cglue :: ext :: core :: clone :: Clone < > + PhysicalMemory < > + ConnectorCpuState < >` traits.
|
||
|
*
|
||
|
* Optional traits are not implemented here, however. There are numerous conversion
|
||
|
* functions available for safely retrieving a concrete collection of traits.
|
||
|
*
|
||
|
* `check_impl_` functions allow to check if the object implements the wanted traits.
|
||
|
*
|
||
|
* `into_impl_` functions consume the object and produce a new final structure that
|
||
|
* keeps only the required information.
|
||
|
*
|
||
|
* `cast_impl_` functions merely check and transform the object into a type that can
|
||
|
*be transformed back into `ConnectorInstance` without losing data.
|
||
|
*
|
||
|
* `as_ref_`, and `as_mut_` functions obtain references to safe objects, but do not
|
||
|
* perform any memory transformations either. They are the safest to use, because
|
||
|
* there is no risk of accidentally consuming the whole object.
|
||
|
*/
|
||
|
template<typename CGlueInst = CBox<void>, typename CGlueCtx = CArc<void>>
|
||
|
struct ConnectorInstance {
|
||
|
const CloneVtbl<ConnectorInstanceContainer<CGlueInst, CGlueCtx>> *vtbl_clone;
|
||
|
const PhysicalMemoryVtbl<ConnectorInstanceContainer<CGlueInst, CGlueCtx>> *vtbl_physicalmemory;
|
||
|
const ConnectorCpuStateVtbl<ConnectorInstanceContainer<CGlueInst, CGlueCtx>> *vtbl_connectorcpustate;
|
||
|
ConnectorInstanceContainer<CGlueInst, CGlueCtx> container;
|
||
|
|
||
|
ConnectorInstance() : container{} , vtbl_clone{}, vtbl_physicalmemory{}, vtbl_connectorcpustate{} {}
|
||
|
|
||
|
~ConnectorInstance() noexcept {
|
||
|
mem_drop(std::move(container));
|
||
|
}
|
||
|
|
||
|
typedef CGlueCtx Context;
|
||
|
|
||
|
inline ConnectorInstance clone() const noexcept {
|
||
|
ConnectorInstance __ret;
|
||
|
__ret.vtbl_clone = this->vtbl_clone;
|
||
|
__ret.vtbl_physicalmemory = this->vtbl_physicalmemory;
|
||
|
__ret.vtbl_connectorcpustate = this->vtbl_connectorcpustate;
|
||
|
__ret.container = (this->vtbl_clone)->clone(&this->container);
|
||
|
return __ret;
|
||
|
}
|
||
|
|
||
|
inline int32_t phys_read_raw_iter(PhysicalReadMemOps data) noexcept {
|
||
|
int32_t __ret = (this->vtbl_physicalmemory)->phys_read_raw_iter(&this->container, data);
|
||
|
return __ret;
|
||
|
}
|
||
|
|
||
|
inline int32_t phys_write_raw_iter(PhysicalWriteMemOps data) noexcept {
|
||
|
int32_t __ret = (this->vtbl_physicalmemory)->phys_write_raw_iter(&this->container, data);
|
||
|
return __ret;
|
||
|
}
|
||
|
|
||
|
inline PhysicalMemoryMetadata metadata() const noexcept {
|
||
|
PhysicalMemoryMetadata __ret = (this->vtbl_physicalmemory)->metadata(&this->container);
|
||
|
return __ret;
|
||
|
}
|
||
|
|
||
|
inline void set_mem_map(CSliceRef<PhysicalMemoryMapping> _mem_map) noexcept {
|
||
|
(this->vtbl_physicalmemory)->set_mem_map(&this->container, _mem_map);
|
||
|
|
||
|
}
|
||
|
|
||
|
inline MemoryViewBase<CBox<void>, Context> into_phys_view() && noexcept {
|
||
|
auto ___ctx = StoreAll()[this->container.clone_context(), StoreAll()];
|
||
|
MemoryViewBase<CBox<void>, Context> __ret = (this->vtbl_physicalmemory)->into_phys_view(this->container);
|
||
|
mem_forget(this->container);
|
||
|
return __ret;
|
||
|
}
|
||
|
|
||
|
inline MemoryViewBase<CBox<void>, Context> phys_view() noexcept {
|
||
|
MemoryViewBase<CBox<void>, Context> __ret = (this->vtbl_physicalmemory)->phys_view(&this->container);
|
||
|
return __ret;
|
||
|
}
|
||
|
|
||
|
inline int32_t cpu_state(CpuStateBase<CBox<void>, Context> * ok_out) noexcept {
|
||
|
int32_t __ret = (this->vtbl_connectorcpustate)->cpu_state(&this->container, ok_out);
|
||
|
return __ret;
|
||
|
}
|
||
|
|
||
|
inline int32_t into_cpu_state(IntoCpuState<CBox<void>, Context> * ok_out) && noexcept {
|
||
|
auto ___ctx = StoreAll()[this->container.clone_context(), StoreAll()];
|
||
|
int32_t __ret = (this->vtbl_connectorcpustate)->into_cpu_state(this->container, ok_out);
|
||
|
mem_forget(this->container);
|
||
|
return __ret;
|
||
|
}
|
||
|
|
||
|
};
|
||
|
|
||
|
template<typename CGlueT, typename CGlueCtx = CArc<void>>
|
||
|
using ConnectorInstanceBaseCtxBox = ConnectorInstance<CBox<CGlueT>, CGlueCtx>;
|
||
|
|
||
|
template<typename CGlueT, typename CGlueArcTy>
|
||
|
using ConnectorInstanceBaseArcBox = ConnectorInstanceBaseCtxBox<CGlueT, CArc<CGlueArcTy>>;
|
||
|
// Typedef for default contaienr and context type
|
||
|
template<typename CGlueT, typename CGlueArcTy>
|
||
|
using ConnectorInstanceBase = ConnectorInstanceBaseArcBox<CGlueT,CGlueArcTy>;
|
||
|
|
||
|
using ConnectorInstanceArcBox = ConnectorInstanceBaseArcBox<void, void>;
|
||
|
|
||
|
using MuConnectorInstanceArcBox = ConnectorInstanceArcBox;
|
||
|
// Typedef for default contaienr and context type
|
||
|
using MuConnectorInstance = MuConnectorInstanceArcBox;
|
||
|
|
||
|
template<typename CGlueInst = CBox<void>, typename CGlueCtx = CArc<void>>
|
||
|
struct OsInstanceContainer {
|
||
|
typedef CGlueCtx Context;
|
||
|
CGlueInst instance;
|
||
|
CGlueCtx context;
|
||
|
|
||
|
inline Context clone_context() noexcept {
|
||
|
return context.clone();
|
||
|
}
|
||
|
|
||
|
inline void drop() && noexcept {
|
||
|
mem_drop(std::move(instance));
|
||
|
mem_drop(std::move(context));
|
||
|
}
|
||
|
|
||
|
inline void forget() noexcept {
|
||
|
mem_forget(instance);
|
||
|
mem_forget(context);
|
||
|
}
|
||
|
};
|
||
|
|
||
|
template<typename CGlueInst>
|
||
|
struct OsInstanceContainer<CGlueInst, void> {
|
||
|
typedef void Context;
|
||
|
CGlueInst instance;
|
||
|
|
||
|
inline Context clone_context() noexcept {}
|
||
|
|
||
|
inline void drop() && noexcept {
|
||
|
mem_drop(std::move(instance));
|
||
|
}
|
||
|
|
||
|
inline void forget() noexcept {
|
||
|
mem_forget(instance);
|
||
|
}
|
||
|
};
|
||
|
|
||
|
using AddressCallback = OpaqueCallback<Address>;
|
||
|
|
||
|
/**
|
||
|
* Type meant for process IDs
|
||
|
*
|
||
|
* If there is a case where Pid can be over 32-bit limit, or negative, please open an issue, we
|
||
|
* would love to see that.
|
||
|
*/
|
||
|
using Pid = uint32_t;
|
||
|
|
||
|
/**
|
||
|
* Exit code of a process
|
||
|
*/
|
||
|
using ExitCode = int32_t;
|
||
|
|
||
|
/**
|
||
|
* The state of a process
|
||
|
*
|
||
|
* # Remarks
|
||
|
*
|
||
|
* In case the exit code isn't known ProcessState::Unknown is set.
|
||
|
*/
|
||
|
struct ProcessState {
|
||
|
enum class Tag {
|
||
|
ProcessState_Unknown,
|
||
|
ProcessState_Alive,
|
||
|
ProcessState_Dead,
|
||
|
};
|
||
|
|
||
|
struct ProcessState_Dead_Body {
|
||
|
ExitCode _0;
|
||
|
};
|
||
|
|
||
|
Tag tag;
|
||
|
union {
|
||
|
ProcessState_Dead_Body dead;
|
||
|
};
|
||
|
};
|
||
|
|
||
|
/**
|
||
|
* Wrapper around null-terminated C-style strings.
|
||
|
*
|
||
|
* Analog to Rust's `String`, [`ReprCString`] owns the underlying data.
|
||
|
*/
|
||
|
using ReprCString = char*;
|
||
|
|
||
|
struct ArchitectureIdent {
|
||
|
enum class Tag {
|
||
|
/**
|
||
|
* Unknown architecture. Could be third-party implemented. memflow knows how to work on them,
|
||
|
* but is unable to instantiate them.
|
||
|
*/
|
||
|
ArchitectureIdent_Unknown,
|
||
|
/**
|
||
|
* X86 with specified bitness and address extensions
|
||
|
*
|
||
|
* First argument - `bitness` controls whether it's 32, or 64 bit variant.
|
||
|
* Second argument - `address_extensions` control whether address extensions are
|
||
|
* enabled (PAE on x32, or LA57 on x64). Warning: LA57 is currently unsupported.
|
||
|
*/
|
||
|
ArchitectureIdent_X86,
|
||
|
/**
|
||
|
* Arm 64-bit architecture with specified page size
|
||
|
*
|
||
|
* Valid page sizes are 4kb, 16kb, 64kb. Only 4kb is supported at the moment
|
||
|
*/
|
||
|
ArchitectureIdent_AArch64,
|
||
|
};
|
||
|
|
||
|
struct ArchitectureIdent_Unknown_Body {
|
||
|
uintptr_t _0;
|
||
|
};
|
||
|
|
||
|
struct ArchitectureIdent_X86_Body {
|
||
|
uint8_t _0;
|
||
|
bool _1;
|
||
|
};
|
||
|
|
||
|
struct ArchitectureIdent_AArch64_Body {
|
||
|
uintptr_t _0;
|
||
|
};
|
||
|
|
||
|
Tag tag;
|
||
|
union {
|
||
|
ArchitectureIdent_Unknown_Body unknown;
|
||
|
ArchitectureIdent_X86_Body x86;
|
||
|
ArchitectureIdent_AArch64_Body a_arch64;
|
||
|
};
|
||
|
};
|
||
|
|
||
|
/**
|
||
|
* Process information structure
|
||
|
*
|
||
|
* This structure implements basic process information. Architectures are provided both of the
|
||
|
* system, and of the process.
|
||
|
*/
|
||
|
struct ProcessInfo {
|
||
|
/**
|
||
|
* The base address of this process.
|
||
|
*
|
||
|
* # Remarks
|
||
|
*
|
||
|
* On Windows this will be the address of the [`_EPROCESS`](https://www.nirsoft.net/kernel_struct/vista/EPROCESS.html) structure.
|
||
|
*/
|
||
|
Address address;
|
||
|
/**
|
||
|
* ID of this process.
|
||
|
*/
|
||
|
Pid pid;
|
||
|
/**
|
||
|
* The current status of the process at the time when this process info was fetched.
|
||
|
*
|
||
|
* # Remarks
|
||
|
*
|
||
|
* This field is highly volatile and can be re-checked with the [`Process::state()`] function.
|
||
|
*/
|
||
|
ProcessState state;
|
||
|
/**
|
||
|
* Name of the process.
|
||
|
*/
|
||
|
ReprCString name;
|
||
|
/**
|
||
|
* Path of the process binary
|
||
|
*/
|
||
|
ReprCString path;
|
||
|
/**
|
||
|
* Command line the process was started with.
|
||
|
*/
|
||
|
ReprCString command_line;
|
||
|
/**
|
||
|
* System architecture of the target system.
|
||
|
*/
|
||
|
ArchitectureIdent sys_arch;
|
||
|
/**
|
||
|
* Process architecture
|
||
|
*
|
||
|
* # Remarks
|
||
|
*
|
||
|
* Specifically on 64-bit systems this could be different
|
||
|
* to the `sys_arch` in case the process is an emulated 32-bit process.
|
||
|
*
|
||
|
* On windows this technique is called [`WOW64`](https://docs.microsoft.com/en-us/windows/win32/winprog64/wow64-implementation-details).
|
||
|
*/
|
||
|
ArchitectureIdent proc_arch;
|
||
|
/**
|
||
|
* Directory Table Base
|
||
|
*
|
||
|
* # Remarks
|
||
|
*
|
||
|
* These fields contain the translation base used to translate virtual memory addresses into physical memory addresses.
|
||
|
* On x86 systems only `dtb1` is set because only one dtb is used.
|
||
|
* On arm systems both `dtb1` and `dtb2` are set to their corresponding values.
|
||
|
*/
|
||
|
Address dtb1;
|
||
|
Address dtb2;
|
||
|
};
|
||
|
|
||
|
using ProcessInfoCallback = OpaqueCallback<ProcessInfo>;
|
||
|
|
||
|
template<typename CGlueInst = CBox<void>, typename CGlueCtx = CArc<void>>
|
||
|
struct ProcessInstanceContainer {
|
||
|
typedef CGlueCtx Context;
|
||
|
CGlueInst instance;
|
||
|
CGlueCtx context;
|
||
|
|
||
|
inline Context clone_context() noexcept {
|
||
|
return context.clone();
|
||
|
}
|
||
|
|
||
|
inline void drop() && noexcept {
|
||
|
mem_drop(std::move(instance));
|
||
|
mem_drop(std::move(context));
|
||
|
}
|
||
|
|
||
|
inline void forget() noexcept {
|
||
|
mem_forget(instance);
|
||
|
mem_forget(context);
|
||
|
}
|
||
|
};
|
||
|
|
||
|
template<typename CGlueInst>
|
||
|
struct ProcessInstanceContainer<CGlueInst, void> {
|
||
|
typedef void Context;
|
||
|
CGlueInst instance;
|
||
|
|
||
|
inline Context clone_context() noexcept {}
|
||
|
|
||
|
inline void drop() && noexcept {
|
||
|
mem_drop(std::move(instance));
|
||
|
}
|
||
|
|
||
|
inline void forget() noexcept {
|
||
|
mem_forget(instance);
|
||
|
}
|
||
|
};
|
||
|
|
||
|
/**
|
||
|
* Pair of address and architecture used for callbacks
|
||
|
*/
|
||
|
struct ModuleAddressInfo {
|
||
|
Address address;
|
||
|
ArchitectureIdent arch;
|
||
|
};
|
||
|
|
||
|
using ModuleAddressCallback = OpaqueCallback<ModuleAddressInfo>;
|
||
|
|
||
|
/**
|
||
|
* Module information structure
|
||
|
*/
|
||
|
struct ModuleInfo {
|
||
|
/**
|
||
|
* Returns the address of the module header.
|
||
|
*
|
||
|
* # Remarks
|
||
|
*
|
||
|
* On Windows this will be the address where the [`PEB`](https://docs.microsoft.com/en-us/windows/win32/api/winternl/ns-winternl-peb) entry is stored.
|
||
|
*/
|
||
|
Address address;
|
||
|
/**
|
||
|
* The base address of the parent process.
|
||
|
*
|
||
|
* # Remarks
|
||
|
*
|
||
|
* This field is analog to the `ProcessInfo::address` field.
|
||
|
*/
|
||
|
Address parent_process;
|
||
|
/**
|
||
|
* The actual base address of this module.
|
||
|
*
|
||
|
* # Remarks
|
||
|
*
|
||
|
* The base address is contained in the virtual address range of the process
|
||
|
* this module belongs to.
|
||
|
*/
|
||
|
Address base;
|
||
|
/**
|
||
|
* Size of the module
|
||
|
*/
|
||
|
umem size;
|
||
|
/**
|
||
|
* Name of the module
|
||
|
*/
|
||
|
ReprCString name;
|
||
|
/**
|
||
|
* Path of the module
|
||
|
*/
|
||
|
ReprCString path;
|
||
|
/**
|
||
|
* Architecture of the module
|
||
|
*
|
||
|
* # Remarks
|
||
|
*
|
||
|
* Emulated processes often have 2 separate lists of modules, one visible to the emulated
|
||
|
* context (e.g. all 32-bit modules in a WoW64 process), and the other for all native modules
|
||
|
* needed to support the process emulation. This should be equal to either
|
||
|
* `ProcessInfo::proc_arch`, or `ProcessInfo::sys_arch` of the parent process.
|
||
|
*/
|
||
|
ArchitectureIdent arch;
|
||
|
};
|
||
|
|
||
|
using ModuleInfoCallback = OpaqueCallback<ModuleInfo>;
|
||
|
|
||
|
/**
|
||
|
* Import information structure
|
||
|
*/
|
||
|
struct ImportInfo {
|
||
|
/**
|
||
|
* Name of the import
|
||
|
*/
|
||
|
ReprCString name;
|
||
|
/**
|
||
|
* Offset of this import from the containing modules base address
|
||
|
*/
|
||
|
umem offset;
|
||
|
};
|
||
|
|
||
|
using ImportCallback = OpaqueCallback<ImportInfo>;
|
||
|
|
||
|
/**
|
||
|
* Export information structure
|
||
|
*/
|
||
|
struct ExportInfo {
|
||
|
/**
|
||
|
* Name of the export
|
||
|
*/
|
||
|
ReprCString name;
|
||
|
/**
|
||
|
* Offset of this export from the containing modules base address
|
||
|
*/
|
||
|
umem offset;
|
||
|
};
|
||
|
|
||
|
using ExportCallback = OpaqueCallback<ExportInfo>;
|
||
|
|
||
|
/**
|
||
|
* Section information structure
|
||
|
*/
|
||
|
struct SectionInfo {
|
||
|
/**
|
||
|
* Name of the section
|
||
|
*/
|
||
|
ReprCString name;
|
||
|
/**
|
||
|
* Virtual address of this section (essentially module_info.base + virtual_address)
|
||
|
*/
|
||
|
Address base;
|
||
|
/**
|
||
|
* Size of this section
|
||
|
*/
|
||
|
umem size;
|
||
|
};
|
||
|
|
||
|
using SectionCallback = OpaqueCallback<SectionInfo>;
|
||
|
|
||
|
using imem = int64_t;
|
||
|
|
||
|
using MemoryRange = CTup3<Address, umem, PageType>;
|
||
|
|
||
|
using MemoryRangeCallback = OpaqueCallback<MemoryRange>;
|
||
|
|
||
|
/**
|
||
|
* CGlue vtable for trait Process.
|
||
|
*
|
||
|
* This virtual function table contains ABI-safe interface for the given trait.
|
||
|
*/
|
||
|
template<typename CGlueC>
|
||
|
struct ProcessVtbl {
|
||
|
typedef typename CGlueC::Context Context;
|
||
|
ProcessState (*state)(CGlueC *cont);
|
||
|
int32_t (*set_dtb)(CGlueC *cont, Address dtb1, Address dtb2);
|
||
|
int32_t (*module_address_list_callback)(CGlueC *cont,
|
||
|
const ArchitectureIdent *target_arch,
|
||
|
ModuleAddressCallback callback);
|
||
|
int32_t (*module_list_callback)(CGlueC *cont,
|
||
|
const ArchitectureIdent *target_arch,
|
||
|
ModuleInfoCallback callback);
|
||
|
int32_t (*module_by_address)(CGlueC *cont,
|
||
|
Address address,
|
||
|
ArchitectureIdent architecture,
|
||
|
ModuleInfo *ok_out);
|
||
|
int32_t (*module_by_name_arch)(CGlueC *cont,
|
||
|
CSliceRef<uint8_t> name,
|
||
|
const ArchitectureIdent *architecture,
|
||
|
ModuleInfo *ok_out);
|
||
|
int32_t (*module_by_name)(CGlueC *cont, CSliceRef<uint8_t> name, ModuleInfo *ok_out);
|
||
|
int32_t (*primary_module_address)(CGlueC *cont, Address *ok_out);
|
||
|
int32_t (*primary_module)(CGlueC *cont, ModuleInfo *ok_out);
|
||
|
int32_t (*module_import_list_callback)(CGlueC *cont,
|
||
|
const ModuleInfo *info,
|
||
|
ImportCallback callback);
|
||
|
int32_t (*module_export_list_callback)(CGlueC *cont,
|
||
|
const ModuleInfo *info,
|
||
|
ExportCallback callback);
|
||
|
int32_t (*module_section_list_callback)(CGlueC *cont,
|
||
|
const ModuleInfo *info,
|
||
|
SectionCallback callback);
|
||
|
int32_t (*module_import_by_name)(CGlueC *cont,
|
||
|
const ModuleInfo *info,
|
||
|
CSliceRef<uint8_t> name,
|
||
|
ImportInfo *ok_out);
|
||
|
int32_t (*module_export_by_name)(CGlueC *cont,
|
||
|
const ModuleInfo *info,
|
||
|
CSliceRef<uint8_t> name,
|
||
|
ExportInfo *ok_out);
|
||
|
int32_t (*module_section_by_name)(CGlueC *cont,
|
||
|
const ModuleInfo *info,
|
||
|
CSliceRef<uint8_t> name,
|
||
|
SectionInfo *ok_out);
|
||
|
const ProcessInfo *(*info)(const CGlueC *cont);
|
||
|
void (*mapped_mem_range)(CGlueC *cont,
|
||
|
imem gap_size,
|
||
|
Address start,
|
||
|
Address end,
|
||
|
MemoryRangeCallback out);
|
||
|
void (*mapped_mem)(CGlueC *cont, imem gap_size, MemoryRangeCallback out);
|
||
|
};
|
||
|
|
||
|
template<typename Impl>
|
||
|
struct ProcessVtblImpl : ProcessVtbl<typename Impl::Parent> {
|
||
|
constexpr ProcessVtblImpl() :
|
||
|
ProcessVtbl<typename Impl::Parent> {
|
||
|
&Impl::state,
|
||
|
&Impl::set_dtb,
|
||
|
&Impl::module_address_list_callback,
|
||
|
&Impl::module_list_callback,
|
||
|
&Impl::module_by_address,
|
||
|
&Impl::module_by_name_arch,
|
||
|
&Impl::module_by_name,
|
||
|
&Impl::primary_module_address,
|
||
|
&Impl::primary_module,
|
||
|
&Impl::module_import_list_callback,
|
||
|
&Impl::module_export_list_callback,
|
||
|
&Impl::module_section_list_callback,
|
||
|
&Impl::module_import_by_name,
|
||
|
&Impl::module_export_by_name,
|
||
|
&Impl::module_section_by_name,
|
||
|
&Impl::info,
|
||
|
&Impl::mapped_mem_range,
|
||
|
&Impl::mapped_mem
|
||
|
} {}
|
||
|
};
|
||
|
|
||
|
using VtopRange = CTup2<Address, umem>;
|
||
|
|
||
|
/**
|
||
|
* Virtual page range information with physical mappings used for callbacks
|
||
|
*/
|
||
|
struct VirtualTranslation {
|
||
|
Address in_virtual;
|
||
|
umem size;
|
||
|
PhysicalAddress out_physical;
|
||
|
};
|
||
|
|
||
|
using VirtualTranslationCallback = OpaqueCallback<VirtualTranslation>;
|
||
|
|
||
|
struct VirtualTranslationFail {
|
||
|
Address from;
|
||
|
umem size;
|
||
|
};
|
||
|
|
||
|
using VirtualTranslationFailCallback = OpaqueCallback<VirtualTranslationFail>;
|
||
|
|
||
|
/**
|
||
|
* A `Page` holds information about a memory page.
|
||
|
*
|
||
|
* More information about paging can be found [here](https://en.wikipedia.org/wiki/Paging).
|
||
|
*/
|
||
|
struct Page {
|
||
|
/**
|
||
|
* Contains the page type (see above).
|
||
|
*/
|
||
|
PageType page_type;
|
||
|
/**
|
||
|
* Contains the base address of this page.
|
||
|
*/
|
||
|
Address page_base;
|
||
|
/**
|
||
|
* Contains the size of this page.
|
||
|
*/
|
||
|
umem page_size;
|
||
|
};
|
||
|
/**
|
||
|
* A page object that is invalid.
|
||
|
*/
|
||
|
constexpr static const Page Page_INVALID = Page{ /* .page_type = */ PageType_UNKNOWN, /* .page_base = */ Address_INVALID, /* .page_size = */ 0 };
|
||
|
|
||
|
/**
|
||
|
* FFI-safe Option.
|
||
|
*
|
||
|
* This type is not really meant for general use, but rather as a last-resort conversion for type
|
||
|
* wrapping.
|
||
|
*
|
||
|
* Typical workflow would include temporarily converting into/from COption.
|
||
|
*/
|
||
|
template<typename T>
|
||
|
struct COption {
|
||
|
enum class Tag {
|
||
|
COption_None,
|
||
|
COption_Some,
|
||
|
};
|
||
|
|
||
|
struct COption_Some_Body {
|
||
|
T _0;
|
||
|
};
|
||
|
|
||
|
Tag tag;
|
||
|
union {
|
||
|
COption_Some_Body some;
|
||
|
};
|
||
|
};
|
||
|
|
||
|
/**
|
||
|
* CGlue vtable for trait VirtualTranslate.
|
||
|
*
|
||
|
* This virtual function table contains ABI-safe interface for the given trait.
|
||
|
*/
|
||
|
template<typename CGlueC>
|
||
|
struct VirtualTranslateVtbl {
|
||
|
typedef typename CGlueC::Context Context;
|
||
|
void (*virt_to_phys_list)(CGlueC *cont,
|
||
|
CSliceRef<VtopRange> addrs,
|
||
|
VirtualTranslationCallback out,
|
||
|
VirtualTranslationFailCallback out_fail);
|
||
|
void (*virt_to_phys_range)(CGlueC *cont,
|
||
|
Address start,
|
||
|
Address end,
|
||
|
VirtualTranslationCallback out);
|
||
|
void (*virt_translation_map_range)(CGlueC *cont,
|
||
|
Address start,
|
||
|
Address end,
|
||
|
VirtualTranslationCallback out);
|
||
|
void (*virt_page_map_range)(CGlueC *cont,
|
||
|
imem gap_size,
|
||
|
Address start,
|
||
|
Address end,
|
||
|
MemoryRangeCallback out);
|
||
|
int32_t (*virt_to_phys)(CGlueC *cont, Address address, PhysicalAddress *ok_out);
|
||
|
int32_t (*virt_page_info)(CGlueC *cont, Address addr, Page *ok_out);
|
||
|
void (*virt_translation_map)(CGlueC *cont, VirtualTranslationCallback out);
|
||
|
COption<Address> (*phys_to_virt)(CGlueC *cont, Address phys);
|
||
|
void (*virt_page_map)(CGlueC *cont, imem gap_size, MemoryRangeCallback out);
|
||
|
};
|
||
|
|
||
|
template<typename Impl>
|
||
|
struct VirtualTranslateVtblImpl : VirtualTranslateVtbl<typename Impl::Parent> {
|
||
|
constexpr VirtualTranslateVtblImpl() :
|
||
|
VirtualTranslateVtbl<typename Impl::Parent> {
|
||
|
&Impl::virt_to_phys_list,
|
||
|
&Impl::virt_to_phys_range,
|
||
|
&Impl::virt_translation_map_range,
|
||
|
&Impl::virt_page_map_range,
|
||
|
&Impl::virt_to_phys,
|
||
|
&Impl::virt_page_info,
|
||
|
&Impl::virt_translation_map,
|
||
|
&Impl::phys_to_virt,
|
||
|
&Impl::virt_page_map
|
||
|
} {}
|
||
|
};
|
||
|
|
||
|
/**
|
||
|
* Trait group potentially implementing `MemoryView < > + Process < > + VirtualTranslate < >` traits.
|
||
|
*
|
||
|
* Optional traits are not implemented here, however. There are numerous conversion
|
||
|
* functions available for safely retrieving a concrete collection of traits.
|
||
|
*
|
||
|
* `check_impl_` functions allow to check if the object implements the wanted traits.
|
||
|
*
|
||
|
* `into_impl_` functions consume the object and produce a new final structure that
|
||
|
* keeps only the required information.
|
||
|
*
|
||
|
* `cast_impl_` functions merely check and transform the object into a type that can
|
||
|
*be transformed back into `ProcessInstance` without losing data.
|
||
|
*
|
||
|
* `as_ref_`, and `as_mut_` functions obtain references to safe objects, but do not
|
||
|
* perform any memory transformations either. They are the safest to use, because
|
||
|
* there is no risk of accidentally consuming the whole object.
|
||
|
*/
|
||
|
template<typename CGlueInst = CBox<void>, typename CGlueCtx = CArc<void>>
|
||
|
struct ProcessInstance {
|
||
|
const MemoryViewVtbl<ProcessInstanceContainer<CGlueInst, CGlueCtx>> *vtbl_memoryview;
|
||
|
const ProcessVtbl<ProcessInstanceContainer<CGlueInst, CGlueCtx>> *vtbl_process;
|
||
|
const VirtualTranslateVtbl<ProcessInstanceContainer<CGlueInst, CGlueCtx>> *vtbl_virtualtranslate;
|
||
|
ProcessInstanceContainer<CGlueInst, CGlueCtx> container;
|
||
|
|
||
|
ProcessInstance() : container{} , vtbl_memoryview{}, vtbl_process{}, vtbl_virtualtranslate{} {}
|
||
|
|
||
|
~ProcessInstance() noexcept {
|
||
|
mem_drop(std::move(container));
|
||
|
}
|
||
|
|
||
|
typedef CGlueCtx Context;
|
||
|
|
||
|
inline int32_t read_raw_iter(ReadRawMemOps data) noexcept {
|
||
|
int32_t __ret = (this->vtbl_memoryview)->read_raw_iter(&this->container, data);
|
||
|
return __ret;
|
||
|
}
|
||
|
|
||
|
inline int32_t write_raw_iter(WriteRawMemOps data) noexcept {
|
||
|
int32_t __ret = (this->vtbl_memoryview)->write_raw_iter(&this->container, data);
|
||
|
return __ret;
|
||
|
}
|
||
|
|
||
|
inline MemoryViewMetadata metadata() const noexcept {
|
||
|
MemoryViewMetadata __ret = (this->vtbl_memoryview)->metadata(&this->container);
|
||
|
return __ret;
|
||
|
}
|
||
|
|
||
|
inline int32_t read_iter(CIterator<ReadData> inp, ReadCallback * out, ReadCallback * out_fail) noexcept {
|
||
|
int32_t __ret = (this->vtbl_memoryview)->read_iter(&this->container, inp, out, out_fail);
|
||
|
return __ret;
|
||
|
}
|
||
|
|
||
|
inline int32_t read_raw_list(CSliceMut<ReadData> data) noexcept {
|
||
|
int32_t __ret = (this->vtbl_memoryview)->read_raw_list(&this->container, data);
|
||
|
return __ret;
|
||
|
}
|
||
|
|
||
|
inline int32_t read_raw_into(Address addr, CSliceMut<uint8_t> out) noexcept {
|
||
|
int32_t __ret = (this->vtbl_memoryview)->read_raw_into(&this->container, addr, out);
|
||
|
return __ret;
|
||
|
}
|
||
|
|
||
|
inline int32_t write_iter(CIterator<WriteData> inp, WriteCallback * out, WriteCallback * out_fail) noexcept {
|
||
|
int32_t __ret = (this->vtbl_memoryview)->write_iter(&this->container, inp, out, out_fail);
|
||
|
return __ret;
|
||
|
}
|
||
|
|
||
|
inline int32_t write_raw_list(CSliceRef<WriteData> data) noexcept {
|
||
|
int32_t __ret = (this->vtbl_memoryview)->write_raw_list(&this->container, data);
|
||
|
return __ret;
|
||
|
}
|
||
|
|
||
|
inline int32_t write_raw(Address addr, CSliceRef<uint8_t> data) noexcept {
|
||
|
int32_t __ret = (this->vtbl_memoryview)->write_raw(&this->container, addr, data);
|
||
|
return __ret;
|
||
|
}
|
||
|
|
||
|
inline ProcessState state() noexcept {
|
||
|
ProcessState __ret = (this->vtbl_process)->state(&this->container);
|
||
|
return __ret;
|
||
|
}
|
||
|
|
||
|
inline int32_t set_dtb(Address dtb1, Address dtb2) noexcept {
|
||
|
int32_t __ret = (this->vtbl_process)->set_dtb(&this->container, dtb1, dtb2);
|
||
|
return __ret;
|
||
|
}
|
||
|
|
||
|
inline int32_t module_address_list_callback(const ArchitectureIdent * target_arch, ModuleAddressCallback callback) noexcept {
|
||
|
int32_t __ret = (this->vtbl_process)->module_address_list_callback(&this->container, target_arch, callback);
|
||
|
return __ret;
|
||
|
}
|
||
|
|
||
|
inline int32_t module_list_callback(const ArchitectureIdent * target_arch, ModuleInfoCallback callback) noexcept {
|
||
|
int32_t __ret = (this->vtbl_process)->module_list_callback(&this->container, target_arch, callback);
|
||
|
return __ret;
|
||
|
}
|
||
|
|
||
|
inline int32_t module_by_address(Address address, ArchitectureIdent architecture, ModuleInfo * ok_out) noexcept {
|
||
|
int32_t __ret = (this->vtbl_process)->module_by_address(&this->container, address, architecture, ok_out);
|
||
|
return __ret;
|
||
|
}
|
||
|
|
||
|
inline int32_t module_by_name_arch(CSliceRef<uint8_t> name, const ArchitectureIdent * architecture, ModuleInfo * ok_out) noexcept {
|
||
|
int32_t __ret = (this->vtbl_process)->module_by_name_arch(&this->container, name, architecture, ok_out);
|
||
|
return __ret;
|
||
|
}
|
||
|
|
||
|
inline int32_t module_by_name(CSliceRef<uint8_t> name, ModuleInfo * ok_out) noexcept {
|
||
|
int32_t __ret = (this->vtbl_process)->module_by_name(&this->container, name, ok_out);
|
||
|
return __ret;
|
||
|
}
|
||
|
|
||
|
inline int32_t primary_module_address(Address * ok_out) noexcept {
|
||
|
int32_t __ret = (this->vtbl_process)->primary_module_address(&this->container, ok_out);
|
||
|
return __ret;
|
||
|
}
|
||
|
|
||
|
inline int32_t primary_module(ModuleInfo * ok_out) noexcept {
|
||
|
int32_t __ret = (this->vtbl_process)->primary_module(&this->container, ok_out);
|
||
|
return __ret;
|
||
|
}
|
||
|
|
||
|
inline int32_t module_import_list_callback(const ModuleInfo * info, ImportCallback callback) noexcept {
|
||
|
int32_t __ret = (this->vtbl_process)->module_import_list_callback(&this->container, info, callback);
|
||
|
return __ret;
|
||
|
}
|
||
|
|
||
|
inline int32_t module_export_list_callback(const ModuleInfo * info, ExportCallback callback) noexcept {
|
||
|
int32_t __ret = (this->vtbl_process)->module_export_list_callback(&this->container, info, callback);
|
||
|
return __ret;
|
||
|
}
|
||
|
|
||
|
inline int32_t module_section_list_callback(const ModuleInfo * info, SectionCallback callback) noexcept {
|
||
|
int32_t __ret = (this->vtbl_process)->module_section_list_callback(&this->container, info, callback);
|
||
|
return __ret;
|
||
|
}
|
||
|
|
||
|
inline int32_t module_import_by_name(const ModuleInfo * info, CSliceRef<uint8_t> name, ImportInfo * ok_out) noexcept {
|
||
|
int32_t __ret = (this->vtbl_process)->module_import_by_name(&this->container, info, name, ok_out);
|
||
|
return __ret;
|
||
|
}
|
||
|
|
||
|
inline int32_t module_export_by_name(const ModuleInfo * info, CSliceRef<uint8_t> name, ExportInfo * ok_out) noexcept {
|
||
|
int32_t __ret = (this->vtbl_process)->module_export_by_name(&this->container, info, name, ok_out);
|
||
|
return __ret;
|
||
|
}
|
||
|
|
||
|
inline int32_t module_section_by_name(const ModuleInfo * info, CSliceRef<uint8_t> name, SectionInfo * ok_out) noexcept {
|
||
|
int32_t __ret = (this->vtbl_process)->module_section_by_name(&this->container, info, name, ok_out);
|
||
|
return __ret;
|
||
|
}
|
||
|
|
||
|
inline const ProcessInfo * info() const noexcept {
|
||
|
const ProcessInfo * __ret = (this->vtbl_process)->info(&this->container);
|
||
|
return __ret;
|
||
|
}
|
||
|
|
||
|
inline void mapped_mem_range(imem gap_size, Address start, Address end, MemoryRangeCallback out) noexcept {
|
||
|
(this->vtbl_process)->mapped_mem_range(&this->container, gap_size, start, end, out);
|
||
|
|
||
|
}
|
||
|
|
||
|
inline void mapped_mem(imem gap_size, MemoryRangeCallback out) noexcept {
|
||
|
(this->vtbl_process)->mapped_mem(&this->container, gap_size, out);
|
||
|
|
||
|
}
|
||
|
|
||
|
inline void virt_to_phys_list(CSliceRef<VtopRange> addrs, VirtualTranslationCallback out, VirtualTranslationFailCallback out_fail) noexcept {
|
||
|
(this->vtbl_virtualtranslate)->virt_to_phys_list(&this->container, addrs, out, out_fail);
|
||
|
|
||
|
}
|
||
|
|
||
|
inline void virt_to_phys_range(Address start, Address end, VirtualTranslationCallback out) noexcept {
|
||
|
(this->vtbl_virtualtranslate)->virt_to_phys_range(&this->container, start, end, out);
|
||
|
|
||
|
}
|
||
|
|
||
|
inline void virt_translation_map_range(Address start, Address end, VirtualTranslationCallback out) noexcept {
|
||
|
(this->vtbl_virtualtranslate)->virt_translation_map_range(&this->container, start, end, out);
|
||
|
|
||
|
}
|
||
|
|
||
|
inline void virt_page_map_range(imem gap_size, Address start, Address end, MemoryRangeCallback out) noexcept {
|
||
|
(this->vtbl_virtualtranslate)->virt_page_map_range(&this->container, gap_size, start, end, out);
|
||
|
|
||
|
}
|
||
|
|
||
|
inline int32_t virt_to_phys(Address address, PhysicalAddress * ok_out) noexcept {
|
||
|
int32_t __ret = (this->vtbl_virtualtranslate)->virt_to_phys(&this->container, address, ok_out);
|
||
|
return __ret;
|
||
|
}
|
||
|
|
||
|
inline int32_t virt_page_info(Address addr, Page * ok_out) noexcept {
|
||
|
int32_t __ret = (this->vtbl_virtualtranslate)->virt_page_info(&this->container, addr, ok_out);
|
||
|
return __ret;
|
||
|
}
|
||
|
|
||
|
inline void virt_translation_map(VirtualTranslationCallback out) noexcept {
|
||
|
(this->vtbl_virtualtranslate)->virt_translation_map(&this->container, out);
|
||
|
|
||
|
}
|
||
|
|
||
|
inline COption<Address> phys_to_virt(Address phys) noexcept {
|
||
|
COption<Address> __ret = (this->vtbl_virtualtranslate)->phys_to_virt(&this->container, phys);
|
||
|
return __ret;
|
||
|
}
|
||
|
|
||
|
inline void virt_page_map(imem gap_size, MemoryRangeCallback out) noexcept {
|
||
|
(this->vtbl_virtualtranslate)->virt_page_map(&this->container, gap_size, out);
|
||
|
|
||
|
}
|
||
|
|
||
|
};
|
||
|
|
||
|
template<typename CGlueInst = CBox<void>, typename CGlueCtx = CArc<void>>
|
||
|
struct IntoProcessInstanceContainer {
|
||
|
typedef CGlueCtx Context;
|
||
|
CGlueInst instance;
|
||
|
CGlueCtx context;
|
||
|
|
||
|
inline Context clone_context() noexcept {
|
||
|
return context.clone();
|
||
|
}
|
||
|
|
||
|
inline void drop() && noexcept {
|
||
|
mem_drop(std::move(instance));
|
||
|
mem_drop(std::move(context));
|
||
|
}
|
||
|
|
||
|
inline void forget() noexcept {
|
||
|
mem_forget(instance);
|
||
|
mem_forget(context);
|
||
|
}
|
||
|
};
|
||
|
|
||
|
template<typename CGlueInst>
|
||
|
struct IntoProcessInstanceContainer<CGlueInst, void> {
|
||
|
typedef void Context;
|
||
|
CGlueInst instance;
|
||
|
|
||
|
inline Context clone_context() noexcept {}
|
||
|
|
||
|
inline void drop() && noexcept {
|
||
|
mem_drop(std::move(instance));
|
||
|
}
|
||
|
|
||
|
inline void forget() noexcept {
|
||
|
mem_forget(instance);
|
||
|
}
|
||
|
};
|
||
|
|
||
|
/**
|
||
|
* Trait group potentially implementing `:: cglue :: ext :: core :: clone :: Clone < > + MemoryView < > + Process < > + VirtualTranslate < >` traits.
|
||
|
*
|
||
|
* Optional traits are not implemented here, however. There are numerous conversion
|
||
|
* functions available for safely retrieving a concrete collection of traits.
|
||
|
*
|
||
|
* `check_impl_` functions allow to check if the object implements the wanted traits.
|
||
|
*
|
||
|
* `into_impl_` functions consume the object and produce a new final structure that
|
||
|
* keeps only the required information.
|
||
|
*
|
||
|
* `cast_impl_` functions merely check and transform the object into a type that can
|
||
|
*be transformed back into `IntoProcessInstance` without losing data.
|
||
|
*
|
||
|
* `as_ref_`, and `as_mut_` functions obtain references to safe objects, but do not
|
||
|
* perform any memory transformations either. They are the safest to use, because
|
||
|
* there is no risk of accidentally consuming the whole object.
|
||
|
*/
|
||
|
template<typename CGlueInst = CBox<void>, typename CGlueCtx = CArc<void>>
|
||
|
struct IntoProcessInstance {
|
||
|
const CloneVtbl<IntoProcessInstanceContainer<CGlueInst, CGlueCtx>> *vtbl_clone;
|
||
|
const MemoryViewVtbl<IntoProcessInstanceContainer<CGlueInst, CGlueCtx>> *vtbl_memoryview;
|
||
|
const ProcessVtbl<IntoProcessInstanceContainer<CGlueInst, CGlueCtx>> *vtbl_process;
|
||
|
const VirtualTranslateVtbl<IntoProcessInstanceContainer<CGlueInst, CGlueCtx>> *vtbl_virtualtranslate;
|
||
|
IntoProcessInstanceContainer<CGlueInst, CGlueCtx> container;
|
||
|
|
||
|
IntoProcessInstance() : container{} , vtbl_clone{}, vtbl_memoryview{}, vtbl_process{}, vtbl_virtualtranslate{} {}
|
||
|
|
||
|
~IntoProcessInstance() noexcept {
|
||
|
mem_drop(std::move(container));
|
||
|
}
|
||
|
|
||
|
typedef CGlueCtx Context;
|
||
|
|
||
|
inline IntoProcessInstance clone() const noexcept {
|
||
|
IntoProcessInstance __ret;
|
||
|
__ret.vtbl_clone = this->vtbl_clone;
|
||
|
__ret.vtbl_memoryview = this->vtbl_memoryview;
|
||
|
__ret.vtbl_process = this->vtbl_process;
|
||
|
__ret.vtbl_virtualtranslate = this->vtbl_virtualtranslate;
|
||
|
__ret.container = (this->vtbl_clone)->clone(&this->container);
|
||
|
return __ret;
|
||
|
}
|
||
|
|
||
|
inline int32_t read_raw_iter(ReadRawMemOps data) noexcept {
|
||
|
int32_t __ret = (this->vtbl_memoryview)->read_raw_iter(&this->container, data);
|
||
|
return __ret;
|
||
|
}
|
||
|
|
||
|
inline int32_t write_raw_iter(WriteRawMemOps data) noexcept {
|
||
|
int32_t __ret = (this->vtbl_memoryview)->write_raw_iter(&this->container, data);
|
||
|
return __ret;
|
||
|
}
|
||
|
|
||
|
inline MemoryViewMetadata metadata() const noexcept {
|
||
|
MemoryViewMetadata __ret = (this->vtbl_memoryview)->metadata(&this->container);
|
||
|
return __ret;
|
||
|
}
|
||
|
|
||
|
inline int32_t read_iter(CIterator<ReadData> inp, ReadCallback * out, ReadCallback * out_fail) noexcept {
|
||
|
int32_t __ret = (this->vtbl_memoryview)->read_iter(&this->container, inp, out, out_fail);
|
||
|
return __ret;
|
||
|
}
|
||
|
|
||
|
inline int32_t read_raw_list(CSliceMut<ReadData> data) noexcept {
|
||
|
int32_t __ret = (this->vtbl_memoryview)->read_raw_list(&this->container, data);
|
||
|
return __ret;
|
||
|
}
|
||
|
|
||
|
inline int32_t read_raw_into(Address addr, CSliceMut<uint8_t> out) noexcept {
|
||
|
int32_t __ret = (this->vtbl_memoryview)->read_raw_into(&this->container, addr, out);
|
||
|
return __ret;
|
||
|
}
|
||
|
|
||
|
inline int32_t write_iter(CIterator<WriteData> inp, WriteCallback * out, WriteCallback * out_fail) noexcept {
|
||
|
int32_t __ret = (this->vtbl_memoryview)->write_iter(&this->container, inp, out, out_fail);
|
||
|
return __ret;
|
||
|
}
|
||
|
|
||
|
inline int32_t write_raw_list(CSliceRef<WriteData> data) noexcept {
|
||
|
int32_t __ret = (this->vtbl_memoryview)->write_raw_list(&this->container, data);
|
||
|
return __ret;
|
||
|
}
|
||
|
|
||
|
inline int32_t write_raw(Address addr, CSliceRef<uint8_t> data) noexcept {
|
||
|
int32_t __ret = (this->vtbl_memoryview)->write_raw(&this->container, addr, data);
|
||
|
return __ret;
|
||
|
}
|
||
|
|
||
|
inline ProcessState state() noexcept {
|
||
|
ProcessState __ret = (this->vtbl_process)->state(&this->container);
|
||
|
return __ret;
|
||
|
}
|
||
|
|
||
|
inline int32_t set_dtb(Address dtb1, Address dtb2) noexcept {
|
||
|
int32_t __ret = (this->vtbl_process)->set_dtb(&this->container, dtb1, dtb2);
|
||
|
return __ret;
|
||
|
}
|
||
|
|
||
|
inline int32_t module_address_list_callback(const ArchitectureIdent * target_arch, ModuleAddressCallback callback) noexcept {
|
||
|
int32_t __ret = (this->vtbl_process)->module_address_list_callback(&this->container, target_arch, callback);
|
||
|
return __ret;
|
||
|
}
|
||
|
|
||
|
inline int32_t module_list_callback(const ArchitectureIdent * target_arch, ModuleInfoCallback callback) noexcept {
|
||
|
int32_t __ret = (this->vtbl_process)->module_list_callback(&this->container, target_arch, callback);
|
||
|
return __ret;
|
||
|
}
|
||
|
|
||
|
inline int32_t module_by_address(Address address, ArchitectureIdent architecture, ModuleInfo * ok_out) noexcept {
|
||
|
int32_t __ret = (this->vtbl_process)->module_by_address(&this->container, address, architecture, ok_out);
|
||
|
return __ret;
|
||
|
}
|
||
|
|
||
|
inline int32_t module_by_name_arch(CSliceRef<uint8_t> name, const ArchitectureIdent * architecture, ModuleInfo * ok_out) noexcept {
|
||
|
int32_t __ret = (this->vtbl_process)->module_by_name_arch(&this->container, name, architecture, ok_out);
|
||
|
return __ret;
|
||
|
}
|
||
|
|
||
|
inline int32_t module_by_name(CSliceRef<uint8_t> name, ModuleInfo * ok_out) noexcept {
|
||
|
int32_t __ret = (this->vtbl_process)->module_by_name(&this->container, name, ok_out);
|
||
|
return __ret;
|
||
|
}
|
||
|
|
||
|
inline int32_t primary_module_address(Address * ok_out) noexcept {
|
||
|
int32_t __ret = (this->vtbl_process)->primary_module_address(&this->container, ok_out);
|
||
|
return __ret;
|
||
|
}
|
||
|
|
||
|
inline int32_t primary_module(ModuleInfo * ok_out) noexcept {
|
||
|
int32_t __ret = (this->vtbl_process)->primary_module(&this->container, ok_out);
|
||
|
return __ret;
|
||
|
}
|
||
|
|
||
|
inline int32_t module_import_list_callback(const ModuleInfo * info, ImportCallback callback) noexcept {
|
||
|
int32_t __ret = (this->vtbl_process)->module_import_list_callback(&this->container, info, callback);
|
||
|
return __ret;
|
||
|
}
|
||
|
|
||
|
inline int32_t module_export_list_callback(const ModuleInfo * info, ExportCallback callback) noexcept {
|
||
|
int32_t __ret = (this->vtbl_process)->module_export_list_callback(&this->container, info, callback);
|
||
|
return __ret;
|
||
|
}
|
||
|
|
||
|
inline int32_t module_section_list_callback(const ModuleInfo * info, SectionCallback callback) noexcept {
|
||
|
int32_t __ret = (this->vtbl_process)->module_section_list_callback(&this->container, info, callback);
|
||
|
return __ret;
|
||
|
}
|
||
|
|
||
|
inline int32_t module_import_by_name(const ModuleInfo * info, CSliceRef<uint8_t> name, ImportInfo * ok_out) noexcept {
|
||
|
int32_t __ret = (this->vtbl_process)->module_import_by_name(&this->container, info, name, ok_out);
|
||
|
return __ret;
|
||
|
}
|
||
|
|
||
|
inline int32_t module_export_by_name(const ModuleInfo * info, CSliceRef<uint8_t> name, ExportInfo * ok_out) noexcept {
|
||
|
int32_t __ret = (this->vtbl_process)->module_export_by_name(&this->container, info, name, ok_out);
|
||
|
return __ret;
|
||
|
}
|
||
|
|
||
|
inline int32_t module_section_by_name(const ModuleInfo * info, CSliceRef<uint8_t> name, SectionInfo * ok_out) noexcept {
|
||
|
int32_t __ret = (this->vtbl_process)->module_section_by_name(&this->container, info, name, ok_out);
|
||
|
return __ret;
|
||
|
}
|
||
|
|
||
|
inline const ProcessInfo * info() const noexcept {
|
||
|
const ProcessInfo * __ret = (this->vtbl_process)->info(&this->container);
|
||
|
return __ret;
|
||
|
}
|
||
|
|
||
|
inline void mapped_mem_range(imem gap_size, Address start, Address end, MemoryRangeCallback out) noexcept {
|
||
|
(this->vtbl_process)->mapped_mem_range(&this->container, gap_size, start, end, out);
|
||
|
|
||
|
}
|
||
|
|
||
|
inline void mapped_mem(imem gap_size, MemoryRangeCallback out) noexcept {
|
||
|
(this->vtbl_process)->mapped_mem(&this->container, gap_size, out);
|
||
|
|
||
|
}
|
||
|
|
||
|
inline void virt_to_phys_list(CSliceRef<VtopRange> addrs, VirtualTranslationCallback out, VirtualTranslationFailCallback out_fail) noexcept {
|
||
|
(this->vtbl_virtualtranslate)->virt_to_phys_list(&this->container, addrs, out, out_fail);
|
||
|
|
||
|
}
|
||
|
|
||
|
inline void virt_to_phys_range(Address start, Address end, VirtualTranslationCallback out) noexcept {
|
||
|
(this->vtbl_virtualtranslate)->virt_to_phys_range(&this->container, start, end, out);
|
||
|
|
||
|
}
|
||
|
|
||
|
inline void virt_translation_map_range(Address start, Address end, VirtualTranslationCallback out) noexcept {
|
||
|
(this->vtbl_virtualtranslate)->virt_translation_map_range(&this->container, start, end, out);
|
||
|
|
||
|
}
|
||
|
|
||
|
inline void virt_page_map_range(imem gap_size, Address start, Address end, MemoryRangeCallback out) noexcept {
|
||
|
(this->vtbl_virtualtranslate)->virt_page_map_range(&this->container, gap_size, start, end, out);
|
||
|
|
||
|
}
|
||
|
|
||
|
inline int32_t virt_to_phys(Address address, PhysicalAddress * ok_out) noexcept {
|
||
|
int32_t __ret = (this->vtbl_virtualtranslate)->virt_to_phys(&this->container, address, ok_out);
|
||
|
return __ret;
|
||
|
}
|
||
|
|
||
|
inline int32_t virt_page_info(Address addr, Page * ok_out) noexcept {
|
||
|
int32_t __ret = (this->vtbl_virtualtranslate)->virt_page_info(&this->container, addr, ok_out);
|
||
|
return __ret;
|
||
|
}
|
||
|
|
||
|
inline void virt_translation_map(VirtualTranslationCallback out) noexcept {
|
||
|
(this->vtbl_virtualtranslate)->virt_translation_map(&this->container, out);
|
||
|
|
||
|
}
|
||
|
|
||
|
inline COption<Address> phys_to_virt(Address phys) noexcept {
|
||
|
COption<Address> __ret = (this->vtbl_virtualtranslate)->phys_to_virt(&this->container, phys);
|
||
|
return __ret;
|
||
|
}
|
||
|
|
||
|
inline void virt_page_map(imem gap_size, MemoryRangeCallback out) noexcept {
|
||
|
(this->vtbl_virtualtranslate)->virt_page_map(&this->container, gap_size, out);
|
||
|
|
||
|
}
|
||
|
|
||
|
};
|
||
|
|
||
|
/**
|
||
|
* Information block about OS
|
||
|
*
|
||
|
* This provides some basic information about the OS in question. `base`, and `size` may be
|
||
|
* omitted in some circumstances (lack of kernel, or privileges). But architecture should always
|
||
|
* be correct.
|
||
|
*/
|
||
|
struct OsInfo {
|
||
|
/**
|
||
|
* Base address of the OS kernel
|
||
|
*/
|
||
|
Address base;
|
||
|
/**
|
||
|
* Size of the OS kernel
|
||
|
*/
|
||
|
umem size;
|
||
|
/**
|
||
|
* System architecture
|
||
|
*/
|
||
|
ArchitectureIdent arch;
|
||
|
};
|
||
|
|
||
|
/**
|
||
|
* CGlue vtable for trait Os.
|
||
|
*
|
||
|
* This virtual function table contains ABI-safe interface for the given trait.
|
||
|
*/
|
||
|
template<typename CGlueC>
|
||
|
struct OsVtbl {
|
||
|
typedef typename CGlueC::Context Context;
|
||
|
int32_t (*process_address_list_callback)(CGlueC *cont, AddressCallback callback);
|
||
|
int32_t (*process_info_list_callback)(CGlueC *cont, ProcessInfoCallback callback);
|
||
|
int32_t (*process_info_by_address)(CGlueC *cont,
|
||
|
Address address,
|
||
|
ProcessInfo *ok_out);
|
||
|
int32_t (*process_info_by_name)(CGlueC *cont,
|
||
|
CSliceRef<uint8_t> name,
|
||
|
ProcessInfo *ok_out);
|
||
|
int32_t (*process_info_by_pid)(CGlueC *cont, Pid pid, ProcessInfo *ok_out);
|
||
|
int32_t (*process_by_info)(CGlueC *cont,
|
||
|
ProcessInfo info,
|
||
|
ProcessInstance<CBox<void>, Context> *ok_out);
|
||
|
int32_t (*into_process_by_info)(CGlueC cont,
|
||
|
ProcessInfo info,
|
||
|
IntoProcessInstance<CBox<void>, Context> *ok_out);
|
||
|
int32_t (*process_by_address)(CGlueC *cont,
|
||
|
Address addr,
|
||
|
ProcessInstance<CBox<void>, Context> *ok_out);
|
||
|
int32_t (*process_by_name)(CGlueC *cont,
|
||
|
CSliceRef<uint8_t> name,
|
||
|
ProcessInstance<CBox<void>, Context> *ok_out);
|
||
|
int32_t (*process_by_pid)(CGlueC *cont,
|
||
|
Pid pid,
|
||
|
ProcessInstance<CBox<void>, Context> *ok_out);
|
||
|
int32_t (*into_process_by_address)(CGlueC cont,
|
||
|
Address addr,
|
||
|
IntoProcessInstance<CBox<void>, Context> *ok_out);
|
||
|
int32_t (*into_process_by_name)(CGlueC cont,
|
||
|
CSliceRef<uint8_t> name,
|
||
|
IntoProcessInstance<CBox<void>, Context> *ok_out);
|
||
|
int32_t (*into_process_by_pid)(CGlueC cont,
|
||
|
Pid pid,
|
||
|
IntoProcessInstance<CBox<void>, Context> *ok_out);
|
||
|
int32_t (*module_address_list_callback)(CGlueC *cont, AddressCallback callback);
|
||
|
int32_t (*module_list_callback)(CGlueC *cont, ModuleInfoCallback callback);
|
||
|
int32_t (*module_by_address)(CGlueC *cont, Address address, ModuleInfo *ok_out);
|
||
|
int32_t (*module_by_name)(CGlueC *cont, CSliceRef<uint8_t> name, ModuleInfo *ok_out);
|
||
|
int32_t (*primary_module_address)(CGlueC *cont, Address *ok_out);
|
||
|
int32_t (*primary_module)(CGlueC *cont, ModuleInfo *ok_out);
|
||
|
int32_t (*module_import_list_callback)(CGlueC *cont,
|
||
|
const ModuleInfo *info,
|
||
|
ImportCallback callback);
|
||
|
int32_t (*module_export_list_callback)(CGlueC *cont,
|
||
|
const ModuleInfo *info,
|
||
|
ExportCallback callback);
|
||
|
int32_t (*module_section_list_callback)(CGlueC *cont,
|
||
|
const ModuleInfo *info,
|
||
|
SectionCallback callback);
|
||
|
int32_t (*module_import_by_name)(CGlueC *cont,
|
||
|
const ModuleInfo *info,
|
||
|
CSliceRef<uint8_t> name,
|
||
|
ImportInfo *ok_out);
|
||
|
int32_t (*module_export_by_name)(CGlueC *cont,
|
||
|
const ModuleInfo *info,
|
||
|
CSliceRef<uint8_t> name,
|
||
|
ExportInfo *ok_out);
|
||
|
int32_t (*module_section_by_name)(CGlueC *cont,
|
||
|
const ModuleInfo *info,
|
||
|
CSliceRef<uint8_t> name,
|
||
|
SectionInfo *ok_out);
|
||
|
const OsInfo *(*info)(const CGlueC *cont);
|
||
|
};
|
||
|
|
||
|
template<typename Impl>
|
||
|
struct OsVtblImpl : OsVtbl<typename Impl::Parent> {
|
||
|
constexpr OsVtblImpl() :
|
||
|
OsVtbl<typename Impl::Parent> {
|
||
|
&Impl::process_address_list_callback,
|
||
|
&Impl::process_info_list_callback,
|
||
|
&Impl::process_info_by_address,
|
||
|
&Impl::process_info_by_name,
|
||
|
&Impl::process_info_by_pid,
|
||
|
&Impl::process_by_info,
|
||
|
&Impl::into_process_by_info,
|
||
|
&Impl::process_by_address,
|
||
|
&Impl::process_by_name,
|
||
|
&Impl::process_by_pid,
|
||
|
&Impl::into_process_by_address,
|
||
|
&Impl::into_process_by_name,
|
||
|
&Impl::into_process_by_pid,
|
||
|
&Impl::module_address_list_callback,
|
||
|
&Impl::module_list_callback,
|
||
|
&Impl::module_by_address,
|
||
|
&Impl::module_by_name,
|
||
|
&Impl::primary_module_address,
|
||
|
&Impl::primary_module,
|
||
|
&Impl::module_import_list_callback,
|
||
|
&Impl::module_export_list_callback,
|
||
|
&Impl::module_section_list_callback,
|
||
|
&Impl::module_import_by_name,
|
||
|
&Impl::module_export_by_name,
|
||
|
&Impl::module_section_by_name,
|
||
|
&Impl::info
|
||
|
} {}
|
||
|
};
|
||
|
|
||
|
/**
|
||
|
* CGlue vtable for trait KeyboardState.
|
||
|
*
|
||
|
* This virtual function table contains ABI-safe interface for the given trait.
|
||
|
*/
|
||
|
template<typename CGlueC>
|
||
|
struct KeyboardStateVtbl {
|
||
|
typedef typename CGlueC::Context Context;
|
||
|
bool (*is_down)(const CGlueC *cont, int32_t vk);
|
||
|
};
|
||
|
|
||
|
template<typename Impl>
|
||
|
struct KeyboardStateVtblImpl : KeyboardStateVtbl<typename Impl::Parent> {
|
||
|
constexpr KeyboardStateVtblImpl() :
|
||
|
KeyboardStateVtbl<typename Impl::Parent> {
|
||
|
&Impl::is_down
|
||
|
} {}
|
||
|
};
|
||
|
|
||
|
/**
|
||
|
* Base CGlue trait object for trait KeyboardState.
|
||
|
*/
|
||
|
template<typename CGlueInst = CBox<void>, typename CGlueCtx = CArc<void>>
|
||
|
using KeyboardStateBase = CGlueTraitObj<CGlueInst, KeyboardStateVtbl<CGlueObjContainer<CGlueInst, CGlueCtx, KeyboardStateRetTmp<CGlueCtx>>>, CGlueCtx, KeyboardStateRetTmp<CGlueCtx>>;
|
||
|
|
||
|
/**
|
||
|
* CGlue vtable for trait Keyboard.
|
||
|
*
|
||
|
* This virtual function table contains ABI-safe interface for the given trait.
|
||
|
*/
|
||
|
template<typename CGlueC>
|
||
|
struct KeyboardVtbl {
|
||
|
typedef typename CGlueC::Context Context;
|
||
|
bool (*is_down)(CGlueC *cont, int32_t vk);
|
||
|
void (*set_down)(CGlueC *cont, int32_t vk, bool down);
|
||
|
int32_t (*state)(CGlueC *cont, KeyboardStateBase<CBox<void>, Context> *ok_out);
|
||
|
};
|
||
|
|
||
|
template<typename Impl>
|
||
|
struct KeyboardVtblImpl : KeyboardVtbl<typename Impl::Parent> {
|
||
|
constexpr KeyboardVtblImpl() :
|
||
|
KeyboardVtbl<typename Impl::Parent> {
|
||
|
&Impl::is_down,
|
||
|
&Impl::set_down,
|
||
|
&Impl::state
|
||
|
} {}
|
||
|
};
|
||
|
|
||
|
/**
|
||
|
* Base CGlue trait object for trait Keyboard.
|
||
|
*/
|
||
|
template<typename CGlueInst = CBox<void>, typename CGlueCtx = CArc<void>>
|
||
|
using KeyboardBase = CGlueTraitObj<CGlueInst, KeyboardVtbl<CGlueObjContainer<CGlueInst, CGlueCtx, KeyboardRetTmp<CGlueCtx>>>, CGlueCtx, KeyboardRetTmp<CGlueCtx>>;
|
||
|
|
||
|
template<typename CGlueInst = CBox<void>, typename CGlueCtx = CArc<void>>
|
||
|
struct IntoKeyboardContainer {
|
||
|
typedef CGlueCtx Context;
|
||
|
CGlueInst instance;
|
||
|
CGlueCtx context;
|
||
|
|
||
|
inline Context clone_context() noexcept {
|
||
|
return context.clone();
|
||
|
}
|
||
|
|
||
|
inline void drop() && noexcept {
|
||
|
mem_drop(std::move(instance));
|
||
|
mem_drop(std::move(context));
|
||
|
}
|
||
|
|
||
|
inline void forget() noexcept {
|
||
|
mem_forget(instance);
|
||
|
mem_forget(context);
|
||
|
}
|
||
|
};
|
||
|
|
||
|
template<typename CGlueInst>
|
||
|
struct IntoKeyboardContainer<CGlueInst, void> {
|
||
|
typedef void Context;
|
||
|
CGlueInst instance;
|
||
|
|
||
|
inline Context clone_context() noexcept {}
|
||
|
|
||
|
inline void drop() && noexcept {
|
||
|
mem_drop(std::move(instance));
|
||
|
}
|
||
|
|
||
|
inline void forget() noexcept {
|
||
|
mem_forget(instance);
|
||
|
}
|
||
|
};
|
||
|
|
||
|
/**
|
||
|
* Trait group potentially implementing `:: cglue :: ext :: core :: clone :: Clone < > + Keyboard < >` traits.
|
||
|
*
|
||
|
* Optional traits are not implemented here, however. There are numerous conversion
|
||
|
* functions available for safely retrieving a concrete collection of traits.
|
||
|
*
|
||
|
* `check_impl_` functions allow to check if the object implements the wanted traits.
|
||
|
*
|
||
|
* `into_impl_` functions consume the object and produce a new final structure that
|
||
|
* keeps only the required information.
|
||
|
*
|
||
|
* `cast_impl_` functions merely check and transform the object into a type that can
|
||
|
*be transformed back into `IntoKeyboard` without losing data.
|
||
|
*
|
||
|
* `as_ref_`, and `as_mut_` functions obtain references to safe objects, but do not
|
||
|
* perform any memory transformations either. They are the safest to use, because
|
||
|
* there is no risk of accidentally consuming the whole object.
|
||
|
*/
|
||
|
template<typename CGlueInst = CBox<void>, typename CGlueCtx = CArc<void>>
|
||
|
struct IntoKeyboard {
|
||
|
const CloneVtbl<IntoKeyboardContainer<CGlueInst, CGlueCtx>> *vtbl_clone;
|
||
|
const KeyboardVtbl<IntoKeyboardContainer<CGlueInst, CGlueCtx>> *vtbl_keyboard;
|
||
|
IntoKeyboardContainer<CGlueInst, CGlueCtx> container;
|
||
|
|
||
|
IntoKeyboard() : container{} , vtbl_clone{}, vtbl_keyboard{} {}
|
||
|
|
||
|
~IntoKeyboard() noexcept {
|
||
|
mem_drop(std::move(container));
|
||
|
}
|
||
|
|
||
|
typedef CGlueCtx Context;
|
||
|
|
||
|
inline IntoKeyboard clone() const noexcept {
|
||
|
IntoKeyboard __ret;
|
||
|
__ret.vtbl_clone = this->vtbl_clone;
|
||
|
__ret.vtbl_keyboard = this->vtbl_keyboard;
|
||
|
__ret.container = (this->vtbl_clone)->clone(&this->container);
|
||
|
return __ret;
|
||
|
}
|
||
|
|
||
|
inline bool is_down(int32_t vk) noexcept {
|
||
|
bool __ret = (this->vtbl_keyboard)->is_down(&this->container, vk);
|
||
|
return __ret;
|
||
|
}
|
||
|
|
||
|
inline void set_down(int32_t vk, bool down) noexcept {
|
||
|
(this->vtbl_keyboard)->set_down(&this->container, vk, down);
|
||
|
|
||
|
}
|
||
|
|
||
|
inline int32_t state(KeyboardStateBase<CBox<void>, Context> * ok_out) noexcept {
|
||
|
int32_t __ret = (this->vtbl_keyboard)->state(&this->container, ok_out);
|
||
|
return __ret;
|
||
|
}
|
||
|
|
||
|
};
|
||
|
|
||
|
/**
|
||
|
* CGlue vtable for trait OsKeyboard.
|
||
|
*
|
||
|
* This virtual function table contains ABI-safe interface for the given trait.
|
||
|
*/
|
||
|
template<typename CGlueC>
|
||
|
struct OsKeyboardVtbl {
|
||
|
typedef typename CGlueC::Context Context;
|
||
|
int32_t (*keyboard)(CGlueC *cont, KeyboardBase<CBox<void>, Context> *ok_out);
|
||
|
int32_t (*into_keyboard)(CGlueC cont, IntoKeyboard<CBox<void>, Context> *ok_out);
|
||
|
};
|
||
|
|
||
|
template<typename Impl>
|
||
|
struct OsKeyboardVtblImpl : OsKeyboardVtbl<typename Impl::Parent> {
|
||
|
constexpr OsKeyboardVtblImpl() :
|
||
|
OsKeyboardVtbl<typename Impl::Parent> {
|
||
|
&Impl::keyboard,
|
||
|
&Impl::into_keyboard
|
||
|
} {}
|
||
|
};
|
||
|
|
||
|
/**
|
||
|
* Trait group potentially implementing `:: cglue :: ext :: core :: clone :: Clone < > + Os < > + MemoryView < > + OsKeyboard < > + PhysicalMemory < > + VirtualTranslate < >` traits.
|
||
|
*
|
||
|
* Optional traits are not implemented here, however. There are numerous conversion
|
||
|
* functions available for safely retrieving a concrete collection of traits.
|
||
|
*
|
||
|
* `check_impl_` functions allow to check if the object implements the wanted traits.
|
||
|
*
|
||
|
* `into_impl_` functions consume the object and produce a new final structure that
|
||
|
* keeps only the required information.
|
||
|
*
|
||
|
* `cast_impl_` functions merely check and transform the object into a type that can
|
||
|
*be transformed back into `OsInstance` without losing data.
|
||
|
*
|
||
|
* `as_ref_`, and `as_mut_` functions obtain references to safe objects, but do not
|
||
|
* perform any memory transformations either. They are the safest to use, because
|
||
|
* there is no risk of accidentally consuming the whole object.
|
||
|
*/
|
||
|
template<typename CGlueInst = CBox<void>, typename CGlueCtx = CArc<void>>
|
||
|
struct OsInstance {
|
||
|
const CloneVtbl<OsInstanceContainer<CGlueInst, CGlueCtx>> *vtbl_clone;
|
||
|
const OsVtbl<OsInstanceContainer<CGlueInst, CGlueCtx>> *vtbl_os;
|
||
|
const MemoryViewVtbl<OsInstanceContainer<CGlueInst, CGlueCtx>> *vtbl_memoryview;
|
||
|
const OsKeyboardVtbl<OsInstanceContainer<CGlueInst, CGlueCtx>> *vtbl_oskeyboard;
|
||
|
const PhysicalMemoryVtbl<OsInstanceContainer<CGlueInst, CGlueCtx>> *vtbl_physicalmemory;
|
||
|
const VirtualTranslateVtbl<OsInstanceContainer<CGlueInst, CGlueCtx>> *vtbl_virtualtranslate;
|
||
|
OsInstanceContainer<CGlueInst, CGlueCtx> container;
|
||
|
|
||
|
OsInstance() : container{} , vtbl_clone{}, vtbl_os{}, vtbl_memoryview{}, vtbl_oskeyboard{}, vtbl_physicalmemory{}, vtbl_virtualtranslate{} {}
|
||
|
|
||
|
~OsInstance() noexcept {
|
||
|
mem_drop(std::move(container));
|
||
|
}
|
||
|
|
||
|
typedef CGlueCtx Context;
|
||
|
|
||
|
inline OsInstance clone() const noexcept {
|
||
|
OsInstance __ret;
|
||
|
__ret.vtbl_clone = this->vtbl_clone;
|
||
|
__ret.vtbl_os = this->vtbl_os;
|
||
|
__ret.vtbl_memoryview = this->vtbl_memoryview;
|
||
|
__ret.vtbl_oskeyboard = this->vtbl_oskeyboard;
|
||
|
__ret.vtbl_physicalmemory = this->vtbl_physicalmemory;
|
||
|
__ret.vtbl_virtualtranslate = this->vtbl_virtualtranslate;
|
||
|
__ret.container = (this->vtbl_clone)->clone(&this->container);
|
||
|
return __ret;
|
||
|
}
|
||
|
|
||
|
inline int32_t process_address_list_callback(AddressCallback callback) noexcept {
|
||
|
int32_t __ret = (this->vtbl_os)->process_address_list_callback(&this->container, callback);
|
||
|
return __ret;
|
||
|
}
|
||
|
|
||
|
inline int32_t process_info_list_callback(ProcessInfoCallback callback) noexcept {
|
||
|
int32_t __ret = (this->vtbl_os)->process_info_list_callback(&this->container, callback);
|
||
|
return __ret;
|
||
|
}
|
||
|
|
||
|
inline int32_t process_info_by_address(Address address, ProcessInfo * ok_out) noexcept {
|
||
|
int32_t __ret = (this->vtbl_os)->process_info_by_address(&this->container, address, ok_out);
|
||
|
return __ret;
|
||
|
}
|
||
|
|
||
|
inline int32_t process_info_by_name(CSliceRef<uint8_t> name, ProcessInfo * ok_out) noexcept {
|
||
|
int32_t __ret = (this->vtbl_os)->process_info_by_name(&this->container, name, ok_out);
|
||
|
return __ret;
|
||
|
}
|
||
|
|
||
|
inline int32_t process_info_by_pid(Pid pid, ProcessInfo * ok_out) noexcept {
|
||
|
int32_t __ret = (this->vtbl_os)->process_info_by_pid(&this->container, pid, ok_out);
|
||
|
return __ret;
|
||
|
}
|
||
|
|
||
|
inline int32_t process_by_info(ProcessInfo info, ProcessInstance<CBox<void>, Context> * ok_out) noexcept {
|
||
|
int32_t __ret = (this->vtbl_os)->process_by_info(&this->container, info, ok_out);
|
||
|
return __ret;
|
||
|
}
|
||
|
|
||
|
inline int32_t into_process_by_info(ProcessInfo info, IntoProcessInstance<CBox<void>, Context> * ok_out) && noexcept {
|
||
|
auto ___ctx = StoreAll()[this->container.clone_context(), StoreAll()];
|
||
|
int32_t __ret = (this->vtbl_os)->into_process_by_info(this->container, info, ok_out);
|
||
|
mem_forget(this->container);
|
||
|
return __ret;
|
||
|
}
|
||
|
|
||
|
inline int32_t process_by_address(Address addr, ProcessInstance<CBox<void>, Context> * ok_out) noexcept {
|
||
|
int32_t __ret = (this->vtbl_os)->process_by_address(&this->container, addr, ok_out);
|
||
|
return __ret;
|
||
|
}
|
||
|
|
||
|
inline int32_t process_by_name(CSliceRef<uint8_t> name, ProcessInstance<CBox<void>, Context> * ok_out) noexcept {
|
||
|
int32_t __ret = (this->vtbl_os)->process_by_name(&this->container, name, ok_out);
|
||
|
return __ret;
|
||
|
}
|
||
|
|
||
|
inline int32_t process_by_pid(Pid pid, ProcessInstance<CBox<void>, Context> * ok_out) noexcept {
|
||
|
int32_t __ret = (this->vtbl_os)->process_by_pid(&this->container, pid, ok_out);
|
||
|
return __ret;
|
||
|
}
|
||
|
|
||
|
inline int32_t into_process_by_address(Address addr, IntoProcessInstance<CBox<void>, Context> * ok_out) && noexcept {
|
||
|
auto ___ctx = StoreAll()[this->container.clone_context(), StoreAll()];
|
||
|
int32_t __ret = (this->vtbl_os)->into_process_by_address(this->container, addr, ok_out);
|
||
|
mem_forget(this->container);
|
||
|
return __ret;
|
||
|
}
|
||
|
|
||
|
inline int32_t into_process_by_name(CSliceRef<uint8_t> name, IntoProcessInstance<CBox<void>, Context> * ok_out) && noexcept {
|
||
|
auto ___ctx = StoreAll()[this->container.clone_context(), StoreAll()];
|
||
|
int32_t __ret = (this->vtbl_os)->into_process_by_name(this->container, name, ok_out);
|
||
|
mem_forget(this->container);
|
||
|
return __ret;
|
||
|
}
|
||
|
|
||
|
inline int32_t into_process_by_pid(Pid pid, IntoProcessInstance<CBox<void>, Context> * ok_out) && noexcept {
|
||
|
auto ___ctx = StoreAll()[this->container.clone_context(), StoreAll()];
|
||
|
int32_t __ret = (this->vtbl_os)->into_process_by_pid(this->container, pid, ok_out);
|
||
|
mem_forget(this->container);
|
||
|
return __ret;
|
||
|
}
|
||
|
|
||
|
inline int32_t module_address_list_callback(AddressCallback callback) noexcept {
|
||
|
int32_t __ret = (this->vtbl_os)->module_address_list_callback(&this->container, callback);
|
||
|
return __ret;
|
||
|
}
|
||
|
|
||
|
inline int32_t module_list_callback(ModuleInfoCallback callback) noexcept {
|
||
|
int32_t __ret = (this->vtbl_os)->module_list_callback(&this->container, callback);
|
||
|
return __ret;
|
||
|
}
|
||
|
|
||
|
inline int32_t module_by_address(Address address, ModuleInfo * ok_out) noexcept {
|
||
|
int32_t __ret = (this->vtbl_os)->module_by_address(&this->container, address, ok_out);
|
||
|
return __ret;
|
||
|
}
|
||
|
|
||
|
inline int32_t module_by_name(CSliceRef<uint8_t> name, ModuleInfo * ok_out) noexcept {
|
||
|
int32_t __ret = (this->vtbl_os)->module_by_name(&this->container, name, ok_out);
|
||
|
return __ret;
|
||
|
}
|
||
|
|
||
|
inline int32_t primary_module_address(Address * ok_out) noexcept {
|
||
|
int32_t __ret = (this->vtbl_os)->primary_module_address(&this->container, ok_out);
|
||
|
return __ret;
|
||
|
}
|
||
|
|
||
|
inline int32_t primary_module(ModuleInfo * ok_out) noexcept {
|
||
|
int32_t __ret = (this->vtbl_os)->primary_module(&this->container, ok_out);
|
||
|
return __ret;
|
||
|
}
|
||
|
|
||
|
inline int32_t module_import_list_callback(const ModuleInfo * info, ImportCallback callback) noexcept {
|
||
|
int32_t __ret = (this->vtbl_os)->module_import_list_callback(&this->container, info, callback);
|
||
|
return __ret;
|
||
|
}
|
||
|
|
||
|
inline int32_t module_export_list_callback(const ModuleInfo * info, ExportCallback callback) noexcept {
|
||
|
int32_t __ret = (this->vtbl_os)->module_export_list_callback(&this->container, info, callback);
|
||
|
return __ret;
|
||
|
}
|
||
|
|
||
|
inline int32_t module_section_list_callback(const ModuleInfo * info, SectionCallback callback) noexcept {
|
||
|
int32_t __ret = (this->vtbl_os)->module_section_list_callback(&this->container, info, callback);
|
||
|
return __ret;
|
||
|
}
|
||
|
|
||
|
inline int32_t module_import_by_name(const ModuleInfo * info, CSliceRef<uint8_t> name, ImportInfo * ok_out) noexcept {
|
||
|
int32_t __ret = (this->vtbl_os)->module_import_by_name(&this->container, info, name, ok_out);
|
||
|
return __ret;
|
||
|
}
|
||
|
|
||
|
inline int32_t module_export_by_name(const ModuleInfo * info, CSliceRef<uint8_t> name, ExportInfo * ok_out) noexcept {
|
||
|
int32_t __ret = (this->vtbl_os)->module_export_by_name(&this->container, info, name, ok_out);
|
||
|
return __ret;
|
||
|
}
|
||
|
|
||
|
inline int32_t module_section_by_name(const ModuleInfo * info, CSliceRef<uint8_t> name, SectionInfo * ok_out) noexcept {
|
||
|
int32_t __ret = (this->vtbl_os)->module_section_by_name(&this->container, info, name, ok_out);
|
||
|
return __ret;
|
||
|
}
|
||
|
|
||
|
inline const OsInfo * info() const noexcept {
|
||
|
const OsInfo * __ret = (this->vtbl_os)->info(&this->container);
|
||
|
return __ret;
|
||
|
}
|
||
|
|
||
|
inline int32_t read_raw_iter(ReadRawMemOps data) noexcept {
|
||
|
int32_t __ret = (this->vtbl_memoryview)->read_raw_iter(&this->container, data);
|
||
|
return __ret;
|
||
|
}
|
||
|
|
||
|
inline int32_t write_raw_iter(WriteRawMemOps data) noexcept {
|
||
|
int32_t __ret = (this->vtbl_memoryview)->write_raw_iter(&this->container, data);
|
||
|
return __ret;
|
||
|
}
|
||
|
|
||
|
inline MemoryViewMetadata memoryview_metadata() const noexcept {
|
||
|
MemoryViewMetadata __ret = (this->vtbl_memoryview)->metadata(&this->container);
|
||
|
return __ret;
|
||
|
}
|
||
|
|
||
|
inline int32_t read_iter(CIterator<ReadData> inp, ReadCallback * out, ReadCallback * out_fail) noexcept {
|
||
|
int32_t __ret = (this->vtbl_memoryview)->read_iter(&this->container, inp, out, out_fail);
|
||
|
return __ret;
|
||
|
}
|
||
|
|
||
|
inline int32_t read_raw_list(CSliceMut<ReadData> data) noexcept {
|
||
|
int32_t __ret = (this->vtbl_memoryview)->read_raw_list(&this->container, data);
|
||
|
return __ret;
|
||
|
}
|
||
|
|
||
|
inline int32_t read_raw_into(Address addr, CSliceMut<uint8_t> out) noexcept {
|
||
|
int32_t __ret = (this->vtbl_memoryview)->read_raw_into(&this->container, addr, out);
|
||
|
return __ret;
|
||
|
}
|
||
|
|
||
|
inline int32_t write_iter(CIterator<WriteData> inp, WriteCallback * out, WriteCallback * out_fail) noexcept {
|
||
|
int32_t __ret = (this->vtbl_memoryview)->write_iter(&this->container, inp, out, out_fail);
|
||
|
return __ret;
|
||
|
}
|
||
|
|
||
|
inline int32_t write_raw_list(CSliceRef<WriteData> data) noexcept {
|
||
|
int32_t __ret = (this->vtbl_memoryview)->write_raw_list(&this->container, data);
|
||
|
return __ret;
|
||
|
}
|
||
|
|
||
|
inline int32_t write_raw(Address addr, CSliceRef<uint8_t> data) noexcept {
|
||
|
int32_t __ret = (this->vtbl_memoryview)->write_raw(&this->container, addr, data);
|
||
|
return __ret;
|
||
|
}
|
||
|
|
||
|
inline int32_t keyboard(KeyboardBase<CBox<void>, Context> * ok_out) noexcept {
|
||
|
int32_t __ret = (this->vtbl_oskeyboard)->keyboard(&this->container, ok_out);
|
||
|
return __ret;
|
||
|
}
|
||
|
|
||
|
inline int32_t into_keyboard(IntoKeyboard<CBox<void>, Context> * ok_out) && noexcept {
|
||
|
auto ___ctx = StoreAll()[this->container.clone_context(), StoreAll()];
|
||
|
int32_t __ret = (this->vtbl_oskeyboard)->into_keyboard(this->container, ok_out);
|
||
|
mem_forget(this->container);
|
||
|
return __ret;
|
||
|
}
|
||
|
|
||
|
inline int32_t phys_read_raw_iter(PhysicalReadMemOps data) noexcept {
|
||
|
int32_t __ret = (this->vtbl_physicalmemory)->phys_read_raw_iter(&this->container, data);
|
||
|
return __ret;
|
||
|
}
|
||
|
|
||
|
inline int32_t phys_write_raw_iter(PhysicalWriteMemOps data) noexcept {
|
||
|
int32_t __ret = (this->vtbl_physicalmemory)->phys_write_raw_iter(&this->container, data);
|
||
|
return __ret;
|
||
|
}
|
||
|
|
||
|
inline PhysicalMemoryMetadata physicalmemory_metadata() const noexcept {
|
||
|
PhysicalMemoryMetadata __ret = (this->vtbl_physicalmemory)->metadata(&this->container);
|
||
|
return __ret;
|
||
|
}
|
||
|
|
||
|
inline void set_mem_map(CSliceRef<PhysicalMemoryMapping> _mem_map) noexcept {
|
||
|
(this->vtbl_physicalmemory)->set_mem_map(&this->container, _mem_map);
|
||
|
|
||
|
}
|
||
|
|
||
|
inline MemoryViewBase<CBox<void>, Context> into_phys_view() && noexcept {
|
||
|
auto ___ctx = StoreAll()[this->container.clone_context(), StoreAll()];
|
||
|
MemoryViewBase<CBox<void>, Context> __ret = (this->vtbl_physicalmemory)->into_phys_view(this->container);
|
||
|
mem_forget(this->container);
|
||
|
return __ret;
|
||
|
}
|
||
|
|
||
|
inline MemoryViewBase<CBox<void>, Context> phys_view() noexcept {
|
||
|
MemoryViewBase<CBox<void>, Context> __ret = (this->vtbl_physicalmemory)->phys_view(&this->container);
|
||
|
return __ret;
|
||
|
}
|
||
|
|
||
|
inline void virt_to_phys_list(CSliceRef<VtopRange> addrs, VirtualTranslationCallback out, VirtualTranslationFailCallback out_fail) noexcept {
|
||
|
(this->vtbl_virtualtranslate)->virt_to_phys_list(&this->container, addrs, out, out_fail);
|
||
|
|
||
|
}
|
||
|
|
||
|
inline void virt_to_phys_range(Address start, Address end, VirtualTranslationCallback out) noexcept {
|
||
|
(this->vtbl_virtualtranslate)->virt_to_phys_range(&this->container, start, end, out);
|
||
|
|
||
|
}
|
||
|
|
||
|
inline void virt_translation_map_range(Address start, Address end, VirtualTranslationCallback out) noexcept {
|
||
|
(this->vtbl_virtualtranslate)->virt_translation_map_range(&this->container, start, end, out);
|
||
|
|
||
|
}
|
||
|
|
||
|
inline void virt_page_map_range(imem gap_size, Address start, Address end, MemoryRangeCallback out) noexcept {
|
||
|
(this->vtbl_virtualtranslate)->virt_page_map_range(&this->container, gap_size, start, end, out);
|
||
|
|
||
|
}
|
||
|
|
||
|
inline int32_t virt_to_phys(Address address, PhysicalAddress * ok_out) noexcept {
|
||
|
int32_t __ret = (this->vtbl_virtualtranslate)->virt_to_phys(&this->container, address, ok_out);
|
||
|
return __ret;
|
||
|
}
|
||
|
|
||
|
inline int32_t virt_page_info(Address addr, Page * ok_out) noexcept {
|
||
|
int32_t __ret = (this->vtbl_virtualtranslate)->virt_page_info(&this->container, addr, ok_out);
|
||
|
return __ret;
|
||
|
}
|
||
|
|
||
|
inline void virt_translation_map(VirtualTranslationCallback out) noexcept {
|
||
|
(this->vtbl_virtualtranslate)->virt_translation_map(&this->container, out);
|
||
|
|
||
|
}
|
||
|
|
||
|
inline COption<Address> phys_to_virt(Address phys) noexcept {
|
||
|
COption<Address> __ret = (this->vtbl_virtualtranslate)->phys_to_virt(&this->container, phys);
|
||
|
return __ret;
|
||
|
}
|
||
|
|
||
|
inline void virt_page_map(imem gap_size, MemoryRangeCallback out) noexcept {
|
||
|
(this->vtbl_virtualtranslate)->virt_page_map(&this->container, gap_size, out);
|
||
|
|
||
|
}
|
||
|
|
||
|
};
|
||
|
|
||
|
template<typename CGlueT, typename CGlueCtx = CArc<void>>
|
||
|
using OsInstanceBaseCtxBox = OsInstance<CBox<CGlueT>, CGlueCtx>;
|
||
|
|
||
|
template<typename CGlueT, typename CGlueArcTy>
|
||
|
using OsInstanceBaseArcBox = OsInstanceBaseCtxBox<CGlueT, CArc<CGlueArcTy>>;
|
||
|
// Typedef for default contaienr and context type
|
||
|
template<typename CGlueT, typename CGlueArcTy>
|
||
|
using OsInstanceBase = OsInstanceBaseArcBox<CGlueT,CGlueArcTy>;
|
||
|
|
||
|
using OsInstanceArcBox = OsInstanceBaseArcBox<void, void>;
|
||
|
|
||
|
using MuOsInstanceArcBox = OsInstanceArcBox;
|
||
|
// Typedef for default contaienr and context type
|
||
|
using MuOsInstance = MuOsInstanceArcBox;
|
||
|
|
||
|
template<typename CGlueT, typename CGlueCtx = CArc<void>>
|
||
|
using ProcessInstanceBaseCtxBox = ProcessInstance<CBox<CGlueT>, CGlueCtx>;
|
||
|
|
||
|
template<typename CGlueT, typename CGlueArcTy>
|
||
|
using ProcessInstanceBaseArcBox = ProcessInstanceBaseCtxBox<CGlueT, CArc<CGlueArcTy>>;
|
||
|
// Typedef for default contaienr and context type
|
||
|
template<typename CGlueT, typename CGlueArcTy>
|
||
|
using ProcessInstanceBase = ProcessInstanceBaseArcBox<CGlueT,CGlueArcTy>;
|
||
|
|
||
|
using ProcessInstanceArcBox = ProcessInstanceBaseArcBox<void, void>;
|
||
|
|
||
|
template<typename CGlueT, typename CGlueCtx = CArc<void>>
|
||
|
using IntoProcessInstanceBaseCtxBox = IntoProcessInstance<CBox<CGlueT>, CGlueCtx>;
|
||
|
|
||
|
template<typename CGlueT, typename CGlueArcTy>
|
||
|
using IntoProcessInstanceBaseArcBox = IntoProcessInstanceBaseCtxBox<CGlueT, CArc<CGlueArcTy>>;
|
||
|
// Typedef for default contaienr and context type
|
||
|
template<typename CGlueT, typename CGlueArcTy>
|
||
|
using IntoProcessInstanceBase = IntoProcessInstanceBaseArcBox<CGlueT,CGlueArcTy>;
|
||
|
|
||
|
using IntoProcessInstanceArcBox = IntoProcessInstanceBaseArcBox<void, void>;
|
||
|
|
||
|
/**
|
||
|
* CtxBoxed CGlue trait object for trait MemoryView with context.
|
||
|
*/
|
||
|
template<typename CGlueT, typename CGlueCtx = CArc<void>>
|
||
|
using MemoryViewBaseCtxBox = MemoryViewBase<CBox<CGlueT>, CGlueCtx>;
|
||
|
|
||
|
/**
|
||
|
* Boxed CGlue trait object for trait MemoryView with a [`CArc`](cglue::arc::CArc) reference counted context.
|
||
|
*/
|
||
|
template<typename CGlueT, typename CGlueC>
|
||
|
using MemoryViewBaseArcBox = MemoryViewBaseCtxBox<CGlueT, CArc<CGlueC>>;
|
||
|
|
||
|
/**
|
||
|
* Opaque Boxed CGlue trait object for trait MemoryView with a [`CArc`](cglue::arc::CArc) reference counted context.
|
||
|
*/
|
||
|
using MemoryViewArcBox = MemoryViewBaseArcBox<void, void>;
|
||
|
// Typedef for default contaienr and context type
|
||
|
using MemoryView = MemoryViewArcBox;
|
||
|
|
||
|
extern "C" {
|
||
|
|
||
|
extern const ArchitectureObj *X86_32;
|
||
|
|
||
|
extern const ArchitectureObj *X86_32_PAE;
|
||
|
|
||
|
extern const ArchitectureObj *X86_64;
|
||
|
|
||
|
/**
|
||
|
* Initialize logging with selected logging level.
|
||
|
*/
|
||
|
void log_init(LevelFilter level_filter);
|
||
|
|
||
|
/**
|
||
|
* Logs a error message via log::error!
|
||
|
*
|
||
|
* # Safety
|
||
|
*
|
||
|
* The provided string must be a valid null-terminated char array.
|
||
|
*/
|
||
|
void log_error(const char *s);
|
||
|
|
||
|
/**
|
||
|
* Logs a warning message via log::warn!
|
||
|
*
|
||
|
* # Safety
|
||
|
*
|
||
|
* The provided string must be a valid null-terminated char array.
|
||
|
*/
|
||
|
void log_warn(const char *s);
|
||
|
|
||
|
/**
|
||
|
* Logs a info message via log::info!
|
||
|
*
|
||
|
* # Safety
|
||
|
*
|
||
|
* The provided string must be a valid null-terminated char array.
|
||
|
*/
|
||
|
void log_info(const char *s);
|
||
|
|
||
|
/**
|
||
|
* Logs a debug message via log::debug!
|
||
|
*
|
||
|
* # Safety
|
||
|
*
|
||
|
* The provided string must be a valid null-terminated char array.
|
||
|
*/
|
||
|
void log_debug(const char *s);
|
||
|
|
||
|
/**
|
||
|
* Logs a trace message via log::trace!
|
||
|
*
|
||
|
* # Safety
|
||
|
*
|
||
|
* The provided string must be a valid null-terminated char array.
|
||
|
*/
|
||
|
void log_trace(const char *s);
|
||
|
|
||
|
/**
|
||
|
* Logs an error code with custom log level.
|
||
|
*/
|
||
|
void log_errorcode(Level level, int32_t error);
|
||
|
|
||
|
/**
|
||
|
* Logs an error with debug log level.
|
||
|
*/
|
||
|
void log_debug_errorcode(int32_t error);
|
||
|
|
||
|
/**
|
||
|
* Sets new maximum log level.
|
||
|
*
|
||
|
* If `inventory` is supplied, the log level is also updated within all plugin instances. However,
|
||
|
* if it is not supplied, plugins will not have their log levels updated, potentially leading to
|
||
|
* lower performance, or less logging than expected.
|
||
|
*/
|
||
|
void log_set_max_level(LevelFilter level_filter, const Inventory *inventory);
|
||
|
|
||
|
/**
|
||
|
* Helper to convert `Address` to a `PhysicalAddress`
|
||
|
*
|
||
|
* This will create a `PhysicalAddress` with `UNKNOWN` PageType.
|
||
|
*/
|
||
|
PhysicalAddress addr_to_paddr(Address address);
|
||
|
|
||
|
/**
|
||
|
* Create a new connector inventory
|
||
|
*
|
||
|
* This function will try to find connectors using PATH environment variable
|
||
|
*
|
||
|
* Note that all functions go through each directories, and look for a `memflow` directory,
|
||
|
* and search for libraries in those.
|
||
|
*
|
||
|
* # Safety
|
||
|
*
|
||
|
* Inventory is inherently unsafe, because it loads shared libraries which can not be
|
||
|
* guaranteed to be safe.
|
||
|
*/
|
||
|
Inventory *inventory_scan();
|
||
|
|
||
|
/**
|
||
|
* Create a new inventory with custom path string
|
||
|
*
|
||
|
* # Safety
|
||
|
*
|
||
|
* `path` must be a valid null terminated string
|
||
|
*/
|
||
|
Inventory *inventory_scan_path(const char *path);
|
||
|
|
||
|
/**
|
||
|
* Add a directory to an existing inventory
|
||
|
*
|
||
|
* # Safety
|
||
|
*
|
||
|
* `dir` must be a valid null terminated string
|
||
|
*/
|
||
|
int32_t inventory_add_dir(Inventory *inv, const char *dir);
|
||
|
|
||
|
/**
|
||
|
* Create a connector with given arguments
|
||
|
*
|
||
|
* This creates an instance of `ConnectorInstance`.
|
||
|
*
|
||
|
* This instance needs to be dropped using `connector_drop`.
|
||
|
*
|
||
|
* # Arguments
|
||
|
*
|
||
|
* * `name` - name of the connector to use
|
||
|
* * `args` - arguments to be passed to the connector upon its creation
|
||
|
*
|
||
|
* # Safety
|
||
|
*
|
||
|
* Both `name`, and `args` must be valid null terminated strings.
|
||
|
*
|
||
|
* Any error strings returned by the connector must not be outputed after the connector gets
|
||
|
* freed, because that operation could cause the underlying shared library to get unloaded.
|
||
|
*/
|
||
|
int32_t inventory_create_connector(Inventory *inv,
|
||
|
const char *name,
|
||
|
const char *args,
|
||
|
MuConnectorInstanceArcBox *out);
|
||
|
|
||
|
/**
|
||
|
* Create a OS instance with given arguments
|
||
|
*
|
||
|
* This creates an instance of `KernelInstance`.
|
||
|
*
|
||
|
* This instance needs to be freed using `os_drop`.
|
||
|
*
|
||
|
* # Arguments
|
||
|
*
|
||
|
* * `name` - name of the OS to use
|
||
|
* * `args` - arguments to be passed to the connector upon its creation
|
||
|
* * `mem` - a previously initialized connector instance
|
||
|
* * `out` - a valid memory location that will contain the resulting os-instance
|
||
|
*
|
||
|
* # Remarks
|
||
|
*
|
||
|
* The `mem` connector instance is being _moved_ into the os layer.
|
||
|
* This means upon calling `os_drop` it is not unnecessary to call `connector_drop` anymore.
|
||
|
*
|
||
|
* # Safety
|
||
|
*
|
||
|
* Both `name`, and `args` must be valid null terminated strings.
|
||
|
*
|
||
|
* Any error strings returned by the connector must not be outputed after the connector gets
|
||
|
* freed, because that operation could cause the underlying shared library to get unloaded.
|
||
|
*/
|
||
|
int32_t inventory_create_os(Inventory *inv,
|
||
|
const char *name,
|
||
|
const char *args,
|
||
|
ConnectorInstanceArcBox *mem,
|
||
|
MuOsInstanceArcBox *out);
|
||
|
|
||
|
/**
|
||
|
* Free a os plugin
|
||
|
*
|
||
|
* # Safety
|
||
|
*
|
||
|
* `os` must point to a valid `OsInstance` that was created using one of the provided
|
||
|
* functions.
|
||
|
*/
|
||
|
void os_drop(OsInstanceArcBox *os);
|
||
|
|
||
|
/**
|
||
|
* Clone a connector
|
||
|
*
|
||
|
* This method is useful when needing to perform multithreaded operations, as a connector is not
|
||
|
* guaranteed to be thread safe. Every single cloned instance also needs to be dropped using
|
||
|
* `connector_drop`.
|
||
|
*
|
||
|
* # Safety
|
||
|
*
|
||
|
* `conn` has to point to a a valid `CloneablePhysicalMemory` created by one of the provided
|
||
|
* functions.
|
||
|
*/
|
||
|
void connector_clone(const ConnectorInstanceArcBox *conn, MuConnectorInstanceArcBox *out);
|
||
|
|
||
|
/**
|
||
|
* Free a connector instance
|
||
|
*
|
||
|
* # Safety
|
||
|
*
|
||
|
* `conn` has to point to a valid [`ConnectorInstance`](ConnectorInstanceArcBox) created by one of the provided
|
||
|
* functions.
|
||
|
*
|
||
|
* There has to be no instance of `PhysicalMemory` created from the input `conn`, because they
|
||
|
* will become invalid.
|
||
|
*/
|
||
|
void connector_drop(ConnectorInstanceArcBox *conn);
|
||
|
|
||
|
/**
|
||
|
* Free a connector inventory
|
||
|
*
|
||
|
* # Safety
|
||
|
*
|
||
|
* `inv` must point to a valid `Inventory` that was created using one of the provided
|
||
|
* functions.
|
||
|
*/
|
||
|
void inventory_free(Inventory *inv);
|
||
|
|
||
|
uint8_t arch_bits(const ArchitectureObj *arch);
|
||
|
|
||
|
Endianess arch_endianess(const ArchitectureObj *arch);
|
||
|
|
||
|
uintptr_t arch_page_size(const ArchitectureObj *arch);
|
||
|
|
||
|
uintptr_t arch_size_addr(const ArchitectureObj *arch);
|
||
|
|
||
|
uint8_t arch_address_space_bits(const ArchitectureObj *arch);
|
||
|
|
||
|
/**
|
||
|
* Free an architecture reference
|
||
|
*
|
||
|
* # Safety
|
||
|
*
|
||
|
* `arch` must be a valid heap allocated reference created by one of the API's functions.
|
||
|
*/
|
||
|
void arch_free(ArchitectureObj *arch);
|
||
|
|
||
|
bool is_x86_arch(const ArchitectureObj *arch);
|
||
|
|
||
|
} // extern "C"
|
||
|
|
||
|
|
||
|
template<typename T, typename C, typename R>
|
||
|
struct CGlueTraitObj<T, CloneVtbl<CGlueObjContainer<T, C, R>>, C, R> {
|
||
|
const CloneVtbl<CGlueObjContainer<T, C, R>> *vtbl;
|
||
|
CGlueObjContainer<T, C, R> container;
|
||
|
|
||
|
CGlueTraitObj() : container{} {}
|
||
|
|
||
|
~CGlueTraitObj() noexcept {
|
||
|
mem_drop(std::move(container));
|
||
|
}
|
||
|
|
||
|
typedef C Context;
|
||
|
|
||
|
inline CGlueTraitObj clone() const noexcept {
|
||
|
CGlueTraitObj __ret;
|
||
|
__ret.vtbl = this->vtbl;
|
||
|
__ret.container = (this->vtbl)->clone(&this->container);
|
||
|
return __ret;
|
||
|
}
|
||
|
|
||
|
};
|
||
|
|
||
|
template<typename T, typename C, typename R>
|
||
|
struct CGlueTraitObj<T, MemoryViewVtbl<CGlueObjContainer<T, C, R>>, C, R> {
|
||
|
const MemoryViewVtbl<CGlueObjContainer<T, C, R>> *vtbl;
|
||
|
CGlueObjContainer<T, C, R> container;
|
||
|
|
||
|
CGlueTraitObj() : container{} {}
|
||
|
|
||
|
~CGlueTraitObj() noexcept {
|
||
|
mem_drop(std::move(container));
|
||
|
}
|
||
|
|
||
|
typedef C Context;
|
||
|
|
||
|
inline int32_t read_raw_iter(ReadRawMemOps data) noexcept {
|
||
|
int32_t __ret = (this->vtbl)->read_raw_iter(&this->container, data);
|
||
|
return __ret;
|
||
|
}
|
||
|
|
||
|
inline int32_t write_raw_iter(WriteRawMemOps data) noexcept {
|
||
|
int32_t __ret = (this->vtbl)->write_raw_iter(&this->container, data);
|
||
|
return __ret;
|
||
|
}
|
||
|
|
||
|
inline MemoryViewMetadata metadata() const noexcept {
|
||
|
MemoryViewMetadata __ret = (this->vtbl)->metadata(&this->container);
|
||
|
return __ret;
|
||
|
}
|
||
|
|
||
|
inline int32_t read_iter(CIterator<ReadData> inp, ReadCallback * out, ReadCallback * out_fail) noexcept {
|
||
|
int32_t __ret = (this->vtbl)->read_iter(&this->container, inp, out, out_fail);
|
||
|
return __ret;
|
||
|
}
|
||
|
|
||
|
inline int32_t read_raw_list(CSliceMut<ReadData> data) noexcept {
|
||
|
int32_t __ret = (this->vtbl)->read_raw_list(&this->container, data);
|
||
|
return __ret;
|
||
|
}
|
||
|
|
||
|
inline int32_t read_raw_into(Address addr, CSliceMut<uint8_t> out) noexcept {
|
||
|
int32_t __ret = (this->vtbl)->read_raw_into(&this->container, addr, out);
|
||
|
return __ret;
|
||
|
}
|
||
|
|
||
|
inline int32_t write_iter(CIterator<WriteData> inp, WriteCallback * out, WriteCallback * out_fail) noexcept {
|
||
|
int32_t __ret = (this->vtbl)->write_iter(&this->container, inp, out, out_fail);
|
||
|
return __ret;
|
||
|
}
|
||
|
|
||
|
inline int32_t write_raw_list(CSliceRef<WriteData> data) noexcept {
|
||
|
int32_t __ret = (this->vtbl)->write_raw_list(&this->container, data);
|
||
|
return __ret;
|
||
|
}
|
||
|
|
||
|
inline int32_t write_raw(Address addr, CSliceRef<uint8_t> data) noexcept {
|
||
|
int32_t __ret = (this->vtbl)->write_raw(&this->container, addr, data);
|
||
|
return __ret;
|
||
|
}
|
||
|
|
||
|
};
|
||
|
|
||
|
template<typename T, typename C, typename R>
|
||
|
struct CGlueTraitObj<T, PhysicalMemoryVtbl<CGlueObjContainer<T, C, R>>, C, R> {
|
||
|
const PhysicalMemoryVtbl<CGlueObjContainer<T, C, R>> *vtbl;
|
||
|
CGlueObjContainer<T, C, R> container;
|
||
|
|
||
|
CGlueTraitObj() : container{} {}
|
||
|
|
||
|
~CGlueTraitObj() noexcept {
|
||
|
mem_drop(std::move(container));
|
||
|
}
|
||
|
|
||
|
typedef C Context;
|
||
|
|
||
|
inline int32_t phys_read_raw_iter(PhysicalReadMemOps data) noexcept {
|
||
|
int32_t __ret = (this->vtbl)->phys_read_raw_iter(&this->container, data);
|
||
|
return __ret;
|
||
|
}
|
||
|
|
||
|
inline int32_t phys_write_raw_iter(PhysicalWriteMemOps data) noexcept {
|
||
|
int32_t __ret = (this->vtbl)->phys_write_raw_iter(&this->container, data);
|
||
|
return __ret;
|
||
|
}
|
||
|
|
||
|
inline PhysicalMemoryMetadata metadata() const noexcept {
|
||
|
PhysicalMemoryMetadata __ret = (this->vtbl)->metadata(&this->container);
|
||
|
return __ret;
|
||
|
}
|
||
|
|
||
|
inline void set_mem_map(CSliceRef<PhysicalMemoryMapping> _mem_map) noexcept {
|
||
|
(this->vtbl)->set_mem_map(&this->container, _mem_map);
|
||
|
|
||
|
}
|
||
|
|
||
|
inline MemoryViewBase<CBox<void>, Context> into_phys_view() && noexcept {
|
||
|
auto ___ctx = StoreAll()[this->container.clone_context(), StoreAll()];
|
||
|
MemoryViewBase<CBox<void>, Context> __ret = (this->vtbl)->into_phys_view(this->container);
|
||
|
mem_forget(this->container);
|
||
|
return __ret;
|
||
|
}
|
||
|
|
||
|
inline MemoryViewBase<CBox<void>, Context> phys_view() noexcept {
|
||
|
MemoryViewBase<CBox<void>, Context> __ret = (this->vtbl)->phys_view(&this->container);
|
||
|
return __ret;
|
||
|
}
|
||
|
|
||
|
};
|
||
|
|
||
|
template<typename T, typename C, typename R>
|
||
|
struct CGlueTraitObj<T, CpuStateVtbl<CGlueObjContainer<T, C, R>>, C, R> {
|
||
|
const CpuStateVtbl<CGlueObjContainer<T, C, R>> *vtbl;
|
||
|
CGlueObjContainer<T, C, R> container;
|
||
|
|
||
|
CGlueTraitObj() : container{} {}
|
||
|
|
||
|
~CGlueTraitObj() noexcept {
|
||
|
mem_drop(std::move(container));
|
||
|
}
|
||
|
|
||
|
typedef C Context;
|
||
|
|
||
|
inline void pause() noexcept {
|
||
|
(this->vtbl)->pause(&this->container);
|
||
|
|
||
|
}
|
||
|
|
||
|
inline void resume() noexcept {
|
||
|
(this->vtbl)->resume(&this->container);
|
||
|
|
||
|
}
|
||
|
|
||
|
};
|
||
|
|
||
|
template<typename T, typename C, typename R>
|
||
|
struct CGlueTraitObj<T, ConnectorCpuStateVtbl<CGlueObjContainer<T, C, R>>, C, R> {
|
||
|
const ConnectorCpuStateVtbl<CGlueObjContainer<T, C, R>> *vtbl;
|
||
|
CGlueObjContainer<T, C, R> container;
|
||
|
|
||
|
CGlueTraitObj() : container{} {}
|
||
|
|
||
|
~CGlueTraitObj() noexcept {
|
||
|
mem_drop(std::move(container));
|
||
|
}
|
||
|
|
||
|
typedef C Context;
|
||
|
|
||
|
inline int32_t cpu_state(CpuStateBase<CBox<void>, Context> * ok_out) noexcept {
|
||
|
int32_t __ret = (this->vtbl)->cpu_state(&this->container, ok_out);
|
||
|
return __ret;
|
||
|
}
|
||
|
|
||
|
inline int32_t into_cpu_state(IntoCpuState<CBox<void>, Context> * ok_out) && noexcept {
|
||
|
auto ___ctx = StoreAll()[this->container.clone_context(), StoreAll()];
|
||
|
int32_t __ret = (this->vtbl)->into_cpu_state(this->container, ok_out);
|
||
|
mem_forget(this->container);
|
||
|
return __ret;
|
||
|
}
|
||
|
|
||
|
};
|
||
|
|
||
|
template<typename T, typename C, typename R>
|
||
|
struct CGlueTraitObj<T, ProcessVtbl<CGlueObjContainer<T, C, R>>, C, R> {
|
||
|
const ProcessVtbl<CGlueObjContainer<T, C, R>> *vtbl;
|
||
|
CGlueObjContainer<T, C, R> container;
|
||
|
|
||
|
CGlueTraitObj() : container{} {}
|
||
|
|
||
|
~CGlueTraitObj() noexcept {
|
||
|
mem_drop(std::move(container));
|
||
|
}
|
||
|
|
||
|
typedef C Context;
|
||
|
|
||
|
inline ProcessState state() noexcept {
|
||
|
ProcessState __ret = (this->vtbl)->state(&this->container);
|
||
|
return __ret;
|
||
|
}
|
||
|
|
||
|
inline int32_t set_dtb(Address dtb1, Address dtb2) noexcept {
|
||
|
int32_t __ret = (this->vtbl)->set_dtb(&this->container, dtb1, dtb2);
|
||
|
return __ret;
|
||
|
}
|
||
|
|
||
|
inline int32_t module_address_list_callback(const ArchitectureIdent * target_arch, ModuleAddressCallback callback) noexcept {
|
||
|
int32_t __ret = (this->vtbl)->module_address_list_callback(&this->container, target_arch, callback);
|
||
|
return __ret;
|
||
|
}
|
||
|
|
||
|
inline int32_t module_list_callback(const ArchitectureIdent * target_arch, ModuleInfoCallback callback) noexcept {
|
||
|
int32_t __ret = (this->vtbl)->module_list_callback(&this->container, target_arch, callback);
|
||
|
return __ret;
|
||
|
}
|
||
|
|
||
|
inline int32_t module_by_address(Address address, ArchitectureIdent architecture, ModuleInfo * ok_out) noexcept {
|
||
|
int32_t __ret = (this->vtbl)->module_by_address(&this->container, address, architecture, ok_out);
|
||
|
return __ret;
|
||
|
}
|
||
|
|
||
|
inline int32_t module_by_name_arch(CSliceRef<uint8_t> name, const ArchitectureIdent * architecture, ModuleInfo * ok_out) noexcept {
|
||
|
int32_t __ret = (this->vtbl)->module_by_name_arch(&this->container, name, architecture, ok_out);
|
||
|
return __ret;
|
||
|
}
|
||
|
|
||
|
inline int32_t module_by_name(CSliceRef<uint8_t> name, ModuleInfo * ok_out) noexcept {
|
||
|
int32_t __ret = (this->vtbl)->module_by_name(&this->container, name, ok_out);
|
||
|
return __ret;
|
||
|
}
|
||
|
|
||
|
inline int32_t primary_module_address(Address * ok_out) noexcept {
|
||
|
int32_t __ret = (this->vtbl)->primary_module_address(&this->container, ok_out);
|
||
|
return __ret;
|
||
|
}
|
||
|
|
||
|
inline int32_t primary_module(ModuleInfo * ok_out) noexcept {
|
||
|
int32_t __ret = (this->vtbl)->primary_module(&this->container, ok_out);
|
||
|
return __ret;
|
||
|
}
|
||
|
|
||
|
inline int32_t module_import_list_callback(const ModuleInfo * info, ImportCallback callback) noexcept {
|
||
|
int32_t __ret = (this->vtbl)->module_import_list_callback(&this->container, info, callback);
|
||
|
return __ret;
|
||
|
}
|
||
|
|
||
|
inline int32_t module_export_list_callback(const ModuleInfo * info, ExportCallback callback) noexcept {
|
||
|
int32_t __ret = (this->vtbl)->module_export_list_callback(&this->container, info, callback);
|
||
|
return __ret;
|
||
|
}
|
||
|
|
||
|
inline int32_t module_section_list_callback(const ModuleInfo * info, SectionCallback callback) noexcept {
|
||
|
int32_t __ret = (this->vtbl)->module_section_list_callback(&this->container, info, callback);
|
||
|
return __ret;
|
||
|
}
|
||
|
|
||
|
inline int32_t module_import_by_name(const ModuleInfo * info, CSliceRef<uint8_t> name, ImportInfo * ok_out) noexcept {
|
||
|
int32_t __ret = (this->vtbl)->module_import_by_name(&this->container, info, name, ok_out);
|
||
|
return __ret;
|
||
|
}
|
||
|
|
||
|
inline int32_t module_export_by_name(const ModuleInfo * info, CSliceRef<uint8_t> name, ExportInfo * ok_out) noexcept {
|
||
|
int32_t __ret = (this->vtbl)->module_export_by_name(&this->container, info, name, ok_out);
|
||
|
return __ret;
|
||
|
}
|
||
|
|
||
|
inline int32_t module_section_by_name(const ModuleInfo * info, CSliceRef<uint8_t> name, SectionInfo * ok_out) noexcept {
|
||
|
int32_t __ret = (this->vtbl)->module_section_by_name(&this->container, info, name, ok_out);
|
||
|
return __ret;
|
||
|
}
|
||
|
|
||
|
inline const ProcessInfo * info() const noexcept {
|
||
|
const ProcessInfo * __ret = (this->vtbl)->info(&this->container);
|
||
|
return __ret;
|
||
|
}
|
||
|
|
||
|
inline void mapped_mem_range(imem gap_size, Address start, Address end, MemoryRangeCallback out) noexcept {
|
||
|
(this->vtbl)->mapped_mem_range(&this->container, gap_size, start, end, out);
|
||
|
|
||
|
}
|
||
|
|
||
|
inline void mapped_mem(imem gap_size, MemoryRangeCallback out) noexcept {
|
||
|
(this->vtbl)->mapped_mem(&this->container, gap_size, out);
|
||
|
|
||
|
}
|
||
|
|
||
|
};
|
||
|
|
||
|
template<typename T, typename C, typename R>
|
||
|
struct CGlueTraitObj<T, VirtualTranslateVtbl<CGlueObjContainer<T, C, R>>, C, R> {
|
||
|
const VirtualTranslateVtbl<CGlueObjContainer<T, C, R>> *vtbl;
|
||
|
CGlueObjContainer<T, C, R> container;
|
||
|
|
||
|
CGlueTraitObj() : container{} {}
|
||
|
|
||
|
~CGlueTraitObj() noexcept {
|
||
|
mem_drop(std::move(container));
|
||
|
}
|
||
|
|
||
|
typedef C Context;
|
||
|
|
||
|
inline void virt_to_phys_list(CSliceRef<VtopRange> addrs, VirtualTranslationCallback out, VirtualTranslationFailCallback out_fail) noexcept {
|
||
|
(this->vtbl)->virt_to_phys_list(&this->container, addrs, out, out_fail);
|
||
|
|
||
|
}
|
||
|
|
||
|
inline void virt_to_phys_range(Address start, Address end, VirtualTranslationCallback out) noexcept {
|
||
|
(this->vtbl)->virt_to_phys_range(&this->container, start, end, out);
|
||
|
|
||
|
}
|
||
|
|
||
|
inline void virt_translation_map_range(Address start, Address end, VirtualTranslationCallback out) noexcept {
|
||
|
(this->vtbl)->virt_translation_map_range(&this->container, start, end, out);
|
||
|
|
||
|
}
|
||
|
|
||
|
inline void virt_page_map_range(imem gap_size, Address start, Address end, MemoryRangeCallback out) noexcept {
|
||
|
(this->vtbl)->virt_page_map_range(&this->container, gap_size, start, end, out);
|
||
|
|
||
|
}
|
||
|
|
||
|
inline int32_t virt_to_phys(Address address, PhysicalAddress * ok_out) noexcept {
|
||
|
int32_t __ret = (this->vtbl)->virt_to_phys(&this->container, address, ok_out);
|
||
|
return __ret;
|
||
|
}
|
||
|
|
||
|
inline int32_t virt_page_info(Address addr, Page * ok_out) noexcept {
|
||
|
int32_t __ret = (this->vtbl)->virt_page_info(&this->container, addr, ok_out);
|
||
|
return __ret;
|
||
|
}
|
||
|
|
||
|
inline void virt_translation_map(VirtualTranslationCallback out) noexcept {
|
||
|
(this->vtbl)->virt_translation_map(&this->container, out);
|
||
|
|
||
|
}
|
||
|
|
||
|
inline COption<Address> phys_to_virt(Address phys) noexcept {
|
||
|
COption<Address> __ret = (this->vtbl)->phys_to_virt(&this->container, phys);
|
||
|
return __ret;
|
||
|
}
|
||
|
|
||
|
inline void virt_page_map(imem gap_size, MemoryRangeCallback out) noexcept {
|
||
|
(this->vtbl)->virt_page_map(&this->container, gap_size, out);
|
||
|
|
||
|
}
|
||
|
|
||
|
};
|
||
|
|
||
|
template<typename T, typename C, typename R>
|
||
|
struct CGlueTraitObj<T, OsVtbl<CGlueObjContainer<T, C, R>>, C, R> {
|
||
|
const OsVtbl<CGlueObjContainer<T, C, R>> *vtbl;
|
||
|
CGlueObjContainer<T, C, R> container;
|
||
|
|
||
|
CGlueTraitObj() : container{} {}
|
||
|
|
||
|
~CGlueTraitObj() noexcept {
|
||
|
mem_drop(std::move(container));
|
||
|
}
|
||
|
|
||
|
typedef C Context;
|
||
|
|
||
|
inline int32_t process_address_list_callback(AddressCallback callback) noexcept {
|
||
|
int32_t __ret = (this->vtbl)->process_address_list_callback(&this->container, callback);
|
||
|
return __ret;
|
||
|
}
|
||
|
|
||
|
inline int32_t process_info_list_callback(ProcessInfoCallback callback) noexcept {
|
||
|
int32_t __ret = (this->vtbl)->process_info_list_callback(&this->container, callback);
|
||
|
return __ret;
|
||
|
}
|
||
|
|
||
|
inline int32_t process_info_by_address(Address address, ProcessInfo * ok_out) noexcept {
|
||
|
int32_t __ret = (this->vtbl)->process_info_by_address(&this->container, address, ok_out);
|
||
|
return __ret;
|
||
|
}
|
||
|
|
||
|
inline int32_t process_info_by_name(CSliceRef<uint8_t> name, ProcessInfo * ok_out) noexcept {
|
||
|
int32_t __ret = (this->vtbl)->process_info_by_name(&this->container, name, ok_out);
|
||
|
return __ret;
|
||
|
}
|
||
|
|
||
|
inline int32_t process_info_by_pid(Pid pid, ProcessInfo * ok_out) noexcept {
|
||
|
int32_t __ret = (this->vtbl)->process_info_by_pid(&this->container, pid, ok_out);
|
||
|
return __ret;
|
||
|
}
|
||
|
|
||
|
inline int32_t process_by_info(ProcessInfo info, ProcessInstance<CBox<void>, Context> * ok_out) noexcept {
|
||
|
int32_t __ret = (this->vtbl)->process_by_info(&this->container, info, ok_out);
|
||
|
return __ret;
|
||
|
}
|
||
|
|
||
|
inline int32_t into_process_by_info(ProcessInfo info, IntoProcessInstance<CBox<void>, Context> * ok_out) && noexcept {
|
||
|
auto ___ctx = StoreAll()[this->container.clone_context(), StoreAll()];
|
||
|
int32_t __ret = (this->vtbl)->into_process_by_info(this->container, info, ok_out);
|
||
|
mem_forget(this->container);
|
||
|
return __ret;
|
||
|
}
|
||
|
|
||
|
inline int32_t process_by_address(Address addr, ProcessInstance<CBox<void>, Context> * ok_out) noexcept {
|
||
|
int32_t __ret = (this->vtbl)->process_by_address(&this->container, addr, ok_out);
|
||
|
return __ret;
|
||
|
}
|
||
|
|
||
|
inline int32_t process_by_name(CSliceRef<uint8_t> name, ProcessInstance<CBox<void>, Context> * ok_out) noexcept {
|
||
|
int32_t __ret = (this->vtbl)->process_by_name(&this->container, name, ok_out);
|
||
|
return __ret;
|
||
|
}
|
||
|
|
||
|
inline int32_t process_by_pid(Pid pid, ProcessInstance<CBox<void>, Context> * ok_out) noexcept {
|
||
|
int32_t __ret = (this->vtbl)->process_by_pid(&this->container, pid, ok_out);
|
||
|
return __ret;
|
||
|
}
|
||
|
|
||
|
inline int32_t into_process_by_address(Address addr, IntoProcessInstance<CBox<void>, Context> * ok_out) && noexcept {
|
||
|
auto ___ctx = StoreAll()[this->container.clone_context(), StoreAll()];
|
||
|
int32_t __ret = (this->vtbl)->into_process_by_address(this->container, addr, ok_out);
|
||
|
mem_forget(this->container);
|
||
|
return __ret;
|
||
|
}
|
||
|
|
||
|
inline int32_t into_process_by_name(CSliceRef<uint8_t> name, IntoProcessInstance<CBox<void>, Context> * ok_out) && noexcept {
|
||
|
auto ___ctx = StoreAll()[this->container.clone_context(), StoreAll()];
|
||
|
int32_t __ret = (this->vtbl)->into_process_by_name(this->container, name, ok_out);
|
||
|
mem_forget(this->container);
|
||
|
return __ret;
|
||
|
}
|
||
|
|
||
|
inline int32_t into_process_by_pid(Pid pid, IntoProcessInstance<CBox<void>, Context> * ok_out) && noexcept {
|
||
|
auto ___ctx = StoreAll()[this->container.clone_context(), StoreAll()];
|
||
|
int32_t __ret = (this->vtbl)->into_process_by_pid(this->container, pid, ok_out);
|
||
|
mem_forget(this->container);
|
||
|
return __ret;
|
||
|
}
|
||
|
|
||
|
inline int32_t module_address_list_callback(AddressCallback callback) noexcept {
|
||
|
int32_t __ret = (this->vtbl)->module_address_list_callback(&this->container, callback);
|
||
|
return __ret;
|
||
|
}
|
||
|
|
||
|
inline int32_t module_list_callback(ModuleInfoCallback callback) noexcept {
|
||
|
int32_t __ret = (this->vtbl)->module_list_callback(&this->container, callback);
|
||
|
return __ret;
|
||
|
}
|
||
|
|
||
|
inline int32_t module_by_address(Address address, ModuleInfo * ok_out) noexcept {
|
||
|
int32_t __ret = (this->vtbl)->module_by_address(&this->container, address, ok_out);
|
||
|
return __ret;
|
||
|
}
|
||
|
|
||
|
inline int32_t module_by_name(CSliceRef<uint8_t> name, ModuleInfo * ok_out) noexcept {
|
||
|
int32_t __ret = (this->vtbl)->module_by_name(&this->container, name, ok_out);
|
||
|
return __ret;
|
||
|
}
|
||
|
|
||
|
inline int32_t primary_module_address(Address * ok_out) noexcept {
|
||
|
int32_t __ret = (this->vtbl)->primary_module_address(&this->container, ok_out);
|
||
|
return __ret;
|
||
|
}
|
||
|
|
||
|
inline int32_t primary_module(ModuleInfo * ok_out) noexcept {
|
||
|
int32_t __ret = (this->vtbl)->primary_module(&this->container, ok_out);
|
||
|
return __ret;
|
||
|
}
|
||
|
|
||
|
inline int32_t module_import_list_callback(const ModuleInfo * info, ImportCallback callback) noexcept {
|
||
|
int32_t __ret = (this->vtbl)->module_import_list_callback(&this->container, info, callback);
|
||
|
return __ret;
|
||
|
}
|
||
|
|
||
|
inline int32_t module_export_list_callback(const ModuleInfo * info, ExportCallback callback) noexcept {
|
||
|
int32_t __ret = (this->vtbl)->module_export_list_callback(&this->container, info, callback);
|
||
|
return __ret;
|
||
|
}
|
||
|
|
||
|
inline int32_t module_section_list_callback(const ModuleInfo * info, SectionCallback callback) noexcept {
|
||
|
int32_t __ret = (this->vtbl)->module_section_list_callback(&this->container, info, callback);
|
||
|
return __ret;
|
||
|
}
|
||
|
|
||
|
inline int32_t module_import_by_name(const ModuleInfo * info, CSliceRef<uint8_t> name, ImportInfo * ok_out) noexcept {
|
||
|
int32_t __ret = (this->vtbl)->module_import_by_name(&this->container, info, name, ok_out);
|
||
|
return __ret;
|
||
|
}
|
||
|
|
||
|
inline int32_t module_export_by_name(const ModuleInfo * info, CSliceRef<uint8_t> name, ExportInfo * ok_out) noexcept {
|
||
|
int32_t __ret = (this->vtbl)->module_export_by_name(&this->container, info, name, ok_out);
|
||
|
return __ret;
|
||
|
}
|
||
|
|
||
|
inline int32_t module_section_by_name(const ModuleInfo * info, CSliceRef<uint8_t> name, SectionInfo * ok_out) noexcept {
|
||
|
int32_t __ret = (this->vtbl)->module_section_by_name(&this->container, info, name, ok_out);
|
||
|
return __ret;
|
||
|
}
|
||
|
|
||
|
inline const OsInfo * info() const noexcept {
|
||
|
const OsInfo * __ret = (this->vtbl)->info(&this->container);
|
||
|
return __ret;
|
||
|
}
|
||
|
|
||
|
};
|
||
|
|
||
|
template<typename T, typename C, typename R>
|
||
|
struct CGlueTraitObj<T, KeyboardStateVtbl<CGlueObjContainer<T, C, R>>, C, R> {
|
||
|
const KeyboardStateVtbl<CGlueObjContainer<T, C, R>> *vtbl;
|
||
|
CGlueObjContainer<T, C, R> container;
|
||
|
|
||
|
CGlueTraitObj() : container{} {}
|
||
|
|
||
|
~CGlueTraitObj() noexcept {
|
||
|
mem_drop(std::move(container));
|
||
|
}
|
||
|
|
||
|
typedef C Context;
|
||
|
|
||
|
inline bool is_down(int32_t vk) const noexcept {
|
||
|
bool __ret = (this->vtbl)->is_down(&this->container, vk);
|
||
|
return __ret;
|
||
|
}
|
||
|
|
||
|
};
|
||
|
|
||
|
template<typename T, typename C, typename R>
|
||
|
struct CGlueTraitObj<T, KeyboardVtbl<CGlueObjContainer<T, C, R>>, C, R> {
|
||
|
const KeyboardVtbl<CGlueObjContainer<T, C, R>> *vtbl;
|
||
|
CGlueObjContainer<T, C, R> container;
|
||
|
|
||
|
CGlueTraitObj() : container{} {}
|
||
|
|
||
|
~CGlueTraitObj() noexcept {
|
||
|
mem_drop(std::move(container));
|
||
|
}
|
||
|
|
||
|
typedef C Context;
|
||
|
|
||
|
inline bool is_down(int32_t vk) noexcept {
|
||
|
bool __ret = (this->vtbl)->is_down(&this->container, vk);
|
||
|
return __ret;
|
||
|
}
|
||
|
|
||
|
inline void set_down(int32_t vk, bool down) noexcept {
|
||
|
(this->vtbl)->set_down(&this->container, vk, down);
|
||
|
|
||
|
}
|
||
|
|
||
|
inline int32_t state(KeyboardStateBase<CBox<void>, Context> * ok_out) noexcept {
|
||
|
int32_t __ret = (this->vtbl)->state(&this->container, ok_out);
|
||
|
return __ret;
|
||
|
}
|
||
|
|
||
|
};
|
||
|
|
||
|
template<typename T, typename C, typename R>
|
||
|
struct CGlueTraitObj<T, OsKeyboardVtbl<CGlueObjContainer<T, C, R>>, C, R> {
|
||
|
const OsKeyboardVtbl<CGlueObjContainer<T, C, R>> *vtbl;
|
||
|
CGlueObjContainer<T, C, R> container;
|
||
|
|
||
|
CGlueTraitObj() : container{} {}
|
||
|
|
||
|
~CGlueTraitObj() noexcept {
|
||
|
mem_drop(std::move(container));
|
||
|
}
|
||
|
|
||
|
typedef C Context;
|
||
|
|
||
|
inline int32_t keyboard(KeyboardBase<CBox<void>, Context> * ok_out) noexcept {
|
||
|
int32_t __ret = (this->vtbl)->keyboard(&this->container, ok_out);
|
||
|
return __ret;
|
||
|
}
|
||
|
|
||
|
inline int32_t into_keyboard(IntoKeyboard<CBox<void>, Context> * ok_out) && noexcept {
|
||
|
auto ___ctx = StoreAll()[this->container.clone_context(), StoreAll()];
|
||
|
int32_t __ret = (this->vtbl)->into_keyboard(this->container, ok_out);
|
||
|
mem_forget(this->container);
|
||
|
return __ret;
|
||
|
}
|
||
|
|
||
|
};
|
||
|
|
||
|
#endif // MEMFLOW_H
|