fxos/include/fxos/target.h

139 lines
4.7 KiB
C++

//---
// fxos.target: The target which is being studied
//---
#ifndef LIBFXOS_TARGET_H
#define LIBFXOS_TARGET_H
#include <fxos/memory.h>
#include <fxos/util.h>
#include <optional>
#include <vector>
#include <cstdint>
namespace FxOS {
/* A common interface for simulated memory */
class AbstractMemory
{
public:
/* Checks if an address or interval is simulated */
virtual bool covers(uint32_t addr, int size=1) const noexcept = 0;
/* Returns the data located at the provided virtual address. Throws
std::out_of_range if the interval is not entirely simulated */
virtual char const *translate(uint32_t addr, int size=1) const = 0;
/* Read data from the memory. The following methods read data of
various types. (Not a template because of the restriction about
template specialization in non-namespaces scopes still in g++.)
When reading data, provide a virtual address. The address is saved
in the returned object for later printing or inspection. The
returned object Addressable<T> automatically converts to T when
used, and supports operator & which returns the original address.
The size parameter is only meaningful for variable-sized types such
as string, and ignored for fixed-size types such as integers. If the
desired object is not within the range of the simulated memory,
throws std::out_of_range. */
/* Read integers with signed or unsigned extension. These functions do
not check alignment, because exceptionally the processor supports
unaligned operations (eg. movual.l). */
Addressable<int8_t> read_i8 (uint32_t addr) const;
Addressable<uint8_t> read_u8 (uint32_t addr) const;
Addressable<int16_t> read_i16(uint32_t addr) const;
Addressable<uint16_t> read_u16(uint32_t addr) const;
Addressable<int32_t> read_i32(uint32_t addr) const;
Addressable<uint32_t> read_u32(uint32_t addr) const;
/* Read a non-NUL-terminated string */
Addressable<std::string> read_str(uint32_t addr, size_t len) const;
/* Search a binary pattern in the specified area. Returns the virtual
address of the first occurrence if any is found, [end] otherwise. */
virtual uint32_t search(uint32_t start, uint32_t end,
void const *pattern, int size) const = 0;
};
/* 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);
/* Targeted region, might overlap with other bindings */
MemoryRegion region;
/* Actual data. This area must have at least [size] bytes */
void const *data;
/* Binding size (equal to the region size) */
uint32_t size;
/* Checks if an address is covered by the binding */
bool covers(uint32_t addr, int size=1) const noexcept override;
/* Returns this process' address (in [data]) corresponding to the
provided virtual address */
char const *translate(uint32_t addr, int size=1) const override;
/* Search a pattern */
uint32_t search(uint32_t start, uint32_t end, void const *pattern,
int size) const override;
};
/* A target description in the database; loadable, but not loaded yet */
struct TargetDescription
{
/* Just a list of bindings to be formed */
using Binding = std::pair<MemoryRegion,std::string>;
std::vector<Binding> bindings;
};
/* A composite target where regions can be bound dynamically */
class Target: public AbstractMemory
{
public:
/* Create an empty target with no regions */
Target();
/* Create a target from a target description by loading files from a
library. */
Target(TargetDescription const &description,
std::vector<std::string> folders);
/* Bind a memory region from a buffer. The region can either be
standard (see <fxos/memory.h>) or custom.
If several loaded regions overlap on some addresses, *the last
loaded region will be used*. Thus, new regions can be loaded to
selectively override parts of the target.
An error is raised if the buffer is smaller than the region being
bound. */
void bind_region(MemoryRegion const &region, Buffer const &buffer);
/* Check if an address is bound */
bool covers(uint32_t addr, int size=1) const noexcept override;
/* Returns the data at the provided virtual address */
char const *translate(uint32_t addr, int size=1) const override;
/* Search a pattern */
uint32_t search(uint32_t start, uint32_t end, void const *pattern,
int size) const override;
private:
/* Bound regions (in order of binding) */
std::vector<Binding> m_bindings;
/* Buffers owned by the target (when loaded from description) */
std::vector<Buffer> m_buffers;
};
} /* namespace FxOS */
#endif /* LIBFXOS_TARGET_H */