boost::tuple<Instruction::Ptr, Instruction::Ptr, bool> IA_x86Details::findMaxSwitchInsn(Block *start) { std::set<Block *> visited; std::vector<Block *> WL; Block *curBlk; int depth = 0; bool foundMaxSwitch = false; bool foundCondBranch = false; WL.push_back(start); Instruction::Ptr compareInsn, condBranchInsn; bool compareOnTakenBranch = false; for(unsigned j=0;j < WL.size(); j++) { curBlk = WL[j]; visited.insert(curBlk); foundMaxSwitch = false; foundCondBranch = false; const unsigned char* buf = (const unsigned char*)(currentBlock->_isrc->getPtrToInstruction(curBlk->start())); if( buf == NULL ) { parsing_printf("%s[%d]: failed to get pointer to instruction by offset\n", FILE__, __LINE__); return boost::make_tuple(Instruction::Ptr(), Instruction::Ptr(), false); } InstructionDecoder dec(buf, curBlk->size(), currentBlock->_isrc->getArch()); Instruction::Ptr i; Address curAdr = curBlk->start(); while((i = dec.decode())) { if(i->getCategory() == c_CompareInsn) // check for cmp { parsing_printf("\tFound jmp table cmp instruction %s at 0x%lx\n", i->format().c_str(), curAdr); compareInsn = i; foundMaxSwitch = true; } if(i->getCategory() == c_BranchInsn && i->allowsFallThrough()) { parsing_printf("\tFound jmp table cond br instruction %s at 0x%lx\n", i->format().c_str(), curAdr); condBranchInsn = i; foundCondBranch = true; Block::edgelist::const_iterator tit = curBlk->targets().begin(); bool taken_hit = false; bool fallthrough_hit = false; for ( ; tit != curBlk->targets().end(); ++tit) { ParseAPI::Edge *t = *tit; if (t->type() == COND_TAKEN && (visited.find(t->trg()) != visited.end())) { taken_hit = true; } if ((t->type() == COND_NOT_TAKEN || t->type() == FALLTHROUGH) && (visited.find(t->trg()) != visited.end())) { fallthrough_hit = true; } } parsing_printf("\tfindMaxSwitchInsn: taken_hit: %d, fallthrough_hit: %d\n", taken_hit, fallthrough_hit); compareOnTakenBranch = taken_hit && !fallthrough_hit; break; } curAdr += i->size(); } if(foundMaxSwitch && foundCondBranch) break; // done // look further back Block::edgelist::const_iterator sit = curBlk->sources().begin(); depth++; // We've seen depth 2 in libc et al if(depth > 2) return boost::make_tuple(Instruction::Ptr(), Instruction::Ptr(), false); for( ; sit != curBlk->sources().end(); ++sit) { ParseAPI::Edge * s = *sit; // ignore return edges if(s->type() == RET) continue; if(s->type() == CALL) return boost::make_tuple(Instruction::Ptr(), Instruction::Ptr(), false); Block * src = s->src(); if( (visited.find( src ) == visited.end())) { WL.push_back(src); } } } WL.clear(); parsing_printf("\tfindMaxSwitchInsn: table on taken branch: %d, returning: %d\n", compareOnTakenBranch, foundMaxSwitch && foundCondBranch); return boost::make_tuple(compareInsn, condBranchInsn, compareOnTakenBranch); }
void DICFG::insert_edges(const CodeObject::funclist& funcs) { CodeObject::funclist::iterator funcs_iter; ParseAPI::Function::blocklist::iterator blocks_iter; ParseAPI::Block::edgelist::const_iterator edges_iter; ParseAPI::Function *fun; ParseAPI::Block *source_block, *target_block; ParseAPI::Edge *edge; ArmsFunction *arms_fun; ArmsBasicBlock *arms_source_block, *arms_target_block; ArmsEdge *arms_edge; std::set<Address> seen; for(funcs_iter = funcs.begin(); funcs_iter != funcs.end(); funcs_iter++) { fun = *funcs_iter; arms_fun = find_function((address_t)fun->addr()); ParseAPI::Function::blocklist blocks = fun->blocks(); for(blocks_iter = blocks.begin(); blocks_iter != blocks.end(); blocks_iter++) { source_block = *blocks_iter; arms_source_block = find_bb((address_t)(source_block->start())); /* don't handle shared blocks multiple times */ if (seen.find(source_block->start()) != seen.end()) continue; seen.insert(source_block->start()); const ParseAPI::Block::edgelist& edges = source_block->targets(); for(edges_iter = edges.begin(); edges_iter != edges.end(); edges_iter++) { edge = *edges_iter; if (edge->type() == CALL_FT) continue; target_block = edge->trg(); /* If it's an indirect call, we'll add the return edge separately */ if ((edge->type() == RET) && (target_block->start() == (Address) -1)) continue; arms_target_block = (target_block->start() == (Address) -1) ? 0 : find_bb((address_t)target_block->start()); /* an indirect call - see if we have data from LLVM to help */ if ((! arms_target_block) && (edge->type() == CALL)) { std::vector<void*> targets; int ret = arms_icall_resolver((void*)(source_block->last()), targets); for (unsigned i = 0; i < targets.size(); i++) { handle_interprocedural(arms_source_block, (address_t)targets[i], arms_indirect_call); } if (targets.size() > 0) { continue; } } if (!arms_target_block) { arms_target_block = ArmsBasicBlock::create_dummy_basic_block(arms_fun, this); } arms_edge = new ArmsEdge(arms_source_block, arms_target_block, this); copy_edge_type(arms_edge, edge, (target_block->start() == (Address) -1)); arms_source_block->add_outgoing_edge(arms_edge); arms_target_block->add_incoming_edge(arms_edge); // fprintf(stderr, "new edge %s\n", arms_edge->to_string().c_str()); } } } }