forked from Lephenixnoir/fxos
166 lines
5.7 KiB
C++
166 lines
5.7 KiB
C++
//---
|
|
// fxos.vspace: A virtual space where code is being studied
|
|
//---
|
|
|
|
#ifndef LIBFXOS_VSPACE_H
|
|
#define LIBFXOS_VSPACE_H
|
|
|
|
#include <fxos/memory.h>
|
|
#include <fxos/os.h>
|
|
#include <fxos/symbols.h>
|
|
#include <fxos/util/Buffer.h>
|
|
#include <fxos/util/Addressable.h>
|
|
|
|
#include <optional>
|
|
#include <vector>
|
|
#include <cstdint>
|
|
#include <memory>
|
|
|
|
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;
|
|
/* Check if a full region is simulated */
|
|
virtual bool covers(MemoryRegion const ®ion) const noexcept;
|
|
|
|
/* Returns the data located at the provided virtual address, nullptr if it
|
|
is not entirely covered. */
|
|
virtual char const *translate(uint32_t addr, int size=1) const = 0;
|
|
|
|
/* 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) 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 [.address] 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, returns
|
|
a dummy value of address -1. You should check the range beforehand! */
|
|
|
|
/* 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
|
|
(including if the range is empty or exceeds simulated memory). */
|
|
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 buffer);
|
|
|
|
/* Targeted region, might overlap with other bindings */
|
|
MemoryRegion region;
|
|
/* Underlying buffer (copy of the original one) */
|
|
Buffer buffer;
|
|
|
|
bool covers(uint32_t addr, int size=1) const noexcept override;
|
|
bool covers(MemoryRegion const ®ion) const noexcept override;
|
|
|
|
char const *translate(uint32_t addr, int size=1) const override;
|
|
char const *translate_dynamic(uint32_t addr, int *size) const override;
|
|
|
|
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 Target
|
|
{
|
|
/* Just a list of bindings to be formed */
|
|
using Binding = std::pair<MemoryRegion,std::string>;
|
|
std::vector<Binding> bindings;
|
|
/* Also the MPU to be set */
|
|
std::string mpu;
|
|
};
|
|
|
|
/* A composite space where regions can be bound dynamically */
|
|
class VirtualSpace: public AbstractMemory
|
|
{
|
|
public:
|
|
/* Create an empty space with no regions */
|
|
VirtualSpace();
|
|
|
|
/* Create a new virtual space with a target loaded. */
|
|
VirtualSpace(Target const &target,std::vector<std::string> const &folders);
|
|
|
|
/* MPU used by this target, or an empty string if unspecified */
|
|
std::string mpu;
|
|
|
|
/* List of bindings */
|
|
std::vector<Binding> const &bindings() const {
|
|
return m_bindings;
|
|
}
|
|
|
|
/* OS analysis; performed on-demand. Returns the new or cached OS analysis,
|
|
and nullptr only if OS cannot be analyzed */
|
|
OS *os_analysis(bool force=false);
|
|
|
|
/* Cursor position, used by the interactive shell */
|
|
uint32_t cursor;
|
|
|
|
/* Symbol table */
|
|
SymbolTable symbols;
|
|
|
|
/* 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 ®ion, Buffer const &buffer);
|
|
|
|
bool covers(uint32_t addr, int size=1) const noexcept override;
|
|
bool covers(MemoryRegion const ®ion) const noexcept override;
|
|
|
|
char const *translate(uint32_t addr, int size=1) const override;
|
|
char const *translate_dynamic(uint32_t addr, int *size) const override;
|
|
|
|
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;
|
|
/* Current OS analyzer */
|
|
std::unique_ptr<OS> m_os;
|
|
};
|
|
|
|
} /* namespace FxOS */
|
|
|
|
#endif /* LIBFXOS_VSPACE_H */
|