mirror of
git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-09-04 20:19:47 +08:00
scripts/tracing: Remove scripts/tracing/draw_functrace.py
The draw_functrace.py hasn't worked in years. There's better ways to accomplish the same thing (via libtracefs). Remove it. Link: https://lore.kernel.org/linux-trace-kernel/20250210-debuginfo-v1-1-368feb58292a@purestorage.com/ Cc: Masami Hiramatsu <mhiramat@kernel.org> Cc: Mark Rutland <mark.rutland@arm.com> Cc: Frederic Weisbecker <fweisbec@gmail.com> Cc: Mathieu Desnoyers <mathieu.desnoyers@efficios.com> Cc: Uday Shankar <ushankar@purestorage.com> Cc: Masahiro Yamada <masahiroy@kernel.org> Link: https://lore.kernel.org/20250307103941.070654e7@gandalf.local.home Signed-off-by: Steven Rostedt (Google) <rostedt@goodmis.org>
This commit is contained in:
parent
d4ae507073
commit
a926d15a79
@ -1,129 +0,0 @@
|
|||||||
#!/usr/bin/env python
|
|
||||||
# SPDX-License-Identifier: GPL-2.0-only
|
|
||||||
|
|
||||||
"""
|
|
||||||
Copyright 2008 (c) Frederic Weisbecker <fweisbec@gmail.com>
|
|
||||||
|
|
||||||
This script parses a trace provided by the function tracer in
|
|
||||||
kernel/trace/trace_functions.c
|
|
||||||
The resulted trace is processed into a tree to produce a more human
|
|
||||||
view of the call stack by drawing textual but hierarchical tree of
|
|
||||||
calls. Only the functions's names and the call time are provided.
|
|
||||||
|
|
||||||
Usage:
|
|
||||||
Be sure that you have CONFIG_FUNCTION_TRACER
|
|
||||||
# mount -t tracefs nodev /sys/kernel/tracing
|
|
||||||
# echo function > /sys/kernel/tracing/current_tracer
|
|
||||||
$ cat /sys/kernel/tracing/trace_pipe > ~/raw_trace_func
|
|
||||||
Wait some times but not too much, the script is a bit slow.
|
|
||||||
Break the pipe (Ctrl + Z)
|
|
||||||
$ scripts/tracing/draw_functrace.py < ~/raw_trace_func > draw_functrace
|
|
||||||
Then you have your drawn trace in draw_functrace
|
|
||||||
"""
|
|
||||||
|
|
||||||
|
|
||||||
import sys, re
|
|
||||||
|
|
||||||
class CallTree:
|
|
||||||
""" This class provides a tree representation of the functions
|
|
||||||
call stack. If a function has no parent in the kernel (interrupt,
|
|
||||||
syscall, kernel thread...) then it is attached to a virtual parent
|
|
||||||
called ROOT.
|
|
||||||
"""
|
|
||||||
ROOT = None
|
|
||||||
|
|
||||||
def __init__(self, func, time = None, parent = None):
|
|
||||||
self._func = func
|
|
||||||
self._time = time
|
|
||||||
if parent is None:
|
|
||||||
self._parent = CallTree.ROOT
|
|
||||||
else:
|
|
||||||
self._parent = parent
|
|
||||||
self._children = []
|
|
||||||
|
|
||||||
def calls(self, func, calltime):
|
|
||||||
""" If a function calls another one, call this method to insert it
|
|
||||||
into the tree at the appropriate place.
|
|
||||||
@return: A reference to the newly created child node.
|
|
||||||
"""
|
|
||||||
child = CallTree(func, calltime, self)
|
|
||||||
self._children.append(child)
|
|
||||||
return child
|
|
||||||
|
|
||||||
def getParent(self, func):
|
|
||||||
""" Retrieve the last parent of the current node that
|
|
||||||
has the name given by func. If this function is not
|
|
||||||
on a parent, then create it as new child of root
|
|
||||||
@return: A reference to the parent.
|
|
||||||
"""
|
|
||||||
tree = self
|
|
||||||
while tree != CallTree.ROOT and tree._func != func:
|
|
||||||
tree = tree._parent
|
|
||||||
if tree == CallTree.ROOT:
|
|
||||||
child = CallTree.ROOT.calls(func, None)
|
|
||||||
return child
|
|
||||||
return tree
|
|
||||||
|
|
||||||
def __repr__(self):
|
|
||||||
return self.__toString("", True)
|
|
||||||
|
|
||||||
def __toString(self, branch, lastChild):
|
|
||||||
if self._time is not None:
|
|
||||||
s = "%s----%s (%s)\n" % (branch, self._func, self._time)
|
|
||||||
else:
|
|
||||||
s = "%s----%s\n" % (branch, self._func)
|
|
||||||
|
|
||||||
i = 0
|
|
||||||
if lastChild:
|
|
||||||
branch = branch[:-1] + " "
|
|
||||||
while i < len(self._children):
|
|
||||||
if i != len(self._children) - 1:
|
|
||||||
s += "%s" % self._children[i].__toString(branch +\
|
|
||||||
" |", False)
|
|
||||||
else:
|
|
||||||
s += "%s" % self._children[i].__toString(branch +\
|
|
||||||
" |", True)
|
|
||||||
i += 1
|
|
||||||
return s
|
|
||||||
|
|
||||||
class BrokenLineException(Exception):
|
|
||||||
"""If the last line is not complete because of the pipe breakage,
|
|
||||||
we want to stop the processing and ignore this line.
|
|
||||||
"""
|
|
||||||
pass
|
|
||||||
|
|
||||||
class CommentLineException(Exception):
|
|
||||||
""" If the line is a comment (as in the beginning of the trace file),
|
|
||||||
just ignore it.
|
|
||||||
"""
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
def parseLine(line):
|
|
||||||
line = line.strip()
|
|
||||||
if line.startswith("#"):
|
|
||||||
raise CommentLineException
|
|
||||||
m = re.match("[^]]+?\\] +([a-z.]+) +([0-9.]+): (\\w+) <-(\\w+)", line)
|
|
||||||
if m is None:
|
|
||||||
raise BrokenLineException
|
|
||||||
return (m.group(2), m.group(3), m.group(4))
|
|
||||||
|
|
||||||
|
|
||||||
def main():
|
|
||||||
CallTree.ROOT = CallTree("Root (Nowhere)", None, None)
|
|
||||||
tree = CallTree.ROOT
|
|
||||||
|
|
||||||
for line in sys.stdin:
|
|
||||||
try:
|
|
||||||
calltime, callee, caller = parseLine(line)
|
|
||||||
except BrokenLineException:
|
|
||||||
break
|
|
||||||
except CommentLineException:
|
|
||||||
continue
|
|
||||||
tree = tree.getParent(caller)
|
|
||||||
tree = tree.calls(callee, calltime)
|
|
||||||
|
|
||||||
print(CallTree.ROOT)
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
main()
|
|
Loading…
Reference in New Issue
Block a user