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; }