mirror of
https://github.com/radareorg/radare2.git
synced 2024-12-02 18:27:18 +00:00
197 lines
4.5 KiB
C
197 lines
4.5 KiB
C
/* radare - LGPL - Copyright 2007-2012 - pancake */
|
|
/* graph with stack facilities implementation */
|
|
|
|
#include <r_util.h>
|
|
|
|
#if 0
|
|
RGraph *r_anal_getgraph(RAnal *anal, ut64 addr) {
|
|
RGraph *g;
|
|
RFunction *f = r_anal_fcn_get (anal, addr);
|
|
if (!f) return NULL;
|
|
g = r_graph_new ();
|
|
// walk basic blocks, and create nodes and edges
|
|
}
|
|
|
|
// r_anal_graph_to_kv()
|
|
node.0x804840={"name":"patata",size:123,"code":"jlasdfjlksf"}
|
|
node.0x804840.to=[0x804805,0x804805,0x0485085,0x90850]
|
|
#endif
|
|
|
|
R_API RGraphNode *r_graph_node_new (ut64 addr, void *data) {
|
|
RGraphNode *p = R_NEW0 (RGraphNode);
|
|
p->parents = r_list_new ();
|
|
p->children = r_list_new ();
|
|
p->addr = addr;
|
|
p->data = data;
|
|
p->refs = 0;
|
|
return p;
|
|
}
|
|
|
|
R_API void r_graph_node_free (RGraphNode *n) {
|
|
r_list_free (n->parents);
|
|
r_list_free (n->children);
|
|
if (n->free)
|
|
n->free (n->data);
|
|
free (n);
|
|
}
|
|
|
|
static void walk_children (RGraph *t, RGraphNode *tn, int level) {
|
|
int i;
|
|
RListIter *iter;
|
|
RGraphNode *n;
|
|
if (r_list_contains (t->path, tn)) {
|
|
// do not repeat pushed nodes
|
|
return;
|
|
}
|
|
for (i=0; i<level; i++)
|
|
t->printf (" ");
|
|
t->printf (" 0x%08"PFMT64x" refs %d\n",
|
|
tn->addr, tn->refs);
|
|
r_list_foreach (tn->parents, iter, n) {
|
|
for (i=0; i<level; i++)
|
|
t->printf (" ");
|
|
t->printf (" |_ 0x%08"PFMT64x"\n", n->addr);
|
|
}
|
|
r_list_push (t->path, tn);
|
|
r_list_foreach (tn->children, iter, n) {
|
|
walk_children (t, n, level+1);
|
|
}
|
|
r_list_pop (t->path);
|
|
}
|
|
|
|
R_API void r_graph_traverse(RGraph *t) {
|
|
RListIter *iter;
|
|
RGraphNode *root;
|
|
RList *path = t->path;
|
|
t->path = r_list_new ();
|
|
r_list_foreach (t->roots, iter, root) {
|
|
walk_children (t, root, 0);
|
|
}
|
|
r_list_free (t->path);
|
|
t->path = path;
|
|
}
|
|
|
|
R_API RGraph* r_graph_new () {
|
|
RGraph *t = R_NEW0 (RGraph);
|
|
t->printf = (PrintfCallback) printf;
|
|
t->path = r_list_new ();
|
|
t->nodes = r_list_new ();
|
|
t->roots = r_list_new ();
|
|
t->nodes->free = (RListFree)r_graph_node_free;
|
|
t->root = NULL;
|
|
t->cur = NULL;
|
|
return t;
|
|
}
|
|
|
|
R_API void r_graph_free (RGraph* t) {
|
|
r_list_free (t->nodes);
|
|
r_list_free (t->path);
|
|
free (t);
|
|
}
|
|
|
|
R_API RGraphNode* r_graph_get_current (RGraph *t, ut64 addr) {
|
|
return t->cur? t->cur->data: NULL;
|
|
}
|
|
|
|
R_API RGraphNode* r_graph_get_node (RGraph *t, ut64 addr, boolt c) {
|
|
RListIter *iter;
|
|
RGraphNode *n;
|
|
r_list_foreach (t->nodes, iter, n) {
|
|
if (n->addr == addr)
|
|
return n;
|
|
}
|
|
if (c) {
|
|
n = r_graph_node_new (addr, NULL);
|
|
r_list_append (t->nodes, n);
|
|
return n;
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
R_API void r_graph_reset (RGraph *t) {
|
|
r_list_free (t->nodes);
|
|
t->nodes = r_list_new ();
|
|
t->nodes->free = (RListFree)r_graph_node_free;
|
|
r_list_free (t->roots);
|
|
t->roots = r_list_new ();
|
|
t->root = NULL;
|
|
}
|
|
|
|
// g.add (0x804840, 0x804408, null);
|
|
R_API void r_graph_add (RGraph *t, ut64 from, ut64 addr, void *data) {
|
|
RGraphNode *n, *f = r_graph_get_node (t, from, R_TRUE);
|
|
n = r_graph_get_node (t, addr, R_TRUE);
|
|
n->data = data;
|
|
if (!r_list_contains (f->children, n))
|
|
r_list_append (f->children, n);
|
|
if (!r_list_contains (f->parents, n))
|
|
r_list_append (n->parents, f);
|
|
}
|
|
|
|
// plant: to set new root :)
|
|
R_API void r_graph_plant(RGraph *t) {
|
|
t->root = NULL;
|
|
}
|
|
|
|
R_API void r_graph_push (RGraph *t, ut64 addr, void *data) {
|
|
RGraphNode *c, *n = r_graph_get_node (t, addr, R_FALSE);
|
|
t->level++;
|
|
if (!n) {
|
|
n = r_graph_node_new (addr, data);
|
|
r_list_append (t->nodes, n);
|
|
if (t->root == NULL) {
|
|
t->root = n;
|
|
r_list_append (t->roots, n);
|
|
}
|
|
} else {
|
|
n->refs++;
|
|
n->data = data; // update data if already pushed?
|
|
}
|
|
if (!t->cur)
|
|
t->cur = r_list_contains (t->nodes, n);
|
|
c = t->cur->data;
|
|
if (!r_list_contains (c->children, n))
|
|
r_list_append (c->children, n);
|
|
if (c->addr && !r_list_contains (n->parents, c))
|
|
r_list_append (n->parents, c);
|
|
t->cur = r_list_append (t->path, n);
|
|
}
|
|
|
|
R_API RGraphNode* r_graph_pop(RGraph *t) {
|
|
RListIter *p;
|
|
if (!t || !t->path || !t->cur)
|
|
return NULL;
|
|
// TODO: handle null
|
|
t->level--;
|
|
if (t->level<0) {
|
|
eprintf ("Negative pop!\n");
|
|
return NULL;
|
|
}
|
|
p = t->cur->p;
|
|
r_list_delete (t->path, t->cur);
|
|
t->cur = p;
|
|
return (RGraphNode*)t->cur;
|
|
}
|
|
|
|
#if TEST
|
|
// usage
|
|
main () {
|
|
RGraph *t = r_graph_new ();
|
|
r_graph_push (t, 0x8048590, NULL);
|
|
r_graph_push (t, 0x8048230, NULL);
|
|
r_graph_pop (t);
|
|
r_graph_push (t, 0x8044300, NULL);
|
|
r_graph_push (t, 0x8046300, NULL);
|
|
r_graph_pop (t);
|
|
r_graph_push (t, 0x8046388, NULL);
|
|
r_graph_pop (t);
|
|
r_graph_push (t, 0x8046388, NULL);
|
|
r_graph_push (t, 0x8046388, NULL);
|
|
r_graph_push (t, 0x8046300, NULL);
|
|
r_graph_push (t, 0x8046300, NULL);
|
|
r_graph_pop (t);
|
|
r_graph_traverse (t);
|
|
r_graph_free (t);
|
|
}
|
|
#endif
|