fxos/include/fxos/passes/print.h

116 lines
4.0 KiB
C++

//---------------------------------------------------------------------------//
// 1100101 |_ mov #0, r4 __ //
// 11 |_ <0xb380 %5c4> / _|_ _____ ___ //
// 0110 |_ 3.50 -> 3.60 | _\ \ / _ (_-< //
// |_ base# + offset |_| /_\_\___/__/ //
//---------------------------------------------------------------------------//
// fxos/passes/print: Disassembly printer
//
// This pass prints the program and adds annotations depending on a number of
// customizable boolean parameters.
//
// Data for an instruction, and arguments in particular, might have a large
// number of equivalent representations, depending on how much information was
// added during disassembly.
//
// The main mechanic of this pass is to define *promotions* which allow high-
// level information to be added or to replace low-level data. For instance, an
// @(disp,pc) argument could promote to a statically-computed address, which
// could promote to its known pointed value in the case of a read, which could
// itself promote to a symbol or syscall number.
//
// Each promotion opportunity has 3 possible settings:
// - Never: the higher-level information is not shown.
// - Append: the higher-level information is shown after the low-level one.
// - Promote: the higher-level information replaces the low-level one.
//
// For example, by default @(disp,pc) is set to Promote to statically-computed
// addresses, their values, and syscall numbers, but syscall names are only set
// to Append. Therefore, a mov.l @(disp,pc) which loads the address of syscall
// %ace on an fx-series model (which is memcp) might show as
//
// mov.l %ace memcmp, r3
//
// where the first element has been promoted twice and the second appended.
//---
#ifndef FXOS_PASSES_PRINT_H
#define FXOS_PASSES_PRINT_H
#include <fxos/disassembly.h>
#include <fxos/symbols.h>
namespace FxOS {
class OS;
class PrintPass: public InstructionPass
{
public:
PrintPass(Disassembly &disasm);
bool analyzeInstruction(uint32_t pc, Instruction &inst) override;
//---
// Print pass parameters
//---
/* Promotion parameters. Default is always to append. */
enum Promotion {
/* Never promote */
Never = 1,
/* Promote but keep the lower-level information */
Append = 0,
/* Promote and hide the lower-level information */
Promote = 2,
};
/** In the following, promote_x always means promote *to x* **/
/* In jumps, promote "pc+<disp>" to the target address */
int promote_pcjump_loc;
/* In a PC-relative mov, promote "@(<disp>,pc)" to computed address */
int promote_pcrel_loc;
/* In a PC-relative mov, promote address to pointed value */
int promote_pcrel_value;
/* Promote an integer to a syscall number */
int promote_syscall;
/* Promote a syscall number to a syscall name */
int promote_syscallname;
/* Promote an integer to a symbol */
int promote_symbol;
/* In a mova, promote "pc+<disp>" to the computed address */
int promote_pcaddr_loc;
/* TODO: More print pass parameters */
private:
/* Symbol tables to look up names */
std::vector<std::reference_wrapper<SymbolTable const>> m_symtables;
/* Query symbol tables, most recent first */
std::optional<std::string> symquery(Symbol::Type type, uint32_t value);
/* OS for the target, to mark syscalls before instructions */
OS *m_os;
/* Last printed address (for ellipses) */
uint32_t m_last_address;
/** Internal promotion tree printers **/
void queue(std::string, bool = false);
void queue_flush();
std::vector<std::string> m_messages;
void pcjumploc(Argument const &);
void pcrelloc(Argument const &);
void pcrelval(Argument const &);
void syscall(Argument const &);
void syscallname(Argument const &);
void symbol(Argument const &);
void pcaddrloc(Argument const &);
};
} /* namespace FxOS */
#endif /* FXOS_PASSES_PRINT_H */