// Example ParseAPI program; produces a graph (in DOT format) of the // control flow graph of the provided binary. // // Improvements by E. Robbins (er209 at kent dot ac dot uk) // #include #include #include #include #include #include #include "CodeObject.h" #include "CFG.h" using namespace std; using namespace Dyninst; using namespace ParseAPI; int main(int argc, char * argv[]) { map seen; vector funcs; SymtabCodeSource *sts; CodeObject *co; // Create a new binary code object from the filename argument sts = new SymtabCodeSource( argv[1] ); co = new CodeObject( sts ); // Parse the binary co->parse(); cout << "digraph G {" << endl; // Print the control flow graph const CodeObject::funclist& all = co->funcs(); auto fit = all.begin(); for(int i = 0; fit != all.end(); ++fit, i++) { // i is index for clusters Function *f = *fit; // Make a cluster for nodes of this function cout << "\t subgraph cluster_" << i << " { \n\t\t label=\"" << f->name() << "\"; \n\t\t color=blue;" << endl; cout << "\t\t\"" << hex << f->addr() << dec << "\" [shape=box"; if (f->retstatus() == NORETURN) cout << ",color=red"; cout << "]" << endl; // Label functions by name cout << "\t\t\"" << hex << f->addr() << dec << "\" [label = \"" << f->name() << "\\n" << hex << f->addr() << dec << "\"];" << endl; stringstream edgeoutput; auto bit = f->blocks().begin(); for( ; bit != f->blocks().end(); ++bit) { Block *b = *bit; // Don't revisit blocks in shared code if(seen.find(b->start()) != seen.end()) continue; seen[b->start()] = true; cout << "\t\t\"" << hex << b->start() << dec << "\";" << endl; auto it = b->targets().begin(); for( ; it != b->targets().end(); ++it) { if(!*it) continue; std::string s = ""; if((*it)->type() == CALL) s = " [color=blue]"; else if((*it)->type() == RET) s = " [color=green]"; // Store the edges somewhere to be printed outside of the cluster edgeoutput << "\t\"" << hex << (*it)->src()->start() << "\" -> \"" << (*it)->trg()->start() << "\"" << s << endl; } } // End cluster cout << "\t}" << endl; // Print edges cout << edgeoutput.str() << endl; } cout << "}" << endl; }