// Mark a node complete, updating its children. // Removes the node from the data structure void mark_done(SliceNode::Ptr n) { // First pull all of the children of this node // that are not on the skip list set<SliceNode::Ptr> children; EdgeIterator begin, end; n->outs(begin, end); for (; begin != end; ++begin) { Edge::Ptr edge = *begin; if(skip_edges.find(edge) == skip_edges.end()) { SliceNode::Ptr child = boost::static_pointer_cast<SliceNode>( edge->target()); if(remove(child)) children.insert(child); } } // remove n and set done remove(n); done.insert(n); // put the children back set<SliceNode::Ptr>::iterator cit = children.begin(); for( ; cit != children.end(); ++cit) { insert(*cit); } }
// Do the previous, but use a Graph as a guide for // performing forward substitution on the AST results SymEval::Retval_t SymEval::expand(Dyninst::Graph::Ptr slice, DataflowAPI::Result_t &res) { bool failedTranslation = false; bool skippedInput = false; //cout << "Calling expand" << endl; // Other than the substitution this is pretty similar to the first example. NodeIterator gbegin, gend; slice->allNodes(gbegin, gend); // First, we'll sort the nodes in some deterministic order so that the loop removal // is deterministic std::vector<SliceNode::Ptr> sortVector; for ( ; gbegin != gend; ++gbegin) { Node::Ptr ptr = *gbegin; expand_cerr << "pushing " << (*gbegin)->format() << " to sortVector" << endl; SliceNode::Ptr cur = boost::static_pointer_cast<SliceNode>(ptr); sortVector.push_back(cur); } std::stable_sort(sortVector.begin(), sortVector.end(), vectorSort); // Optimal ordering of search ExpandOrder worklist; std::queue<Node::Ptr> dfs_worklist; std::vector<SliceNode::Ptr>::iterator vit = sortVector.begin(); for ( ; vit != sortVector.end(); ++vit) { SliceNode::Ptr ptr = *vit; Node::Ptr cur = boost::static_pointer_cast<Node>(ptr); dfs_worklist.push(cur); } /* First, we'll do DFS to check for circularities in the graph; * if so, mark them so we don't do infinite substitution */ std::map<Node::Ptr, int> state; while (!dfs_worklist.empty()) { Node::Ptr ptr = dfs_worklist.front(); dfs_worklist.pop(); dfs(ptr, state, worklist.skipEdges()); } slice->allNodes(gbegin, gend); for (; gbegin != gend; ++gbegin) { expand_cerr << "adding " << (*gbegin)->format() << " to worklist" << endl; Node::Ptr ptr = *gbegin; SliceNode::Ptr sptr = boost::static_pointer_cast<SliceNode>(ptr); worklist.insert(sptr,false); } /* have a list * for each node, process * if processessing succeeded, remove the element * if the size of the list has changed, continue */ while (1) { SliceNode::Ptr aNode; int order; boost::tie(aNode,order) = worklist.pop_next(); if (order == -1) // empty break; if (!aNode->assign()) { worklist.mark_done(aNode); continue; // Could be a widen point } expand_cerr << "Visiting node " << aNode->assign()->format() << " order " << order << endl; if (order != 0) { cerr << "ERROR: order is non zero: " << order << endl; } assert(order == 0); // there are no loops AST::Ptr prev = res[aNode->assign()]; Retval_t result = process(aNode, res, worklist.skipEdges()); AST::Ptr post = res[aNode->assign()]; switch (result) { case FAILED: return FAILED; break; case WIDEN_NODE: // Okay... break; case FAILED_TRANSLATION: failedTranslation = true; break; case SKIPPED_INPUT: skippedInput = true; break; case SUCCESS: break; } // We've visited this node, freeing its children // to be visited in turn worklist.mark_done(aNode); if (post && !(post->equals(prev))) { expand_cerr << "Adding successors to list, as new expansion " << endl << "\t" << post->format() << endl << " != " << endl << "\t" << (prev ? prev->format() : "<NULL>") << endl; EdgeIterator oB, oE; aNode->outs(oB, oE); for (; oB != oE; ++oB) { if(worklist.skipEdges().find(*oB) == worklist.skipEdges().end()) { SliceNode::Ptr out = boost::static_pointer_cast<SliceNode>( (*oB)->target()); worklist.insert(out); } } } } if (failedTranslation) return FAILED_TRANSLATION; else if (skippedInput) return SKIPPED_INPUT; else return SUCCESS; }