draw_functrace.py 3.5 KB

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