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,
00050 boost::vecS,
00051 boost::bidirectionalS,
00052 boost::property<boost::vertex_name_t, SgAsmFunction*>
00053 > Graph;
00054
00055
00056
00057
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
00134
00135 public:
00136
00151 template<class FunctionCallGraph>
00152 void cache_vertex_descriptors(const FunctionCallGraph&);
00153
00154
00155
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);
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);
00221 template<class FunctionCallGraph>
00222 FunctionCallGraph copy(const FunctionCallGraph &src);
00223 template<class FunctionCallGraph>
00224 void copy(const FunctionCallGraph &src, FunctionCallGraph &dst);
00227 };
00228 }
00229
00230
00231
00232
00233
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)
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
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
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)
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
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
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);
00345 SgAsmFunction *func_a = function_of(block_a);
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());
00351 SgAsmFunction *func_b = function_of(block_b);
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);
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