diff --git a/SMPStaticAnalyzer b/SMPStaticAnalyzer index 26497da37ca82c270e44546d729d66ca0b83a4fa..37851eabacb015faecf0ef92f334b7176165c8b3 160000 --- a/SMPStaticAnalyzer +++ b/SMPStaticAnalyzer @@ -1 +1 @@ -Subproject commit 26497da37ca82c270e44546d729d66ca0b83a4fa +Subproject commit 37851eabacb015faecf0ef92f334b7176165c8b3 diff --git a/irdb-libs/ir_builders/fill_in_cfg.cpp b/irdb-libs/ir_builders/fill_in_cfg.cpp index e1f694fd28c7b84093a4cb5f31aa897de958cf8d..8e131c6b5b1dc0e84669bb9755ba2cdd9518fa83 100644 --- a/irdb-libs/ir_builders/fill_in_cfg.cpp +++ b/irdb-libs/ir_builders/fill_in_cfg.cpp @@ -664,15 +664,16 @@ void PopulateCFG::ctor_detection(FileIR_t *firp) auto find_ctor_start=[&](const exeio_section_t* sec, const VirtualOffset_t end_of_ctor) -> VirtualOffset_t { // values needed later for various things - const auto ptrsize = 8; + const auto ptrsize = firp->getArchitectureBitWidth() / 8 ; const auto sec_data = sec->get_data(); const auto sec_start = sec->get_address(); // check for a null terminator at the stated end of table const auto null_term_addr=end_of_ctor-ptrsize; - const auto null_term_value= + const auto null_term_value = ptrsize == 8 ? *(uint64_t*)(sec_data+null_term_addr-sec_start) : - throw invalid_argument("Unknown ptrsize"); + ptrsize == 4 ? *(uint32_t*)(sec_data+null_term_addr-sec_start) : + throw invalid_argument("Unknown ptrsize"); // not found, return this isn't sane. if(null_term_value!=0) return 0; @@ -685,12 +686,14 @@ void PopulateCFG::ctor_detection(FileIR_t *firp) if(next_addr<sec_start) return 0; // get the table entry - const auto ctor_entry_value= + const auto ctor_entry_value = ptrsize == 8 ? *(uint64_t*)(sec_data+next_addr-sec_start) : - throw invalid_argument("Unknown ptrsize"); + ptrsize == 4 ? *(uint32_t*)(sec_data+next_addr-sec_start) : + throw invalid_argument("Unknown ptrsize"); // check for the -1 terminator - if((int64_t)ctor_entry_value==int64_t(-1)) return next_addr; + if(ptrsize == 8 && (int64_t)ctor_entry_value==int64_t(-1)) return next_addr; + if(ptrsize == 4 && (int32_t)ctor_entry_value==int32_t(-1)) return next_addr; // check if the table entry isn't a valid address const auto is_before_start = ctor_entry_value < sec->get_address() ; @@ -718,6 +721,7 @@ void PopulateCFG::ctor_detection(FileIR_t *firp) // finally, create the new scoop firp->addNewDataScoop( name, startaddr, endaddr, NULL, permissions, is_relro, the_contents); + cout << "Added ctor/dtor scoop called " << name << " at " << hex << start_vo << "-" << end_vo << endl; }; const auto text_sec = exeiop->sections[".text"]; diff --git a/irdb-libs/ir_builders/fill_in_indtargs.cpp b/irdb-libs/ir_builders/fill_in_indtargs.cpp index b13d9c2228e26c98a62176226b15c1fd3d6a996f..e8a27bd8085cbef7a199dd02df69aa487796bfed 100644 --- a/irdb-libs/ir_builders/fill_in_indtargs.cpp +++ b/irdb-libs/ir_builders/fill_in_indtargs.cpp @@ -479,6 +479,21 @@ void handle_scoop_scanning(FileIR_t* firp) // check for addresses in scoops in the text section. for(auto scoop : firp->getDataScoops()) { + if(scoop->getName() == ".ctor" || scoop->getName() == ".dtor" ) + { + const auto ptrsize = firp->getArchitectureBitWidth() / 8 ; + const auto &scoop_contents = scoop->getContents(); + for(auto i = 0u; i + ptrsize < scoop_contents.size(); i += ptrsize) + { + const auto ptr = + ptrsize == 8 ? *reinterpret_cast<const uint64_t*>(scoop_contents.c_str() + i) : + ptrsize == 4 ? *reinterpret_cast<const uint32_t*>(scoop_contents.c_str() + i) : + throw invalid_argument("Cannot map ptrsize to deref type"); + possible_target(ptr, scoop->getStart()->getVirtualOffset() + i, ibt_provenance_t::ibtp_data); + } + + } + // test if scoop was added by fill_in_cfg -- make this test better. if(scoop->getName().find("data_in_text_")==string::npos) continue; @@ -547,113 +562,6 @@ set<Instruction_t*> find_in_function(string needle, Function_t *haystack) } -#if 0 -bool backup_until(const string &insn_type_regex_str, - Instruction_t *& prev, - Instruction_t* orig, - const string & stop_if_set="", - bool recursive=false, - uint32_t max_insns=10000u, - uint32_t max_recursions=5u) -{ - - const auto find_or_build_regex=[&] (const string& s) -> regex_t& - { - // declare a freer for regexs so they go away when the program ends. - const auto regex_freer=[](regex_t* to_free) -> void - { - regfree(to_free); - delete to_free; - }; - // keep the map safe from anyone but me using it. - using regex_unique_ptr_t=unique_ptr<regex_t, decltype(regex_freer)>; - static map<string, regex_unique_ptr_t > regexs_used; - - if(s=="") - { - static regex_t empty; - return empty; - } - const auto it=regexs_used.find(s); - if(it==regexs_used.end()) - { - // allocate a new regex ptr - regexs_used.insert(pair<string,regex_unique_ptr_t>(s,move(regex_unique_ptr_t(new regex_t, regex_freer)))); - // and compile it. - auto ®ex_ptr=regexs_used.at(s); - const auto ret=regcomp(regex_ptr.get(), s.c_str(), REG_EXTENDED); - // error check - assert(ret==0); - } - return *regexs_used.at(s).get(); - }; - - - // build regexs. - const auto &preg = find_or_build_regex(insn_type_regex_str); - const auto &stop_expression = find_or_build_regex(stop_if_set); - - - prev=orig; - while(preds[prev].size()==1 && max_insns > 0) - { - // dec max for next loop - max_insns--; - - // get the only item in the list. - prev=*(preds[prev].begin()); - - - // get I7's disassembly - const auto disasm=DecodedInstruction_t::factory(prev); - - // check it's the requested type - if(regexec(&preg, disasm->getDisassembly().c_str(), 0, nullptr, 0) == 0) - return true; - - if(stop_if_set!="") - { - for(const auto operand : disasm->getOperands()) - { - if(operand->isWritten() && regexec(&stop_expression, operand->getString().c_str(), 0, nullptr, 0) == 0) - return false; - } - } - - // otherwise, try backing up again. - } - if(recursive && max_insns > 0 && max_recursions > 0 ) - { - const auto myprev=prev; - // can't just use prev because recursive call will update it. - const auto &mypreds=preds[myprev]; - for(const auto pred : mypreds) - { - prev=pred;// mark that we are here, in case we return true here. - const auto disasm=DecodedInstruction_t::factory(pred); - // check it's the requested type - if(regexec(&preg, disasm->getDisassembly().c_str(), 0, nullptr, 0) == 0) - return true; - if(stop_if_set!="") - { - for(const auto operand : disasm->getOperands()) - { - if(operand->isWritten() && regexec(&stop_expression, operand->getString().c_str(), 0, nullptr, 0) == 0) - return false; - } - } - if(backup_until(insn_type_regex_str, prev, pred, stop_if_set, recursive, max_insns, max_recursions/mypreds.size())) - return true; - - // reset for next call - prev=myprev; - } - } - return false; -} -#endif - - void check_for_arm32_switch_type1( FileIR_t *firp, Instruction_t* insn, @@ -4058,16 +3966,6 @@ set<VirtualOffset_t> forced_pins; int parseArgs(const vector<string> step_args) { - -#if 0 - if(step_args.size()<1) - { - cerr<<"Usage: <id> [--[no-]split-eh-frame] [--[no-]unpin] [addr,...]"<<endl; - exit(-1); - } -#endif - - // variant_id=stoi(step_args[0]); cout<<"Parsing parameters with argc= " << step_args.size()<<endl; // parse dash-style options. diff --git a/irdb-libs/libIRDB-cfg/include/domgraph.hpp b/irdb-libs/libIRDB-cfg/include/domgraph.hpp index db37459ae80730a03cc2a15e599ba5b8003d5a72..b7fb70b29ba986ead40f2a5502b02a36d8682f4f 100644 --- a/irdb-libs/libIRDB-cfg/include/domgraph.hpp +++ b/irdb-libs/libIRDB-cfg/include/domgraph.hpp @@ -51,8 +51,8 @@ namespace libIRDB using pred_func_ptr_t = const IRDB_SDK::BasicBlockSet_t& (*) (const IRDB_SDK::BasicBlock_t* node); - 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_Comp(const IRDB_SDK::BasicBlockVector_t& N, pred_func_ptr_t pred_func, IRDB_SDK::BasicBlock_t* r); + BlockToBlockMap_t Idom_Comp(const IRDB_SDK::BasicBlockVector_t& N, const DominatorMap_t &Domin, IRDB_SDK::BasicBlock_t* r); DominatorMap_t dom_graph; diff --git a/irdb-libs/libIRDB-cfg/src/SConscript b/irdb-libs/libIRDB-cfg/src/SConscript index cb08c53f8c8a1a5c37f4e1c1247a591fdda427e5..17ecf7b5232a4fb6214c975845070e75f0983216 100644 --- a/irdb-libs/libIRDB-cfg/src/SConscript +++ b/irdb-libs/libIRDB-cfg/src/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 domgraph.cpp criticaledge.cpp + BasicBlock.cpp callgraph.cpp CFG.cpp domgraph.cpp criticaledge.cpp dfs.cpp ''' cpppath=''' $IRDB_SDK/include/ diff --git a/irdb-libs/libIRDB-cfg/src/dfs.cpp b/irdb-libs/libIRDB-cfg/src/dfs.cpp new file mode 100644 index 0000000000000000000000000000000000000000..b8d28a26022eb84521bbe83a18645efa15f0de9c --- /dev/null +++ b/irdb-libs/libIRDB-cfg/src/dfs.cpp @@ -0,0 +1,49 @@ + + +#include <irdb-core> +#include <irdb-cfg> +#include <vector> + +using namespace IRDB_SDK; + +using VisitedMap_t = map<BasicBlock_t*,bool> ; + +static void doDFS(BasicBlockVector_t &order, VisitedMap_t &visited, BasicBlock_t* node) +{ + // visit this node + visited[node]=true; + order.push_back(node); + + // visit each successor + for(auto successor : node->getSuccessors()) + { + if(!visited[successor]) + doDFS(order,visited,successor); + } + +} + +BasicBlockVector_t IRDB_SDK::getDFSOrder(ControlFlowGraph_t* cfg) +{ + assert(cfg!=nullptr); + + auto ret = BasicBlockVector_t(); + ret.reserve(cfg->getBlocks().size()); + auto visited = VisitedMap_t(); + + // explicitly fill the map with falses. + for(auto& node : cfg->getBlocks()) + visited[node]=false; + + doDFS(ret,visited,cfg->getEntry()); + + // for each node in the map + for(auto &p : visited) + // if it's not visited + if(p.second == false) + // that means it appeared unreachable from the entry block + // add it to the dfs end. + ret.push_back(p.first); + + return move(ret); +} diff --git a/irdb-libs/libIRDB-cfg/src/domgraph.cpp b/irdb-libs/libIRDB-cfg/src/domgraph.cpp index 9c90080ba77618dcb5866ba43fdd940c1b1d9a93..714c78de800488c163613bd1067d06365c5971c4 100644 --- a/irdb-libs/libIRDB-cfg/src/domgraph.cpp +++ b/irdb-libs/libIRDB-cfg/src/domgraph.cpp @@ -44,20 +44,18 @@ inline S const& find_map_object( const std::map< T , S > &a_map, const T& key) DominatorGraph_t::DominatorGraph_t(const ControlFlowGraph_t* p_cfg, bool needs_postdoms, bool needs_idoms) : cfg(*p_cfg), warn(false) { - auto &blocks=p_cfg->getBlocks(); - - assert(needs_postdoms==false); assert(needs_idoms==false); + const auto dfs_order = getDFSOrder(const_cast<ControlFlowGraph_t*>(p_cfg)); pred_func_ptr_t func_get_predecessors=[](const IRDB_SDK::BasicBlock_t* node) -> const IRDB_SDK::BasicBlockSet_t& { return node->getPredecessors(); }; - dom_graph=Dom_Comp(blocks, func_get_predecessors, p_cfg->getEntry()); - idom_graph=Idom_Comp(blocks, dom_graph, p_cfg->getEntry()); + dom_graph = Dom_Comp(dfs_order, func_get_predecessors, p_cfg->getEntry()); + idom_graph = Idom_Comp(dfs_order, dom_graph, p_cfg->getEntry()); Dominated_Compute(); @@ -111,7 +109,7 @@ end || Dom_Comp */ -DominatorMap_t DominatorGraph_t::Dom_Comp(const IRDB_SDK::BasicBlockSet_t& N, pred_func_ptr_t get_preds, IRDB_SDK::BasicBlock_t* r) +DominatorMap_t DominatorGraph_t::Dom_Comp(const IRDB_SDK::BasicBlockVector_t& N, pred_func_ptr_t get_preds, IRDB_SDK::BasicBlock_t* r) { /* D, T: set of Node @@ -125,17 +123,15 @@ DominatorMap_t DominatorGraph_t::Dom_Comp(const IRDB_SDK::BasicBlockSet_t& N, pr DominatorMap_t Domin; Domin[r].insert(r); - IRDB_SDK::BasicBlockSet_t NminusR=N; - NminusR.erase(r); - /* for each n \in N - {r} do Domin(n)={N} od */ - for( auto n : NminusR) + for( const auto &n : N) { - Domin[n]=N; + if(n==r) continue; + Domin[n]=IRDB_SDK::BasicBlockSet_t(ALLOF(N)); }; /* @@ -147,17 +143,18 @@ DominatorMap_t DominatorGraph_t::Dom_Comp(const IRDB_SDK::BasicBlockSet_t& N, pr /* for each n \in N - {r} do */ - for( auto n : NminusR) + for( const auto &n : N) { + if(n == r) continue; /* T := N */ - T=N; + T = IRDB_SDK::BasicBlockSet_t(ALLOF(N)); /* for each p \in Pred(n) do T = T intersect Domin(p) done */ - for(auto p : get_preds(n) ) + for(const auto &p : get_preds(n) ) { IRDB_SDK::BasicBlockSet_t tmp; set_intersection(T.begin(), T.end(), Domin[p].begin(), Domin[p].end(), inserter(tmp,tmp.begin())); @@ -248,21 +245,20 @@ end || IDom_Comp -BlockToBlockMap_t DominatorGraph_t::Idom_Comp(const IRDB_SDK::BasicBlockSet_t& N, const DominatorMap_t &Domin, IRDB_SDK::BasicBlock_t* r) +BlockToBlockMap_t DominatorGraph_t::Idom_Comp(const IRDB_SDK::BasicBlockVector_t& N, const DominatorMap_t &Domin, IRDB_SDK::BasicBlock_t* r) { // n, s, t: Node - //BasicBlock_t* n=NULL, *s=NULL, *t=NULL; + const auto verbose=false; // Tmp: Node -> set of Node - DominatorMap_t Tmp; + auto Tmp = DominatorMap_t(); // IDom: Node->Node - BlockToBlockMap_t IDom; - + auto IDom = BlockToBlockMap_t() ; - // calculate this set as we use it several times - IRDB_SDK::BasicBlockSet_t NminusR = N; - NminusR.erase(r); + auto tmp_n_total_size = 0u; + auto inner_total = 0u; + auto inner_checks = 0u; // for each n \in N do @@ -271,15 +267,22 @@ BlockToBlockMap_t DominatorGraph_t::Idom_Comp(const IRDB_SDK::BasicBlockSet_t& N //Tmp(n) := Domin(n) - {n} Tmp[n] = Domin.at(n); Tmp[n].erase(n); + tmp_n_total_size += Tmp[n].size(); // od - }; + } + + if(verbose) + cout << "Average size of Tmp[n] = " << tmp_n_total_size / Tmp.size() << endl; //for each n \in N - {r} do - for(auto n : NminusR) + for(auto n : N) { + if( n == r) continue; + // for each s \in Tmp(n) do auto Tmp_n=Tmp[n]; + // for_each( Tmp_n.begin(), Tmp_n.end(), [&]( BasicBlock_t* s) for (auto s : Tmp_n) { @@ -292,20 +295,29 @@ BlockToBlockMap_t DominatorGraph_t::Idom_Comp(const IRDB_SDK::BasicBlockSet_t& N if(t != s) { //if t \in Tmp(s) then + inner_checks ++; if( is_in_container(Tmp[s],t)) { //Tmp(n) -= {t} - Tmp[n].erase(t); + Tmp[n].erase(t); + inner_total ++; } } }; }; }; + if(verbose) + { + cout << "Inner checks = " << inner_checks << endl; + cout << "Inner total = " << inner_total << endl; + } //for each n \in N-{r} do - for (auto n : NminusR) + for (auto n : N) { + if(n == r) continue; + //IDom(n) = <only element in>Tmp(n) IDom[n]= *(Tmp[n].begin()); if(Tmp[n].size()!=1) // should only be one idominator. diff --git a/irdb-libs/libehp b/irdb-libs/libehp index 173beca81faecfed391fa4c6c881ccf8f49c002c..2991595bd58c79ea894e3cce25b3e67ad02bb99b 160000 --- a/irdb-libs/libehp +++ b/irdb-libs/libehp @@ -1 +1 @@ -Subproject commit 173beca81faecfed391fa4c6c881ccf8f49c002c +Subproject commit 2991595bd58c79ea894e3cce25b3e67ad02bb99b diff --git a/irdb-sdk b/irdb-sdk index 3267ac26338c701dffa3267da6c6ca15475b4999..f2ad120cbf9fa7d965288472b67cecb197bb5a12 160000 --- a/irdb-sdk +++ b/irdb-sdk @@ -1 +1 @@ -Subproject commit 3267ac26338c701dffa3267da6c6ca15475b4999 +Subproject commit f2ad120cbf9fa7d965288472b67cecb197bb5a12