//--- // fxos.target: The target which is being studied //--- #ifndef LIBFXOS_TARGET_H #define LIBFXOS_TARGET_H #include #include #include #include #include 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. 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 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 read_i8 (uint32_t addr) const; Addressable read_u8 (uint32_t addr) const; Addressable read_i16(uint32_t addr) const; Addressable read_u16(uint32_t addr) const; Addressable read_i32(uint32_t addr) const; Addressable read_u32(uint32_t addr) const; /* Read a non-NUL-terminated string */ Addressable 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 const &buffer); /* Targeted region, might overlap with other bindings */ MemoryRegion region; /* Actual data. This area must have at least [size] bytes */ std::shared_ptr 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; /* Check if a region is covered by the binding */ bool covers(MemoryRegion const ®ion) 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; std::vector 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 folders); /* Bind a memory region from a buffer. The region can either be standard (see ) 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); /* Check if an address is bound */ bool covers(uint32_t addr, int size=1) const noexcept override; /* Check if a full region is bound */ bool covers(MemoryRegion const ®ion) 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 m_bindings; /* Buffers owned by the target (when loaded from description) */ std::vector m_buffers; }; } /* namespace FxOS */ #endif /* LIBFXOS_TARGET_H */