fxos/include/fxos/passes/cfg.h

80 lines
3.2 KiB
C++

//---------------------------------------------------------------------------//
// 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 unconditional 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 terms of 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 <fxos/disassembly.h>
#include <fxos/passes/pcrel.h>
#include <set>
namespace FxOS {
class CfgPass: public InstructionPass
{
public:
CfgPass(Disassembly &disasm);
bool analyzeInstruction(uint32_t pc, OldInstruction &inst) override;
/* Explore a new function at the specified address. This method creates the
function if it doesn't exist yet, explores its CFG, and generates claims
over relevant parts of the binary. */
bool exploreFunction(uint32_t pc);
/* Access the set of claims generated by the last call to
exploreFunctions(). */
std::set<Claim> resultClaims();
private:
/* Last explored function */
uint32_t m_lastFunction;
/* Set of instructions in a function, used to generate new claims */
std::set<uint32_t> m_claimedInstructions;
/* pcrel pass used to find call to other functions */
PcrelPass m_pcrel;
};
} /* namespace FxOS */
#endif /* FXOS_PASSES_CFG_H */