1#ifndef ROSE_BinaryAnalysis_DataFlow_H
2#define ROSE_BinaryAnalysis_DataFlow_H
3#include <featureTests.h>
4#ifdef ROSE_ENABLE_BINARY_ANALYSIS
6#include <Rose/BinaryAnalysis/InstructionSemantics/DataFlowSemantics.h>
7#include <Rose/BinaryAnalysis/InstructionSemantics/SymbolicSemantics.h>
8#include <Rose/Diagnostics.h>
9#include <Rose/Exception.h>
10#include <Rose/StringUtility/Convert.h>
11#include <Rose/StringUtility/Diagnostics.h>
12#include <Rose/StringUtility/NumberToString.h>
14#include <Sawyer/GraphTraversal.h>
15#include <Sawyer/DistinctList.h>
16#include <boost/lexical_cast.hpp>
23namespace BinaryAnalysis {
113 InstructionSemantics::DataFlowSemantics::RiscOperatorsPtr dfOps_;
126 init(userDispatcher);
156 typedef std::vector<SgAsmInstruction*> Instructions;
157 Instructions operator()(
SgAsmInstruction *insn) {
return Instructions(1, insn); }
173 template<
class CFG,
class VertexUnpacker>
175 using namespace Diagnostics;
177 ASSERT_require(startVertex < cfg.nVertices());
178 Stream mesg(mlog[WHERE] <<
"buildGraphPerVertex startVertex=" <<startVertex);
181 result.
insert(startVertex,
buildGraph(vertexUnpacker(cfg.findVertex(startVertex)->value())));
182 std::vector<InstructionSemantics::BaseSemantics::StatePtr> postState(cfg.nVertices());
183 postState[startVertex] = userOps_->currentState();
186 for (Traversal t(cfg, cfg.findVertex(startVertex)); t; ++t) {
187 typename CFG::ConstVertexIterator source = t->source();
188 typename CFG::ConstVertexIterator target = t->target();
191 ASSERT_not_null(postState[source->id()]);
192 state = postState[target->id()] = postState[source->id()]->clone();
193 userOps_->currentState(state);
194 std::vector<SgAsmInstruction*> insns = vertexUnpacker(target->value());
226 struct PreserveCurrentState {
230 : ops(ops), state(ops->currentState()) {}
231 ~PreserveCurrentState() { ops->currentState(state); }
238 ops_->currentState(src);
239 return dst->merge(src, ops_.get(), ops_.get());
248 template<
class CFG,
class State>
251 bool operator()(
const CFG&,
const typename CFG::Edge&,
const State&,
const State&) {
313 template<
class Cfg_,
class State_,
class TransferFunction_,
class MergeFunction_,
335 size_t maxIterations_;
347 : cfg_(
cfg), xfer_(xfer), merge_(merge), maxIterations_(-1), nIterations_(0), isFeasible_(isFeasible) {
362 incomingState_.clear();
363 incomingState_.resize(cfg_.nVertices(), initialState);
364 outgoingState_.clear();
365 outgoingState_.resize(cfg_.nVertices(), initialState);
375 const std::string&
name()
const {
return name_; }
376 void name(
const std::string &s) { name_ = s; }
408 using namespace Diagnostics;
410 if (++nIterations_ > maxIterations_) {
414 size_t cfgVertexId = workList_.
popFront();
416 mlog[DEBUG] <<
prefix() <<
"runOneIteration: vertex #" <<cfgVertexId <<
"\n";
417 mlog[DEBUG] <<
prefix() <<
" remaining worklist is {";
418 for (
size_t id: workList_.
items())
419 mlog[DEBUG] <<
" " <<
id;
420 mlog[DEBUG] <<
" }\n";
423 ASSERT_require2(cfgVertexId < cfg_.nVertices(),
424 "vertex " + boost::lexical_cast<std::string>(cfgVertexId) +
" must be valid within CFG");
425 typename Cfg::ConstVertexIterator vertex = cfg_.findVertex(cfgVertexId);
426 State state = incomingState_[cfgVertexId];
428 mlog[DEBUG] <<
prefix() <<
" incoming state for vertex #" <<cfgVertexId <<
":\n"
432 state = outgoingState_[cfgVertexId] = xfer_(cfg_, cfgVertexId, state);
434 mlog[DEBUG] <<
prefix() <<
" outgoing state for vertex #" <<cfgVertexId <<
":\n"
440 SAWYER_MESG(mlog[DEBUG]) <<
prefix() <<
" forwarding vertex #" <<cfgVertexId <<
" output state to "
442 for (
const typename Cfg::Edge &edge: vertex->outEdges()) {
443 size_t nextVertexId = edge.target()->id();
444 if (!isFeasible_(cfg_, edge, state, incomingState_[nextVertexId])) {
445 SAWYER_MESG(mlog[DEBUG]) <<
prefix() <<
" path to vertex #" <<nextVertexId
446 <<
" is not feasible, thus skipped\n";
447 }
else if (merge_(incomingState_[nextVertexId], state)) {
449 mlog[DEBUG] <<
prefix() <<
" merged with vertex #" <<nextVertexId <<
" (which changed as a result)\n";
450 mlog[DEBUG] <<
prefix() <<
" merge state is:\n"
452 prefix() +
" ",
false) <<
"\n";
456 SAWYER_MESG(mlog[DEBUG]) <<
prefix() <<
" merged with vertex #" <<nextVertexId <<
" (no change)\n";
465 incomingState_[startVertexId] = initialState;
492 return incomingState_[cfgVertexId];
497 incomingState_[cfgVertexId] = state;
505 return outgoingState_[cfgVertexId];
513 return incomingState_;
521 return outgoingState_;
Functor to return instructions for a cfg vertex.
MergeFunction_ MergeFunction
Type of the function that merges two states into a single state.
void runToFixedPoint()
Run data-flow until it reaches a fixed point.
const VertexStates & getInitialStates() const
All incoming states.
PathFeasibility_ PathFeasibility
Predicate testing whether certain CFG edges should be followed.
size_t maxIterations() const
Max number of iterations to allow.
State_ State
Type of the states stored at each CFG vertex.
const Cfg & cfg() const
Data-flow control flow graph.
Engine(const Cfg &cfg, TransferFunction &xfer, MergeFunction merge=MergeFunction(), PathFeasibility isFeasible=PathFeasibility())
Constructor.
const VertexStates & getFinalStates() const
All outgoing states.
void runToFixedPoint(size_t startVertexId, const State &initialState)
Add starting point and run to fixed point.
Cfg_ Cfg
Type of the data-flow control flow graph.
std::string prefix() const
Line prefix for debugging.
State getInitialState(size_t cfgVertexId) const
Return the incoming state for the specified CFG vertex.
void name(const std::string &s)
Property: Name for debugging.
std::vector< State > VertexStates
Vector of states per vertex.
void setInitialState(size_t cfgVertexId, State state)
Set the initial state for the specified CFG vertex.
const std::string & name() const
Property: Name for debugging.
void reset(State initialState=State())
Reset engine to initial state.
size_t nIterations() const
Number of iterations run.
void maxIterations(size_t n)
Max number of iterations to allow.
void insertStartingVertex(size_t startVertexId, const State &initialState)
Add a starting vertex.
State getFinalState(size_t cfgVertexId) const
Return the outgoing state for the specified CFG vertex.
TransferFunction_ TransferFunction
Type of the transfer function that creates new states.
bool runOneIteration()
Runs one iteration.
Data-flow exception base class.
Exceptions when a fixed point is not reached.
Trivial path feasibility predicate.
Basic merge operation for instruction semantics.
Various tools for data-flow analysis.
InstructionSemantics::DataFlowSemantics::DataFlowGraph Graph
Data-flow graph.
std::list< Variable > VariableList
List of variables.
VertexFlowGraphs buildGraphPerVertex(const CFG &cfg, size_t startVertex)
Compute data-flow per CFG vertex.
VariableList getUniqueVariables(const VertexFlowGraphs &)
Get list of unique variables.
static void initDiagnostics()
Initialize diagnostics.
VertexFlowGraphs buildGraphPerVertex(const CFG &cfg, size_t startVertex, VertexUnpacker vertexUnpacker)
Compute data-flow per CFG vertex.
AbstractLocation Variable
Variable participating in data flow.
Sawyer::Container::Map< size_t, Graph > VertexFlowGraphs
Map from CFG vertex to data-flow graph.
DataFlow(const InstructionSemantics::BaseSemantics::DispatcherPtr &userDispatcher)
Constructor.
Graph buildGraph(const std::vector< SgAsmInstruction * > &)
Compute data-flow.
Base class for all ROSE exceptions.
Depth-first, forward traversal for edges.
A doubly-linked list of distinct items.
void clear()
Clear the list.
const Items & items() const
Return all items as a list.
void pushBack(const Item &item)
Insert item at back of list if distinct.
Item popFront()
Return and erase item at front of list.
bool isEmpty() const
Determines whether list is empty.
Container associating values with keys.
size_t size() const
Number of nodes, keys, or values in this container.
Map & insert(const Key &key, const Value &value)
Insert or update a key/value pair.
Base class for machine instructions.
boost::shared_ptr< RiscOperators > RiscOperatorsPtr
Shared-ownership pointer to a RISC operators object.
boost::shared_ptr< Dispatcher > DispatcherPtr
Shared-ownership pointer to a semantics instruction dispatcher.
boost::shared_ptr< State > StatePtr
Shared-ownership pointer to a semantic state.
ROSE_UTIL_API std::string numberToString(long long)
Convert an integer to a string.
ROSE_UTIL_API std::string prefixLines(const std::string &lines, const std::string &prefix, bool prefixAtFront=true, bool prefixAtBack=false)
Insert a prefix string before every line.
std::string plural(T n, const std::string &plural_phrase, const std::string &singular_phrase="")
Helpful way to print singular or plural words.