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,
00138 boost::vecS,
00139 boost::bidirectionalS,
00140 boost::property<boost::vertex_name_t, SgAsmBlock*> > Graph;
00141
00142
00143
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
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
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);
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);
00312 template<class ControlFlowGraph>
00313 ControlFlowGraph copy(const ControlFlowGraph &src);
00314
00315 template<class ControlFlowGraph>
00316 void copy(const ControlFlowGraph &src, ControlFlowGraph &dst);
00319
00320
00321
00322
00323 private:
00324
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
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
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
00418 const SgAsmIntegerValuePtrList &targets = block->get_successors();
00419 for (SgAsmIntegerValuePtrList::const_iterator ti=targets.begin(); ti!=targets.end(); ++ti)
00420 delete *ti;
00421
00422
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
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);
00478
00479
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());
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)
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)
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());
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)
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