예제 #1
0
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);
}
예제 #2
0
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());
			}
		} 
	}
}