cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

draw_functrace.py (3568B)


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