// FIXME[Robb P. Matzke 2014-02-18]: Make this a member of rose::BinaryAnalysis::BinaryControlFlow
// Return true if a call edge also has a return edge.  We're assuming that fixup_fcall_fret() has not been called for this
// graph.  In other words, if there's a function call edge for a function that returns, then the source vertex will also have
// an edge to another vertex in the caller function.
static bool callReturns(const Cfg &cfg, CfgEdge callEdge) {
    assert(isFunctionCall(cfg, callEdge));
    CfgVertex callerVertex = source(callEdge, cfg);
    CfgOutEdgeIterator ei, ei_end;
    for (boost::tie(ei, ei_end)=out_edges(callerVertex, cfg); ei!=ei_end; ++ei) {
        if (isIntraFunctionEdge(cfg, *ei))
            return true;
    }
    return false;
}
// FIXME[Robb P. Matzke 2014-02-18]: Make this a member of rose::BinaryAnalysis::BinaryControlFlow
// Given a function call edge for a function that returns, return the vertex for the function return point.  If there's more
// than one such vertex return just the first one.
static CfgVertex firstReturnVertex(const Cfg &cfg, CfgEdge callEdge) {
    assert(isFunctionCall(cfg, callEdge));
    assert(callReturns(cfg, callEdge));
    CfgVertex callerVertex = source(callEdge, cfg);
    CfgOutEdgeIterator ei, ei_end;
    for (boost::tie(ei, ei_end)=out_edges(callerVertex, cfg); ei!=ei_end; ++ei) {
        if (isIntraFunctionEdge(cfg, *ei))
            return target(*ei, cfg);
    }
    abort();                                            // not reachable
}
// 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;
}
Beispiel #4
0
OptionalNode FindDivisions(const ast::Operands& operands, eval::SessionEnvironment& sessionEnvironment) {
	if ( operands.size() != 2 ) {
		sessionEnvironment.raiseMessage( Message(ids::FindDivisions, ids::argrx, {
				ast::Node::make<ast::Identifier>( ids::FindDivisions ),
				ast::Node::make<math::Rational>( operands.size() ),
				ast::Node::make<math::Rational>( 2 )
		} ));
		return EvaluationFailure();
	}

	const auto range = operands[0];
	const auto numberOfElements = operands[1];

	if ( !range.isFunctionCall(ids::List) || range.get<ast::FunctionCall>().getOperands().size() != 2) {
		sessionEnvironment.raiseMessage( Message(ids::FindDivisions, ids::fdargs, {
				range,
				ast::Node::make<ast::FunctionCall>( ids::FindDivisions, operands )
		} ));
		return EvaluationFailure();
	}

	if ( !numberOfElements.is<math::Rational>() || !math::isInteger(numberOfElements.get<math::Rational>()) ) {
		sessionEnvironment.raiseMessage( Message(ids::FindDivisions, ids::fdargs, {
				numberOfElements,
				ast::Node::make<ast::FunctionCall>( ids::FindDivisions, operands )
		} ));
		return EvaluationFailure();
	}

	std::vector<ast::Node> listParams = range.get<ast::FunctionCall>().getOperands();

	auto endIt = std::find_if_not(listParams.begin(), listParams.end(), [](const ast::Node& param) {
			return param.isNumeric();
	});

	if (endIt != listParams.end()) {
		sessionEnvironment.raiseMessage( Message(ids::FindDivisions, ids::fdargs, {
				*endIt,
				ast::Node::make<ast::FunctionCall>( ids::FindDivisions, operands )
		} ));
		return EvaluationFailure();
	}

	const math::Real precision = (listParams[1].getNumeric() - listParams[0].getNumeric())/numberOfElements.getInteger();

	const math::Rational left = math::findRationalNear(listParams[0].getNumeric(), precision);
	const math::Rational right = math::findRationalNear(listParams[1].getNumeric(), precision);

	std::vector<math::Rational> intermediates;

	// Impl here

	intermediates.push_back(left);

	const math::Rational distance = right - left;

	std::vector<math::Rational> multipliersbase = {1, 2, 5};
	std::vector<math::Rational> multipliers;

	for(int i=-2;i<2;++i) {
		std::vector<math::Rational> newValues(multipliersbase.begin(), multipliersbase.end());
		math::Rational magnitude = math::power(math::Rational{10}, i);
		for(auto& nv: newValues) { nv*=magnitude; }
		multipliers.insert(multipliers.end(), newValues.begin(), newValues.end());
	}

	const auto multiplierIt = std::find_if(multipliers.begin(), multipliers.end(), [&](const math::Rational& multiplier) {
			// return true if multiplier would result in less ticks that requested
			return (math::Real{distance}/multiplier) < numberOfElements.getNumeric();
	});


	const auto multiplier = *(multiplierIt-1);
	for(math::Rational next = left + multiplier; next <= right ; next += multiplier) {
		intermediates.push_back(next);
	}

	ast::Operands elements;
	for(auto& intermediate: intermediates) {
		elements.push_back(ast::Node::make<math::Rational>(intermediate));
	}
	return ast::Node::make<ast::FunctionCall>(ids::List, elements);
}