SymEval::Retval_t SymEval::process(SliceNode::Ptr ptr, Result_t &dbase, std::set<Edge::Ptr> &skipEdges) { bool failedTranslation; bool skippedEdge = false; bool skippedInput = false; bool success = false; std::map<const AbsRegion*, std::set<Assignment::Ptr> > inputMap; expand_cerr << "Calling process on " << ptr->format() << endl; // Don't try an expansion of a widen node... if (!ptr->assign()) return WIDEN_NODE; EdgeIterator begin, end; ptr->ins(begin, end); for (; begin != end; ++begin) { SliceEdge::Ptr edge = boost::static_pointer_cast<SliceEdge>(*begin); SliceNode::Ptr source = boost::static_pointer_cast<SliceNode>(edge->source()); // Skip this one to break a cycle. if (skipEdges.find(edge) != skipEdges.end()) { expand_cerr << "In process, skipping edge from " << source->format() << endl; skippedEdge = true; continue; } Assignment::Ptr assign = source->assign(); if (!assign) continue; // widen node expand_cerr << "Assigning input " << edge->data().format() << " from assignment " << assign->format() << endl; inputMap[&edge->data()].insert(assign); } expand_cerr << "\t Input map has size " << inputMap.size() << endl; // All of the expanded inputs are in the parameter dbase // If not (like this one), add it AST::Ptr ast; boost::tie(ast, failedTranslation) = SymEval::expand(ptr->assign()); // expand_cerr << "\t ... resulting in " << dbase.format() << endl; // We have an AST. Now substitute in all of its predecessors. for (std::map<const AbsRegion*, std::set<Assignment::Ptr> >::iterator iter = inputMap.begin(); iter != inputMap.end(); ++iter) { // If we have multiple secondary definitions, we: // if all definitions are equal, use the first // otherwise, use nothing AST::Ptr definition; for (std::set<Assignment::Ptr>::iterator iter2 = iter->second.begin(); iter2 != iter->second.end(); ++iter2) { AST::Ptr newDef = dbase[*iter2]; if (!definition) { definition = newDef; continue; } else if (definition->equals(newDef)) { continue; } else { // Not equal definition = AST::Ptr(); skippedInput = true; break; } } // The region used by the current assignment... const AbsRegion ® = *iter->first; // Create an AST around this one VariableAST::Ptr use = VariableAST::create(Variable(reg, ptr->addr())); if (!definition) { // Can happen if we're expanding out of order, and is generally harmless. continue; } expand_cerr << "Before substitution: " << (ast ? ast->format() : "<NULL AST>") << endl; if (!ast) { expand_cerr << "Skipping substitution because of null AST" << endl; } else { ast = AST::substitute(ast, use, definition); success = true; } expand_cerr << "\t result is " << (ast ? ast->format() : "<NULL AST>") << endl; } expand_cerr << "Result of substitution: " << ptr->assign()->format() << " == " << (ast ? ast->format() : "<NULL AST>") << endl; // And attempt simplification again ast = simplifyStack(ast, ptr->addr(), ptr->func(), ptr->block()); expand_cerr << "Result of post-substitution simplification: " << ptr->assign()->format() << " == " << (ast ? ast->format() : "<NULL AST>") << endl; dbase[ptr->assign()] = ast; if (failedTranslation) return FAILED_TRANSLATION; else if (skippedEdge || skippedInput) return SKIPPED_INPUT; else if (success) return SUCCESS; else return FAILED; }
// 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; }