fxos/include/fxos/disasm-passes/cfg.h

52 lines
1.9 KiB
C++

//---
// fxos.disasm-passes.cfg: Control Flow Graph construction
//
// This pass explores functions and computes the [jmptarget] field of concrete
// instructions as it goes. This is required for other passes that work by
// traversing the CFG, such as the abstract interpretor.
//
// This is the main exploration pass. Other passes do not typically load new
// instructions from the underlying disassembly. Straightforward passes such as
// [print] iterate on instructions loaded by this pass.
//
// The main gimmick of this pass is to "resolve delay slots" by forcing down
// the properties of delayed instructions into their respective delay slots.
// For instance, in
// jmp @r0
// mov #1, r4
// the jump is delayed until after the move. To handle this, fxos makes the jmp
// a no-op and applies dual move-jump semantics to the mov below it.
//
// This could be tricky for the abstract interpreter because the jump target
// has to be computed with the environment before the jmp, which is not
// available when considering the mov. Luckily all delayed jumps are state
// no-ops so the state before the mov can be used instead.
//
// Note that jumping into a delay slot will activate the jump in fxos, which is
// not the actual behavior of the processor. fxos usually complains about the
// crazy compiler when this occurs. Note that if it happens but we don't know
// that it's a delay slot (ie. the instruction from above is never executed in
// the current function), then everything's fine.
//
// Take-home message: delay slots are a pain to analyze, so we get rid of them
// as soon as possible and proceed with normal semantics.
//---
#ifndef LIBFXOS_DISASM_PASSES_CFG_H
#define LIBFXOS_DISASM_PASSES_CFG_H
#include <fxos/disassembly.h>
namespace FxOS {
class CfgPass: public DisassemblyPass
{
public:
CfgPass(Disassembly &disasm);
void analyze(uint32_t pc, ConcreteInstruction &inst) override;
};
} /* namespace FxOS */
#endif /* LIBFXOS_DISASM_PASSES_CFG_H */