From 803a17402a2e18b028b632f7d68ca45155c09007 Mon Sep 17 00:00:00 2001 From: jdh8d <jdh8d@git.zephyr-software.com> Date: Thu, 2 Jun 2016 20:00:55 +0000 Subject: [PATCH] working on building dominators and post dominators Former-commit-id: 4acf40b8c0d0c8ddfa78dc5d338bd79c7b0d556a --- .gitattributes | 1 + libIRDB/include/cfg/BasicBlock.hpp | 8 ++++- libIRDB/include/cfg/CFG.hpp | 1 + libIRDB/include/cfg/domgraph.hpp | 50 ++++++++++++++++++++++++++++ libIRDB/include/libIRDB-cfg.hpp | 1 + libIRDB/src/cfg/BasicBlock.cpp | 53 ++++++++++++++++++++++++++++-- libIRDB/src/cfg/CFG.cpp | 29 +++++++++++++--- libIRDB/src/cfg/SConscript | 3 +- libIRDB/test/fix_calls.cpp | 9 +++++ 9 files changed, 146 insertions(+), 9 deletions(-) create mode 100644 libIRDB/include/cfg/domgraph.hpp diff --git a/.gitattributes b/.gitattributes index 5d6462a71..ce4a0f652 100644 --- a/.gitattributes +++ b/.gitattributes @@ -204,6 +204,7 @@ libIRDB/SConstruct -text libIRDB/include/cfg/BasicBlock.hpp -text libIRDB/include/cfg/CFG.hpp -text libIRDB/include/cfg/callgraph.hpp -text +libIRDB/include/cfg/domgraph.hpp -text libIRDB/include/core/address.hpp -text libIRDB/include/core/archdesc.hpp -text libIRDB/include/core/baseobj.hpp -text diff --git a/libIRDB/include/cfg/BasicBlock.hpp b/libIRDB/include/cfg/BasicBlock.hpp index bd61587db..340c9d697 100644 --- a/libIRDB/include/cfg/BasicBlock.hpp +++ b/libIRDB/include/cfg/BasicBlock.hpp @@ -36,9 +36,15 @@ class BasicBlock_t BasicBlockSet_t& GetPredecessors() { return predecessors; } BasicBlockSet_t& GetSuccessors() { return successors; } BasicBlockSet_t& GetIndirectTargets() { return indirect_targets; } - BasicBlock_t* GetFallthrough(); BasicBlock_t* GetTarget(); + + // 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; } + bool EndsInBranch(); bool EndsInIndirectBranch(); bool EndsInConditionalBranch(); diff --git a/libIRDB/include/cfg/CFG.hpp b/libIRDB/include/cfg/CFG.hpp index afb0e63bb..532570be5 100644 --- a/libIRDB/include/cfg/CFG.hpp +++ b/libIRDB/include/cfg/CFG.hpp @@ -42,6 +42,7 @@ class ControlFlowGraph_t public: friend std::ostream& operator<<(std::ostream& os, const ControlFlowGraph_t& cfg); BasicBlockSet_t& GetBlocks() { return blocks; } + const BasicBlockSet_t& GetBlocks() const { return blocks; } }; diff --git a/libIRDB/include/cfg/domgraph.hpp b/libIRDB/include/cfg/domgraph.hpp new file mode 100644 index 000000000..d5de10e5e --- /dev/null +++ b/libIRDB/include/cfg/domgraph.hpp @@ -0,0 +1,50 @@ + + + +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); } + + + // get the immeidate (post) dominators for a node + const BasicBlock_t* GetImmediateDominator(const BasicBlock_t* node) const + { auto it=idom_graph.find(node); return (it!=idom_graph.end()) ? it->second : NULL; } + const BasicBlock_t* GetImmediatePostDominators(const BasicBlock_t* node) const + { auto 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. + + 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 6cfc423df..1a720ec61 100644 --- a/libIRDB/include/libIRDB-cfg.hpp +++ b/libIRDB/include/libIRDB-cfg.hpp @@ -36,6 +36,7 @@ namespace libIRDB #include <cfg/BasicBlock.hpp> #include <cfg/CFG.hpp> #include <cfg/callgraph.hpp> +#include <cfg/domgraph.hpp> }; diff --git a/libIRDB/src/cfg/BasicBlock.cpp b/libIRDB/src/cfg/BasicBlock.cpp index 8cf835061..f45440423 100644 --- a/libIRDB/src/cfg/BasicBlock.cpp +++ b/libIRDB/src/cfg/BasicBlock.cpp @@ -69,6 +69,35 @@ void BasicBlock_t::BuildBlock successors.insert(target_block); } + /* This is also the end of the block if this is a function exit instruction */ + if(insn->IsFunctionExit()) + { + is_exit_block=true; + } + + // handle fixed-call fallthroughs. + for_each(insn->GetRelocations().begin(), insn->GetRelocations().end(), [this,&insn2block_map](Relocation_t* reloc) + { + /* and has a reloc that's a pcrel with a WRT object */ + if( reloc->GetType()==string("fix_call_fallthrough")) + { + assert(reloc->GetWRT()!=NULL); + Instruction_t* fix_call_fallthrough_insn=dynamic_cast<Instruction_t*>(reloc->GetWRT()); + assert(fix_call_fallthrough_insn); + + // this block has a fallthrough to the return block. + if(is_in_container(insn2block_map,fix_call_fallthrough_insn)) + { + BasicBlock_t* fix_call_fallthrough_blk=find_map_object(insn2block_map,fix_call_fallthrough_insn); + successors.insert(fix_call_fallthrough_blk); + fix_call_fallthrough_blk->GetPredecessors().insert(this); + } + + is_exit_block=false; + } + }); + + /* if there's a fallthrough block, insert it into the appropriate sets */ if(ft_block) { @@ -81,16 +110,34 @@ void BasicBlock_t::BuildBlock break; /* or if there is a fallthrough block already built */ - if(target_insn || ft_block) + if(ft_block) break; - /* This is also the end of the block if this is a function exit instruction */ - if(insn->IsFunctionExit()) + /* check for a fallthrough out of the function */ + if(ft_insn && !is_in_container(func->GetInstructions(),ft_insn)) break; + /* otherwise, move to the fallthrough */ insn=ft_insn; } + + // deal with IB targets for the end of the block + + insn=instructions[instructions.size()-1]; // get last instruction. + assert(insn); + if(insn->GetIBTargets()) + { + for_each(insn->GetIBTargets()->begin(), insn->GetIBTargets()->end(), [this,&insn2block_map,func](Instruction_t* target) + { + if(is_in_container(insn2block_map,target) && target!=func->GetEntryPoint()) // don't link calls to the entry block. + { + BasicBlock_t* target_block=find_map_object(insn2block_map,target); + target_block->GetPredecessors().insert(this); + successors.insert(target_block); + } + }); + } } diff --git a/libIRDB/src/cfg/CFG.cpp b/libIRDB/src/cfg/CFG.cpp index 3203c947c..2e1b80c83 100644 --- a/libIRDB/src/cfg/CFG.cpp +++ b/libIRDB/src/cfg/CFG.cpp @@ -139,7 +139,18 @@ void ControlFlowGraph_t::Build(Function_t* func) ostream& libIRDB::operator<<(ostream& os, const ControlFlowGraph_t& cfg) { int i=0; + + map<BasicBlock_t*,int> blk_numbers; + for( + set<BasicBlock_t*>::const_iterator it=cfg.blocks.begin(); + it!=cfg.blocks.end(); + ++it + ) + { + blk_numbers[*it]=i++; + } + for( set<BasicBlock_t*>::const_iterator it=cfg.blocks.begin(); it!=cfg.blocks.end(); @@ -152,11 +163,21 @@ ostream& libIRDB::operator<<(ostream& os, const ControlFlowGraph_t& cfg) os<<"**** Entry "; else os<<"---- NotEntry "; - os<<"block "<<std::dec<<i<<endl; - i++; - + os<<"block "<<std::dec<<blk_numbers[block]<<endl; + os<<"Successors: "; + for_each(block->GetSuccessors().begin(), block->GetSuccessors().end(), [&](BasicBlock_t* succ) + { + os<<blk_numbers[succ]<<", "; + + }); + os<<endl; + os<<"Predecessors: "; + for_each(block->GetPredecessors().begin(), block->GetPredecessors().end(), [&](BasicBlock_t* pred) + { + os<<blk_numbers[pred]<<", "; + }); + os<<endl; os << *block; - } return os; diff --git a/libIRDB/src/cfg/SConscript b/libIRDB/src/cfg/SConscript index ad91f9943..572af8276 100644 --- a/libIRDB/src/cfg/SConscript +++ b/libIRDB/src/cfg/SConscript @@ -8,7 +8,7 @@ myenv.Replace(SECURITY_TRANSFORMS_HOME=os.environ['SECURITY_TRANSFORMS_HOME']) libname="IRDB-cfg" files= ''' - BasicBlock.cpp callgraph.cpp CFG.cpp + BasicBlock.cpp callgraph.cpp CFG.cpp domgraph.cpp ''' cpppath=''' $SECURITY_TRANSFORMS_HOME/include/ @@ -18,6 +18,7 @@ cpppath=''' ''' #myenv.Append(CCFLAGS=" -Wall -W -Wextra -Wconversion ") +myenv.Append(CCFLAGS=" -Wall -W -Wextra -Wconversion -std=c++11") myenv=myenv.Clone(CPPPATH=Split(cpppath)) lib=myenv.Library(libname, Split(files)) diff --git a/libIRDB/test/fix_calls.cpp b/libIRDB/test/fix_calls.cpp index 533dc8889..b96895c2e 100644 --- a/libIRDB/test/fix_calls.cpp +++ b/libIRDB/test/fix_calls.cpp @@ -677,6 +677,15 @@ void fix_call(Instruction_t* insn, FileIR_t *firp, bool can_unpin) } } + + // mark in the IR what the fallthrough of this insn is. + Relocation_t* fix_call_reloc=new Relocation_t(); + fix_call_reloc->SetOffset(0); + fix_call_reloc->SetType("fix_call_fallthrough"); + fix_call_reloc->SetWRT(newindirtarg); + callinsn->GetRelocations().insert(fix_call_reloc); + firp->GetRelocations().insert(fix_call_reloc); + } -- GitLab