Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

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