diff --git a/ir_builders/build_callgraph.cpp b/ir_builders/build_callgraph.cpp index 2542a41799296c1bfb9b606332f167905391c4cd..a0ca36f7209ae516387bcc5893e81674ac06714b 100644 --- a/ir_builders/build_callgraph.cpp +++ b/ir_builders/build_callgraph.cpp @@ -20,8 +20,8 @@ -#include <libIRDB-core.hpp> -#include <libIRDB-cfg.hpp> +#include <irdb=-sdk> +#include <irdb-cfg> #include <utils.hpp> // to_string function from libIRDB #include <iostream> #include <fstream> @@ -29,7 +29,6 @@ #include <string.h> #include <assert.h> -using namespace libIRDB; using namespace std; // @@ -62,7 +61,7 @@ main(int argc, char* argv[]) varidp=new VariantID_t(atoi(argv[1])); // A callgraph - Callgraph_t *cg=new Callgraph_t; + auto cg=Callgraph_t::factory(); assert(varidp->IsRegistered()==true); diff --git a/ir_builders/check_thunks.cpp b/ir_builders/check_thunks.cpp index dd3052250e7cedf3b631dd6ab244fd3576059cea..1c0dfa54c14fa092e4774cf26e64f00d93b23249 100644 --- a/ir_builders/check_thunks.cpp +++ b/ir_builders/check_thunks.cpp @@ -24,7 +24,6 @@ #include <irdb-core> -#include <libIRDB-cfg.hpp> #include <utils.hpp> #include <iostream> #include <stdlib.h> diff --git a/ir_builders/find_strings.cpp b/ir_builders/find_strings.cpp index a91071a648113177c306da94e5955057ada7a0ce..e1f7146d093f6f81d99ae6a029d99e919fef350b 100644 --- a/ir_builders/find_strings.cpp +++ b/ir_builders/find_strings.cpp @@ -21,7 +21,7 @@ #include <libIRDB-core.hpp> -#include <libIRDB-cfg.hpp> +#include <irdb-cfg.hpp> #include <iostream> #include <stdlib.h> #include <cctype> diff --git a/ir_builders/fix_calls.cpp b/ir_builders/fix_calls.cpp index 9ef6496b41304e7afdf51eaf9bd8c9ec38908db3..5959be0ca1de48f56ff8cc9d55a35d3e68846514 100644 --- a/ir_builders/fix_calls.cpp +++ b/ir_builders/fix_calls.cpp @@ -20,7 +20,7 @@ #include <irdb-core> -#include <libIRDB-cfg.hpp> +#include <irdb-cfg> #include <utils.hpp> #include <iostream> #include <stdlib.h> @@ -95,13 +95,13 @@ size_t not_calls=0; bool opt_fix_icalls = false; bool opt_fix_safefn = true; -bool check_entry(bool &found, libIRDB::ControlFlowGraph_t* cfg) +bool check_entry(bool &found, ControlFlowGraph_t* cfg) { - auto entry=cfg->GetEntry(); + auto entry=cfg->getEntry(); found=false; - for(auto insn : entry->GetInstructions()) + for(auto insn : entry->getInstructions()) { auto disasmp = DecodedInstruction_t::factory(insn); auto &disasm = *disasmp; @@ -136,7 +136,7 @@ bool check_entry(bool &found, libIRDB::ControlFlowGraph_t* cfg) return false; } -using ControlFlowGraphMap_t = map<Function_t*, libIRDB::ControlFlowGraph_t*>; +using ControlFlowGraphMap_t = map<Function_t*, shared_ptr<ControlFlowGraph_t> >; ControlFlowGraphMap_t cfg_optimizer; bool call_needs_fix(Instruction_t* insn) @@ -242,16 +242,16 @@ bool call_needs_fix(Instruction_t* insn) if(!is_found) /* build a cfg for this function */ - cfg_optimizer[func]=new libIRDB::ControlFlowGraph_t(func); + cfg_optimizer[func]=shared_ptr<ControlFlowGraph_t>(move(ControlFlowGraph_t::factory(func))); - auto cfg=cfg_optimizer[func]; + auto cfg=cfg_optimizer[func].get(); - assert(cfg->GetEntry()); + assert(cfg->getEntry()); /* if the call instruction isn't to a function entry point */ - if(cfg->GetEntry()->GetInstructions()[0]!=target) + if(cfg->getEntry()->getInstructions()[0]!=target) { call_to_not_entry++; /* then we need to fix it */ diff --git a/ir_builders/read_ehframe.cpp b/ir_builders/read_ehframe.cpp index 1ea7a13a37a3317a662db51d60a85318e63f35c6..1cf13f499735b89de30cd4bb9da72d5b41cfc2db 100644 --- a/ir_builders/read_ehframe.cpp +++ b/ir_builders/read_ehframe.cpp @@ -23,7 +23,6 @@ #include <irdb-core> -#include <libIRDB-cfg.hpp> #include <utils.hpp> #include <iostream> #include <stdlib.h> diff --git a/libIRDB/include/bea_deprecated.hpp b/libIRDB/include/bea_deprecated.hpp deleted file mode 100644 index 6868f1cd1118fe8b01c7c972a49f5191157192cd..0000000000000000000000000000000000000000 --- a/libIRDB/include/bea_deprecated.hpp +++ /dev/null @@ -1,52 +0,0 @@ -#ifndef bea_deprecated_h -#define bea_deprecated_h - - -#include <libIRDB-core.hpp> -#include <beaengine/BeaEngine.h> - - -static inline int Disassemble(const libIRDB::Instruction_t* const insn, DISASM &disasm) -{ - assert(insn); - memset(&disasm, 0, sizeof(DISASM)); - disasm.Options = NasmSyntax + PrefixedNumeral; - disasm.Archi = libIRDB::FileIR_t::GetArchitectureBitWidth(); - disasm.EIP = (UIntPtr) insn->GetDataBits().c_str(); - disasm.VirtualAddr = insn->GetAddress()->GetVirtualOffset(); - int instr_len = Disasm(&disasm); - return instr_len; -} - -static inline bool SetsStackPointer(const ARGTYPE* arg) -{ - if((arg->AccessMode & WRITE ) == 0) - return false; - int access_type=arg->ArgType; - - if(access_type==REGISTER_TYPE + GENERAL_REG +REG4) - return true; - return false; - -} - -static inline bool SetsStackPointer(const DISASM* disasm) -{ - if(strstr(disasm->Instruction.Mnemonic, "push")!=NULL) - return true; - if(strstr(disasm->Instruction.Mnemonic, "pop")!=NULL) - return true; - if(strstr(disasm->Instruction.Mnemonic, "call")!=NULL) - return true; - if(disasm->Instruction.ImplicitModifiedRegs==REGISTER_TYPE+GENERAL_REG+REG4) - return true; - - if(SetsStackPointer(&disasm->Argument1)) return true; - if(SetsStackPointer(&disasm->Argument2)) return true; - if(SetsStackPointer(&disasm->Argument3)) return true; - - return false; - -} - -#endif diff --git a/libIRDB/include/cfg/BasicBlock.hpp b/libIRDB/include/cfg/BasicBlock.hpp index 3abf761d6162e1bbe028c9acade6f438fa4d4497..d2059b22eca8bf27a7df1c8991de15116ede1822 100644 --- a/libIRDB/include/cfg/BasicBlock.hpp +++ b/libIRDB/include/cfg/BasicBlock.hpp @@ -19,56 +19,57 @@ */ -class BasicBlock_t; -typedef std::set<BasicBlock_t*> BasicBlockSet_t; -typedef std::vector<IRDB_SDK::Instruction_t*> InstructionVector_t; - -class BasicBlock_t +namespace libIRDB { + using namespace std; + + class BasicBlock_t : public IRDB_SDK::BasicBlock_t + { - public: - BasicBlock_t(); + public: + BasicBlock_t(); + virtual ~BasicBlock_t() { } - bool GetIsExitBlock() { return is_exit_block; } - void SetIsExitBlock(bool is_exit) { is_exit_block=is_exit; } + bool getIsExitBlock() const { return is_exit_block; } + void setIsExitBlock(bool is_exit) { is_exit_block=is_exit; } - InstructionVector_t& GetInstructions() { return instructions; } - BasicBlockSet_t& GetPredecessors() { return predecessors; } - BasicBlockSet_t& GetSuccessors() { return successors; } - BasicBlockSet_t& GetIndirectTargets() { return indirect_targets; } - BasicBlock_t* GetFallthrough(); - BasicBlock_t* getTarget(); + IRDB_SDK::InstructionVector_t& GetInstructions() { return instructions; } + IRDB_SDK::BasicBlockSet_t& GetPredecessors() { return predecessors; } + IRDB_SDK::BasicBlockSet_t& GetSuccessors() { return successors; } + IRDB_SDK::BasicBlockSet_t& GetIndirectTargets() { return indirect_targets; } - // for const correctness if you aren't modifying. - const InstructionVector_t& GetInstructions() const { return instructions; } - const BasicBlockSet_t& GetPredecessors() const { return predecessors; } - const BasicBlockSet_t& GetSuccessors() const { return successors; } - const BasicBlockSet_t& GetIndirectTargets() const { return indirect_targets; } + // for const correctness if you aren't modifying. + const IRDB_SDK::InstructionVector_t& getInstructions() const { return instructions; } + const IRDB_SDK::BasicBlockSet_t& getPredecessors() const { return predecessors; } + const IRDB_SDK::BasicBlockSet_t& getSuccessors() const { return successors; } + const IRDB_SDK::BasicBlockSet_t& getIndirectTargets() const { return indirect_targets; } +// IRDB_SDK::BasicBlock_t * getFallthrough() const ; +// IRDB_SDK::BasicBlock_t * getTarget() const ; - bool EndsInBranch(); - bool EndsInIndirectBranch(); - bool EndsInConditionalBranch(); - IRDB_SDK::Instruction_t* GetBranchInstruction(); - void dump(std::ostream &os=std::cout) const { os<<*this; } + bool endsInBranch() const; + bool endsInIndirectBranch() const; + bool endsInConditionalBranch() const; + IRDB_SDK::Instruction_t* getBranchInstruction() const; + void dump(ostream &os=cout) const ; - protected: + protected: - void BuildBlock( IRDB_SDK::Instruction_t* insn, - const std::map<IRDB_SDK::Instruction_t*,BasicBlock_t*> &insn2block_map - ); + void BuildBlock( IRDB_SDK::Instruction_t* insn, + const map<IRDB_SDK::Instruction_t*,BasicBlock_t*> &insn2block_map + ); - private: + private: - InstructionVector_t instructions; - BasicBlockSet_t predecessors; - BasicBlockSet_t successors; - BasicBlockSet_t indirect_targets; - bool is_exit_block; + IRDB_SDK::InstructionVector_t instructions; + IRDB_SDK::BasicBlockSet_t predecessors; + IRDB_SDK::BasicBlockSet_t successors; + IRDB_SDK::BasicBlockSet_t indirect_targets; + bool is_exit_block; - friend std::ostream& operator<<(std::ostream& os, const BasicBlock_t& block); - friend class ControlFlowGraph_t; -}; + friend ostream& operator<<(ostream& os, const BasicBlock_t& block); + friend class ControlFlowGraph_t; + }; -std::ostream& operator<<(std::ostream& os, const BasicBlock_t& block); +} diff --git a/libIRDB/include/cfg/CFG.hpp b/libIRDB/include/cfg/CFG.hpp index f254fe734395dc21a0bda6f1147da62cd3fbd95c..2499b994eea66f87fe85f49cd85dffaaa056489e 100644 --- a/libIRDB/include/cfg/CFG.hpp +++ b/libIRDB/include/cfg/CFG.hpp @@ -18,39 +18,35 @@ * */ -enum CFG_EdgeTypeEnum { CFG_FallthroughEdge, CFG_TargetEdge, CFG_IndirectEdge }; -typedef std::set<CFG_EdgeTypeEnum> CFG_EdgeType; - -class ControlFlowGraph_t +namespace libIRDB { - public: - ControlFlowGraph_t(IRDB_SDK::Function_t* func); - BasicBlock_t* GetEntry() const { return entry; } - IRDB_SDK::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(IRDB_SDK::Function_t *func); - void alloc_blocks(const IRDB_SDK::InstructionSet_t &starts, map<IRDB_SDK::Instruction_t*,BasicBlock_t*>& insn2block_map); - void build_blocks(const map<IRDB_SDK::Instruction_t*,BasicBlock_t*>& insn2block_map); - void find_unblocked_instructions(InstructionSet_t &starts, IRDB_SDK::Function_t* func); - - // data - BasicBlockSet_t blocks; - BasicBlock_t* entry; - IRDB_SDK::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); - - + using namespace std; + + class ControlFlowGraph_t : public IRDB_SDK::ControlFlowGraph_t + { + public: + ControlFlowGraph_t(IRDB_SDK::Function_t* func); + virtual ~ControlFlowGraph_t() { } + IRDB_SDK::BasicBlock_t* getEntry() const { return entry; } + IRDB_SDK::Function_t* getFunction() const { return function; } + IRDB_SDK::BasicBlockSet_t& GetBlocks() { return blocks; } + const IRDB_SDK::BasicBlockSet_t& getBlocks() const { return blocks; } + void dump(ostream &os=cout) const; + bool hasEdge(IRDB_SDK::BasicBlock_t *p_src, IRDB_SDK::BasicBlock_t *p_tgt) const; + IRDB_SDK::CFGEdgeType_t getEdgeType(const IRDB_SDK::BasicBlock_t *p_src, const IRDB_SDK::BasicBlock_t *p_tgt) const; + + private: + // methods + void Build(IRDB_SDK::Function_t *func); + void alloc_blocks(const IRDB_SDK::InstructionSet_t &starts, map<IRDB_SDK::Instruction_t*,BasicBlock_t*>& insn2block_map); + void build_blocks(const map<IRDB_SDK::Instruction_t*,BasicBlock_t*>& insn2block_map); + void find_unblocked_instructions(InstructionSet_t &starts, IRDB_SDK::Function_t* func); + + // data + IRDB_SDK::BasicBlockSet_t blocks; + IRDB_SDK::BasicBlock_t* entry; + IRDB_SDK::Function_t* function; + + }; + +} diff --git a/libIRDB/include/cfg/callgraph.hpp b/libIRDB/include/cfg/callgraph.hpp index f60221c7ce03f0e7708f18eaa3376de3fb99a801..bc5f383923e2e686c9c08325aa175a7b008db8b4 100644 --- a/libIRDB/include/cfg/callgraph.hpp +++ b/libIRDB/include/cfg/callgraph.hpp @@ -21,138 +21,169 @@ #ifndef irdb_cfg_callgraph_h #define irdb_cfg_callgraph_h -// only one type of hell node for now, but leave -// open the possibilty for multiple hell nodes -typedef enum { DEFAULT_HELL_NODE = 0 } HellNodeType; - -class CallGraphNode_t +namespace libIRDB { - public: - CallGraphNode_t(IRDB_SDK::Function_t* f = NULL) { - if (f) { - SetFunction(f); - } else { - m_isHellNode = true; - m_node.hellNodeType = DEFAULT_HELL_NODE; + + using namespace std; + + // only one type of hell node for now, but leave + // open the possibilty for multiple hell nodes + typedef enum { DEFAULT_HELL_NODE = 0 } HellNodeType; + + class CallGraphNode_t : public IRDB_SDK::CallGraphNode_t + { + public: + virtual ~CallGraphNode_t(){ } + CallGraphNode_t(IRDB_SDK::Function_t* f = NULL) { + if (f) { + SetFunction(f); + } else { + m_isHellNode = true; + m_node.hellNodeType = DEFAULT_HELL_NODE; + } } - } - - bool IsHellnode() const { return m_isHellNode; } - - IRDB_SDK::Function_t* getFunction() const { - assert(!m_isHellNode); - if (m_isHellNode) - return NULL; - else - return m_node.func; - } - - HellNodeType GetHellNodeType() const { - assert(m_isHellNode); - return m_node.hellNodeType; - } - - bool operator==(const CallGraphNode_t &other) const { - if (this == &other) return true; - if (m_isHellNode) - { - return m_node.hellNodeType == other.m_node.hellNodeType; + + bool isHellnode() const { return m_isHellNode; } + + IRDB_SDK::Function_t* getFunction() const { + assert(!m_isHellNode); + if (m_isHellNode) + return NULL; + else + return m_node.func; } - else - return m_node.func == other.m_node.func; - } - - private: - void SetFunction(IRDB_SDK::Function_t* const f) { - assert(f); - m_node.func = f; - m_isHellNode = false; - } - - private: - bool m_isHellNode; - union { - IRDB_SDK::Function_t* func; - HellNodeType hellNodeType; - } m_node; -}; - -typedef std::pair<CallGraphNode_t*,CallGraphNode_t*> CallGraphEdge_t; -typedef std::set<CallGraphNode_t*> CallGraphNodeSet_t; -typedef IRDB_SDK::Instruction_t* CallSite_t; -typedef std::set<CallSite_t> CallSiteSet_t; - -class Callgraph_t -{ - public: - Callgraph_t(); - virtual ~Callgraph_t(); - void AddFile(IRDB_SDK::FileIR_t* const firp); - - bool EdgeExists(const CallGraphEdge_t& edge) - { - CallGraphNode_t *from=edge.first; - CallGraphNode_t *to=edge.second; - - const CallGraphNodeSet_t& calleeSet = callers[from]; - return calleeSet.find(to)!=calleeSet.end(); - } - bool EdgeExists(CallGraphNode_t& n1, CallGraphNode_t& n2) - { return EdgeExists(CallGraphEdge_t(&n1,&n2));} - - CallGraphNodeSet_t& GetCallersOfNode(CallGraphNode_t* const node) - { return callers[node]; } - CallGraphNodeSet_t& GetCalleesOfNode(CallGraphNode_t* const node) - { return callees[node]; } - - void GetAncestors(IRDB_SDK::Function_t* const fn, CallGraphNodeSet_t& ancestors, bool skipHellNode = false); - void GetAncestors(CallGraphNode_t* const node, CallGraphNodeSet_t& ancestors, bool skipHellNode = false); - - CallSiteSet_t& GetCallSites(CallGraphNode_t* const n1) - { return call_sites[n1]; } - - void Dump(std::ostream& fout); - - std::string GetNodeName(const CallGraphNode_t* const n1) const { - assert(n1); - if (n1->IsHellnode()) { - std::ostringstream s; - s << "HELLNODE" << n1->GetHellNodeType(); - return s.str(); - } else { - assert(n1->getFunction()); - return n1->getFunction()->getName(); + + HellNodeType GetHellNodeType() const { + assert(m_isHellNode); + return m_node.hellNodeType; + } + + bool operator==(const CallGraphNode_t &other) const { + if (this == &other) return true; + if (m_isHellNode) + { + return m_node.hellNodeType == other.m_node.hellNodeType; + } + else + return m_node.func == other.m_node.func; + } + void dump(ostream& os=cout) const; + + private: + void SetFunction(IRDB_SDK::Function_t* const f) { + assert(f); + m_node.func = f; + m_isHellNode = false; } - } - std::string GetCallsiteDisassembly(const CallSite_t &c) const - { return c ? c->getDisassembly() : "NOFROMFUNC"; } + private: + bool m_isHellNode; + union { + IRDB_SDK::Function_t* func; + HellNodeType hellNodeType; + } m_node; + }; + + + class Callgraph_t : public IRDB_SDK::CallGraph_t + { + public: + Callgraph_t(); + virtual ~Callgraph_t(); + void addFile(IRDB_SDK::FileIR_t* const firp); + + bool edgeExists(const IRDB_SDK::CallGraphEdge_t& edge) const + { + const auto from = dynamic_cast<CallGraphNode_t*>(edge.first); + const auto to = dynamic_cast<CallGraphNode_t*>(edge.second); + + const auto caller_it = callers.find(from); + if(caller_it==callers.end()) + return false; + + const auto &calleeSet = caller_it->second; + return calleeSet.find(to)!=calleeSet.end(); + } + bool edgeExists(IRDB_SDK::CallGraphNode_t& n1, IRDB_SDK::CallGraphNode_t& n2) const + { return edgeExists(IRDB_SDK::CallGraphEdge_t(&n1,&n2));} + + IRDB_SDK::CallGraphNodeSet_t& GetCallersOfNode(IRDB_SDK::CallGraphNode_t* const node) + { return callers[node]; } + IRDB_SDK::CallGraphNodeSet_t& GetCalleesOfNode(IRDB_SDK::CallGraphNode_t* const node) + { return callees[node]; } + + const IRDB_SDK::CallGraphNodeSet_t& getCallersOfNode(IRDB_SDK::CallGraphNode_t* const node) const + { + static const auto empty = IRDB_SDK::CallGraphNodeSet_t(); + const auto it=callers.find(node); + return (it==callers.end()) ? empty : it->second; + } + const IRDB_SDK::CallGraphNodeSet_t& getCalleesOfNode(IRDB_SDK::CallGraphNode_t* const node) const + { + static const auto empty = IRDB_SDK::CallGraphNodeSet_t(); + const auto it=callees.find(node); + return (it==callees.end()) ? empty : it->second; + } + + void GetAncestors(IRDB_SDK::Function_t* const fn, IRDB_SDK::CallGraphNodeSet_t& ancestors, bool skipHellNode = false) const; + void GetAncestors(IRDB_SDK::CallGraphNode_t* const node, IRDB_SDK::CallGraphNodeSet_t& ancestors, bool skipHellNode = false) const; + + const IRDB_SDK::CallSiteSet_t& GetCallSites(IRDB_SDK::CallGraphNode_t* const n1) const + { + static const auto empty = IRDB_SDK::CallSiteSet_t(); + const auto it=call_sites.find(n1); + return (it==call_sites.end()) ? empty : it->second; + } + + + IRDB_SDK::CallSiteSet_t& getCallSites(IRDB_SDK::CallGraphNode_t* const n1) + { return call_sites[n1]; } + + void dump(ostream& fout) const; + + string GetNodeName(const IRDB_SDK::CallGraphNode_t* const p_n1) const { + auto n1=dynamic_cast<CallGraphNode_t const*>(p_n1); + assert(n1); + if (n1->isHellnode()) { + ostringstream s; + s << "HELLNODE" << n1->GetHellNodeType(); + return s.str(); + } else { + assert(n1->getFunction()); + return n1->getFunction()->getName(); + } + } - bool Reachable(CallGraphNode_t* const from, CallGraphNode_t* const to, bool skipHellNode = false); + string GetCallsiteDisassembly(const IRDB_SDK::CallSite_t &c) const + { return c ? c->getDisassembly() : "NOFROMFUNC"; } - CallGraphNode_t& GetDefaultHellNode() { return default_hellnode; } + bool isReachable(IRDB_SDK::CallGraphNode_t* const from, IRDB_SDK::CallGraphNode_t* const to, bool skipHellNode = false) const; - CallGraphNode_t* FindNode(IRDB_SDK::Function_t* const fn); + CallGraphNode_t& GetDefaultHellNode() { return default_hellnode; } + const CallGraphNode_t& getDefaultHellNode() const { return default_hellnode; } - private: - // create nodes from functions - void CreateNodes(IRDB_SDK::FileIR_t *firp); + IRDB_SDK::CallGraphNode_t* findNode(IRDB_SDK::Function_t* const fn) const; - // mark the given insn as a call site. - void MarkCallSite(Instruction_t* const insn); + private: + // create nodes from functions + void CreateNodes(IRDB_SDK::FileIR_t *firp); - // traverse graph to retrieve all ancestors - void _GetAncestors(CallGraphNode_t* const node, CallGraphNodeSet_t &ancestors, CallGraphNodeSet_t &visited, bool skipHellNode); + // mark the given insn as a call site. + void MarkCallSite(IRDB_SDK::Instruction_t* const insn); - typedef std::map<CallGraphNode_t*, CallGraphNodeSet_t > CGNodeToCGNodeSetMap_t; - typedef std::map<CallGraphNode_t*, CallSiteSet_t > NodeToCallSiteSetMap_t; - typedef std::map<IRDB_SDK::Function_t*, CallGraphNode_t*> FunctionToCGNodeMap_t; + // traverse graph to retrieve all ancestors + void _GetAncestors(IRDB_SDK::CallGraphNode_t* const node, IRDB_SDK::CallGraphNodeSet_t &ancestors, IRDB_SDK::CallGraphNodeSet_t &visited, bool skipHellNode) const; - CGNodeToCGNodeSetMap_t callers; // map a callee to its callees - CGNodeToCGNodeSetMap_t callees; // map a caller to its callers - NodeToCallSiteSetMap_t call_sites; - CallGraphNode_t default_hellnode; // default hell node - FunctionToCGNodeMap_t nodes; // maps functions to call graph nodes -}; + using CGNodeToCGNodeSetMap_t = map<IRDB_SDK::CallGraphNode_t*, IRDB_SDK::CallGraphNodeSet_t > ; + using NodeToCallSiteSetMap_t = map<IRDB_SDK::CallGraphNode_t*, IRDB_SDK::CallSiteSet_t > ; + using FunctionToCGNodeMap_t = map<IRDB_SDK::Function_t* , IRDB_SDK::CallGraphNode_t* > ; +; + CGNodeToCGNodeSetMap_t callers; // map a callee to its callees + CGNodeToCGNodeSetMap_t callees; // map a caller to its callers + NodeToCallSiteSetMap_t call_sites; + CallGraphNode_t default_hellnode; // default hell node + FunctionToCGNodeMap_t nodes; // maps functions to call graph nodes + }; +} #endif diff --git a/libIRDB/include/cfg/criticaledge.hpp b/libIRDB/include/cfg/criticaledge.hpp index 6126703ea5fa32f25c13ad7aeca0392dcaff6508..244e68347ab77f4e565bb300fc98e8a6b4e81911 100644 --- a/libIRDB/include/cfg/criticaledge.hpp +++ b/libIRDB/include/cfg/criticaledge.hpp @@ -18,16 +18,22 @@ * */ -typedef std::tuple<BasicBlock_t*, BasicBlock_t*> BasicBlockEdge_t; -typedef std::set<BasicBlockEdge_t> BasicBlockEdgeSet_t; - -class CriticalEdgeAnalyzer_t +namespace libIRDB { - public: - CriticalEdgeAnalyzer_t(const ControlFlowGraph_t &p_cfg, const bool p_conservative=true); - BasicBlockEdgeSet_t GetAllCriticalEdges() const; + using namespace std; + + class CriticalEdgeAnalyzer_t : public IRDB_SDK::CriticalEdges_t + { + public: + CriticalEdgeAnalyzer_t(const ControlFlowGraph_t *p_cfg, const bool p_conservative=true); + virtual ~CriticalEdgeAnalyzer_t() { } + const IRDB_SDK::BasicBlockEdgeSet_t& getAllCriticalEdges() const { return criticals; } + + private: + void init(); + const IRDB_SDK::ControlFlowGraph_t *m_cfg; + const bool m_conservative; + IRDB_SDK::BasicBlockEdgeSet_t criticals; - private: - const ControlFlowGraph_t m_cfg; - const bool m_conservative; -}; + }; +} diff --git a/libIRDB/include/cfg/domgraph.hpp b/libIRDB/include/cfg/domgraph.hpp index 087fc4dd604d8458be76de68b188447ffaf68ba9..932a34475e59e7044cffb485dcca828bc87a6f43 100644 --- a/libIRDB/include/cfg/domgraph.hpp +++ b/libIRDB/include/cfg/domgraph.hpp @@ -1,54 +1,61 @@ +#include <ostream> +namespace libIRDB +{ + using namespace std; + using DominatorMap_t = map<const IRDB_SDK::BasicBlock_t*, IRDB_SDK::BasicBlockSet_t>; + using BlockToBlockMap_t = map<const IRDB_SDK::BasicBlock_t*, IRDB_SDK::BasicBlock_t*>; -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]; } + class DominatorGraph_t : public IRDB_SDK::DominatorGraph_t + { + public: + DominatorGraph_t(const ControlFlowGraph_t* p_cfg, bool needs_postdoms=false, bool needs_idoms=false); + virtual ~DominatorGraph_t() { } + + + // get the (post) dominators for a node + IRDB_SDK::BasicBlockSet_t& GetDominators(const IRDB_SDK::BasicBlock_t* node) { return dom_graph[node]; } + IRDB_SDK::BasicBlockSet_t& GetPostDominators(const IRDB_SDK::BasicBlock_t* node) { return post_dom_graph[node]; } + + const IRDB_SDK::BasicBlockSet_t& getDominators(const IRDB_SDK::BasicBlock_t* node) const { return dom_graph.at(node); } + const IRDB_SDK::BasicBlockSet_t& getPostDominators(const IRDB_SDK::BasicBlock_t* node) const { return post_dom_graph.at(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; } - bool HasWarnings() const { return warn; } + // get the immeidate (post) dominators for a node + const IRDB_SDK::BasicBlock_t* getImmediateDominator(const IRDB_SDK::BasicBlock_t* node) const + { auto it=idom_graph.find(node); return (it!=idom_graph.end()) ? it->second : NULL; } + const IRDB_SDK::BasicBlock_t* getImmediatePostDominators(const IRDB_SDK::BasicBlock_t* node) const + { auto it=post_idom_graph.find(node); return (it!=post_idom_graph.end()) ? it->second : NULL; } - // 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; } + void dump(ostream& os=cout) const; - private: + private: - typedef const BasicBlockSet_t& (*pred_func_ptr_t) (const BasicBlock_t* node); + typedef const IRDB_SDK::BasicBlockSet_t& (*pred_func_ptr_t) (const IRDB_SDK::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_Comp(const IRDB_SDK::BasicBlockSet_t& N, pred_func_ptr_t pred_func, IRDB_SDK::BasicBlock_t* r); + BlockToBlockMap_t Idom_Comp(const IRDB_SDK::BasicBlockSet_t& N, const DominatorMap_t &Domin, IRDB_SDK::BasicBlock_t* r); - DominatorMap_t dom_graph; - BlockToBlockMap_t idom_graph; + DominatorMap_t dom_graph; + BlockToBlockMap_t idom_graph; - DominatorMap_t post_dom_graph; - BlockToBlockMap_t post_idom_graph; + DominatorMap_t post_dom_graph; + BlockToBlockMap_t post_idom_graph; - const ControlFlowGraph_t& cfg; // a reference to our cfg. + const ControlFlowGraph_t& cfg; // a reference to our cfg. - bool warn; + 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/libIRDB/include/libIRDB-cfg.hpp b/libIRDB/include/libIRDB-cfg.hpp index 3546227c6cd6845328825c61424f945f8a043581..25ed68d1d8b8bc9cedcb1cc068115e6c9daa9a7a 100644 --- a/libIRDB/include/libIRDB-cfg.hpp +++ b/libIRDB/include/libIRDB-cfg.hpp @@ -23,6 +23,7 @@ /* Building a CFG depends on core functionality */ +#include <irdb-cfg> #include <libIRDB-core.hpp> #include <vector> @@ -30,17 +31,11 @@ #include <map> #include <ostream> -namespace libIRDB -{ - - using namespace std; - #include <cfg/BasicBlock.hpp> #include <cfg/CFG.hpp> #include <cfg/callgraph.hpp> #include <cfg/domgraph.hpp> #include <cfg/criticaledge.hpp> -}; #endif diff --git a/libIRDB/src/cfg/BasicBlock.cpp b/libIRDB/src/cfg/BasicBlock.cpp index db79f64fb935c2deb0faff85cb90d9f00e859c5b..a294e07dcc45fb6f25357051844420127f2acaf7 100644 --- a/libIRDB/src/cfg/BasicBlock.cpp +++ b/libIRDB/src/cfg/BasicBlock.cpp @@ -146,23 +146,8 @@ void BasicBlock_t::BuildBlock } -std::ostream& libIRDB::operator<<(std::ostream& os, const BasicBlock_t& block) -{ - os<<block.is_exit_block; - os<<"\t ---- Starting block print -----" <<endl; - for(auto i=0U;i<block.instructions.size();i++) - { - const auto insn=block.instructions[i]; - os<<"\t Instruction "<<std::dec<<i<<" at " << std::hex << insn->getAddress()->getVirtualOffset() << " with id " << std::dec << insn->getBaseID() << " " << insn->getComment() << endl; - } - os<<"\t ---- done block print -----" <<endl; - os<<endl; - - return os; -} - -bool BasicBlock_t::EndsInBranch() +bool BasicBlock_t::endsInBranch() const { const auto branch=instructions[instructions.size()-1]; assert(branch); @@ -172,7 +157,7 @@ bool BasicBlock_t::EndsInBranch() } -bool BasicBlock_t::EndsInIndirectBranch() +bool BasicBlock_t::endsInIndirectBranch() const { const auto *branch=instructions[instructions.size()-1]; assert(branch); @@ -192,9 +177,9 @@ bool BasicBlock_t::EndsInIndirectBranch() } return false; } -bool BasicBlock_t::EndsInConditionalBranch() +bool BasicBlock_t::endsInConditionalBranch() const { - if(!EndsInBranch()) + if(!endsInBranch()) return false; const auto branch=instructions[instructions.size()-1]; assert(branch); @@ -203,13 +188,32 @@ bool BasicBlock_t::EndsInConditionalBranch() return d->isConditionalBranch(); } -IRDB_SDK::Instruction_t* BasicBlock_t::GetBranchInstruction() +IRDB_SDK::Instruction_t* BasicBlock_t::getBranchInstruction() const { - if(!EndsInBranch()) + if(!endsInBranch()) return NULL; auto branch=instructions[instructions.size()-1]; return branch; } + +std::ostream& IRDB_SDK::operator<<(std::ostream& os, const IRDB_SDK::BasicBlock_t& block) +{ + block.dump(os); + return os; +} +void BasicBlock_t::dump(std::ostream& os) const +{ + os<<getIsExitBlock(); + os<<"\t ---- Starting block print -----" <<endl; + for(auto i=0U;i<getInstructions().size();i++) + { + const auto insn=getInstructions()[i]; + os<<"\t Instruction "<<std::dec<<i<<" at " << std::hex << insn->getAddress()->getVirtualOffset() << " with id " << std::dec << insn->getBaseID() << " " << insn->getComment() << endl; + } + os<<"\t ---- done block print -----" <<endl; + os<<endl; +} + diff --git a/libIRDB/src/cfg/CFG.cpp b/libIRDB/src/cfg/CFG.cpp index 36be933e2e58df273adfd393fd5449a7f48f86b7..3a20e1a2d95ba882aed6ce4b79e21e5a20080737 100644 --- a/libIRDB/src/cfg/CFG.cpp +++ b/libIRDB/src/cfg/CFG.cpp @@ -89,7 +89,7 @@ ControlFlowGraph_t::ControlFlowGraph_t(IRDB_SDK::Function_t* func) : } -void ControlFlowGraph_t::alloc_blocks(const InstructionSet_t &starts, map<IRDB_SDK::Instruction_t*,BasicBlock_t*>& insn2block_map) +void ControlFlowGraph_t::alloc_blocks(const IRDB_SDK::InstructionSet_t &starts, map<IRDB_SDK::Instruction_t*,BasicBlock_t*>& insn2block_map) { /* create a basic block for each instruction that starts a block */ for(const auto &insn : starts) @@ -115,7 +115,7 @@ void ControlFlowGraph_t::build_blocks(const map<IRDB_SDK::Instruction_t*,BasicBl const auto insn=it.first; const auto block=it.second; - if(block->GetInstructions().size()>0) // already built + if(block->getInstructions().size()>0) // already built continue; assert(insn && block); @@ -126,12 +126,12 @@ void ControlFlowGraph_t::build_blocks(const map<IRDB_SDK::Instruction_t*,BasicBl } -void ControlFlowGraph_t::find_unblocked_instructions(InstructionSet_t &starts, IRDB_SDK::Function_t* func) +void ControlFlowGraph_t::find_unblocked_instructions(IRDB_SDK::InstructionSet_t &starts, IRDB_SDK::Function_t* func) { auto mapped_instructions=InstructionSet_t(); auto missed_instructions=InstructionSet_t(); for(const auto block : GetBlocks()) - mapped_instructions.insert(ALLOF(block->GetInstructions())); + mapped_instructions.insert(ALLOF(block->getInstructions())); auto my_inserter=inserter(missed_instructions,missed_instructions.end()); set_difference(ALLOF(func->getInstructions()), ALLOF(mapped_instructions), my_inserter); @@ -166,37 +166,37 @@ void ControlFlowGraph_t::Build(IRDB_SDK::Function_t* func) } // returns true iff there's an edge from <p_src> to <p_tgt> in the CFG -bool ControlFlowGraph_t::HasEdge(BasicBlock_t *p_src, BasicBlock_t *p_tgt) const +bool ControlFlowGraph_t::hasEdge(IRDB_SDK::BasicBlock_t *p_src, IRDB_SDK::BasicBlock_t *p_tgt) const { const auto src_exists = blocks.find(p_src) != blocks.end(); const auto tgt_exists = blocks.find(p_tgt) != blocks.end(); if (!src_exists || !tgt_exists) return false; - const auto successors = p_src->GetSuccessors(); + const auto successors = p_src->getSuccessors(); return successors.find(p_tgt) != successors.end(); } -CFG_EdgeType ControlFlowGraph_t::GetEdgeType(const BasicBlock_t *p_src, const BasicBlock_t *p_tgt) const +IRDB_SDK::CFGEdgeType_t ControlFlowGraph_t::getEdgeType(const IRDB_SDK::BasicBlock_t *p_src, const IRDB_SDK::BasicBlock_t *p_tgt) const { - const auto last_in_src = p_src->GetInstructions()[p_src->GetInstructions().size()-1]; - const auto first_in_tgt = p_tgt->GetInstructions()[0]; + const auto last_in_src = p_src->getInstructions()[p_src->getInstructions().size()-1]; + const auto first_in_tgt = p_tgt->getInstructions()[0]; - auto edgeType = CFG_EdgeType(); + auto edgeType = IRDB_SDK::CFGEdgeType_t(); if (last_in_src->getFallthrough() == first_in_tgt) { - edgeType.insert(CFG_FallthroughEdge); + edgeType.insert(IRDB_SDK::cetFallthroughEdge); } if (last_in_src->getTarget() == first_in_tgt) { - edgeType.insert(CFG_TargetEdge); + edgeType.insert(IRDB_SDK::cetTargetEdge); } if (edgeType.size() == 0) { - edgeType.insert(CFG_IndirectEdge); + edgeType.insert(IRDB_SDK::cetIndirectEdge); } return edgeType; @@ -205,50 +205,50 @@ CFG_EdgeType ControlFlowGraph_t::GetEdgeType(const BasicBlock_t *p_src, const Ba /* * output operator */ -ostream& libIRDB::operator<<(ostream& os, const ControlFlowGraph_t& cfg) +ostream& IRDB_SDK::operator<<(ostream& os, const IRDB_SDK::ControlFlowGraph_t& cfg) +{ + cfg.dump(os); + return os; +} + +void ControlFlowGraph_t::dump(ostream& os) const { int i=0; - map<BasicBlock_t*,int> blk_numbers; - for( - set<BasicBlock_t*>::const_iterator it=cfg.blocks.begin(); - it!=cfg.blocks.end(); - ++it - ) + auto blk_numbers = map<IRDB_SDK::BasicBlock_t*,int>(); + for(auto blk : getBlocks() ) { - blk_numbers[*it]=i++; + blk_numbers[blk]=i++; } - for( - set<BasicBlock_t*>::const_iterator it=cfg.blocks.begin(); - it!=cfg.blocks.end(); - ++it - ) + for(auto block : getBlocks()) { - BasicBlock_t *block=*it; - - if(block==cfg.GetEntry()) + if(block==getEntry()) os<<"**** Entry "; else os<<"---- NotEntry "; os<<"block "<<std::dec<<blk_numbers[block]<<endl; os<<"Successors: "; - for_each(block->GetSuccessors().begin(), block->GetSuccessors().end(), [&](BasicBlock_t* succ) + for(auto succ : block->getSuccessors()) { os<<blk_numbers[succ]<<", "; - }); + }; os<<endl; os<<"Predecessors: "; - for_each(block->GetPredecessors().begin(), block->GetPredecessors().end(), [&](BasicBlock_t* pred) + for(auto pred : block->getPredecessors()) { os<<blk_numbers[pred]<<", "; - }); + }; os<<endl; os << *block; } - return os; +} + +unique_ptr<IRDB_SDK::ControlFlowGraph_t> IRDB_SDK::ControlFlowGraph_t::factory(IRDB_SDK::Function_t* func) +{ + return unique_ptr<IRDB_SDK::ControlFlowGraph_t>(new libIRDB::ControlFlowGraph_t(func)); } diff --git a/libIRDB/src/cfg/callgraph.cpp b/libIRDB/src/cfg/callgraph.cpp index e126f5620f99f6150de2d4b360f62df8b5776f62..31f4b036f54b5bd8211bffbb912f06d4b1817080 100644 --- a/libIRDB/src/cfg/callgraph.cpp +++ b/libIRDB/src/cfg/callgraph.cpp @@ -34,12 +34,20 @@ Callgraph_t::Callgraph_t() : { } +unique_ptr<IRDB_SDK::CallGraph_t> IRDB_SDK::CallGraph_t::factory(FileIR_t* const firp) +{ + auto ret=unique_ptr<IRDB_SDK::CallGraph_t>(new libIRDB::Callgraph_t()); + if(firp != nullptr) + ret->addFile(firp); + return ret; +} + + Callgraph_t::~Callgraph_t() { - for (FunctionToCGNodeMap_t::iterator it = nodes.begin(); it != nodes.end(); ++it) + for (auto p : nodes) { - CallGraphNode_t* n = it->second; - delete(n); + delete p.second; } nodes.clear(); } @@ -80,14 +88,14 @@ static bool IsPushJmpSite(Instruction_t* insn) return true; } -void Callgraph_t::MarkCallSite(Instruction_t* insn) +void Callgraph_t::MarkCallSite(IRDB_SDK::Instruction_t* insn) { auto from_func=insn->getFunction(); auto to_insn=insn->getTarget(); auto to_func= to_insn==NULL? NULL : to_insn->getFunction(); - auto from_node = FindNode(from_func); - auto to_node = FindNode(to_func); + auto from_node = findNode(from_func); + auto to_node = findNode(to_func); if (!from_node) from_node = &GetDefaultHellNode(); @@ -114,7 +122,7 @@ void Callgraph_t::CreateNodes(IRDB_SDK::FileIR_t *firp) } } -void Callgraph_t::AddFile(IRDB_SDK::FileIR_t* const firp) +void Callgraph_t::addFile(IRDB_SDK::FileIR_t* const firp) { // Create CG Nodes from functions CreateNodes(firp); @@ -133,7 +141,7 @@ void Callgraph_t::AddFile(IRDB_SDK::FileIR_t* const firp) if(insn->getFunction() && insn->getFunction()->getEntryPoint()==insn && insn->getIndirectBranchTargetAddress()) { - auto node = FindNode(insn->getFunction()); + auto node = findNode(insn->getFunction()); assert(node); callees[&GetDefaultHellNode()].insert(node); callers[node].insert(&GetDefaultHellNode()); @@ -141,43 +149,102 @@ void Callgraph_t::AddFile(IRDB_SDK::FileIR_t* const firp) } } -void Callgraph_t::Dump(std::ostream& fout) + +void Callgraph_t::_GetAncestors(IRDB_SDK::CallGraphNode_t* const node, IRDB_SDK::CallGraphNodeSet_t &ancestors, IRDB_SDK::CallGraphNodeSet_t &visited, bool skipHellNode) const +{ + if (!node || visited.count(node) > 0) + return; + + cerr << "visiting node: " << GetNodeName(node) << " visited(size):" << visited.size() << endl; + + // ancestor-traversal(node X) + // mark X visited + // get parents P of X + // if P[i] not visited: + // add P[i] to ancestors + // ancestor-traversal(P[i]) + + visited.insert(node); + + const auto &directPredecessors = getCallersOfNode(node); + for (const auto pred : directPredecessors ) // it = directPredecessors.begin(); it != directPredecessors.end(); ++it) + { + if (visited.count(pred) == 0) + { + assert(pred); + if (pred->isHellnode() && skipHellNode) continue; + + cerr << "adding " << GetNodeName(pred) << " to ancestor list " << hex << pred << dec << endl; + ancestors.insert(pred); + _GetAncestors(pred, ancestors, visited, skipHellNode); + } + } +} + +IRDB_SDK::CallGraphNode_t* Callgraph_t::findNode(IRDB_SDK::Function_t* const fn) const +{ + auto node_it=nodes.find(fn); + return (node_it==nodes.end()) ? nullptr : node_it->second; +} + +void Callgraph_t::GetAncestors(IRDB_SDK::Function_t* const fn, IRDB_SDK::CallGraphNodeSet_t &ancestors, bool skipHellNode) const +{ + auto node = findNode(fn); + if (node) + GetAncestors(node, ancestors, skipHellNode); +} + +void Callgraph_t::GetAncestors(IRDB_SDK::CallGraphNode_t* const node, IRDB_SDK::CallGraphNodeSet_t &ancestors, bool skipHellNode) const +{ + auto visited=IRDB_SDK::CallGraphNodeSet_t(); + _GetAncestors(node, ancestors, visited, skipHellNode); +} + +bool Callgraph_t::isReachable(IRDB_SDK::CallGraphNode_t* const from, IRDB_SDK::CallGraphNode_t* const to, bool skipHellNode) const +{ + auto ancestors=IRDB_SDK::CallGraphNodeSet_t(); + GetAncestors(to, ancestors, skipHellNode); + return (ancestors.count(from) > 0); +} + +void Callgraph_t::dump(std::ostream& fout) const { fout<<"Dumping callgraph ..."<<endl; fout<<"Mapping one way ..."<<endl; - for(auto it=callees.begin(); callees.end()!=it; ++it) + for(const auto p : callees) // it=callees.begin(); callees.end()!=it; ++it) { - CallGraphNode_t* node = it->first; + // CallGraphNode_t* node = it->first; + // CallGraphNodeSet_t &node_callers=it->second; + const auto node =p.first; + const auto &node_callers=p.second; fout<<"Function "<<GetNodeName(node)<<" calls: "; - CallGraphNodeSet_t &node_callers=it->second; - for(auto it2=node_callers.begin(); node_callers.end()!=it2; ++it2) + for(const auto &the_callee : node_callers) // auto it2=node_callers.begin(); node_callers.end()!=it2; ++it2) { - CallGraphNode_t* the_callee=*it2; + // CallGraphNode_t* the_callee=*it2; fout<<GetNodeName(the_callee)<<", "; } fout<<endl; - for(auto it2=GetCallSites(node).begin(); GetCallSites(node).end() != it2; ++it2) + for(const auto the_call_site : GetCallSites(node)) // auto it2=GetCallSites(node).begin(); GetCallSites(node).end() != it2; ++it2) { - CallSite_t the_call_site=*it2; + // CallSite_t the_call_site=*it2; fout<<"\t"<<GetCallsiteDisassembly(the_call_site)<<endl; } } fout<<"Mapping the other way ..."<<endl; - for(auto it=callers.begin(); callers.end()!=it; ++it) + for(const auto p : callers) // auto it=callers.begin(); callers.end()!=it; ++it) { - CallGraphNode_t* n=it->first; + // CallGraphNode_t* n=it->first; + const auto n =p.first; + const auto &node_callees=p.second; fout<<"Function "<<GetNodeName(n)<<" called by: "; - CallGraphNodeSet_t &node_callees=it->second; - for(CallGraphNodeSet_t::iterator it2=node_callees.begin(); - node_callees.end()!=it2; - ++it2) + for(auto the_caller : node_callees) // CallGraphNodeSet_t::iterator it2=node_callees.begin(); node_callees.end()!=it2; ++it2) { - CallGraphNode_t* the_caller=*it2; + // CallGraphNode_t* the_caller=*it2; fout<<GetNodeName(the_caller)<<", "; } @@ -186,16 +253,16 @@ void Callgraph_t::Dump(std::ostream& fout) fout<<"Printing call sites..."<<endl; - for(auto it=call_sites.begin(); call_sites.end()!=it; ++it) + for(const auto p : call_sites) // auto it=call_sites.begin(); call_sites.end()!=it; ++it) { - auto from_node=it->first; - auto &call_sites_for_func=it->second; + const auto from_node=p.first; + const auto &call_sites_for_func=p.second; fout<<"Call Sites for "<<GetNodeName(from_node)<<": "; - for(auto it2=call_sites_for_func.begin(); call_sites_for_func.end() != it2; ++it2) + for(const auto the_call_site : call_sites_for_func) // auto it2=call_sites_for_func.begin(); call_sites_for_func.end() != it2; ++it2) { - auto the_call_site=*it2; + // auto the_call_site=*it2; fout<<GetCallsiteDisassembly(the_call_site)<<", "; } fout<<endl; @@ -204,58 +271,27 @@ void Callgraph_t::Dump(std::ostream& fout) fout<<"Done!"<<endl; } -void Callgraph_t::_GetAncestors(CallGraphNode_t* const node, CallGraphNodeSet_t &ancestors, CallGraphNodeSet_t &visited, bool skipHellNode) +void CallGraphNode_t::dump(std::ostream& fout) const { - if (!node || visited.count(node) > 0) - return; - -cerr << "visiting node: " << GetNodeName(node) << " visited(size):" << visited.size() << endl; - - // ancestor-traversal(node X) - // mark X visited - // get parents P of X - // if P[i] not visited: - // add P[i] to ancestors - // ancestor-traversal(P[i]) - - visited.insert(node); - - auto directPredecessors = GetCallersOfNode(node); - for (auto it = directPredecessors.begin(); it != directPredecessors.end(); ++it) + if (isHellnode()) { - if (visited.count(*it) == 0) - { - assert(*it); - if ((*it)->IsHellnode() && skipHellNode) continue; - -cerr << "adding " << GetNodeName(*it) << " to ancestor list " << hex << *it << dec << endl; - ancestors.insert(*it); - _GetAncestors(*it, ancestors, visited, skipHellNode); - } + fout << "HELLNODE" << GetHellNodeType(); + } + else + { + assert(getFunction()); + fout << getFunction()->getName(); } } -CallGraphNode_t* Callgraph_t::FindNode(IRDB_SDK::Function_t* const fn) +ostream& IRDB_SDK::operator<<(ostream& os, const IRDB_SDK::CallGraph_t& cg) { - return nodes[fn]; + cg.dump(os); + return os; } - -void Callgraph_t::GetAncestors(IRDB_SDK::Function_t* const fn, CallGraphNodeSet_t &ancestors, bool skipHellNode) +ostream& IRDB_SDK::operator<<(ostream& os, const IRDB_SDK::CallGraphNode_t& cgn) { - auto node = FindNode(fn); - if (node) - GetAncestors(node, ancestors, skipHellNode); + cgn.dump(os); + return os; } -void Callgraph_t::GetAncestors(CallGraphNode_t* const node, CallGraphNodeSet_t &ancestors, bool skipHellNode) -{ - auto visited=CallGraphNodeSet_t(); - _GetAncestors(node, ancestors, visited, skipHellNode); -} - -bool Callgraph_t::Reachable(CallGraphNode_t* const from, CallGraphNode_t* const to, bool skipHellNode) -{ - auto ancestors=CallGraphNodeSet_t(); - GetAncestors(to, ancestors, skipHellNode); - return (ancestors.count(from) > 0); -} diff --git a/libIRDB/src/cfg/criticaledge.cpp b/libIRDB/src/cfg/criticaledge.cpp index d1d58e4e59e7197f5620ffcb168d47080c2e37ca..17011037e6536e3e98532f7aedc993dcbe98ca13 100644 --- a/libIRDB/src/cfg/criticaledge.cpp +++ b/libIRDB/src/cfg/criticaledge.cpp @@ -25,59 +25,66 @@ using namespace std; using namespace libIRDB; -CriticalEdgeAnalyzer_t::CriticalEdgeAnalyzer_t(const ControlFlowGraph_t& p_cfg, const bool p_conservative) : +#define ALLOF(a) begin(a),end(a) + +CriticalEdgeAnalyzer_t::CriticalEdgeAnalyzer_t(const ControlFlowGraph_t* p_cfg, const bool p_conservative) : m_cfg(p_cfg), m_conservative(p_conservative) { + init(); } /* * Critical edge between two nodes is where the source node has multiple successsors, * and the target node has multiple predecessors */ -BasicBlockEdgeSet_t CriticalEdgeAnalyzer_t::GetAllCriticalEdges() const +void CriticalEdgeAnalyzer_t::init() { - BasicBlockEdgeSet_t criticals; - for (const auto &src : m_cfg.GetBlocks()) + for (const auto &src : m_cfg->getBlocks()) { - auto num_successors = src->GetSuccessors().size(); + auto num_successors = src->getSuccessors().size(); if (!m_conservative) { // in aggressive (non conservative) mode, ignore indirect edges // when counting number of successors - num_successors = count_if( - src->GetSuccessors().begin(), src->GetSuccessors().end(), - [&] (const BasicBlock_t* bb_tgt) { - CFG_EdgeType myEdgeType = m_cfg.GetEdgeType(src, bb_tgt); - return myEdgeType.find(CFG_TargetEdge)!=myEdgeType.end() || - myEdgeType.find(CFG_FallthroughEdge)!=myEdgeType.end(); - }); + num_successors = count_if + ( + ALLOF(src->getSuccessors()), + [&] (const IRDB_SDK::BasicBlock_t* bb_tgt) + { + auto myEdgeType = m_cfg->getEdgeType(src, bb_tgt); + return myEdgeType.find(IRDB_SDK::cetTargetEdge)!=myEdgeType.end() || + myEdgeType.find(IRDB_SDK::cetFallthroughEdge)!=myEdgeType.end(); + } + ); } if (num_successors <= 1) continue; - for (const auto &tgt : src->GetSuccessors()) + for (const auto &tgt : src->getSuccessors()) { - auto num_predecessors = tgt->GetPredecessors().size(); + auto num_predecessors = tgt->getPredecessors().size(); if (!m_conservative) { // in aggressive (non conservative) mode, ignore indirect edges // when counting number of predecessors - num_predecessors = count_if( - tgt->GetPredecessors().begin(), tgt->GetPredecessors().end(), - [&] (const BasicBlock_t* bb_pred) { - CFG_EdgeType myEdgeType = m_cfg.GetEdgeType(bb_pred, tgt); - return myEdgeType.find(CFG_TargetEdge)!=myEdgeType.end() || - myEdgeType.find(CFG_FallthroughEdge)!=myEdgeType.end(); - }); + num_predecessors = count_if + ( + ALLOF(tgt->getPredecessors()), + [&] (const IRDB_SDK::BasicBlock_t* bb_pred) + { + auto myEdgeType = m_cfg->getEdgeType(bb_pred, tgt); + return myEdgeType.find(IRDB_SDK::cetTargetEdge)!=myEdgeType.end() || + myEdgeType.find(IRDB_SDK::cetFallthroughEdge)!=myEdgeType.end(); + } + ); } if (num_predecessors > 1) { - BasicBlockEdge_t e(src, tgt); + auto e=IRDB_SDK::BasicBlockEdge_t(src, tgt); criticals.insert(e); } } } - return criticals; } diff --git a/libIRDB/src/cfg/domgraph.cpp b/libIRDB/src/cfg/domgraph.cpp index 228a13673c6a3e97de2302997d6c011108d7086a..5ba6beee3f258edb14c79368e2245d04d3d5d6ae 100644 --- a/libIRDB/src/cfg/domgraph.cpp +++ b/libIRDB/src/cfg/domgraph.cpp @@ -20,13 +20,13 @@ DominatorGraph_t::DominatorGraph_t(const ControlFlowGraph_t* p_cfg, bool needs_p // typedef const BasicBlockSet_t& (*) (const BasicBlock_t* node) pred_func_ptr_t; - pred_func_ptr_t func_get_predecessors=[](const BasicBlock_t* node) -> const BasicBlockSet_t& + pred_func_ptr_t func_get_predecessors=[](const IRDB_SDK::BasicBlock_t* node) -> const IRDB_SDK::BasicBlockSet_t& { - return node->GetPredecessors(); + return node->getPredecessors(); }; - dom_graph=Dom_Comp(p_cfg->GetBlocks(), func_get_predecessors, p_cfg->GetEntry()); - idom_graph=Idom_Comp(p_cfg->GetBlocks(), dom_graph, p_cfg->GetEntry()); + dom_graph=Dom_Comp(p_cfg->getBlocks(), func_get_predecessors, p_cfg->getEntry()); + idom_graph=Idom_Comp(p_cfg->getBlocks(), dom_graph, p_cfg->getEntry()); // a func may have multiple exit nodes. how do we deal with that? // psuedo-block? invoke this for each exit block? @@ -78,7 +78,7 @@ end || Dom_Comp */ -DominatorMap_t DominatorGraph_t::Dom_Comp(const BasicBlockSet_t& N, pred_func_ptr_t get_preds, BasicBlock_t* r) +DominatorMap_t DominatorGraph_t::Dom_Comp(const IRDB_SDK::BasicBlockSet_t& N, pred_func_ptr_t get_preds, IRDB_SDK::BasicBlock_t* r) { /* D, T: set of Node @@ -87,12 +87,12 @@ DominatorMap_t DominatorGraph_t::Dom_Comp(const BasicBlockSet_t& N, pred_func_pt Domin: Node -> set of Node Domin(r) := { r } */ - BasicBlockSet_t D, T; + IRDB_SDK::BasicBlockSet_t D, T; bool change=true; DominatorMap_t Domin; Domin[r].insert(r); - BasicBlockSet_t NminusR=N; + IRDB_SDK::BasicBlockSet_t NminusR=N; NminusR.erase(r); /* @@ -100,10 +100,10 @@ DominatorMap_t DominatorGraph_t::Dom_Comp(const BasicBlockSet_t& N, pred_func_pt Domin(n)={N} od */ - for_each( NminusR.begin(), NminusR.end(), [&](BasicBlock_t* n) + for( auto n : NminusR) { Domin[n]=N; - }); + }; /* repeat @@ -114,7 +114,7 @@ DominatorMap_t DominatorGraph_t::Dom_Comp(const BasicBlockSet_t& N, pred_func_pt /* for each n \in N - {r} do */ - for_each(NminusR.begin(), NminusR.end(), [&](BasicBlock_t* n) + for( auto n : NminusR) { /* T := N */ T=N; @@ -124,13 +124,13 @@ DominatorMap_t DominatorGraph_t::Dom_Comp(const BasicBlockSet_t& N, pred_func_pt T = T intersect Domin(p) done */ - for_each(get_preds(n).begin(), get_preds(n).end(), [&](const BasicBlock_t* p) + for(auto p : get_preds(n) ) { - BasicBlockSet_t tmp; + IRDB_SDK::BasicBlockSet_t tmp; set_intersection(T.begin(), T.end(), Domin[p].begin(), Domin[p].end(), inserter(tmp,tmp.begin())); T=tmp; - }); + }; /* D = {n} union T */ @@ -148,7 +148,7 @@ DominatorMap_t DominatorGraph_t::Dom_Comp(const BasicBlockSet_t& N, pred_func_pt change=true; // keep trying Domin[n]=D; } - }); + }; /* done until ! change @@ -164,7 +164,7 @@ DominatorMap_t DominatorGraph_t::Dom_Comp(const BasicBlockSet_t& N, pred_func_pt { assert(blk); const BasicBlockSet_t& blk_dominates=Domin[blk]; - Instruction_t* first_insn=*(blk->GetInstructions().begin()); + Instruction_t* first_insn=*(blk->getInstructions().begin()); assert(first_insn); #if 1 cout<<"\tBlock " <<endl<<*blk<<endl; @@ -215,7 +215,7 @@ end || IDom_Comp -BlockToBlockMap_t DominatorGraph_t::Idom_Comp(const BasicBlockSet_t& N, const DominatorMap_t &Domin, BasicBlock_t* r) +BlockToBlockMap_t DominatorGraph_t::Idom_Comp(const IRDB_SDK::BasicBlockSet_t& N, const DominatorMap_t &Domin, IRDB_SDK::BasicBlock_t* r) { // n, s, t: Node //BasicBlock_t* n=NULL, *s=NULL, *t=NULL; @@ -228,30 +228,32 @@ BlockToBlockMap_t DominatorGraph_t::Idom_Comp(const BasicBlockSet_t& N, const Do // calculate this set as we use it several times - BasicBlockSet_t NminusR = N; + IRDB_SDK::BasicBlockSet_t NminusR = N; NminusR.erase(r); // for each n \in N do - for_each( N.begin(), N.end(), [&](BasicBlock_t* n) + for(auto n : N) { //Tmp(n) := Domin(n) - {n} Tmp[n] = Domin.at(n); Tmp[n].erase(n); // od - }); + }; //for each n \in N - {r} do - for_each( NminusR.begin(), NminusR.end(), [&]( BasicBlock_t* n) + for(auto n : NminusR) { // for each s \in Tmp(n) do auto Tmp_n=Tmp[n]; - for_each( Tmp_n.begin(), Tmp_n.end(), [&]( BasicBlock_t* s) + // for_each( Tmp_n.begin(), Tmp_n.end(), [&]( BasicBlock_t* s) + for (auto s : Tmp_n) { //for each t \in Tmp(n) - {s} do - for_each( Tmp_n.begin(), Tmp_n.end(), [&]( BasicBlock_t* t) + // for_each( Tmp_n.begin(), Tmp_n.end(), [&]( BasicBlock_t* t) + for (auto t : Tmp_n) { // quickly do Tmp(n)-s if(t != s) @@ -263,48 +265,54 @@ BlockToBlockMap_t DominatorGraph_t::Idom_Comp(const BasicBlockSet_t& N, const Do Tmp[n].erase(t); } } - }); - }); - }); + }; + }; + }; //for each n \in N-{r} do - for_each( NminusR.begin(), NminusR.end(), [&](BasicBlock_t* n) + for (auto n : NminusR) { //IDom(n) = <only element in>Tmp(n) IDom[n]= *(Tmp[n].begin()); if(Tmp[n].size()!=1) // should only be one idominator. warn=true; - }); + }; return IDom; } // IDom_Comp -ostream& libIRDB::operator<<(ostream& os, const DominatorGraph_t& dg) +ostream& IRDB_SDK::operator<<(ostream& os, const DominatorGraph_t& dg) +{ + dg.dump(os); + return os; +} + +void DominatorGraph_t::dump(ostream& os) const { - for_each(dg.cfg.GetBlocks().begin(), dg.cfg.GetBlocks().end(), [&](const BasicBlock_t* blk) + // for_each(dg.cfg.GetBlocks().begin(), dg.cfg.GetBlocks().end(), [&](const BasicBlock_t* blk) + for(auto blk : cfg.getBlocks()) { assert(blk); - const BasicBlockSet_t& blk_dominates=dg.GetDominators(blk); - auto first_insn=*(blk->GetInstructions().begin()); + const auto& blk_dominates=getDominators(blk); + auto first_insn=*(blk->getInstructions().begin()); assert(first_insn); - os<<"\tBlock entry id:" <<blk->GetInstructions()[0]->getBaseID()<<endl; + os<<"\tBlock entry id:" <<blk->getInstructions()[0]->getBaseID()<<endl; os<<"\t\tDominated by: "; - for_each(blk_dominates.begin(), blk_dominates.end(), [&os](const BasicBlock_t* dom) + for(auto dom : blk_dominates) { - os<<dom->GetInstructions()[0]->getBaseID()<<", "; - }); + os<<dom->getInstructions()[0]->getBaseID()<<", "; + }; os<<endl; - const BasicBlock_t* idom=dg.GetImmediateDominator(blk); + const IRDB_SDK::BasicBlock_t* idom=getImmediateDominator(blk); if(idom) - os<<"\t\tImmediate Dominator: "<<hex<<idom->GetInstructions()[0]->getBaseID()<<endl; + os<<"\t\tImmediate Dominator: "<<hex<<idom->getInstructions()[0]->getBaseID()<<endl; else os<<"\t\tNo Immed Dominator."<<endl; - }); + }; - return os; }