BinaryControlFlow.h

Go to the documentation of this file.
00001 #ifndef ROSE_BinaryAnalysis_ControlFlow_H
00002 #define ROSE_BinaryAnalysis_ControlFlow_H
00003 
00004 #include <boost/graph/adjacency_list.hpp>
00005 #include <boost/graph/depth_first_search.hpp>
00006 
00007 class SgNode;
00008 class SgAsmBlock;
00009 
00011 namespace BinaryAnalysis {
00012 
00112     class ControlFlow {
00113     public:
00114         ControlFlow()
00115             : vertex_filter(NULL), edge_filter(NULL)
00116             {}
00117         
00118 
00137         typedef boost::adjacency_list<boost::setS,                                  /* edges of each vertex in std::list */
00138                                       boost::vecS,                                  /* vertices in std::vector */
00139                                       boost::bidirectionalS,
00140                                       boost::property<boost::vertex_name_t, SgAsmBlock*> > Graph;
00141 
00142         /**********************************************************************************************************************
00143          *                                      Filters
00144          **********************************************************************************************************************/
00145     public:
00146 
00151         class VertexFilter {
00152         public:
00153             virtual ~VertexFilter() {}
00154             virtual bool operator()(ControlFlow*, SgAsmBlock*) = 0;
00155         };
00156 
00161         class EdgeFilter {
00162         public:
00163             virtual ~EdgeFilter() {}
00164             virtual bool operator()(ControlFlow*, SgAsmBlock *source, SgAsmBlock *target) = 0;
00165         };
00166 
00174         void set_vertex_filter(VertexFilter *filter) { vertex_filter = filter; }
00175         VertexFilter *get_vertex_filter() const { return vertex_filter; }
00184         void set_edge_filter(EdgeFilter *filter) { edge_filter = filter; }
00185         EdgeFilter *get_edge_filter() const { return edge_filter; }
00193         bool is_vertex_filtered(SgAsmBlock *block, VertexFilter *filter) { return filter && !(*filter)(this, block); }
00194         bool is_vertex_filtered(SgAsmBlock *block) { return is_vertex_filtered(block, vertex_filter); }
00202         bool is_edge_filtered(SgAsmBlock *src, SgAsmBlock *dst, EdgeFilter *filter) {
00203             return filter && !(*filter)(this, src, dst);
00204         }
00205         bool is_edge_filtered(SgAsmBlock *src, SgAsmBlock *dst) {
00206             return is_edge_filtered(src, dst, edge_filter);
00207         }
00210     protected:
00211         VertexFilter *vertex_filter;
00212         EdgeFilter *edge_filter;
00213 
00214         /**********************************************************************************************************************
00215          *                                      Methods that modify the AST
00216          **********************************************************************************************************************/
00217     public:
00218 
00225         void clear_ast(SgNode *ast);
00226 
00236         template<class ControlFlowGraph>
00237         void apply_to_ast(const ControlFlowGraph&);
00238 
00252         template<class ControlFlowGraph>
00253         void cache_vertex_descriptors(const ControlFlowGraph&);
00254 
00255         /**********************************************************************************************************************
00256          *                                      Graph construction methods
00257          **********************************************************************************************************************/
00258     public:
00259 
00279         template<class ControlFlowGraph>
00280         ControlFlowGraph build_cfg_from_ast(SgNode *root);
00281 
00282         template<class ControlFlowGraph>
00283         void build_cfg_from_ast(SgNode *root, ControlFlowGraph &cfg/*out*/);
00295         template<class ControlFlowGraph>
00296         ControlFlowGraph build_cg_from_ast(SgNode *root);
00297 
00298         template<class ControlFlowGraph>
00299         void build_cg_from_ast(SgNode *root, ControlFlowGraph &cfg/*out*/);
00312         template<class ControlFlowGraph>
00313         ControlFlowGraph copy(const ControlFlowGraph &src);
00314 
00315         template<class ControlFlowGraph>
00316         void copy(const ControlFlowGraph &src, ControlFlowGraph &dst/*out*/);
00319         /**********************************************************************************************************************
00320          *                                      Miscellaneous members
00321          **********************************************************************************************************************/
00322 
00323     private:
00324         /* Visitor used by flow_order().  Declaring this in function scope results in boost errors (boost-1.42, 2011-05). */
00325         template<class ControlFlowGraph>
00326         struct FlowOrder: public boost::default_dfs_visitor {
00327             typedef typename boost::graph_traits<ControlFlowGraph>::vertex_descriptor Vertex;
00328             typedef std::vector<Vertex> VertexList;
00329             typedef std::vector<size_t> ReverseVertexList;
00330             VertexList *forward_order;
00331             FlowOrder(VertexList *forward_order): forward_order(forward_order) {}
00332             void compute(const ControlFlowGraph &g, Vertex v0, ReverseVertexList *reverse_order);
00333             void finish_vertex(Vertex v, ControlFlowGraph g);
00334         };
00335             
00336     public:
00369         template<class ControlFlowGraph>
00370         std::vector<typename boost::graph_traits<ControlFlowGraph>::vertex_descriptor>
00371         flow_order(const ControlFlowGraph&,
00372                    typename boost::graph_traits<ControlFlowGraph>::vertex_descriptor start,
00373                    std::vector<size_t> *reverse_order=NULL);
00374 
00375     private:
00376         /* Visitor used by return_blocks(). Declaring this in function scope results in boost errors (boost-1.42, 2011-05). */
00377         template<class ControlFlowGraph>
00378         struct ReturnBlocks: public boost::default_dfs_visitor {
00379             typedef typename boost::graph_traits<ControlFlowGraph>::vertex_descriptor Vertex;
00380             typedef std::vector<Vertex> Vector;
00381             Vector &blocks;
00382             ReturnBlocks(Vector &blocks): blocks(blocks) {}
00383             void finish_vertex(Vertex v, ControlFlowGraph g);
00384         };
00385 
00386     public:
00392         template<class ControlFlowGraph>
00393         std::vector<typename boost::graph_traits<ControlFlowGraph>::vertex_descriptor>
00394         return_blocks(const ControlFlowGraph &cfg,
00395                       typename boost::graph_traits<ControlFlowGraph>::vertex_descriptor start);
00396     };
00397 }
00398 
00399 
00400 
00401 
00402 
00403 /******************************************************************************************************************************
00404  *                                      Function template definitions
00405  ******************************************************************************************************************************/
00406 
00407 template<class ControlFlowGraph>
00408 void
00409 BinaryAnalysis::ControlFlow::apply_to_ast(const ControlFlowGraph &cfg)
00410 {
00411     typename boost::graph_traits<ControlFlowGraph>::vertex_iterator vi, vi_end;
00412     for (boost::tie(vi, vi_end)=vertices(cfg); vi!=vi_end; ++vi) {
00413         SgAsmBlock *block = get(boost::vertex_name, cfg, *vi);
00414         if (!block || is_vertex_filtered(block))
00415             continue;
00416 
00417         /* Delete old targets */
00418         const SgAsmIntegerValuePtrList &targets = block->get_successors();
00419         for (SgAsmIntegerValuePtrList::const_iterator ti=targets.begin(); ti!=targets.end(); ++ti)
00420             delete *ti;
00421 
00422         /* Add new targets */
00423         block->set_successors_complete(true);
00424         block->get_successors().clear();
00425         typename boost::graph_traits<ControlFlowGraph>::out_edge_iterator ei, ei_end;
00426         for (boost::tie(ei, ei_end)=out_edges(*vi, cfg); ei!=ei_end; ++ei) {
00427             SgAsmBlock *target_block = get(boost::vertex_name, cfg, target(*ei, cfg));
00428             if (target_block && !is_edge_filtered(block, target_block)) {
00429                 SgAsmIntegerValueExpression *target = new SgAsmIntegerValueExpression(target_block->get_address());
00430                 target->make_relative_to(target_block);
00431                 target->set_parent(block);
00432                 block->get_successors().push_back(target);
00433             }
00434         }
00435     }
00436 }
00437 
00438 template<class ControlFlowGraph>
00439 void
00440 BinaryAnalysis::ControlFlow::cache_vertex_descriptors(const ControlFlowGraph &cfg)
00441 {
00442     typename boost::graph_traits<ControlFlowGraph>::vertex_iterator vi, vi_end;
00443     for (boost::tie(vi, vi_end)=vertices(cfg); vi!=vi_end; ++vi) {
00444         SgAsmBlock *block = get(boost::vertex_name, cfg, *vi);
00445         if (block && !is_vertex_filtered(block))
00446             block->set_cached_vertex(*vi);
00447     }
00448 }
00449 
00450 template<class ControlFlowGraph>
00451 void
00452 BinaryAnalysis::ControlFlow::build_cfg_from_ast(SgNode *root, ControlFlowGraph &cfg)
00453 {
00454     typedef typename boost::graph_traits<ControlFlowGraph>::vertex_descriptor Vertex;
00455     typedef std::map<SgAsmBlock*, Vertex> BlockVertexMap;
00456     BlockVertexMap bv_map;
00457 
00458     cfg.clear();
00459 
00460     /* Define the vertices. Vertices are any SgAsmBlock that contains at least one SgAsmInstruction. */
00461     struct T1: public AstSimpleProcessing {
00462         ControlFlow *analyzer;
00463         ControlFlowGraph &cfg;
00464         BlockVertexMap &bv_map;
00465         T1(ControlFlow *analyzer, ControlFlowGraph &cfg, BlockVertexMap &bv_map)
00466             : analyzer(analyzer), cfg(cfg), bv_map(bv_map)
00467             {}
00468         void visit(SgNode *node) {
00469             SgAsmBlock *block = isSgAsmBlock(node);
00470             if (block && block->has_instructions() && !analyzer->is_vertex_filtered(block)) {
00471                 Vertex vertex = add_vertex(cfg);
00472                 bv_map[block] = vertex;
00473                 put(boost::vertex_name, cfg, vertex, block);
00474             }
00475         }
00476     };
00477     T1(this, cfg, bv_map).traverse(root, preorder); /* preorder guarantees that the highest SgAsmBlock will be vertex zero */
00478 
00479     /* Add the edges. */
00480     typename boost::graph_traits<ControlFlowGraph>::vertex_iterator vi, vi_end;
00481     for (boost::tie(vi, vi_end)=vertices(cfg); vi!=vi_end; ++vi) {
00482         SgAsmBlock *source = boost::get(boost::vertex_name, cfg, *vi);
00483         const SgAsmIntegerValuePtrList &succs = source->get_successors();
00484         for (SgAsmIntegerValuePtrList::const_iterator si=succs.begin(); si!=succs.end(); ++si) {
00485             SgAsmBlock *target = isSgAsmBlock((*si)->get_base_node()); // might be null
00486             if (target && !is_edge_filtered(source, target)) {
00487                 typename BlockVertexMap::iterator bvmi=bv_map.find(target);
00488                 if (bvmi!=bv_map.end())
00489                     add_edge(*vi, bvmi->second, cfg);
00490             }
00491         }
00492     }
00493 }
00494 
00495 template<class ControlFlowGraph>
00496 void
00497 BinaryAnalysis::ControlFlow::build_cg_from_ast(SgNode *root, ControlFlowGraph &cfg/*out*/)
00498 {
00499     struct T1: public EdgeFilter {
00500         EdgeFilter *parent;
00501         T1(EdgeFilter *parent): parent(parent) {}
00502         bool operator()(ControlFlow *analyzer, SgAsmBlock *src, SgAsmBlock *dst) {
00503             SgAsmFunction *func = dst ? dst->get_enclosing_function() : NULL;
00504             if (!func || dst!=func->get_entry_block())
00505                 return false;
00506             if (parent)
00507                 return (*parent)(analyzer, src, dst);
00508             return true;
00509         }
00510     };
00511 
00512     EdgeFilter *parent = get_edge_filter();
00513     T1 edge_filter(parent);
00514     try {
00515         set_edge_filter(&edge_filter);
00516         build_cfg_from_ast(root, cfg);
00517     } catch (...) {
00518         set_edge_filter(parent);
00519         throw;
00520     }
00521     set_edge_filter(parent);
00522 }
00523 
00524 template<class ControlFlowGraph>
00525 void
00526 BinaryAnalysis::ControlFlow::copy(const ControlFlowGraph &src, ControlFlowGraph &dst/*out*/)
00527 {
00528     typedef typename boost::graph_traits<ControlFlowGraph>::vertex_descriptor Vertex;
00529     Vertex NO_VERTEX = boost::graph_traits<ControlFlowGraph>::null_vertex();
00530 
00531     dst.clear();
00532     std::vector<Vertex> src_to_dst(num_vertices(src), NO_VERTEX);
00533 
00534     typename boost::graph_traits<ControlFlowGraph>::vertex_iterator vi, vi_end;
00535     for (boost::tie(vi, vi_end)=vertices(src); vi!=vi_end; ++vi) {
00536         SgAsmBlock *block = get(boost::vertex_name, src, *vi);
00537         if (!is_vertex_filtered(block)) {
00538             src_to_dst[*vi] = add_vertex(dst);
00539             put(boost::vertex_name, dst, src_to_dst[*vi], block);
00540         }
00541     }
00542 
00543     typename boost::graph_traits<ControlFlowGraph>::edge_iterator ei, ei_end;
00544     for (boost::tie(ei, ei_end)=edges(src); ei!=ei_end; ++ei) {
00545         if (NO_VERTEX!=src_to_dst[source(*ei, src)] && NO_VERTEX!=src_to_dst[target(*ei, src)]) {
00546             SgAsmBlock *block1 = get(boost::vertex_name, src, source(*ei, src));
00547             SgAsmBlock *block2 = get(boost::vertex_name, src, target(*ei, src));
00548             if (!is_edge_filtered(block1, block2))
00549                 add_edge(src_to_dst[source(*ei, src)], src_to_dst[target(*ei, src)], dst);
00550         }
00551     }
00552 }
00553 
00554 template<class ControlFlowGraph>
00555 ControlFlowGraph
00556 BinaryAnalysis::ControlFlow::copy(const ControlFlowGraph &src)
00557 {
00558     ControlFlowGraph dst;
00559     copy(src, dst);
00560     return dst;
00561 }
00562 
00563 template<class ControlFlowGraph>
00564 void
00565 BinaryAnalysis::ControlFlow::FlowOrder<ControlFlowGraph>::compute(const ControlFlowGraph &g, Vertex v0,
00566                                                                   ReverseVertexList *reverse_order) {
00567     forward_order->clear();
00568     std::vector<boost::default_color_type> colors(num_vertices(g), boost::white_color);
00569     depth_first_visit(g, v0, *this, &(colors[0]));
00570     assert(!forward_order->empty()); /* it should at least contain v0 */
00571     std::reverse(forward_order->begin(), forward_order->end());
00572     if (reverse_order) {
00573         reverse_order->clear();
00574         reverse_order->resize(num_vertices(g), (size_t)(-1));
00575         for (size_t i=0; i<forward_order->size(); i++)
00576             (*reverse_order)[(*forward_order)[i]] = i;
00577     }
00578 }
00579 
00580 template<class ControlFlowGraph>
00581 void
00582 BinaryAnalysis::ControlFlow::FlowOrder<ControlFlowGraph>::finish_vertex(Vertex v, ControlFlowGraph g) {
00583     forward_order->push_back(v);
00584 }
00585 
00586 template<class ControlFlowGraph>
00587 std::vector<typename boost::graph_traits<ControlFlowGraph>::vertex_descriptor>
00588 BinaryAnalysis::ControlFlow::flow_order(const ControlFlowGraph &cfg,
00589                                         typename boost::graph_traits<ControlFlowGraph>::vertex_descriptor start,
00590                                         std::vector<size_t> *reverse_order/*=NULL*/)
00591 {
00592     std::vector<typename boost::graph_traits<ControlFlowGraph>::vertex_descriptor> forward_order;
00593     FlowOrder<ControlFlowGraph>(&forward_order).compute(cfg, start, reverse_order);
00594     return forward_order;
00595 }
00596 
00597 template<class ControlFlowGraph>
00598 void
00599 BinaryAnalysis::ControlFlow::ReturnBlocks<ControlFlowGraph>::finish_vertex(Vertex v, ControlFlowGraph g)
00600 {
00601     typename boost::graph_traits<ControlFlowGraph>::out_edge_iterator ei, ei_end;
00602     boost::tie(ei, ei_end) = out_edges(v, g);
00603     if (ei==ei_end)
00604         blocks.push_back(v);
00605 }
00606     
00607 template<class ControlFlowGraph>
00608 std::vector<typename boost::graph_traits<ControlFlowGraph>::vertex_descriptor>
00609 BinaryAnalysis::ControlFlow::return_blocks(const ControlFlowGraph &cfg,
00610                                            typename boost::graph_traits<ControlFlowGraph>::vertex_descriptor start)
00611 {
00612     typename ReturnBlocks<ControlFlowGraph>::Vector result;
00613     ReturnBlocks<ControlFlowGraph> visitor(result);
00614     std::vector<boost::default_color_type> colors(num_vertices(cfg), boost::white_color);
00615     depth_first_visit(cfg, start, visitor, &(colors[0]));
00616     return result;
00617 }
00618 
00619 template<class ControlFlowGraph>
00620 ControlFlowGraph
00621 BinaryAnalysis::ControlFlow::build_cfg_from_ast(SgNode *root)
00622 {
00623     ControlFlowGraph cfg;
00624     build_cfg_from_ast(root, cfg);
00625     return cfg;
00626 }
00627 
00628 template<class ControlFlowGraph>
00629 ControlFlowGraph
00630 BinaryAnalysis::ControlFlow::build_cg_from_ast(SgNode *root)
00631 {
00632     ControlFlowGraph cfg;
00633     build_cg_from_ast(root, cfg);
00634     return cfg;
00635 }
00636 
00637 #endif

Generated on Wed May 16 06:17:53 2012 for ROSE by  doxygen 1.4.7