+read_dot2, write_dot
This commit is contained in:
parent
915e7ec469
commit
4e3d5b005b
100
srcxray.py
100
srcxray.py
|
@ -18,12 +18,15 @@ import collections
|
||||||
import subprocess
|
import subprocess
|
||||||
import re
|
import re
|
||||||
import networkx as nx
|
import networkx as nx
|
||||||
from networkx.drawing.nx_agraph import *
|
# from networkx.drawing.nx_agraph import read_dot # changes order of successors
|
||||||
|
from networkx.drawing.nx_pydot import read_dot
|
||||||
from networkx.generators.ego import *
|
from networkx.generators.ego import *
|
||||||
|
from networkx.utils import open_file, make_str
|
||||||
from pprint import pprint
|
from pprint import pprint
|
||||||
import difflib
|
import difflib
|
||||||
import glob
|
import glob
|
||||||
from pathlib import *
|
from pathlib import *
|
||||||
|
import pygraphviz
|
||||||
|
|
||||||
default_root = 'starts'
|
default_root = 'starts'
|
||||||
black_list = ('aligned __attribute__ unlikely typeof u32'
|
black_list = ('aligned __attribute__ unlikely typeof u32'
|
||||||
|
@ -448,23 +451,24 @@ def digraph_print(dg, starts=None, dst_fn=None, sort=False):
|
||||||
dst = open(dst_fn, 'w') if dst_fn else None
|
dst = open(dst_fn, 'w') if dst_fn else None
|
||||||
|
|
||||||
def digraph_print_sub(path='', node=None, printed=None, level=0):
|
def digraph_print_sub(path='', node=None, printed=None, level=0):
|
||||||
outs = {_: dg.out_degree(_) for _ in dg.successors(node)}
|
if node in black_list:
|
||||||
if sort:
|
return
|
||||||
outs = {a: b for a, b in sorted(outs.items(), key=lambda k: k[1], reverse=True)}
|
|
||||||
if node in printed:
|
if node in printed:
|
||||||
print_limited(level*'\t' + str(node) + ' ^', dst)
|
print_limited(level*'\t' + str(node) + ' ^', dst)
|
||||||
return
|
return
|
||||||
else:
|
outs = {_: dg.out_degree(_) for _ in dg.successors(node)}
|
||||||
s = ''
|
if sort:
|
||||||
if outs:
|
outs = {a: b for a, b in sorted(outs.items(), key=lambda k: k[1], reverse=True)}
|
||||||
s = ' ...' if level > level_limit - 2 else ' @' + path
|
s = ''
|
||||||
print_limited(level*'\t' + str(node) + s, dst)
|
if outs:
|
||||||
|
s = ' ...' if level > level_limit - 2 else ' @' + path
|
||||||
|
print_limited(level*'\t' + str(node) + s, dst)
|
||||||
printed.add(node)
|
printed.add(node)
|
||||||
if level > level_limit - 2:
|
if level > level_limit - 2:
|
||||||
return ''
|
return ''
|
||||||
passed = set()
|
passed = set()
|
||||||
for o in outs.keys():
|
for o in outs.keys():
|
||||||
if o in passed or o in black_list:
|
if o in passed:
|
||||||
continue
|
continue
|
||||||
passed.add(o)
|
passed.add(o)
|
||||||
digraph_print_sub(path + ' ' + str(node), o, printed, level + 1)
|
digraph_print_sub(path + ' ' + str(node), o, printed, level + 1)
|
||||||
|
@ -481,11 +485,13 @@ def digraph_print(dg, starts=None, dst_fn=None, sort=False):
|
||||||
print_limited('\t' + s + ' ->', dst)
|
print_limited('\t' + s + ' ->', dst)
|
||||||
passed = set()
|
passed = set()
|
||||||
for o in starts:
|
for o in starts:
|
||||||
if o in passed or o in black_list:
|
if o in passed:
|
||||||
continue
|
continue
|
||||||
passed.add(o)
|
passed.add(o)
|
||||||
if o in dg:
|
if o in dg:
|
||||||
digraph_print_sub('', o, printed)
|
for o in dg.nodes():
|
||||||
|
if o not in printed:
|
||||||
|
digraph_print_sub('', o, printed)
|
||||||
if dst_fn:
|
if dst_fn:
|
||||||
print(dst_fn)
|
print(dst_fn)
|
||||||
dst.close()
|
dst.close()
|
||||||
|
@ -507,7 +513,7 @@ def cflow_preprocess(a):
|
||||||
s = re.sub(r"SYSCALL_DEFINE[0-9]\((\w*),", r"sys_\1(", s)
|
s = re.sub(r"SYSCALL_DEFINE[0-9]\((\w*),", r"sys_\1(", s)
|
||||||
s = re.sub(r"__setup\(.*,(.*)\)", r"void __setup() {\1();}", s)
|
s = re.sub(r"__setup\(.*,(.*)\)", r"void __setup() {\1();}", s)
|
||||||
s = re.sub(r"^(\w*)param\(.*,(.*)\)", r"void \1param() {\2();}", s)
|
s = re.sub(r"^(\w*)param\(.*,(.*)\)", r"void \1param() {\2();}", s)
|
||||||
s = re.sub(r"(\w*)initcall\((.*)\)",
|
s = re.sub(r"^(\w*)initcall\((.*)\)",
|
||||||
r"void \1initcall() {\2();}", s)
|
r"void \1initcall() {\2();}", s)
|
||||||
s = re.sub(r"^static ", "", s)
|
s = re.sub(r"^static ", "", s)
|
||||||
# s = re.sub(r"__read_mostly", "", s)
|
# s = re.sub(r"__read_mostly", "", s)
|
||||||
|
@ -515,6 +521,8 @@ def cflow_preprocess(a):
|
||||||
s = re.sub(r"^const ", "", s)
|
s = re.sub(r"^const ", "", s)
|
||||||
s = re.sub(r"^struct (.*) =", r"\1()", s)
|
s = re.sub(r"^struct (.*) =", r"\1()", s)
|
||||||
s = re.sub(r"^struct ", "", s)
|
s = re.sub(r"^struct ", "", s)
|
||||||
|
s = re.sub(r"\b__initdata\b", "", s)
|
||||||
|
# s = re.sub(r"__init_or_module", "", s)
|
||||||
# __attribute__
|
# __attribute__
|
||||||
# for line in sys.stdin:
|
# for line in sys.stdin:
|
||||||
sys.stdout.write(s)
|
sys.stdout.write(s)
|
||||||
|
@ -522,7 +530,7 @@ def cflow_preprocess(a):
|
||||||
|
|
||||||
cflow_param = {
|
cflow_param = {
|
||||||
"modifier": "__init __inline__ noinline __initdata __randomize_layout __read_mostly asmlinkage "
|
"modifier": "__init __inline__ noinline __initdata __randomize_layout __read_mostly asmlinkage "
|
||||||
" __visible __init __leaf__ __ref __latent_entropy",
|
" __visible __init __leaf__ __ref __latent_entropy __init_or_module ",
|
||||||
"wrapper": "__attribute__ __section__ "
|
"wrapper": "__attribute__ __section__ "
|
||||||
"TRACE_EVENT MODULE_AUTHOR MODULE_DESCRIPTION MODULE_LICENSE MODULE_LICENSE MODULE_SOFTDEP "
|
"TRACE_EVENT MODULE_AUTHOR MODULE_DESCRIPTION MODULE_LICENSE MODULE_LICENSE MODULE_SOFTDEP "
|
||||||
"__acquires __releases __ATTR"
|
"__acquires __releases __ATTR"
|
||||||
|
@ -555,14 +563,18 @@ def cflow(a):
|
||||||
for p in cflow_param.keys()])
|
for p in cflow_param.keys()])
|
||||||
+ " --include=_sxt --brief --level-indent='0=\t' "
|
+ " --include=_sxt --brief --level-indent='0=\t' "
|
||||||
+ a)
|
+ a)
|
||||||
|
# print(cflow)
|
||||||
return popen(cflow)
|
return popen(cflow)
|
||||||
|
|
||||||
|
|
||||||
def import_cflow(a=None):
|
def import_cflow(a=None, cflow_out=None):
|
||||||
cf = my_graph()
|
cf = my_graph()
|
||||||
stack = list()
|
stack = list()
|
||||||
nprev = -1
|
nprev = -1
|
||||||
|
cflow_out = open(cflow_out, 'w') if cflow_out else None
|
||||||
for line in cflow(a):
|
for line in cflow(a):
|
||||||
|
if cflow_out:
|
||||||
|
cflow_out.write(line + '\n')
|
||||||
# --print-level
|
# --print-level
|
||||||
m = re.match(r'^([\t]*)([^(^ ^<]+)', str(line))
|
m = re.match(r'^([\t]*)([^(^ ^<]+)', str(line))
|
||||||
if m:
|
if m:
|
||||||
|
@ -582,6 +594,45 @@ def import_cflow(a=None):
|
||||||
return cf
|
return cf
|
||||||
|
|
||||||
|
|
||||||
|
def write_dot(g, dot):
|
||||||
|
dot = str(dot)
|
||||||
|
dot = open(dot, 'w')
|
||||||
|
dot.write('strict digraph "None" {\n')
|
||||||
|
dot.write('rankdir=LR;\n')
|
||||||
|
dot.write('node [fontname=Ubuntu,shape=none,fontsize=1000];\n')
|
||||||
|
dot.write('edge [width=1000];\n')
|
||||||
|
g.remove_nodes_from(black_list)
|
||||||
|
for n in g.nodes():
|
||||||
|
if n == ',':
|
||||||
|
continue
|
||||||
|
if not g.out_degree(n):
|
||||||
|
continue
|
||||||
|
# dot.write((n if n != 'node' else '"node"') + ';\n')
|
||||||
|
dot.write((n if n != 'node' else '"node"') + ' -> { ')
|
||||||
|
dot.write(' '.join([str(a) if a != 'node' else '"node"' for a in g.successors(n) if str(a) != ',']))
|
||||||
|
dot.write(' };\n')
|
||||||
|
dot.write('}\n')
|
||||||
|
dot.close()
|
||||||
|
print(dot.name)
|
||||||
|
|
||||||
|
|
||||||
|
@open_file(0, mode='r')
|
||||||
|
def read_dot2(dot):
|
||||||
|
# read_dot pydot.graph_from_dot_data parse_dot_data from_pydot
|
||||||
|
dg = nx.DiGraph()
|
||||||
|
for a in dot:
|
||||||
|
if '->' in a:
|
||||||
|
m = re.match('^(.+) -> {(.+)}', a)
|
||||||
|
if m:
|
||||||
|
dg.add_edges_from([(m.group(1), b) for b in m.group(2).split()])
|
||||||
|
else:
|
||||||
|
m = re.match('(.+) -> (.*);', a)
|
||||||
|
if m:
|
||||||
|
dg.add_edge(m.group(1), m.group(2))
|
||||||
|
print(m.group(1), m.group(2))
|
||||||
|
return dg
|
||||||
|
|
||||||
|
|
||||||
def cflow_linux():
|
def cflow_linux():
|
||||||
dirs = ('init kernel kernel/time '
|
dirs = ('init kernel kernel/time '
|
||||||
'mm fs fs/ext4 block '
|
'mm fs fs/ext4 block '
|
||||||
|
@ -596,19 +647,28 @@ def cflow_linux():
|
||||||
print(a)
|
print(a)
|
||||||
dir = nx.DiGraph()
|
dir = nx.DiGraph()
|
||||||
for c in glob.glob(os.path.join(a, "*.c")):
|
for c in glob.glob(os.path.join(a, "*.c")):
|
||||||
|
g = None
|
||||||
dot = str(Path(c).with_suffix(".dot"))
|
dot = str(Path(c).with_suffix(".dot"))
|
||||||
if not os.path.isfile(dot):
|
if not os.path.isfile(dot):
|
||||||
g = import_cflow(c)
|
g = import_cflow(c, Path(c).with_suffix(".cflow"))
|
||||||
|
print(g['start_kernel'])
|
||||||
write_dot(g, dot)
|
write_dot(g, dot)
|
||||||
print(dot, popen("ctags -x %s | wc -l" % (c))[0], len(set(e[0] for e in g.edges())))
|
print(dot, popen("ctags -x %s | wc -l" % (c))[0], len(set(e[0] for e in g.edges())))
|
||||||
else:
|
else:
|
||||||
g = read_dot(dot)
|
try:
|
||||||
|
g = read_dot(dot)
|
||||||
|
except TypeError:
|
||||||
|
g = nx.drawing.nx_agraph.read_dot(dot)
|
||||||
|
g2 = nx.DiGraph()
|
||||||
|
g2.add_edges_from(g.edges())
|
||||||
|
write_dot(g, dot + '2')
|
||||||
# print(dot)
|
# print(dot)
|
||||||
dir.add_nodes_from(g.nodes())
|
digraph_print(g, [], Path(c).with_suffix(".tree"))
|
||||||
|
# dir.add_nodes_from(g.nodes())
|
||||||
dir.add_edges_from(g.edges())
|
dir.add_edges_from(g.edges())
|
||||||
write_dot(dir, os.path.join(a, 'dir.dot'))
|
write_dot(dir, str(os.path.join(a, 'dir.dot')))
|
||||||
digraph_print(digraph_tree(dir), [], os.path.join(a, 'dir.tree'))
|
digraph_print(digraph_tree(dir), [], os.path.join(a, 'dir.tree'))
|
||||||
all.add_nodes_from(dir.nodes())
|
# all.add_nodes_from(dir.nodes())
|
||||||
all.add_edges_from(dir.edges())
|
all.add_edges_from(dir.edges())
|
||||||
write_dot(all, 'all.dot')
|
write_dot(all, 'all.dot')
|
||||||
digraph_print(all, ['x86_64_start_kernel', 'start_kernel', 'main', 'initcall', 'early_param', '__setup'],
|
digraph_print(all, ['x86_64_start_kernel', 'start_kernel', 'main', 'initcall', 'early_param', '__setup'],
|
||||||
|
|
Loading…
Reference in New Issue