fxos/include/fxos/vspace.h

142 lines
5.4 KiB
C++

//---------------------------------------------------------------------------//
// 1100101 |_ mov #0, r4 __ //
// 11 |_ <0xb380 %5c4> / _|_ _____ ___ //
// 0110 |_ 3.50 -> 3.60 | _\ \ / _ (_-< //
// |_ base# + offset |_| /_\_\___/__/ //
//---------------------------------------------------------------------------//
// fxos/vspace: Virtual address space where files are loaded for analysis
//
// This file defines the VirtualSpace class, which is a virtual 32-bit address
// space in which buffers can be selectively mapped. Usually, there is one
// virtual space for each add-in/OS being studied. Data from the program is
// accessed through the virtual space's memory interface.
//
// The (mostly internal) AbstractMemory typeclass describes the memory
// interface, which mainly consists of translate_dynamic() to access underlying
// buffers, and general read functions. Note that most "small" read operations
// only try to translate_dynamic() once, which means that the object being read
// must be loaded as a single block. This is only a concern if bindings are
// used to hide/replace parts of loaded files.
//---
#ifndef FXOS_VSPACE_H
#define FXOS_VSPACE_H
#include <fxos/memory.h>
#include <fxos/os.h>
#include <fxos/symbols.h>
#include <fxos/disassembly.h>
#include <fxos/util/Buffer.h>
#include <fxos/util/Addressable.h>
#include <fxos/util/bson.h>
#include <optional>
#include <vector>
#include <cstdint>
#include <memory>
namespace FxOS {
/* A common interface for simulated memory. All non-virtual methods are
provided by the base class and need not be implemented. */
class AbstractMemory
{
public:
/* Checks if an address or interval is simulated (in its entirety) */
bool covers(uint32_t addr, int size = 1);
/* Check if a full region is simulated */
bool covers(MemoryRegion const &region);
/* Returns the data located at the provided virtual address, nullptr if it
is not entirely covered. */
char const *translate(uint32_t addr, int size = 1);
/* Returns the data located at the provided virtual address, and indicates
how much is available in *size. The pointer is null if [addr] itself is
not covered, in which case *size is also set to 0. */
virtual char const *translate_dynamic(uint32_t addr, int *size) = 0;
/* Search a binary pattern in the specified area. Returns the virtual
address of the first occurrence if any is found, [end] otherwise
(including if the range is empty or exceeds simulated memory). */
uint32_t search(uint32_t start, uint32_t end, void const *pat, int size);
/* Read a simple object from memory. The following methods all assume that
the specified address is simulated, and return a default value if it's
not -- you should probably check beforehand! Alignment constraints are
not checked either, that's up to you.
The return type has the value in [.value] and remembers the address in
[.address], which is sometimes useful. It implicitly converts to the
data type, see <fxos/util/Addressable.h>. */
/* Various sizes of integers with sign-extension or zero-extension. */
Addressable<int8_t> read_i8(uint32_t addr);
Addressable<uint8_t> read_u8(uint32_t addr);
Addressable<int16_t> read_i16(uint32_t addr);
Addressable<uint16_t> read_u16(uint32_t addr);
Addressable<int32_t> read_i32(uint32_t addr);
Addressable<uint32_t> read_u32(uint32_t addr);
/* Read a non-NUL-terminated string */
Addressable<std::string> read_str(uint32_t addr, size_t len);
};
/* A binding of a data buffer into a memory region of the target. */
struct Binding: public AbstractMemory
{
/* Constructor from data buffer. An error is raised if the buffer is
not at least of the size of the region. In this case, a new buffer
can be constructed with the required size. */
Binding(MemoryRegion region, Buffer const &buffer);
BSON serialize() const;
Binding(BSON const &);
/* Targeted region, might overlap with other bindings */
MemoryRegion region;
/* Underlying buffer (copy of the original one) */
Buffer buffer;
// - AbstractMemory interface
char const *translate_dynamic(uint32_t addr, int *size) override;
};
/* A composite space where regions can be bound dynamically */
// TODO: Use a class interface for VirtualSpace
// TODO: Move non-memory-management members to Binary
class VirtualSpace: public AbstractMemory
{
public:
/* Create an empty space with no regions */
VirtualSpace();
BSON serialize() const;
void deserialize(BSON const &);
/* List of bindings (most recent first) */
std::vector<Binding> bindings;
/* Bind a buffer to a standard or custom memory region. Functions in the
library tend to assume that bindings don't overlap and are not
immediately consecutive in memory. If the buffer is smaller than the
region, it is 0-padded to the proper size. */
void bind_region(MemoryRegion const &region, Buffer const &buffer);
// - AbstractMemory interface
char const *translate_dynamic(uint32_t addr, int *size) override;
// TODO: Remove these
std::string mpu;
SymbolTable symbols;
uint32_t cursor;
Disassembly disasm;
OS *os_analysis(bool force = false);
private:
std::unique_ptr<OS> m_os;
};
} /* namespace FxOS */
#endif /* FXOS_VSPACE_H */