4 Copyright 2008 (c) Frederic Weisbecker <fweisbec@gmail.com>
5 Licensed under the terms of the GNU GPL License version 2
7 This script parses a trace provided by the function tracer in
8 kernel/trace/trace_functions.c
9 The resulted trace is processed into a tree to produce a more human
10 view of the call stack by drawing textual but hierarchical tree of
11 calls. Only the functions's names and the the call time are provided.
14 Be sure that you have CONFIG_FUNCTION_TRACER
16 # mount -t debug debug /debug
17 # echo function > /debug/tracing/current_tracer
18 $ cat /debug/tracing/trace_pipe > ~/raw_trace_func
19 Wait some times but not too much, the script is a bit slow.
20 Break the pipe (Ctrl + Z)
21 $ scripts/draw_functrace.py < raw_trace_func > draw_functrace
22 Then you have your drawn trace in draw_functrace
29 """ This class provides a tree representation of the functions
30 call stack. If a function has no parent in the kernel (interrupt,
31 syscall, kernel thread...) then it is attached to a virtual parent
36 def __init__(self
, func
, time
= None, parent
= None):
40 self
._parent
= CallTree
.ROOT
45 def calls(self
, func
, calltime
):
46 """ If a function calls another one, call this method to insert it
47 into the tree at the appropriate place.
48 @return: A reference to the newly created child node.
50 child
= CallTree(func
, calltime
, self
)
51 self
._children
.append(child
)
54 def getParent(self
, func
):
55 """ Retrieve the last parent of the current node that
56 has the name given by func. If this function is not
57 on a parent, then create it as new child of root
58 @return: A reference to the parent.
61 while tree
!= CallTree
.ROOT
and tree
._func
!= func
:
63 if tree
== CallTree
.ROOT
:
64 child
= CallTree
.ROOT
.calls(func
, None)
69 return self
.__toString
("", True)
71 def __toString(self
, branch
, lastChild
):
72 if self
._time
is not None:
73 s
= "%s----%s (%s)\n" % (branch
, self
._func
, self
._time
)
75 s
= "%s----%s\n" % (branch
, self
._func
)
79 branch
= branch
[:-1] + " "
80 while i
< len(self
._children
):
81 if i
!= len(self
._children
) - 1:
82 s
+= "%s" % self
._children
[i
].__toString
(branch
+\
85 s
+= "%s" % self
._children
[i
].__toString
(branch
+\
90 class BrokenLineException(Exception):
91 """If the last line is not complete because of the pipe breakage,
92 we want to stop the processing and ignore this line.
96 class CommentLineException(Exception):
97 """ If the line is a comment (as in the beginning of the trace file),
105 if line
.startswith("#"):
106 raise CommentLineException
107 m
= re
.match("[^]]+?\\] +([0-9.]+): (\\w+) <-(\\w+)", line
)
109 raise BrokenLineException
110 return (m
.group(1), m
.group(2), m
.group(3))
114 CallTree
.ROOT
= CallTree("Root (Nowhere)", None, None)
117 for line
in sys
.stdin
:
119 calltime
, callee
, caller
= parseLine(line
)
120 except BrokenLineException
:
122 except CommentLineException
:
124 tree
= tree
.getParent(caller
)
125 tree
= tree
.calls(callee
, calltime
)
129 if __name__
== "__main__":