fxos/include/fxos/target.h

122 lines
3.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 <vector>
#include <cstdint>
namespace FxOS {
class OS;
/* 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 void const *translate(uint32_t addr, int size=1) const = 0;
/* Read data, with signed or unsigned extension. Virtual addresses
are used here, so they should be within the range of the region.
Throws std::out_of_range if this is not satisfied.
These functions do *not* check alignment because exceptionally there
are instructions which can read unaligned (movua.l). Check it
yourself! */
int32_t read_i8 (uint32_t addr) const;
uint32_t read_u8 (uint32_t addr) const;
int32_t read_i16(uint32_t addr) const;
uint32_t read_u16(uint32_t addr) const;
int32_t read_i32(uint32_t addr) const;
uint32_t read_u32(uint32_t addr) 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 file */
Binding(MemoryRegion const &region, File &file);
/* Targeted region, might overlap with other bindings */
MemoryRegion region;
/* Actual data. This buffer must have at least [size] bytes */
uint8_t *data;
/* Binding size, is the minimum of the region size and the data 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 */
void 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;
};
class Target: public AbstractMemory
{
public:
/* Create an empty target with no sections */
Target();
/* Bind an OS. This is used to either disassemble the OS itself, or
select the OS version for which code is being disassembled (typical
use is for add-ins). */
void bind_os(OS &os);
/* Bind a memory region from a file. 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.
Generally it is preferable to bind an OS image to the target's ROM
area using bind_os(), rather than using bind_region(). This is
because bind_os() which will also enable OS-specific tasks such as
syscall resolution.
If the file is smaller than the region being bound, the region is
shrunk to fit the file. */
void bind_region(MemoryRegion const &region, File &file);
/* 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 */
void 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 OS image */
OS *m_os;
/* Bound regions (in order of binding) */
std::vector<Binding> m_bindings;
};
} /* namespace FxOS */
#endif /* LIBFXOS_TARGET_H */