mirror of
https://github.com/cea-sec/miasm
synced 2026-06-21 13:48:18 +00:00
ed5c3668cc
* API has changed, so old scripts need updates * See example for API usage * Use tcc or llvm for jit emulation * Go to test and run test_all.py to check install Enjoy !
127 lines
3.2 KiB
Python
127 lines
3.2 KiB
Python
class DiGraph:
|
|
|
|
def __init__(self):
|
|
self._nodes = set()
|
|
self._edges = []
|
|
self._nodes_to = {}
|
|
self._nodes_from = {}
|
|
|
|
def __repr__(self):
|
|
out = []
|
|
for n in self._nodes:
|
|
out.append(str(n))
|
|
for a, b in self._edges:
|
|
out.append("%s -> %s" % (a, b))
|
|
return '\n'.join(out)
|
|
|
|
def nodes(self):
|
|
return self._nodes
|
|
|
|
def edges(self):
|
|
return self._edges
|
|
|
|
def add_node(self, n):
|
|
if n in self._nodes:
|
|
return
|
|
self._nodes.add(n)
|
|
self._nodes_to[n] = []
|
|
self._nodes_from[n] = []
|
|
|
|
def add_edge(self, a, b):
|
|
if not a in self._nodes:
|
|
self.add_node(a)
|
|
if not b in self._nodes:
|
|
self.add_node(b)
|
|
self._edges.append((a, b))
|
|
self._nodes_to[a].append((a, b))
|
|
self._nodes_from[b].append((a, b))
|
|
|
|
def add_uniq_edge(self, a, b):
|
|
if (a, b) in self._edges:
|
|
return
|
|
else:
|
|
self.add_edge(a, b)
|
|
|
|
def del_edge(self, a, b):
|
|
self._edges.remove((a, b))
|
|
self._nodes_to[a].remove((a, b))
|
|
self._nodes_from[b].remove((a, b))
|
|
|
|
def predecessors_iter(self, n):
|
|
if not n in self._nodes_from:
|
|
raise StopIteration
|
|
for a, _ in self._nodes_from[n]:
|
|
yield a
|
|
|
|
def predecessors(self, n):
|
|
return [x for x in self.predecessors_iter(n)]
|
|
|
|
def successors_iter(self, n):
|
|
if not n in self._nodes_to:
|
|
raise StopIteration
|
|
for _, b in self._nodes_to[n]:
|
|
yield b
|
|
|
|
def successors(self, n):
|
|
return [x for x in self.successors_iter(n)]
|
|
|
|
def leaves_iter(self):
|
|
for n in self._nodes:
|
|
if len(self._nodes_to[n]) == 0:
|
|
yield n
|
|
|
|
def leaves(self):
|
|
return [x for x in self.leaves_iter()]
|
|
|
|
def roots_iter(self):
|
|
for n in self._nodes:
|
|
if len(self._nodes_from[n]) == 0:
|
|
yield n
|
|
|
|
def roots(self):
|
|
return [x for x in self.roots_iter()]
|
|
|
|
def find_path(self, a, b, cycles_count=0, done=None):
|
|
if done is None:
|
|
done = {}
|
|
if b in done and done[b] > cycles_count:
|
|
return [[]]
|
|
if a == b:
|
|
return [[a]]
|
|
out = []
|
|
for n in self.predecessors(b):
|
|
done_n = dict(done)
|
|
done_n[b] = done_n.get(b, 0) + 1
|
|
for path in self.find_path(a, n, cycles_count, done_n):
|
|
if path and path[0] == a:
|
|
out.append(path + [b])
|
|
return out
|
|
|
|
def node2str(self, n):
|
|
return str(n)
|
|
|
|
def edge2str(self, a, b):
|
|
return ""
|
|
|
|
def dot(self):
|
|
out = """
|
|
digraph asm_graph {
|
|
graph [
|
|
splines=polyline,
|
|
];
|
|
node [
|
|
fontsize = "16",
|
|
shape = "box"
|
|
];
|
|
"""
|
|
for n in self.nodes():
|
|
out += '%s [label="%s"];\n' % (
|
|
hash(n) & 0xFFFFFFFFFFFFFFFF, self.node2str(n))
|
|
|
|
for a, b in self.edges():
|
|
out += '%s -> %s [label="%s"]\n' % (hash(a) & 0xFFFFFFFFFFFFFFFF,
|
|
hash(b) & 0xFFFFFFFFFFFFFFFF,
|
|
self.edge2str(a, b))
|
|
out += "}"
|
|
return out
|