6767 'current_user_ns spin_lock_irq spin_unlock_irq prepare_creds '
6868 'tasklist_lock commit_creds read_lock read_unlock SIGKILL SIGSTOP abort_creds fd_install '
6969 'real_mount FMODE_WRITE tv_nsec putname '
70- ).split ()
70+ ).split () # TODO: move to file
7171
7272
7373level_limit = 10
8181
8282
8383def print_limited (a , out = None ):
84+ # exits when reaches limit of printed lines
8485 out = out if out else sys .stdout
8586 out .write (str (a ) + '\n ' )
8687 global n
@@ -92,6 +93,7 @@ def print_limited(a, out=None):
9293
9394
9495def log (* args , ** kwargs ):
96+ # log with context function
9597 if not verbose :
9698 return
9799 s = str (* args ).rstrip ()
@@ -102,11 +104,15 @@ def log(*args, **kwargs):
102104
103105
104106def popen (p ):
107+ # shortcut for reading output of subcommand
105108 log (p )
106109 return check_output (p , shell = True ).decode ('utf-8' ).splitlines ()
107110
108111
109112def extract_referrer (line ):
113+ # Extract referrer function from oupput of
114+ # git grep --show-function.
115+ # With quirks for linux kernel
110116 line = re .sub (r'__ro_after_init' , '' , line )
111117 line = re .sub (r'FNAME\((\w+)\)' , r'\1' , line )
112118 line = re .sub (r'.*TRACE_EVENT.*' , '' , line )
@@ -122,6 +128,7 @@ def extract_referrer(line):
122128
123129
124130def extract_referrer_test ():
131+ # unittest of extract_referrer
125132 passed = 0
126133 for a in {
127134 "f=1=good2()" ,
@@ -147,6 +154,10 @@ def extract_referrer_test():
147154
148155
149156def func_referrers_git_grep (name ):
157+ # Subfunction for searching referrers with
158+ # git grep --show-function.
159+ # Works slowly.
160+ # Obsoleted by doxygen_xml.
150161 res = list ()
151162 r = None
152163 for line in popen (r'git grep --threads 1 --no-index --word-regexp '
@@ -179,6 +190,9 @@ def func_referrers_git_grep(name):
179190
180191
181192def func_referrers_cscope (name ):
193+ # Subfunction for searching referrers with cscope.
194+ # Works fast.
195+ # Obsoleted by doxygen_xml.
182196 global cscope_warned
183197 if not os .path .isfile ('cscope.out' ):
184198 if not cscope_warned :
@@ -201,14 +215,11 @@ def func_referrers_cscope(name):
201215 return res
202216
203217
204- def func_referrers_all (name ):
205- return list (dict .fromkeys (func_referrers_git_grep (name ) + func_referrers_cscope (name )))
206-
207-
208218def referrers_tree (name , referrer = None , printed = None , level = 0 ):
209219 '''
210- Arg: <identifier>
220+ Arg: <identifier> - prints text referrers tree.
211221 Ex: nfs_root_data
222+ Obsoleted by doxygen_xml.
212223 '''
213224 if not referrer :
214225 if os .path .isfile ('cscope.out' ):
@@ -239,16 +250,17 @@ def referrers_tree(name, referrer=None, printed=None, level=0):
239250
240251def referrers (name ):
241252 '''
242- Arg: <identifier>
253+ Arg: <identifier> - simply greps referrers of a symbol
243254 Ex: nfs_root_data
255+ Prefer to use doxygen_xml.
244256 '''
245- # for a in func_referrers_git_grep(name):
246- # print("%s:%s: %s"%(a[0],a[1],a[2]))
247257 print (' ' .join ([a [2 ] for a in func_referrers_git_grep (name )]))
248258
249259
250260def referrers_dep (name , referrer = None , printed = None , level = 0 ):
251- # Arg: <identifier>
261+ # Arg: <identifier> - prints referrers tree in compact format of
262+ # dependency of make
263+ # Obsoleted by doxygen_xml.
252264 if not referrer :
253265 if os .path .isfile ('cscope.out' ):
254266 referrer = func_referrers_cscope
@@ -278,8 +290,9 @@ def referrers_dep(name, referrer=None, printed=None, level=0):
278290
279291def call_tree (node , printed = None , level = 0 ):
280292 '''
281- Arg: <identifier>
293+ Arg: <identifier> - prints call tree of a function
282294 Ex: start_kernel
295+ Obsoleted by doxygen_xml.
283296 '''
284297 if not os .path .isfile ('cscope.out' ):
285298 print ("Please run: cscope -Rcbk" , file = sys .stderr )
@@ -308,6 +321,8 @@ def call_tree(node, printed=None, level=0):
308321
309322
310323def call_dep (node , printed = None , level = 0 ):
324+ # prints call tree in compact format of dependency of make
325+ # Obsoleted by doxygen_xml.
311326 if not os .path .isfile ('cscope.out' ):
312327 print ("Please run: cscope -Rcbk" , file = sys .stderr )
313328 return False
@@ -334,6 +349,7 @@ def call_dep(node, printed=None, level=0):
334349
335350
336351def my_graph (name = None ):
352+ # common subfunction
337353 g = nx .DiGraph (name = name )
338354 # g.graph.update({'node': {'shape': 'none', 'fontsize': 50}})
339355 # g.graph.update({'rankdir': 'LR', 'nodesep': 0, })
@@ -354,7 +370,9 @@ def reduce_graph(g, m=None):
354370 return g
355371
356372
357- def includes (a ):
373+ def includes (sym ):
374+ # subfunction, used in syscalls
375+ # extracts include files of a symbol
358376 res = []
359377 # log(a)
360378 for a in popen ('man -s 2 %s 2> /dev/null |'
@@ -376,19 +394,24 @@ def includes(a):
376394 if res and len (res ) > 1 :
377395 r = set ()
378396 for f in res :
379- # log('grep " %s \+\(" --include "%s" -r /usr/include/'%(a , f))
397+ # log('grep " %s \+\(" --include "%s" -r /usr/include/'%(sym , f))
380398 # log(os.system(
381- # 'grep -w "%s" --include "%s" -r /usr/include/'%(a , f)))
399+ # 'grep -w "%s" --include "%s" -r /usr/include/'%(sym , f)))
382400 if 0 != os .system (
383401 'grep " %s *(" --include "%s" -r /usr/include/ -q'
384- % (a , os .path .basename (f ))):
402+ % (sym , os .path .basename (f ))):
385403 r .add (f )
386404 res = res .difference (r )
387405 log (res )
388406 return ',' .join (list (res )) if res else 'unexported'
389407
390408
391409def syscalls ():
410+ # Experimental function for exporting syscalls info
411+ # from various sources.
412+ # Used in creation of
413+ # https://en.wikibooks.org/wiki/The_Linux_Kernel/Syscalls
414+ # Ex: srcxray.py "write_dot(syscalls(), 'syscalls.dot')"
392415 sc = my_graph ('syscalls' )
393416 inc = 'includes.list'
394417 if not os .path .isfile (inc ):
@@ -454,20 +477,9 @@ def syscalls():
454477 return sc
455478
456479
457- # DiGraph
458- # write_dot to_agraph AGraph
459- # agwrite
460- # srcxray.py 'write_dot(syscalls(), "syscalls.dot")'
461- # write_graphml
462- # srcxray.py "most_used(read_dot('a.dot'))"
463- # srcxray.py "digraph_print(read_dot('a.dot'))"
464- # srcxray.py "write_dot(reduce_graph(read_dot('no-loops.dot')),'reduced.dot')"
465- # a=sys_clone;srcxray.py "write_dot(rank_couples(reduce_graph(remove_loops(read_dot('$a.dot')))),'$a.dot')"
466- # srcxray.py "pprint(most_used(read_dot('a.dot')))"
467- # srcxray.py "write_dot(add_rank('reduced.dot'), 'ranked.dot')"
468- # srcxray.py "write_dot(remove_loops(read_dot('reduced.dot')), 'no-loops.dot')"
469-
470480def cleanup (a ):
481+ # cleanups graph file
482+ # wrapper for remove_nodes_from
471483 log ('' )
472484 g = to_dg (a )
473485 print (dg .number_of_edges ())
@@ -480,15 +492,7 @@ def sort_dict(d):
480492 return [a for a , b in sorted (d .items (), key = lambda k : k [1 ], reverse = True )]
481493
482494
483- def most_used (dg , ins = 10 , outs = 10 ):
484- # return {a: b for a, b in sorted(dg.in_degree, key=lambda k: k[1]) if b > 1 and}
485- # return [(x, dg.in_degree(x), dg.out_degree(x))
486- return [x
487- for x in dg .nodes ()
488- if dg .in_degree (x ) >= ins and dg .out_degree (x ) >= outs ]
489-
490-
491- def starts (dg ): # roots
495+ def starts (dg ): # roots of trees in a graph
492496 return {n : dg .out_degree (n ) for (n , d ) in dg .in_degree if not d }
493497
494498
@@ -559,6 +563,7 @@ def sub(node):
559563def digraph_print (dg , starts = None , dst_fn = None , sort = False ):
560564 '''
561565 Arg: <graph> - print graphs as text tree
566+ Ex2: \" digraph_print(read_dot('a.dot'))\"
562567 '''
563568 dst = open (dst_fn , 'w' ) if dst_fn else None
564569 printed = set ()
@@ -777,6 +782,7 @@ def write_dot(g, dot):
777782 '''
778783 Arg: <graph> <file> - writes a graph into a file with custom attributes
779784 '''
785+ # Other similar external functions to_agraph agwrite
780786 dot = str (dot )
781787 dot = open (dot , 'w' )
782788 dot .write ('strict digraph "None" {\n ' )
@@ -867,6 +873,7 @@ def to_dg(a):
867873
868874
869875def remove_loops (dg ):
876+ # srcxray.py "write_dot(remove_loops(read_dot('reduced.dot')), 'no-loops.dot')"
870877 rm = []
871878 visited = set ()
872879 path = [object ()]
@@ -903,6 +910,7 @@ def remove_couples(dg):
903910
904911
905912def rank_couples (dg ):
913+ # a=sys_clone;srcxray.py "write_dot(rank_couples(reduce_graph(remove_loops(read_dot('$a.dot')))),'$a.dot')"
906914 couples = []
907915 ranked = set ()
908916 for n in dg :
@@ -1048,6 +1056,7 @@ def dot_expand(a, b):
10481056
10491057
10501058def add_rank (g ):
1059+ # srcxray.py "write_dot(add_rank('reduced.dot'), 'ranked.dot')"
10511060 g = to_dg (g )
10521061 passed1 = set ()
10531062 passed2 = set ()
@@ -1079,6 +1088,7 @@ def add_rank(g):
10791088
10801089
10811090def import_symbols ():
1091+ # extracts and import symbols from shared libraries
10821092 sym = my_graph ('symbols' )
10831093 for l in popen ('(shopt -s globstar; nm -D -C -A **/*.so.*)' ):
10841094 q = l .split (maxsplit = 2 )
@@ -1165,6 +1175,7 @@ def doxygen(*input):
11651175def doxygen_xml (a ):
11661176 '''
11671177 Arg: <xml directory generated by doxygen> - extracts call graph
1178+ Ex2: \" write_dot(doxygen_xml('xml'), 'doxygen.dot')\"
11681179 '''
11691180 g = my_graph ()
11701181 for x in list (glob .glob (os .path .join (a , "*.xml" )) + [a ]):
@@ -1234,6 +1245,7 @@ def usage():
12341245
12351246class _unittest_autotest (unittest .TestCase ):
12361247 def test_1 (self ):
1248+ extract_referrer_test ()
12371249 write_dot (nx .DiGraph ([(1 , 2 ), (2 , 3 ), (2 , 4 )]), 'test.dot' )
12381250 g = read_dot ("test.dot" )
12391251 self .assertEqual (list (g .successors ("2" )), ["3" , "4" ])
0 commit comments