#ifndef __CPUI_CALLGRAPH__
#define __CPUI_CALLGRAPH__
#include "address.hh"
class Architecture;
class Funcdata;
class CallGraphNode;
class CallGraph;
class CallGraphEdge {
public:
enum {
cycle = 1, dontfollow = 2 };
private:
friend class CallGraphNode;
friend class CallGraph;
CallGraphNode *from; CallGraphNode *to; Address callsiteaddr; int4 complement; mutable uint4 flags;
public:
CallGraphEdge(void) { flags = 0; }
bool isCycle(void) const { return ((flags&1)!=0); }
void saveXml(ostream &s) const;
const Address &getCallSiteAddr(void) const { return callsiteaddr; }
static void restoreXml(const Element *el,CallGraph *graph);
};
class CallGraphNode {
public:
enum {
mark = 1,
onlycyclein = 2,
currentcycle = 4,
entrynode = 8
};
private:
friend class CallGraph;
Address entryaddr; string name; Funcdata *fd; vector<CallGraphEdge> inedge;
vector<CallGraphEdge> outedge;
int4 parentedge; mutable uint4 flags;
public:
CallGraphNode(void) { fd = (Funcdata *)0; flags = 0; parentedge = -1; }
void clearMark(void) const { flags &= ~((uint4)mark); }
bool isMark(void) const { return ((flags&mark)!=0); }
const Address getAddr(void) const { return entryaddr; }
const string &getName(void) const { return name; }
Funcdata *getFuncdata(void) const { return fd; }
int4 numInEdge(void) const { return inedge.size(); }
const CallGraphEdge &getInEdge(int4 i) const { return inedge[i]; }
CallGraphNode *getInNode(int4 i) const { return inedge[i].from; }
int4 numOutEdge(void) const { return outedge.size(); }
const CallGraphEdge &getOutEdge(int4 i) const { return outedge[i]; }
CallGraphNode *getOutNode(int4 i) const { return outedge[i].to; }
void setFuncdata(Funcdata *f);
void saveXml(ostream &s) const;
static void restoreXml(const Element *el,CallGraph *graph);
};
struct LeafIterator {
CallGraphNode *node;
int4 outslot;
LeafIterator(CallGraphNode *n) { node=n; outslot = 0; }
};
class Scope; class CallGraph {
Architecture *glb;
map<Address,CallGraphNode> graph; vector<CallGraphNode *> seeds;
bool findNoEntry(vector<CallGraphNode *> &seeds);
void snipCycles(CallGraphNode *node);
void snipEdge(CallGraphNode *node,int4 i);
void clearMarks(void);
void cycleStructure(void);
CallGraphNode *popPossible(CallGraphNode *node,int4 &outslot);
CallGraphNode *pushPossible(CallGraphNode *node,int4 outslot);
CallGraphEdge &insertBlankEdge(CallGraphNode *node,int4 slot);
void iterateScopesRecursive(Scope *scope);
void iterateFunctionsAddrOrder(Scope *scope);
public:
CallGraph(Architecture *g) { glb = g; }
Architecture *getArch(void) const { return glb; }
CallGraphNode *addNode(Funcdata *f);
CallGraphNode *addNode(const Address &addr,const string &nm);
CallGraphNode *findNode(const Address &addr);
void addEdge(CallGraphNode *from,CallGraphNode *to,const Address &addr);
void deleteInEdge(CallGraphNode *node,int4 i);
CallGraphNode * initLeafWalk(void);
CallGraphNode *nextLeaf(CallGraphNode *node);
map<Address,CallGraphNode>::iterator begin(void) { return graph.begin(); }
map<Address,CallGraphNode>::iterator end(void) { return graph.end(); }
void buildAllNodes(void);
void buildEdges(Funcdata *fd);
void saveXml(ostream &s) const;
void restoreXml(const Element *el);
};
#endif