Example #1
0
File: scope.cpp Project: hsk/Dachs
std::string func_scope::to_string() const noexcept
{
    if (is_builtin) {
        return "func " + name + '('
            + boost::algorithm::join(
                    params |
                    boost::adaptors::transformed(
                        [](auto const& p)
                        {
                            return p->name;
                        }
                    ), ", "
                )
            + ')';
    }

    auto const def = get_ast_node();
    std::string ret = ast::symbol::to_string(def->kind) + ' ' + name + '(';

    ret += boost::algorithm::join(def->params | boost::adaptors::transformed([](auto const& p){ return p->type.to_string(); }), ", ");
    ret += ')';

    if (def->ret_type) {
        ret += ": " + def->ret_type->to_string();
    }

    return ret;
}
Results analyze(SgAsmInterpretation *interp) {
    assert(interp!=NULL);
    Results results;

    Cfg cfg = ControlFlow().build_block_cfg_from_ast<Cfg>(interp);
    CfgEdgeIterator ei, ei_end;
    for (boost::tie(ei, ei_end)=edges(cfg); ei!=ei_end; ++ei) {
        SgAsmBlock *src_blk = get_ast_node(cfg, source(*ei, cfg));
        SgAsmBlock *dst_blk = get_ast_node(cfg, target(*ei, cfg));
        SgAsmFunction *src_func = SageInterface::getEnclosingNode<SgAsmFunction>(src_blk);
        SgAsmFunction *dst_func = SageInterface::getEnclosingNode<SgAsmFunction>(dst_blk);
        if (!src_func || !dst_func)
            continue;
        if (src_func != dst_func && callReturns(cfg, *ei))
            results[dst_func].update(returnValueUsed(cfg, firstReturnVertex(cfg, *ei), interp->get_registers()));
    }

    results = combineLikeNames(interp, results);        // optional
    return results;
}
// The actual analysis for a function call starting at a function call return point and terminating each path whenever we reach
// another function call.  Try to figure out if we ever read from EAX without first writing to it and return true if we do.
static bool returnValueUsed(const Cfg &cfg, CfgVertex startVertex, const RegisterDictionary *regdict) {
    BaseSemantics::SValuePtr protoval = NullSemantics::SValue::instance();
    RegisterStatePtr registers = RegisterState::instance(protoval, regdict);
    BaseSemantics::MemoryStatePtr memory = BaseSemantics::MemoryCellList::instance(protoval, protoval);
    BaseSemantics::StatePtr state = BaseSemantics::State::instance(registers, memory);
    BaseSemantics::RiscOperatorsPtr ops = NullSemantics::RiscOperators::instance(state);
    size_t addrWidth = regdict->findLargestRegister(x86_regclass_gpr, x86_gpr_sp).get_nbits();
    BaseSemantics::DispatcherPtr dispatcher = DispatcherX86::instance(ops, addrWidth);

    WorkList<CfgVertex> worklist(true);
    Map<CfgVertex, size_t> seen;
    worklist.push(startVertex);
    while (!worklist.empty()) {
        CfgVertex v = worklist.pop();
        seen[v] = 1;
        SgAsmBlock *bb = get_ast_node(cfg, v);
        std::vector<SgAsmInstruction*> insns = SageInterface::querySubTree<SgAsmInstruction>(bb);

        // "Run" the basic block
        bool failed = false;
        BOOST_FOREACH (SgAsmInstruction *insn, insns) {
            try {
                dispatcher->processInstruction(insn);
                if (registers->readUninitialized())
                    return true;
            } catch (...) {
                failed = true;
                break;
            }
        }
        if (failed)
            continue;

        // Add new vertices to the work list, but only if none of the outgoing edges are function calls.
        bool isCall = false;
        CfgOutEdgeIterator ei, ei_end;
        for (boost::tie(ei, ei_end)=out_edges(v, cfg); ei!=ei_end && !isCall; ++ei)
            isCall = isFunctionCall(cfg, *ei);
        if (!isCall) {
            for (boost::tie(ei, ei_end)=out_edges(v, cfg); ei!=ei_end && !isCall; ++ei) {
                if (!seen.exists(v))
                    worklist.push(v);
            }
        }
    }
    return false;
}