diff options
Diffstat (limited to 'scripts')
| -rw-r--r-- | scripts/Makefile.build | 12 | ||||
| -rw-r--r-- | scripts/bootgraph.pl | 16 | ||||
| -rwxr-xr-x | scripts/recordmcount.pl | 51 | ||||
| -rw-r--r-- | scripts/trace/power.pl | 108 | ||||
| -rw-r--r-- | scripts/tracing/draw_functrace.py | 130 |
5 files changed, 293 insertions, 24 deletions
diff --git a/scripts/Makefile.build b/scripts/Makefile.build index 468fbc9016c7..7a176773af85 100644 --- a/scripts/Makefile.build +++ b/scripts/Makefile.build | |||
| @@ -198,16 +198,10 @@ cmd_modversions = \ | |||
| 198 | fi; | 198 | fi; |
| 199 | endif | 199 | endif |
| 200 | 200 | ||
| 201 | ifdef CONFIG_64BIT | ||
| 202 | arch_bits = 64 | ||
| 203 | else | ||
| 204 | arch_bits = 32 | ||
| 205 | endif | ||
| 206 | |||
| 207 | ifdef CONFIG_FTRACE_MCOUNT_RECORD | 201 | ifdef CONFIG_FTRACE_MCOUNT_RECORD |
| 208 | cmd_record_mcount = perl $(srctree)/scripts/recordmcount.pl \ | 202 | cmd_record_mcount = perl $(srctree)/scripts/recordmcount.pl "$(ARCH)" \ |
| 209 | "$(ARCH)" "$(arch_bits)" "$(OBJDUMP)" "$(OBJCOPY)" "$(CC)" "$(LD)" \ | 203 | "$(if $(CONFIG_64BIT),64,32)" \ |
| 210 | "$(NM)" "$(RM)" "$(MV)" "$(@)"; | 204 | "$(OBJDUMP)" "$(OBJCOPY)" "$(CC)" "$(LD)" "$(NM)" "$(RM)" "$(MV)" "$(@)"; |
| 211 | endif | 205 | endif |
| 212 | 206 | ||
| 213 | define rule_cc_o_c | 207 | define rule_cc_o_c |
diff --git a/scripts/bootgraph.pl b/scripts/bootgraph.pl index d2c61efc216f..f0af9aa9b243 100644 --- a/scripts/bootgraph.pl +++ b/scripts/bootgraph.pl | |||
| @@ -78,11 +78,13 @@ while (<>) { | |||
| 78 | } | 78 | } |
| 79 | 79 | ||
| 80 | if ($count == 0) { | 80 | if ($count == 0) { |
| 81 | print "No data found in the dmesg. Make sure that 'printk.time=1' and\n"; | 81 | print STDERR <<END; |
| 82 | print "'initcall_debug' are passed on the kernel command line.\n\n"; | 82 | No data found in the dmesg. Make sure that 'printk.time=1' and |
| 83 | print "Usage: \n"; | 83 | 'initcall_debug' are passed on the kernel command line. |
| 84 | print " dmesg | perl scripts/bootgraph.pl > output.svg\n\n"; | 84 | Usage: |
| 85 | exit; | 85 | dmesg | perl scripts/bootgraph.pl > output.svg |
| 86 | END | ||
| 87 | exit 1; | ||
| 86 | } | 88 | } |
| 87 | 89 | ||
| 88 | print "<?xml version=\"1.0\" standalone=\"no\"?> \n"; | 90 | print "<?xml version=\"1.0\" standalone=\"no\"?> \n"; |
| @@ -109,8 +111,8 @@ my $stylecounter = 0; | |||
| 109 | my %rows; | 111 | my %rows; |
| 110 | my $rowscount = 1; | 112 | my $rowscount = 1; |
| 111 | my @initcalls = sort { $start{$a} <=> $start{$b} } keys(%start); | 113 | my @initcalls = sort { $start{$a} <=> $start{$b} } keys(%start); |
| 112 | my $key; | 114 | |
| 113 | foreach $key (@initcalls) { | 115 | foreach my $key (@initcalls) { |
| 114 | my $duration = $end{$key} - $start{$key}; | 116 | my $duration = $end{$key} - $start{$key}; |
| 115 | 117 | ||
| 116 | if ($duration >= $threshold) { | 118 | if ($duration >= $threshold) { |
diff --git a/scripts/recordmcount.pl b/scripts/recordmcount.pl index 6b9fe3eb8360..fe831412bea9 100755 --- a/scripts/recordmcount.pl +++ b/scripts/recordmcount.pl | |||
| @@ -112,6 +112,9 @@ my ($arch, $bits, $objdump, $objcopy, $cc, | |||
| 112 | # Acceptable sections to record. | 112 | # Acceptable sections to record. |
| 113 | my %text_sections = ( | 113 | my %text_sections = ( |
| 114 | ".text" => 1, | 114 | ".text" => 1, |
| 115 | ".sched.text" => 1, | ||
| 116 | ".spinlock.text" => 1, | ||
| 117 | ".irqentry.text" => 1, | ||
| 115 | ); | 118 | ); |
| 116 | 119 | ||
| 117 | $objdump = "objdump" if ((length $objdump) == 0); | 120 | $objdump = "objdump" if ((length $objdump) == 0); |
| @@ -130,10 +133,13 @@ my %weak; # List of weak functions | |||
| 130 | my %convert; # List of local functions used that needs conversion | 133 | my %convert; # List of local functions used that needs conversion |
| 131 | 134 | ||
| 132 | my $type; | 135 | my $type; |
| 136 | my $nm_regex; # Find the local functions (return function) | ||
| 133 | my $section_regex; # Find the start of a section | 137 | my $section_regex; # Find the start of a section |
| 134 | my $function_regex; # Find the name of a function | 138 | my $function_regex; # Find the name of a function |
| 135 | # (return offset and func name) | 139 | # (return offset and func name) |
| 136 | my $mcount_regex; # Find the call site to mcount (return offset) | 140 | my $mcount_regex; # Find the call site to mcount (return offset) |
| 141 | my $alignment; # The .align value to use for $mcount_section | ||
| 142 | my $section_type; # Section header plus possible alignment command | ||
| 137 | 143 | ||
| 138 | if ($arch eq "x86") { | 144 | if ($arch eq "x86") { |
| 139 | if ($bits == 64) { | 145 | if ($bits == 64) { |
| @@ -143,11 +149,21 @@ if ($arch eq "x86") { | |||
| 143 | } | 149 | } |
| 144 | } | 150 | } |
| 145 | 151 | ||
| 152 | # | ||
| 153 | # We base the defaults off of i386, the other archs may | ||
| 154 | # feel free to change them in the below if statements. | ||
| 155 | # | ||
| 156 | $nm_regex = "^[0-9a-fA-F]+\\s+t\\s+(\\S+)"; | ||
| 157 | $section_regex = "Disassembly of section\\s+(\\S+):"; | ||
| 158 | $function_regex = "^([0-9a-fA-F]+)\\s+<(.*?)>:"; | ||
| 159 | $mcount_regex = "^\\s*([0-9a-fA-F]+):.*\\smcount\$"; | ||
| 160 | $section_type = '@progbits'; | ||
| 161 | $type = ".long"; | ||
| 162 | |||
| 146 | if ($arch eq "x86_64") { | 163 | if ($arch eq "x86_64") { |
| 147 | $section_regex = "Disassembly of section\\s+(\\S+):"; | ||
| 148 | $function_regex = "^([0-9a-fA-F]+)\\s+<(.*?)>:"; | ||
| 149 | $mcount_regex = "^\\s*([0-9a-fA-F]+):.*\\smcount([+-]0x[0-9a-zA-Z]+)?\$"; | 164 | $mcount_regex = "^\\s*([0-9a-fA-F]+):.*\\smcount([+-]0x[0-9a-zA-Z]+)?\$"; |
| 150 | $type = ".quad"; | 165 | $type = ".quad"; |
| 166 | $alignment = 8; | ||
| 151 | 167 | ||
| 152 | # force flags for this arch | 168 | # force flags for this arch |
| 153 | $ld .= " -m elf_x86_64"; | 169 | $ld .= " -m elf_x86_64"; |
| @@ -156,10 +172,7 @@ if ($arch eq "x86_64") { | |||
| 156 | $cc .= " -m64"; | 172 | $cc .= " -m64"; |
| 157 | 173 | ||
| 158 | } elsif ($arch eq "i386") { | 174 | } elsif ($arch eq "i386") { |
| 159 | $section_regex = "Disassembly of section\\s+(\\S+):"; | 175 | $alignment = 4; |
| 160 | $function_regex = "^([0-9a-fA-F]+)\\s+<(.*?)>:"; | ||
| 161 | $mcount_regex = "^\\s*([0-9a-fA-F]+):.*\\smcount\$"; | ||
| 162 | $type = ".long"; | ||
| 163 | 176 | ||
| 164 | # force flags for this arch | 177 | # force flags for this arch |
| 165 | $ld .= " -m elf_i386"; | 178 | $ld .= " -m elf_i386"; |
| @@ -167,6 +180,27 @@ if ($arch eq "x86_64") { | |||
| 167 | $objcopy .= " -O elf32-i386"; | 180 | $objcopy .= " -O elf32-i386"; |
| 168 | $cc .= " -m32"; | 181 | $cc .= " -m32"; |
| 169 | 182 | ||
| 183 | } elsif ($arch eq "sh") { | ||
| 184 | $alignment = 2; | ||
| 185 | |||
| 186 | # force flags for this arch | ||
| 187 | $ld .= " -m shlelf_linux"; | ||
| 188 | $objcopy .= " -O elf32-sh-linux"; | ||
| 189 | $cc .= " -m32"; | ||
| 190 | |||
| 191 | } elsif ($arch eq "powerpc") { | ||
| 192 | $nm_regex = "^[0-9a-fA-F]+\\s+t\\s+(\\.?\\S+)"; | ||
| 193 | $function_regex = "^([0-9a-fA-F]+)\\s+<(\\.?.*?)>:"; | ||
| 194 | $mcount_regex = "^\\s*([0-9a-fA-F]+):.*\\s\\.?_mcount\$"; | ||
| 195 | |||
| 196 | if ($bits == 64) { | ||
| 197 | $type = ".quad"; | ||
| 198 | } | ||
| 199 | |||
| 200 | } elsif ($arch eq "arm") { | ||
| 201 | $alignment = 2; | ||
| 202 | $section_type = '%progbits'; | ||
| 203 | |||
| 170 | } else { | 204 | } else { |
| 171 | die "Arch $arch is not supported with CONFIG_FTRACE_MCOUNT_RECORD"; | 205 | die "Arch $arch is not supported with CONFIG_FTRACE_MCOUNT_RECORD"; |
| 172 | } | 206 | } |
| @@ -236,7 +270,7 @@ if (!$found_version) { | |||
| 236 | # | 270 | # |
| 237 | open (IN, "$nm $inputfile|") || die "error running $nm"; | 271 | open (IN, "$nm $inputfile|") || die "error running $nm"; |
| 238 | while (<IN>) { | 272 | while (<IN>) { |
| 239 | if (/^[0-9a-fA-F]+\s+t\s+(\S+)/) { | 273 | if (/$nm_regex/) { |
| 240 | $locals{$1} = 1; | 274 | $locals{$1} = 1; |
| 241 | } elsif (/^[0-9a-fA-F]+\s+([wW])\s+(\S+)/) { | 275 | } elsif (/^[0-9a-fA-F]+\s+([wW])\s+(\S+)/) { |
| 242 | $weak{$2} = $1; | 276 | $weak{$2} = $1; |
| @@ -287,7 +321,8 @@ sub update_funcs | |||
| 287 | if (!$opened) { | 321 | if (!$opened) { |
| 288 | open(FILE, ">$mcount_s") || die "can't create $mcount_s\n"; | 322 | open(FILE, ">$mcount_s") || die "can't create $mcount_s\n"; |
| 289 | $opened = 1; | 323 | $opened = 1; |
| 290 | print FILE "\t.section $mcount_section,\"a\",\@progbits\n"; | 324 | print FILE "\t.section $mcount_section,\"a\",$section_type\n"; |
| 325 | print FILE "\t.align $alignment\n" if (defined($alignment)); | ||
| 291 | } | 326 | } |
| 292 | printf FILE "\t%s %s + %d\n", $type, $ref_func, $offsets[$i] - $offset; | 327 | printf FILE "\t%s %s + %d\n", $type, $ref_func, $offsets[$i] - $offset; |
| 293 | } | 328 | } |
diff --git a/scripts/trace/power.pl b/scripts/trace/power.pl new file mode 100644 index 000000000000..4f729b3501e0 --- /dev/null +++ b/scripts/trace/power.pl | |||
| @@ -0,0 +1,108 @@ | |||
| 1 | #!/usr/bin/perl | ||
| 2 | |||
| 3 | # Copyright 2008, Intel Corporation | ||
| 4 | # | ||
| 5 | # This file is part of the Linux kernel | ||
| 6 | # | ||
| 7 | # This program file is free software; you can redistribute it and/or modify it | ||
| 8 | # under the terms of the GNU General Public License as published by the | ||
| 9 | # Free Software Foundation; version 2 of the License. | ||
| 10 | # | ||
| 11 | # This program is distributed in the hope that it will be useful, but WITHOUT | ||
| 12 | # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
| 13 | # FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | ||
| 14 | # for more details. | ||
| 15 | # | ||
| 16 | # You should have received a copy of the GNU General Public License | ||
| 17 | # along with this program in a file named COPYING; if not, write to the | ||
| 18 | # Free Software Foundation, Inc., | ||
| 19 | # 51 Franklin Street, Fifth Floor, | ||
| 20 | # Boston, MA 02110-1301 USA | ||
| 21 | # | ||
| 22 | # Authors: | ||
| 23 | # Arjan van de Ven <arjan@linux.intel.com> | ||
| 24 | |||
| 25 | |||
| 26 | # | ||
| 27 | # This script turns a cstate ftrace output into a SVG graphic that shows | ||
| 28 | # historic C-state information | ||
| 29 | # | ||
| 30 | # | ||
| 31 | # cat /sys/kernel/debug/tracing/trace | perl power.pl > out.svg | ||
| 32 | # | ||
| 33 | |||
| 34 | my @styles; | ||
| 35 | my $base = 0; | ||
| 36 | |||
| 37 | my @pstate_last; | ||
| 38 | my @pstate_level; | ||
| 39 | |||
| 40 | $styles[0] = "fill:rgb(0,0,255);fill-opacity:0.5;stroke-width:1;stroke:rgb(0,0,0)"; | ||
| 41 | $styles[1] = "fill:rgb(0,255,0);fill-opacity:0.5;stroke-width:1;stroke:rgb(0,0,0)"; | ||
| 42 | $styles[2] = "fill:rgb(255,0,20);fill-opacity:0.5;stroke-width:1;stroke:rgb(0,0,0)"; | ||
| 43 | $styles[3] = "fill:rgb(255,255,20);fill-opacity:0.5;stroke-width:1;stroke:rgb(0,0,0)"; | ||
| 44 | $styles[4] = "fill:rgb(255,0,255);fill-opacity:0.5;stroke-width:1;stroke:rgb(0,0,0)"; | ||
| 45 | $styles[5] = "fill:rgb(0,255,255);fill-opacity:0.5;stroke-width:1;stroke:rgb(0,0,0)"; | ||
| 46 | $styles[6] = "fill:rgb(0,128,255);fill-opacity:0.5;stroke-width:1;stroke:rgb(0,0,0)"; | ||
| 47 | $styles[7] = "fill:rgb(0,255,128);fill-opacity:0.5;stroke-width:1;stroke:rgb(0,0,0)"; | ||
| 48 | $styles[8] = "fill:rgb(0,25,20);fill-opacity:0.5;stroke-width:1;stroke:rgb(0,0,0)"; | ||
| 49 | |||
| 50 | |||
| 51 | print "<?xml version=\"1.0\" standalone=\"no\"?> \n"; | ||
| 52 | print "<svg width=\"10000\" height=\"100%\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n"; | ||
| 53 | |||
| 54 | my $scale = 30000.0; | ||
| 55 | while (<>) { | ||
| 56 | my $line = $_; | ||
| 57 | if ($line =~ /([0-9\.]+)\] CSTATE: Going to C([0-9]) on cpu ([0-9]+) for ([0-9\.]+)/) { | ||
| 58 | if ($base == 0) { | ||
| 59 | $base = $1; | ||
| 60 | } | ||
| 61 | my $time = $1 - $base; | ||
| 62 | $time = $time * $scale; | ||
| 63 | my $C = $2; | ||
| 64 | my $cpu = $3; | ||
| 65 | my $y = 400 * $cpu; | ||
| 66 | my $duration = $4 * $scale; | ||
| 67 | my $msec = int($4 * 100000)/100.0; | ||
| 68 | my $height = $C * 20; | ||
| 69 | $style = $styles[$C]; | ||
| 70 | |||
| 71 | $y = $y + 140 - $height; | ||
| 72 | |||
| 73 | $x2 = $time + 4; | ||
| 74 | $y2 = $y + 4; | ||
| 75 | |||
| 76 | |||
| 77 | print "<rect x=\"$time\" width=\"$duration\" y=\"$y\" height=\"$height\" style=\"$style\"/>\n"; | ||
| 78 | print "<text transform=\"translate($x2,$y2) rotate(90)\">C$C $msec</text>\n"; | ||
| 79 | } | ||
| 80 | if ($line =~ /([0-9\.]+)\] PSTATE: Going to P([0-9]) on cpu ([0-9]+)/) { | ||
| 81 | my $time = $1 - $base; | ||
| 82 | my $state = $2; | ||
| 83 | my $cpu = $3; | ||
| 84 | |||
| 85 | if (defined($pstate_last[$cpu])) { | ||
| 86 | my $from = $pstate_last[$cpu]; | ||
| 87 | my $oldstate = $pstate_state[$cpu]; | ||
| 88 | my $duration = ($time-$from) * $scale; | ||
| 89 | |||
| 90 | $from = $from * $scale; | ||
| 91 | my $to = $from + $duration; | ||
| 92 | my $height = 140 - ($oldstate * (140/8)); | ||
| 93 | |||
| 94 | my $y = 400 * $cpu + 200 + $height; | ||
| 95 | my $y2 = $y+4; | ||
| 96 | my $style = $styles[8]; | ||
| 97 | |||
| 98 | print "<rect x=\"$from\" y=\"$y\" width=\"$duration\" height=\"5\" style=\"$style\"/>\n"; | ||
| 99 | print "<text transform=\"translate($from,$y2)\">P$oldstate (cpu $cpu)</text>\n"; | ||
| 100 | }; | ||
| 101 | |||
| 102 | $pstate_last[$cpu] = $time; | ||
| 103 | $pstate_state[$cpu] = $state; | ||
| 104 | } | ||
| 105 | } | ||
| 106 | |||
| 107 | |||
| 108 | print "</svg>\n"; | ||
diff --git a/scripts/tracing/draw_functrace.py b/scripts/tracing/draw_functrace.py new file mode 100644 index 000000000000..902f9a992620 --- /dev/null +++ b/scripts/tracing/draw_functrace.py | |||
| @@ -0,0 +1,130 @@ | |||
| 1 | #!/usr/bin/python | ||
| 2 | |||
| 3 | """ | ||
| 4 | Copyright 2008 (c) Frederic Weisbecker <fweisbec@gmail.com> | ||
| 5 | Licensed under the terms of the GNU GPL License version 2 | ||
| 6 | |||
| 7 | This script parses a trace provided by the function tracer in | ||
| 8 | kernel/trace/trace_functions.c | ||
| 9 | The resulted trace is processed into a tree to produce a more human | ||
| 10 | view of the call stack by drawing textual but hierarchical tree of | ||
| 11 | calls. Only the functions's names and the the call time are provided. | ||
| 12 | |||
| 13 | Usage: | ||
| 14 | Be sure that you have CONFIG_FUNCTION_TRACER | ||
| 15 | # mkdir /debugfs | ||
| 16 | # mount -t debug debug /debug | ||
| 17 | # echo function > /debug/tracing/current_tracer | ||
| 18 | $ cat /debug/tracing/trace_pipe > ~/raw_trace_func | ||
| 19 | Wait some times but not too much, the script is a bit slow. | ||
| 20 | Break the pipe (Ctrl + Z) | ||
| 21 | $ scripts/draw_functrace.py < raw_trace_func > draw_functrace | ||
| 22 | Then you have your drawn trace in draw_functrace | ||
| 23 | """ | ||
| 24 | |||
| 25 | |||
| 26 | import sys, re | ||
| 27 | |||
| 28 | class CallTree: | ||
| 29 | """ This class provides a tree representation of the functions | ||
| 30 | call stack. If a function has no parent in the kernel (interrupt, | ||
| 31 | syscall, kernel thread...) then it is attached to a virtual parent | ||
| 32 | called ROOT. | ||
| 33 | """ | ||
| 34 | ROOT = None | ||
| 35 | |||
| 36 | def __init__(self, func, time = None, parent = None): | ||
| 37 | self._func = func | ||
| 38 | self._time = time | ||
| 39 | if parent is None: | ||
| 40 | self._parent = CallTree.ROOT | ||
| 41 | else: | ||
| 42 | self._parent = parent | ||
| 43 | self._children = [] | ||
| 44 | |||
| 45 | def calls(self, func, calltime): | ||
| 46 | """ If a function calls another one, call this method to insert it | ||
| 47 | into the tree at the appropriate place. | ||
| 48 | @return: A reference to the newly created child node. | ||
| 49 | """ | ||
| 50 | child = CallTree(func, calltime, self) | ||
| 51 | self._children.append(child) | ||
| 52 | return child | ||
| 53 | |||
| 54 | def getParent(self, func): | ||
| 55 | """ Retrieve the last parent of the current node that | ||
| 56 | has the name given by func. If this function is not | ||
| 57 | on a parent, then create it as new child of root | ||
| 58 | @return: A reference to the parent. | ||
| 59 | """ | ||
| 60 | tree = self | ||
| 61 | while tree != CallTree.ROOT and tree._func != func: | ||
| 62 | tree = tree._parent | ||
| 63 | if tree == CallTree.ROOT: | ||
| 64 | child = CallTree.ROOT.calls(func, None) | ||
| 65 | return child | ||
| 66 | return tree | ||
| 67 | |||
| 68 | def __repr__(self): | ||
| 69 | return self.__toString("", True) | ||
| 70 | |||
| 71 | def __toString(self, branch, lastChild): | ||
| 72 | if self._time is not None: | ||
| 73 | s = "%s----%s (%s)\n" % (branch, self._func, self._time) | ||
| 74 | else: | ||
| 75 | s = "%s----%s\n" % (branch, self._func) | ||
| 76 | |||
| 77 | i = 0 | ||
| 78 | if lastChild: | ||
| 79 | branch = branch[:-1] + " " | ||
| 80 | while i < len(self._children): | ||
| 81 | if i != len(self._children) - 1: | ||
| 82 | s += "%s" % self._children[i].__toString(branch +\ | ||
| 83 | " |", False) | ||
| 84 | else: | ||
| 85 | s += "%s" % self._children[i].__toString(branch +\ | ||
| 86 | " |", True) | ||
| 87 | i += 1 | ||
| 88 | return s | ||
| 89 | |||
| 90 | class BrokenLineException(Exception): | ||
| 91 | """If the last line is not complete because of the pipe breakage, | ||
| 92 | we want to stop the processing and ignore this line. | ||
| 93 | """ | ||
| 94 | pass | ||
| 95 | |||
| 96 | class CommentLineException(Exception): | ||
| 97 | """ If the line is a comment (as in the beginning of the trace file), | ||
| 98 | just ignore it. | ||
| 99 | """ | ||
| 100 | pass | ||
| 101 | |||
| 102 | |||
| 103 | def parseLine(line): | ||
| 104 | line = line.strip() | ||
| 105 | if line.startswith("#"): | ||
| 106 | raise CommentLineException | ||
| 107 | m = re.match("[^]]+?\\] +([0-9.]+): (\\w+) <-(\\w+)", line) | ||
| 108 | if m is None: | ||
| 109 | raise BrokenLineException | ||
| 110 | return (m.group(1), m.group(2), m.group(3)) | ||
| 111 | |||
| 112 | |||
| 113 | def main(): | ||
| 114 | CallTree.ROOT = CallTree("Root (Nowhere)", None, None) | ||
| 115 | tree = CallTree.ROOT | ||
| 116 | |||
| 117 | for line in sys.stdin: | ||
| 118 | try: | ||
| 119 | calltime, callee, caller = parseLine(line) | ||
| 120 | except BrokenLineException: | ||
| 121 | break | ||
| 122 | except CommentLineException: | ||
| 123 | continue | ||
| 124 | tree = tree.getParent(caller) | ||
| 125 | tree = tree.calls(callee, calltime) | ||
| 126 | |||
| 127 | print CallTree.ROOT | ||
| 128 | |||
| 129 | if __name__ == "__main__": | ||
| 130 | main() | ||
