BinaryFunctionCall.h

Go to the documentation of this file.
00001 #ifndef ROSE_BinaryAnalysis_FunctionCall_H
00002 #define ROSE_BinaryAnalysis_FunctionCall_H
00003 
00004 #include "BinaryControlFlow.h"
00005 
00006 class SgAsmFunction;
00007 
00008 namespace BinaryAnalysis {
00009 
00018     class FunctionCall {
00019     public:
00020 
00021         FunctionCall()
00022             : vertex_filter(NULL), edge_filter(NULL)
00023             {}
00024 
00049         typedef boost::adjacency_list<boost::setS,                                  /* out-edges of each vertex in std::list */
00050                                       boost::vecS,                                  /* store vertices in std::vector */
00051                                       boost::bidirectionalS,                        /* call graph is directed */
00052                                       boost::property<boost::vertex_name_t, SgAsmFunction*>
00053                                      > Graph;
00054 
00055 
00056         /**********************************************************************************************************************
00057          *                                      Filters
00058          **********************************************************************************************************************/
00059     public:
00060 
00065         class VertexFilter {
00066         public:
00067             virtual ~VertexFilter() {}
00068             virtual bool operator()(FunctionCall*, SgAsmFunction*) = 0;
00069         };
00070 
00075         class EdgeFilter {
00076         public:
00077             virtual ~EdgeFilter() {}
00078             virtual bool operator()(FunctionCall*, SgAsmFunction *source, SgAsmFunction *target) = 0;
00079         };
00080 
00088         void set_vertex_filter(VertexFilter *filter) { vertex_filter = filter; }
00089         VertexFilter *get_vertex_filter() const { return vertex_filter; }
00098         void set_edge_filter(EdgeFilter *filter) { edge_filter = filter; }
00099         EdgeFilter *get_edge_filter() const { return edge_filter; }
00107         bool is_vertex_filtered(SgAsmFunction *func, VertexFilter *filter) {
00108             return filter && !(*filter)(this, func);
00109         }
00110         bool is_vertex_filtered(SgAsmFunction *func) {
00111             return is_vertex_filtered(func, vertex_filter);
00112         }
00120         bool is_edge_filtered(SgAsmFunction *src, SgAsmFunction *dst, EdgeFilter *filter) {
00121             return filter && !(*filter)(this, src, dst);
00122         }
00123         bool is_edge_filtered(SgAsmFunction *src, SgAsmFunction *dst) {
00124             return is_edge_filtered(src, dst, edge_filter);
00125         }
00128     protected:
00129         VertexFilter *vertex_filter;
00130         EdgeFilter *edge_filter;
00131 
00132         /**********************************************************************************************************************
00133          *                                      Methods that modify the AST
00134          **********************************************************************************************************************/
00135     public:
00136 
00151         template<class FunctionCallGraph>
00152         void cache_vertex_descriptors(const FunctionCallGraph&);
00153 
00154         /**********************************************************************************************************************
00155          *                                      Graph construction methods
00156          **********************************************************************************************************************/
00157     public:
00158 
00170         template<class FunctionCallGraph, class ControlFlowGraph>
00171         FunctionCallGraph build_cg_from_cfg(const ControlFlowGraph&);
00172 
00173         template<class ControlFlowGraph, class FunctionCallGraph>
00174         void build_cg_from_cfg(const ControlFlowGraph &cfg, FunctionCallGraph &cg/*out*/);
00204         template<class FunctionCallGraph>
00205         FunctionCallGraph build_cg_from_ast(SgNode *root);
00206 
00207         template<class FunctionCallGraph>
00208         void build_cg_from_ast(SgNode *root, FunctionCallGraph &cg/*out*/);
00221         template<class FunctionCallGraph>
00222         FunctionCallGraph copy(const FunctionCallGraph &src);
00223         template<class FunctionCallGraph>
00224         void copy(const FunctionCallGraph &src, FunctionCallGraph &dst/*out*/);
00227     };
00228 }
00229 
00230 
00231 
00232 /******************************************************************************************************************************
00233  *                                      Function template definitions
00234  ******************************************************************************************************************************/
00235 
00236 template<class FunctionCallGraph>
00237 void
00238 BinaryAnalysis::FunctionCall::cache_vertex_descriptors(const FunctionCallGraph &cg)
00239 {
00240     typename boost::graph_traits<FunctionCallGraph>::vertex_iterator vi, vi_end;
00241     for (boost::tie(vi, vi_end)=vertices(cg); vi!=vi_end; ++vi) {
00242         SgAsmFunction *func = get(boost::vertex_name, cg, *vi);
00243         if (func && !is_vertex_filtered(func))
00244             func->set_cached_vertex(*vi);
00245     }
00246 }
00247 
00248 template<class ControlFlowGraph, class FunctionCallGraph>
00249 void
00250 BinaryAnalysis::FunctionCall::build_cg_from_cfg(const ControlFlowGraph &cfg, FunctionCallGraph &cg/*out*/)
00251 {
00252     typedef typename boost::graph_traits<FunctionCallGraph>::vertex_descriptor CG_Vertex;
00253     typedef typename boost::graph_traits<ControlFlowGraph>::vertex_descriptor CFG_Vertex;
00254     typedef std::map<SgAsmFunction*, CG_Vertex> FunctionVertexMap;
00255 
00256     cg.clear();
00257 
00258     /* Add CG vertices by collapsing CFG nodes that belong to a common function. */
00259     FunctionVertexMap fv_map;
00260     typename boost::graph_traits<ControlFlowGraph>::vertex_iterator vi, vi_end;
00261     for (boost::tie(vi, vi_end)=vertices(cfg); vi!=vi_end; ++vi) {
00262         SgAsmBlock *block = get(boost::vertex_name, cfg, *vi);
00263         SgAsmFunction *func = block->get_enclosing_function();
00264         if (!is_vertex_filtered(func)) {
00265             typename FunctionVertexMap::iterator fi=fv_map.find(func);
00266             if (func && fi==fv_map.end()) {
00267                 CG_Vertex v = add_vertex(cg);
00268                 put(boost::vertex_name, cg, v, func);
00269                 fv_map[func] = v;
00270             }
00271         }
00272     }
00273 
00274     /* Add edges whose target is a function entry block. */
00275     typename boost::graph_traits<ControlFlowGraph>::edge_iterator ei, ei_end;
00276     for (boost::tie(ei, ei_end)=edges(cfg); ei!=ei_end; ++ei) {
00277         CFG_Vertex cfg_a = source(*ei, cfg);
00278         CFG_Vertex cfg_b = target(*ei, cfg);
00279         SgAsmBlock *block_a = get(boost::vertex_name, cfg, cfg_a);
00280         SgAsmBlock *block_b = get(boost::vertex_name, cfg, cfg_b);
00281         SgAsmFunction *func_a = block_a->get_enclosing_function();
00282         SgAsmFunction *func_b = block_b->get_enclosing_function();
00283         if (func_a && func_b && block_b==func_b->get_entry_block() && !is_edge_filtered(func_a, func_b)) {
00284             typename FunctionVertexMap::iterator fi_a = fv_map.find(func_a);
00285             if (fi_a!=fv_map.end()) {
00286                 typename FunctionVertexMap::iterator fi_b = fv_map.find(func_b);
00287                 if (fi_b!=fv_map.end())
00288                     add_edge(fi_a->second, fi_b->second, cg);
00289             }
00290         }
00291     }
00292 }
00293 
00294 template<class FunctionCallGraph, class ControlFlowGraph>
00295 FunctionCallGraph
00296 BinaryAnalysis::FunctionCall::build_cg_from_cfg(const ControlFlowGraph &cfg)
00297 {
00298     FunctionCallGraph cg;
00299     build_cg_from_cfg(cfg, cg);
00300     return cg;
00301 }
00302 
00303 template<class FunctionCallGraph>
00304 void
00305 BinaryAnalysis::FunctionCall::build_cg_from_ast(SgNode *root, FunctionCallGraph &cg/*out*/)
00306 {
00307     typedef typename boost::graph_traits<FunctionCallGraph>::vertex_descriptor Vertex;
00308     typedef std::map<SgAsmFunction*, Vertex> FunctionVertexMap;
00309     FunctionVertexMap fv_map;
00310 
00311     cg.clear();
00312 
00313     /* Visiter that adds a vertex for each unique function. */
00314     struct VertexAdder: public AstSimpleProcessing {
00315         FunctionCall *analyzer;
00316         FunctionCallGraph &cg;
00317         FunctionVertexMap &fv_map;
00318         VertexAdder(FunctionCall *analyzer, FunctionCallGraph &cg, FunctionVertexMap &fv_map)
00319             : analyzer(analyzer), cg(cg), fv_map(fv_map)
00320             {}
00321         void visit(SgNode *node) {
00322             SgAsmFunction *func = isSgAsmFunction(node);
00323             if (func && !analyzer->is_vertex_filtered(func)) {
00324                 Vertex vertex = add_vertex(cg);
00325                 fv_map[func] = vertex;
00326                 put(boost::vertex_name, cg, vertex, func);
00327             }
00328         }
00329     };
00330 
00331     /* Visitor that adds edges for each vertex.  Traversal should be over one function at a time. */
00332     struct EdgeAdder: public AstSimpleProcessing {
00333         FunctionCall *analyzer;
00334         FunctionCallGraph &cg;
00335         FunctionVertexMap &fv_map;
00336         Vertex source_vertex;
00337         EdgeAdder(FunctionCall *analyzer, FunctionCallGraph &cg, FunctionVertexMap &fv_map, Vertex source_vertex)
00338             : analyzer(analyzer), cg(cg), fv_map(fv_map), source_vertex(source_vertex)
00339             {}
00340         SgAsmFunction *function_of(SgAsmBlock *block) {
00341             return block ? block->get_enclosing_function() : NULL;
00342         }
00343         void visit(SgNode *node) {
00344             SgAsmBlock *block_a = isSgAsmBlock(node); /* the calling block */
00345             SgAsmFunction *func_a = function_of(block_a); /* the calling function */
00346             if (!func_a)
00347                 return;
00348             const SgAsmIntegerValuePtrList &succs = block_a->get_successors();
00349             for (SgAsmIntegerValuePtrList::const_iterator si=succs.begin(); si!=succs.end(); ++si) {
00350                 SgAsmBlock *block_b = isSgAsmBlock((*si)->get_base_node()); /* the called block */
00351                 SgAsmFunction *func_b = function_of(block_b); /* the called function */
00352                 if (func_b && block_b==func_b->get_entry_block() && !analyzer->is_edge_filtered(func_a, func_b)) {
00353                     typename FunctionVertexMap::iterator fi_b = fv_map.find(func_b); /* find vertex for called function */
00354                     if (fi_b!=fv_map.end())
00355                         add_edge(source_vertex, fi_b->second, cg);
00356                 }
00357             }
00358         }
00359     };
00360 
00361     VertexAdder(this, cg, fv_map).traverse(root, preorder);
00362     typename boost::graph_traits<FunctionCallGraph>::vertex_iterator vi, vi_end;
00363     for (boost::tie(vi, vi_end)=vertices(cg); vi!=vi_end; ++vi) {
00364         SgAsmFunction *source_func = get(boost::vertex_name, cg, *vi);
00365         EdgeAdder(this, cg, fv_map, *vi).traverse(source_func, preorder);
00366     }
00367 }
00368 
00369 template<class FunctionCallGraph>
00370 FunctionCallGraph
00371 BinaryAnalysis::FunctionCall::build_cg_from_ast(SgNode *root)
00372 {
00373     FunctionCallGraph cg;
00374     build_cg_from_ast(root, cg);
00375     return cg;
00376 }
00377 
00378 template<class FunctionCallGraph>
00379 void
00380 BinaryAnalysis::FunctionCall::copy(const FunctionCallGraph &src, FunctionCallGraph &dst)
00381 {
00382     typedef typename boost::graph_traits<FunctionCallGraph>::vertex_descriptor Vertex;
00383     Vertex NO_VERTEX = typename boost::graph_traits<FunctionCallGraph>::null_vertex();
00384 
00385     dst.clear();
00386     std::vector<Vertex> src_to_dst(num_vertices(src), NO_VERTEX);
00387 
00388     typename boost::graph_traits<FunctionCallGraph>::vertex_iterator vi, vi_end;
00389     for (boost::tie(vi, vi_end)=vertices(src); vi!=vi_end; ++vi) {
00390         SgAsmFunction *func = get(boost::vertex_name, src, *vi);
00391         if (!is_vertex_filtered(func)) {
00392             src_to_dst[*vi] = add_vertex(dst);
00393             put(boost::vertex_name, dst, src_to_dst[*vi], func);
00394         }
00395     }
00396 
00397     typename boost::graph_traits<FunctionCallGraph>::edge_iterator ei, ei_end;
00398     for (boost::tie(ei, ei_end)=edges(src); ei!=ei_end; ++ei) {
00399         if (NO_VERTEX!=src_to_dst[source(*ei, src)] && NO_VERTEX!=src_to_dst[target(*ei, src)]) {
00400             SgAsmFunction *func1 = get(boost::vertex_name, src, source(*ei, src));
00401             SgAsmFunction *func2 = get(boost::vertex_name, src, target(*ei, src));
00402             if (!is_edge_filtered(func1, func2))
00403                 add_edge(src_to_dst[source(*ei, src)], src_to_dst[target(*ei, src)], dst);
00404         }
00405     }
00406 }
00407 
00408 template<class FunctionCallGraph>
00409 FunctionCallGraph
00410 BinaryAnalysis::FunctionCall::copy(const FunctionCallGraph &src)
00411 {
00412     FunctionCallGraph dst;
00413     copy(src, dst);
00414     return dst;
00415 }
00416 
00417 
00418 
00419 #endif

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