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/Diagnostics.h>
8 #include <Rose/Exception.h>
9 #include <Rose/BinaryAnalysis/InstructionSemantics/SymbolicSemantics.h>
11 #include <boost/lexical_cast.hpp>
13 #include <Sawyer/GraphTraversal.h>
14 #include <Sawyer/DistinctList.h>
20 namespace BinaryAnalysis {
110 InstructionSemantics::DataFlowSemantics::RiscOperatorsPtr dfOps_;
123 init(userDispatcher);
143 Graph
buildGraph(
const std::vector<SgAsmInstruction*>&);
153 typedef std::vector<SgAsmInstruction*> Instructions;
154 Instructions operator()(
SgAsmInstruction *insn) {
return Instructions(1, insn); }
170 template<
class CFG,
class VertexUnpacker>
172 using namespace Diagnostics;
174 ASSERT_require(startVertex < cfg.nVertices());
175 Stream mesg(mlog[WHERE] <<
"buildGraphPerVertex startVertex=" <<startVertex);
177 VertexFlowGraphs result;
178 result.
insert(startVertex,
buildGraph(vertexUnpacker(cfg.findVertex(startVertex)->value())));
179 std::vector<InstructionSemantics::BaseSemantics::StatePtr> postState(cfg.nVertices());
180 postState[startVertex] = userOps_->currentState();
183 for (Traversal t(cfg, cfg.findVertex(startVertex)); t; ++t) {
184 typename CFG::ConstVertexIterator source = t->source();
185 typename CFG::ConstVertexIterator target = t->target();
188 ASSERT_not_null(postState[source->id()]);
189 state = postState[target->id()] = postState[source->id()]->clone();
190 userOps_->currentState(state);
191 std::vector<SgAsmInstruction*> insns = vertexUnpacker(target->value());
223 struct PreserveCurrentState {
227 : ops(ops), state(ops->currentState()) {}
228 ~PreserveCurrentState() { ops->currentState(state); }
235 ops_->currentState(src);
236 return dst->merge(src, ops_.get());
245 template<
class CFG,
class State>
248 bool operator()(
const CFG&,
const typename CFG::Edge&,
const State&,
const State&) {
310 template<
class Cfg_,
class State_,
class TransferFunction_,
class MergeFunction_,
332 size_t maxIterations_;
344 : cfg_(cfg), xfer_(xfer), merge_(merge), maxIterations_(-1), nIterations_(0), isFeasible_(isFeasible) {
359 incomingState_.clear();
360 incomingState_.resize(cfg_.nVertices(), initialState);
361 outgoingState_.clear();
362 outgoingState_.resize(cfg_.nVertices(), initialState);
372 const std::string&
name()
const {
return name_; }
373 void name(
const std::string &s) { name_ = s; }
405 using namespace Diagnostics;
407 if (++nIterations_ > maxIterations_) {
411 size_t cfgVertexId = workList_.
popFront();
413 mlog[DEBUG] <<
prefix() <<
"runOneIteration: vertex #" <<cfgVertexId <<
"\n";
414 mlog[DEBUG] <<
prefix() <<
" remaining worklist is {";
415 for (
size_t id: workList_.
items())
416 mlog[DEBUG] <<
" " <<
id;
417 mlog[DEBUG] <<
" }\n";
420 ASSERT_require2(cfgVertexId < cfg_.nVertices(),
421 "vertex " + boost::lexical_cast<std::string>(cfgVertexId) +
" must be valid within CFG");
422 typename Cfg::ConstVertexIterator vertex = cfg_.findVertex(cfgVertexId);
423 State state = incomingState_[cfgVertexId];
425 mlog[DEBUG] <<
prefix() <<
" incoming state for vertex #" <<cfgVertexId <<
":\n"
429 state = outgoingState_[cfgVertexId] = xfer_(cfg_, cfgVertexId, state);
431 mlog[DEBUG] <<
prefix() <<
" outgoing state for vertex #" <<cfgVertexId <<
":\n"
437 SAWYER_MESG(mlog[DEBUG]) <<
prefix() <<
" forwarding vertex #" <<cfgVertexId <<
" output state to "
439 for (
const typename Cfg::Edge &edge: vertex->outEdges()) {
440 size_t nextVertexId = edge.target()->id();
441 if (!isFeasible_(cfg_, edge, state, incomingState_[nextVertexId])) {
442 SAWYER_MESG(mlog[DEBUG]) <<
prefix() <<
" path to vertex #" <<nextVertexId
443 <<
" is not feasible, thus skipped\n";
444 }
else if (merge_(incomingState_[nextVertexId], state)) {
446 mlog[DEBUG] <<
prefix() <<
" merged with vertex #" <<nextVertexId <<
" (which changed as a result)\n";
447 mlog[DEBUG] <<
prefix() <<
" merge state is: "
449 prefix() +
" ",
false) <<
"\n";
453 SAWYER_MESG(mlog[DEBUG]) <<
prefix() <<
" merged with vertex #" <<nextVertexId <<
" (no change)\n";
462 incomingState_[startVertexId] = initialState;
489 return incomingState_[cfgVertexId];
494 incomingState_[cfgVertexId] = state;
502 return outgoingState_[cfgVertexId];
510 return incomingState_;
518 return outgoingState_;
const VertexStates & getFinalStates() const
All outgoing states.
Sawyer::Container::Map< size_t, Graph > VertexFlowGraphs
Map from CFG vertex to data-flow graph.
ROSE_UTIL_API std::string numberToString(long long)
Convert an integer to a string.
size_t nIterations() const
Number of iterations run.
std::string plural(T n, const std::string &plural_phrase, const std::string &singular_phrase="")
Helpful way to print singular or plural words.
Basic merge operation for instruction semantics.
size_t maxIterations() const
Max number of iterations to allow.
State getInitialState(size_t cfgVertexId) const
Return the incoming state for the specified CFG vertex.
Engine(const Cfg &cfg, TransferFunction &xfer, MergeFunction merge=MergeFunction(), PathFeasibility isFeasible=PathFeasibility())
Constructor.
MergeFunction_ MergeFunction
Type of the function that merges two states into a single state.
boost::shared_ptr< RiscOperators > RiscOperatorsPtr
Shared-ownership pointer to a RISC operators object.
Base class for machine instructions.
Cfg_ Cfg
Type of the data-flow control flow graph.
AbstractLocation Variable
Variable participating in data flow.
void runToFixedPoint()
Run data-flow until it reaches a fixed point.
Depth-first, forward traversal for edges.
static void initDiagnostics()
Initialize diagnostics.
std::list< Variable > VariableList
List of variables.
void runToFixedPoint(size_t startVertexId, const State &initialState)
Add starting point and run to fixed point.
std::vector< State > VertexStates
Vector of states per vertex.
void maxIterations(size_t n)
Max number of iterations to allow.
Main namespace for the ROSE library.
bool isEmpty() const
Determines whether list is empty.
Graph buildGraph(const std::vector< SgAsmInstruction * > &)
Compute data-flow.
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.
InstructionSemantics::DataFlowSemantics::DataFlowGraph Graph
Data-flow graph.
boost::shared_ptr< State > StatePtr
Shared-ownership pointer to a semantic state.
boost::shared_ptr< Dispatcher > DispatcherPtr
Shared-ownership pointer to a semantics instruction dispatcher.
DataFlow(const InstructionSemantics::BaseSemantics::DispatcherPtr &userDispatcher)
Constructor.
VariableList getUniqueVariables(const VertexFlowGraphs &)
Get list of unique variables.
std::string prefix() const
Line prefix for debugging.
void reset(State initialState=State())
Reset engine to initial state.
const std::string & name() const
Property: Name for debugging.
VertexFlowGraphs buildGraphPerVertex(const CFG &cfg, size_t startVertex)
Compute data-flow per CFG vertex.
Exceptions when a fixed point is not reached.
bool runOneIteration()
Runs one iteration.
Trivial path feasibility predicate.
const Items & items() const
Return all items as a list.
void pushBack(const Item &item)
Insert item at back of list if distinct.
const Cfg & cfg() const
Data-flow control flow graph.
Item popFront()
Return and erase item at front of list.
Data-flow exception base class.
Various tools for data-flow analysis.
Map & insert(const Key &key, const Value &value)
Insert or update a key/value pair.
const VertexStates & getInitialStates() const
All incoming states.
void insertStartingVertex(size_t startVertexId, const State &initialState)
Add a starting vertex.
Functor to return instructions for a cfg vertex.
void name(const std::string &s)
Property: Name for debugging.
State getFinalState(size_t cfgVertexId) const
Return the outgoing state for the specified CFG vertex.
Base class for all ROSE exceptions.
VertexFlowGraphs buildGraphPerVertex(const CFG &cfg, size_t startVertex, VertexUnpacker vertexUnpacker)
Compute data-flow per CFG vertex.
State_ State
Type of the states stored at each CFG vertex.
size_t size() const
Number of nodes, keys, or values in this container.
void setInitialState(size_t cfgVertexId, State state)
Set the initial state for the specified CFG vertex.
void clear()
Clear the list.
PathFeasibility_ PathFeasibility
Predicate testing whether certain CFG edges should be followed.
TransferFunction_ TransferFunction
Type of the transfer function that creates new states.