diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..1377554ebea6f98a2c748183bc5a96852af12ac2 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +*.swp diff --git a/include/inc-cfg/BasicBlock.hpp b/include/inc-cfg/BasicBlock.hpp new file mode 100644 index 0000000000000000000000000000000000000000..c04e48348f90f90a215efa7107b2b931ffae7184 --- /dev/null +++ b/include/inc-cfg/BasicBlock.hpp @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2014 - Zephyr Software LLC + * + * This file may be used and modified for non-commercial purposes as long as + * all copyright, permission, and nonwarranty notices are preserved. + * Redistribution is prohibited without prior written consent from Zephyr + * Software. + * + * Please contact the authors for restrictions applying to commercial use. + * + * THIS SOURCE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF + * MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + * + * Author: Zephyr Software + * e-mail: jwd@zephyr-software.com + * URL : http://www.zephyr-software.com/ + * + */ + +#include <ostream> +#include <set> + +namespace IRDB_SDK +{ + using namespace std; + + class BasicBlock_t; + + using BasicBlockSet_t = set<BasicBlock_t*>; + + class BasicBlock_t + { + protected: + BasicBlock_t() {} + BasicBlock_t(const BasicBlock_t& copy) = delete; + public: + + bool getIsExitBlock() const = 0; + const InstructionVector_t& getInstructions() const = 0; + const BasicBlockSet_t& getPredecessors() const = 0; + const BasicBlockSet_t& getSuccessors() const = 0; + const BasicBlockSet_t& getIndirectTargets() const = 0; + const BasicBlock_t* getFallthrough() const = 0; + const BasicBlock_t* getTarget() const = 0; + + + bool endsInBranch() = 0; + bool endsInIndirectBranch() = 0; + bool endsInConditionalBranch() = 0; + Instruction_t* getBranchInstruction() = 0; + + void dump(ostream &os=std::cout) = 0 ; + + }; + ostream& operator<<(ostream& os, const BasicBlock_t& block); + +} diff --git a/include/inc-cfg/CFG.hpp b/include/inc-cfg/CFG.hpp new file mode 100644 index 0000000000000000000000000000000000000000..8bf1d0b2f752590fb8609b2e79807eb1d3cf6895 --- /dev/null +++ b/include/inc-cfg/CFG.hpp @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2014 - Zephyr Software LLC + * + * This file may be used and modified for non-commercial purposes as long as + * all copyright, permission, and nonwarranty notices are preserved. + * Redistribution is prohibited without prior written consent from Zephyr + * Software. + * + * Please contact the authors for restrictions applying to commercial use. + * + * THIS SOURCE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF + * MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + * + * Author: Zephyr Software + * e-mail: jwd@zephyr-software.com + * URL : http://www.zephyr-software.com/ + * + */ + +enum CFG_EdgeTypeEnum { CFG_FallthroughEdge, CFG_TargetEdge, CFG_IndirectEdge }; +typedef std::set<CFG_EdgeTypeEnum> CFG_EdgeType; + +class ControlFlowGraph_t +{ + public: + ControlFlowGraph_t(Function_t* func); + BasicBlock_t* GetEntry() const { return entry; } + Function_t* GetFunction() const { return function; } + BasicBlockSet_t& GetBlocks() { return blocks; } + const BasicBlockSet_t& GetBlocks() const { return blocks; } + void dump(std::ostream &os=std::cout) const { os<<*this; } + bool HasEdge(BasicBlock_t *p_src, BasicBlock_t *p_tgt) const; + CFG_EdgeType GetEdgeType(const BasicBlock_t *p_src, const BasicBlock_t *p_tgt) const; + + private: + // methods + void Build(Function_t *func); + void alloc_blocks(const InstructionSet_t &starts, map<Instruction_t*,BasicBlock_t*>& insn2block_map); + void build_blocks(const map<Instruction_t*,BasicBlock_t*>& insn2block_map); + void find_unblocked_instructions(InstructionSet_t &starts, Function_t* func); + + // data + BasicBlockSet_t blocks; + BasicBlock_t* entry; + Function_t* function; + + /* friends */ + public: + friend std::ostream& operator<<(std::ostream& os, const ControlFlowGraph_t& cfg); +}; + + +std::ostream& operator<<(std::ostream& os, const ControlFlowGraph_t& cfg); + + diff --git a/include/inc-cfg/callgraph.hpp b/include/inc-cfg/callgraph.hpp new file mode 100644 index 0000000000000000000000000000000000000000..f1c00777e687000a1034e1ec2c8d39fc265e8d4d --- /dev/null +++ b/include/inc-cfg/callgraph.hpp @@ -0,0 +1,71 @@ + + +namespace IRDB_SDK +{ + using namespace std; + + + class CallGraphNode_t + { + protected: + CallGraphNode_t() { } + CallGraphNode_t(const CallGraphNode_t& copy) = delete; + public: + virtual ~CallGraphNode_t() { } + + bool isHellnode() const =0; + Function_t* getFunction() const =0; + }; + + + + using CallGraphEdge_t = pair<CallGraphNode_t*,CallGraphNode_t*>; + using CallGraphNodeSet_t = set<CallGraphNode_t*>; + using CallSite_t = Instruction_t*; + using CallSiteSet_t = set<CallSite_t>; + + class Callgraph_t + { + protected: + Callgraph_t() {} + Callgraph_t(const Callgraph_t& copy) = delete; + public: + virtual ~Callgraph_t() { } + + virtual void addFile() = 0; + + virtual bool edgeExists(const CallGraphEdge_t& edge) const = 0; + + virtual const CallGraphNodeSet_t& + getCallersOfNode(CallGraphNode_t* const node) const = 0; + + virtual const CallGraphNodeSet_t& + getCalleesOfNode(CallGraphNode_t* const node) const = 0; + + virtual const CallGraphNodeSet_t& ancestors, + getAncestors + ( + const Function_t* const fn, + const bool skipHellNode = false + ) const = 0; + virtual const CallSiteSet_t& + getCallSites(CallGraphNode_t* const n1) const = 0; + + virtual void dump(std::ostream& fout) const = 0; + virtual string getNodeName(const CallGraphNode_t* const n1) const = 0; + virtual string getCallsiteDisassembly(const CallSite_t &c) const = 0; + virtual bool isReachable + ( + CallGraphNode_t* const from, + CallGraphNode_t* const to, + bool skipHellNode = false + ) const = 0; + + virtual const CallGraphNode_t& + getDefaultHellNode() const = 0; + + virtual CallGraphNode_t* + findNode(Function_t* const fn) const = 0; + }; + +} diff --git a/include/inc-cfg/criticaledge.hpp b/include/inc-cfg/criticaledge.hpp new file mode 100644 index 0000000000000000000000000000000000000000..6126703ea5fa32f25c13ad7aeca0392dcaff6508 --- /dev/null +++ b/include/inc-cfg/criticaledge.hpp @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2019 - Zephyr Software LLC + * + * This file may be used and modified for non-commercial purposes as long as + * all copyright, permission, and nonwarranty notices are preserved. + * Redistribution is prohibited without prior written consent from Zephyr + * Software. + * + * Please contact the authors for restrictions applying to commercial use. + * + * THIS SOURCE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF + * MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + * + * Author: Zephyr Software + * e-mail: jwd@zephyr-software.com + * URL : http://www.zephyr-software.com/ + * + */ + +typedef std::tuple<BasicBlock_t*, BasicBlock_t*> BasicBlockEdge_t; +typedef std::set<BasicBlockEdge_t> BasicBlockEdgeSet_t; + +class CriticalEdgeAnalyzer_t +{ + public: + CriticalEdgeAnalyzer_t(const ControlFlowGraph_t &p_cfg, const bool p_conservative=true); + BasicBlockEdgeSet_t GetAllCriticalEdges() const; + + private: + const ControlFlowGraph_t m_cfg; + const bool m_conservative; +}; diff --git a/include/inc-cfg/domgraph.hpp b/include/inc-cfg/domgraph.hpp new file mode 100644 index 0000000000000000000000000000000000000000..087fc4dd604d8458be76de68b188447ffaf68ba9 --- /dev/null +++ b/include/inc-cfg/domgraph.hpp @@ -0,0 +1,54 @@ + + + +typedef std::map<const BasicBlock_t*, BasicBlockSet_t> DominatorMap_t; +typedef std::map<const BasicBlock_t*, BasicBlock_t*> BlockToBlockMap_t; + +class DominatorGraph_t +{ + public: + DominatorGraph_t(const ControlFlowGraph_t* p_cfg, bool needs_postdoms=false, bool needs_idoms=false); + + + // get the (post) dominators for a node + BasicBlockSet_t& GetDominators(const BasicBlock_t* node) { return dom_graph[node]; } + BasicBlockSet_t& GetPostDominators(const BasicBlock_t* node) { return post_dom_graph[node]; } + + const BasicBlockSet_t& GetDominators(const BasicBlock_t* node) const { return dom_graph.at(node); } + const BasicBlockSet_t& GetPostDominators(const BasicBlock_t* node) const { return post_dom_graph.at(node); } + + bool HasWarnings() const { return warn; } + + + // get the immeidate (post) dominators for a node + const BasicBlock_t* GetImmediateDominator(const BasicBlock_t* node) const + { BlockToBlockMap_t::const_iterator it=idom_graph.find(node); return (it!=idom_graph.end()) ? it->second : NULL; } + const BasicBlock_t* GetImmediatePostDominators(const BasicBlock_t* node) const + { BlockToBlockMap_t::const_iterator it=post_idom_graph.find(node); return (it!=post_idom_graph.end()) ? it->second : NULL; } + + + private: + + typedef const BasicBlockSet_t& (*pred_func_ptr_t) (const BasicBlock_t* node); + + DominatorMap_t Dom_Comp(const BasicBlockSet_t& N, pred_func_ptr_t pred_func, BasicBlock_t* r); + BlockToBlockMap_t Idom_Comp(const BasicBlockSet_t& N, const DominatorMap_t &Domin, BasicBlock_t* r); + + + DominatorMap_t dom_graph; + BlockToBlockMap_t idom_graph; + + DominatorMap_t post_dom_graph; + BlockToBlockMap_t post_idom_graph; + + const ControlFlowGraph_t& cfg; // a reference to our cfg. + + bool warn; + + friend std::ostream& operator<<(std::ostream& os, const DominatorGraph_t& cfg); + +}; + +std::ostream& operator<<(std::ostream& os, const DominatorGraph_t& cfg); + + diff --git a/include/inc-core/eh.hpp b/include/inc-core/eh.hpp index 7ee13d4ab6bdea79fd51da118e0444a30d7c3110..de66dde36bce5125e6ac4611d8bf1af3087af5ed 100644 --- a/include/inc-core/eh.hpp +++ b/include/inc-core/eh.hpp @@ -21,8 +21,8 @@ namespace IRDB_SDK virtual void setCodeAlignmentFactor(const uint64_t caf) = 0; virtual void setDataAlignmentFactor(const int64_t daf) = 0; virtual void setReturnRegNumber (const uint8_t rr ) = 0; - virtual void getCIEProgram(const EhProgramListing_t& pgm) const = 0; - virtual void getFDEProgram(const EhProgramListing_t& pgm) const = 0; + virtual void setCIEProgram(const EhProgramListing_t& p) = 0; + virtual void setFDEProgram(const EhProgramListing_t& p) = 0; // helpers virtual void print() const = 0; diff --git a/include/inc-core/fileir.hpp b/include/inc-core/fileir.hpp index 0f2973c21e05c785dcfd9857f4c1a8c38b192835..ee9c49232015b4e804988c9ea5947f04b74da53d 100644 --- a/include/inc-core/fileir.hpp +++ b/include/inc-core/fileir.hpp @@ -25,22 +25,23 @@ namespace IRDB_SDK virtual DataScoop_t* findScoop( const VirtualOffset_t &p_addr) const = 0; - virtual void setBaseIDS() = 0; - virtual void assembleRegistry() = 0; - virtual void registerAssembly(Instruction_t *p_instr, string p_assembly) = 0; - virtual void unregisterAssembly(Instruction_t *p_instr) = 0; - virtual string lookupAssembly(Instruction_t *p_instr) = 0; - virtual void changeRegistryKey( - Instruction_t* p_orig, Instruction_t* p_updated) = 0; - virtual void splitScoop( - DataScoop_t *p_to_split, - const VirtualOffset_t &p_addr, - size_t p_size, - DataScoop_t* &p_before, - DataScoop_t* &p_containing, - DataScoop_t* &p_after, - DatabaseID_t *p_max_id=NULL - ) = 0; + virtual void setAllEhPrograms(const EhProgramSet_t& new_pgms) = 0; + virtual void setBaseIDS() = 0; + virtual void assembleRegistry() = 0; + virtual void registerAssembly(Instruction_t *p_instr, string p_assembly) = 0; + virtual void unregisterAssembly(Instruction_t *p_instr) = 0; + virtual string lookupAssembly(Instruction_t *p_instr) = 0; + virtual void changeRegistryKey( + Instruction_t* p_orig, Instruction_t* p_updated) = 0; + virtual void splitScoop( + DataScoop_t *p_to_split, + const VirtualOffset_t &p_addr, + size_t p_size, + DataScoop_t* &p_before, + DataScoop_t* &p_containing, + DataScoop_t* &p_after, + DatabaseID_t *p_max_id=NULL + ) = 0; virtual void writeToDB(std::ostream *verbose_logging=&std::cerr) = 0; @@ -63,7 +64,7 @@ namespace IRDB_SDK const EhProgramListing_t& p_fde_program={} ) = 0; - virtual AddressID_t* addNewAddress(const DatabaseID_t& myfileID, const VirtualOffset_t& voff) =0 ; + virtual AddressID_t* addNewAddress(const DatabaseID_t& myfileID, const VirtualOffset_t& voff=0) =0 ; virtual ICFS_t* addNewICFS (Instruction_t* insn=nullptr, const InstructionSet_t& targets={}, const ICFSAnalysisStatus_t& status=iasAnalysisIncomplete) = 0; virtual Instruction_t* addNewInstruction( @@ -88,6 +89,7 @@ namespace IRDB_SDK virtual void removeScoop(DataScoop_t* s) = 0; virtual void moveRelocation(Relocation_t* reloc, Instruction_t* from, Instruction_t* to) = 0; + virtual EhProgram_t* copyEhProgram(const EhProgram_t& orig) = 0; // static methods