//---------------------------------------------------------------------------// // 1100101 |_ mov #0, r4 __ // // 11 |_ <0xb380 %5c4> / _|_ _____ ___ // // 0110 |_ 3.50 -> 3.60 | _\ \ / _ (_-< // // |_ base# + offset |_| /_\_\___/__/ // //---------------------------------------------------------------------------// // fxos/passes/cfg: Control Flow Graph construction // // This pass explores functions by loading every instruction's potential // successor into the diassembly store. It also sets the [jmptarget] field of // the Instructions as it goes, allowing other passes to traverse the (somewhat // implicit) CFG. // // 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 problem that this pass has to deal with is delay slots. These are // pretty tricky to deal with; for instance, in // // bra pc+120 // mov #1, r4 // // the CPU will run [mov #1, r4] while performing the branch to pc+120 in order // to fill an otherwise-unfillable pipeline cycle. This is annoying for all // kinds of reasons, and fxos handles this by acting as if the mov itself had // pc+120 as an uncondition successor. // // This could be tricky for the abstract interpreter because the jump target // has to be computed using the state at the jump instruction, not the one at // the delay slot. Luckily all delayed jumps are no-ops in termsof state, so // the confusion has no effect. // // Note that jumping into a delay slot will activate the jump in fxos, which is // not the actual behavior of the processor. I don't believe any compiler does // this kind of things (most are not inherently designed for delay slots // anyway). If such an instance is found, fxos will throw an exception and give // up to make sure no analysis pass returns invalid results. // // 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 FXOS_PASSES_CFG_H #define FXOS_PASSES_CFG_H #include namespace FxOS { class CfgPass: public DisassemblyPass { public: CfgPass(Disassembly &disasm); bool analyze(uint32_t pc, Instruction &inst) override; }; } /* namespace FxOS */ #endif /* FXOS_PASSES_CFG_H */