//--- // fxos.target: The target which is being studied //--- #ifndef LIBFXOS_TARGET_H #define LIBFXOS_TARGET_H #include #include #include #include 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 ®ion, 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 ) 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 ®ion, 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 m_bindings; }; } /* namespace FxOS */ #endif /* LIBFXOS_TARGET_H */