draw_functrace.py 3.5 KB

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