1 #!/usr/bin/env python 1 #!/usr/bin/env python 2 # SPDX-License-Identifier: GPL-2.0-only 2 # SPDX-License-Identifier: GPL-2.0-only 3 3 4 """ 4 """ 5 Copyright 2008 (c) Frederic Weisbecker <fweisbe 5 Copyright 2008 (c) Frederic Weisbecker <fweisbec@gmail.com> 6 6 7 This script parses a trace provided by the fun 7 This script parses a trace provided by the function tracer in 8 kernel/trace/trace_functions.c 8 kernel/trace/trace_functions.c 9 The resulted trace is processed into a tree to 9 The resulted trace is processed into a tree to produce a more human 10 view of the call stack by drawing textual but 10 view of the call stack by drawing textual but hierarchical tree of 11 calls. Only the functions's names and the call !! 11 calls. Only the functions's names and the the call time are provided. 12 12 13 Usage: 13 Usage: 14 Be sure that you have CONFIG_FUNCTION_ 14 Be sure that you have CONFIG_FUNCTION_TRACER 15 # mount -t tracefs nodev /sys/kernel/t !! 15 # mount -t debugfs nodev /sys/kernel/debug 16 # echo function > /sys/kernel/tracing/ !! 16 # echo function > /sys/kernel/debug/tracing/current_tracer 17 $ cat /sys/kernel/tracing/trace_pipe > !! 17 $ cat /sys/kernel/debug/tracing/trace_pipe > ~/raw_trace_func 18 Wait some times but not too much, the 18 Wait some times but not too much, the script is a bit slow. 19 Break the pipe (Ctrl + Z) 19 Break the pipe (Ctrl + Z) 20 $ scripts/tracing/draw_functrace.py < 20 $ scripts/tracing/draw_functrace.py < ~/raw_trace_func > draw_functrace 21 Then you have your drawn trace in draw 21 Then you have your drawn trace in draw_functrace 22 """ 22 """ 23 23 24 24 25 import sys, re 25 import sys, re 26 26 27 class CallTree: 27 class CallTree: 28 """ This class provides a tree represe 28 """ This class provides a tree representation of the functions 29 call stack. If a function has 29 call stack. If a function has no parent in the kernel (interrupt, 30 syscall, kernel thread...) the 30 syscall, kernel thread...) then it is attached to a virtual parent 31 called ROOT. 31 called ROOT. 32 """ 32 """ 33 ROOT = None 33 ROOT = None 34 34 35 def __init__(self, func, time = None, 35 def __init__(self, func, time = None, parent = None): 36 self._func = func 36 self._func = func 37 self._time = time 37 self._time = time 38 if parent is None: 38 if parent is None: 39 self._parent = CallTre 39 self._parent = CallTree.ROOT 40 else: 40 else: 41 self._parent = parent 41 self._parent = parent 42 self._children = [] 42 self._children = [] 43 43 44 def calls(self, func, calltime): 44 def calls(self, func, calltime): 45 """ If a function calls anothe 45 """ If a function calls another one, call this method to insert it 46 into the tree at the a 46 into the tree at the appropriate place. 47 @return: A reference t 47 @return: A reference to the newly created child node. 48 """ 48 """ 49 child = CallTree(func, calltim 49 child = CallTree(func, calltime, self) 50 self._children.append(child) 50 self._children.append(child) 51 return child 51 return child 52 52 53 def getParent(self, func): 53 def getParent(self, func): 54 """ Retrieve the last parent o 54 """ Retrieve the last parent of the current node that 55 has the name given by 55 has the name given by func. If this function is not 56 on a parent, then crea 56 on a parent, then create it as new child of root 57 @return: A reference t 57 @return: A reference to the parent. 58 """ 58 """ 59 tree = self 59 tree = self 60 while tree != CallTree.ROOT an 60 while tree != CallTree.ROOT and tree._func != func: 61 tree = tree._parent 61 tree = tree._parent 62 if tree == CallTree.ROOT: 62 if tree == CallTree.ROOT: 63 child = CallTree.ROOT. 63 child = CallTree.ROOT.calls(func, None) 64 return child 64 return child 65 return tree 65 return tree 66 66 67 def __repr__(self): 67 def __repr__(self): 68 return self.__toString("", Tru 68 return self.__toString("", True) 69 69 70 def __toString(self, branch, lastChild 70 def __toString(self, branch, lastChild): 71 if self._time is not None: 71 if self._time is not None: 72 s = "%s----%s (%s)\n" 72 s = "%s----%s (%s)\n" % (branch, self._func, self._time) 73 else: 73 else: 74 s = "%s----%s\n" % (br 74 s = "%s----%s\n" % (branch, self._func) 75 75 76 i = 0 76 i = 0 77 if lastChild: 77 if lastChild: 78 branch = branch[:-1] + 78 branch = branch[:-1] + " " 79 while i < len(self._children): 79 while i < len(self._children): 80 if i != len(self._chil 80 if i != len(self._children) - 1: 81 s += "%s" % se 81 s += "%s" % self._children[i].__toString(branch +\ 82 82 " |", False) 83 else: 83 else: 84 s += "%s" % se 84 s += "%s" % self._children[i].__toString(branch +\ 85 85 " |", True) 86 i += 1 86 i += 1 87 return s 87 return s 88 88 89 class BrokenLineException(Exception): 89 class BrokenLineException(Exception): 90 """If the last line is not complete be 90 """If the last line is not complete because of the pipe breakage, 91 we want to stop the processing and 91 we want to stop the processing and ignore this line. 92 """ 92 """ 93 pass 93 pass 94 94 95 class CommentLineException(Exception): 95 class CommentLineException(Exception): 96 """ If the line is a comment (as in th 96 """ If the line is a comment (as in the beginning of the trace file), 97 just ignore it. 97 just ignore it. 98 """ 98 """ 99 pass 99 pass 100 100 101 101 102 def parseLine(line): 102 def parseLine(line): 103 line = line.strip() 103 line = line.strip() 104 if line.startswith("#"): 104 if line.startswith("#"): 105 raise CommentLineException 105 raise CommentLineException 106 m = re.match("[^]]+?\\] +([a-z.]+) +([ 106 m = re.match("[^]]+?\\] +([a-z.]+) +([0-9.]+): (\\w+) <-(\\w+)", line) 107 if m is None: 107 if m is None: 108 raise BrokenLineException 108 raise BrokenLineException 109 return (m.group(2), m.group(3), m.grou 109 return (m.group(2), m.group(3), m.group(4)) 110 110 111 111 112 def main(): 112 def main(): 113 CallTree.ROOT = CallTree("Root (Nowher 113 CallTree.ROOT = CallTree("Root (Nowhere)", None, None) 114 tree = CallTree.ROOT 114 tree = CallTree.ROOT 115 115 116 for line in sys.stdin: 116 for line in sys.stdin: 117 try: 117 try: 118 calltime, callee, call 118 calltime, callee, caller = parseLine(line) 119 except BrokenLineException: 119 except BrokenLineException: 120 break 120 break 121 except CommentLineException: 121 except CommentLineException: 122 continue 122 continue 123 tree = tree.getParent(caller) 123 tree = tree.getParent(caller) 124 tree = tree.calls(callee, call 124 tree = tree.calls(callee, calltime) 125 125 126 print(CallTree.ROOT) 126 print(CallTree.ROOT) 127 127 128 if __name__ == "__main__": 128 if __name__ == "__main__": 129 main() 129 main()
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.