mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-04 18:29:37 +02:00
128 lines
4.4 KiB
C++
128 lines
4.4 KiB
C++
/* ###
|
|
* IP: GHIDRA
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
#ifndef __CALLGRAPH_HH__
|
|
#define __CALLGRAPH_HH__
|
|
|
|
#include "address.hh"
|
|
|
|
namespace ghidra {
|
|
|
|
// Forward declarations
|
|
class Architecture;
|
|
class Funcdata;
|
|
class CallGraphNode;
|
|
class CallGraph;
|
|
|
|
extern ElementId ELEM_CALLGRAPH; ///< Marshaling element \<callgraph>
|
|
extern ElementId ELEM_NODE; ///< Marshaling element \<node>
|
|
|
|
class CallGraphEdge {
|
|
public:
|
|
enum {
|
|
cycle = 1, // Edge that was snipped to eliminate cycles
|
|
dontfollow = 2 // Edge that is not in the spanning tree
|
|
};
|
|
private:
|
|
friend class CallGraphNode;
|
|
friend class CallGraph;
|
|
CallGraphNode *from; // Node of the caller
|
|
CallGraphNode *to; // Node of the callee
|
|
Address callsiteaddr; // Address where call was made from
|
|
int4 complement; // Index of complementary edge
|
|
mutable uint4 flags;
|
|
public:
|
|
CallGraphEdge(void) { flags = 0; }
|
|
bool isCycle(void) const { return ((flags&1)!=0); }
|
|
void encode(Encoder &encoder) const;
|
|
const Address &getCallSiteAddr(void) const { return callsiteaddr; }
|
|
static void decode(Decoder &decoder,CallGraph *graph);
|
|
};
|
|
|
|
class CallGraphNode {
|
|
public:
|
|
enum {
|
|
mark = 1,
|
|
onlycyclein = 2,
|
|
currentcycle = 4,
|
|
entrynode = 8
|
|
};
|
|
private:
|
|
friend class CallGraph;
|
|
Address entryaddr; // Starting address of function
|
|
string name; // Name of the function if available
|
|
Funcdata *fd; // Pointer to funcdata if we have it
|
|
vector<CallGraphEdge> inedge;
|
|
vector<CallGraphEdge> outedge;
|
|
int4 parentedge; // Incoming edge for spanning tree
|
|
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 encode(Encoder &encoder) const;
|
|
static void decode(Decoder &decoder,CallGraph *graph);
|
|
};
|
|
|
|
struct LeafIterator {
|
|
CallGraphNode *node;
|
|
int4 outslot;
|
|
LeafIterator(CallGraphNode *n) { node=n; outslot = 0; }
|
|
};
|
|
|
|
class Scope; // forward declaration
|
|
class CallGraph {
|
|
Architecture *glb;
|
|
map<Address,CallGraphNode> graph; // Nodes in the graph sorted by address
|
|
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; }
|
|
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 encode(Encoder &encoder) const;
|
|
void decoder(Decoder &decoder);
|
|
};
|
|
|
|
} // End namespace ghidra
|
|
#endif
|