//---------------------------------------------------------------------------// // 1100101 |_ mov #0, r4 __ // // 11 |_ <0xb380 %5c4> / _|_ _____ ___ // // 0110 |_ 3.50 -> 3.60 | _\ \ / _ (_-< // // |_ base# + offset |_| /_\_\___/__/ // //---------------------------------------------------------------------------// // fxos/analysis: Static analysis for assembler programs // // TODO: Designed to be an abstract interpreter, still WIP //--- #ifndef FXOS_ANALYSIS_H #define FXOS_ANALYSIS_H #include #include #include #include #include namespace FxOS { struct ProgramStateDiff; /* Full description of a program state for the analyzer, at a known PC. */ struct ProgramState { ProgramState() { setBottom(); } RelConst getRegister(int n) const { return ((unsigned)n >= 16) ? RelConstDomain().bottom() : m_regs[n]; } // TODO: More value in program state /* Set to initial program state at entry of function. */ void setFunctionInit(); /* Set to initial non-entry-block state at entry of function (all bot). */ void setBottom(); /* Apply a diff. */ void applyDiff(ProgramStateDiff const &diff); /* Join with another program state. */ void joinWith(ProgramState const &other); /* Lattice order. */ bool le(ProgramState const &other) const; private: /* Values for registers r0..r15 */ RelConst m_regs[16]; }; /* Change in program state over a single (contextually known) instruction. */ struct ProgramStateDiff { enum class Target : int { None = -1, Unknown = -2, CallStandard = -3 }; /* Number of the register that changes, or Target::*. */ int target() const { return m_target; } /* New value for that register. */ RelConst value() const { return m_value; } // TODO: Needs way more flexibility /* Set the diff to changing register rn to new value v. */ void setRegisterUpdate(int n, RelConst v) { m_target = n; m_value = v; } /* Set the diff to changing register rn to an unknown value. */ void setRegisterTouched(int n) { setRegisterUpdate(n, RelConstDomain().top()); } /* Set the diff to changing no register state. */ void setNoop() { m_target = static_cast(Target::None); } /* Set the diff to modifyin register states as allowed by the standard function calling convention. */ void setCallStandard() { m_target = static_cast(Target::CallStandard); } /* Set the diff to unknown effect on registers. */ void setUnknown() { m_target = static_cast(Target::Unknown); } std::string str() const; private: int m_target; RelConst m_value; }; /* Function's storage of program states at every control point. */ struct StaticFunctionAnalysis { /* Information stored for each block */ struct Block { ProgramState entry; std::vector diffs; }; std::vector blocks; }; /* Analyze a function; returns analysis results if successful, a null pointer on error. Does not store the results in f itself. */ std::unique_ptr analyzeFunction(Function const &f); } // namespace FxOS #endif /* FXOS_ANALYSIS_H */