1*cf84ac9aSAndroid Build Coastguard Worker#!/usr/bin/perl 2*cf84ac9aSAndroid Build Coastguard Worker 3*cf84ac9aSAndroid Build Coastguard Worker# This script processes strace -f output. It displays a graph of invoked 4*cf84ac9aSAndroid Build Coastguard Worker# subprocesses, and is useful for finding out what complex commands do. 5*cf84ac9aSAndroid Build Coastguard Worker 6*cf84ac9aSAndroid Build Coastguard Worker# You will probably want to invoke strace with -q as well, and with 7*cf84ac9aSAndroid Build Coastguard Worker# -s 100 to get complete filenames. 8*cf84ac9aSAndroid Build Coastguard Worker 9*cf84ac9aSAndroid Build Coastguard Worker# The script can also handle the output with strace -t, -tt, or -ttt. 10*cf84ac9aSAndroid Build Coastguard Worker# It will add elapsed time for each process in that case. 11*cf84ac9aSAndroid Build Coastguard Worker 12*cf84ac9aSAndroid Build Coastguard Worker# Copyright (c) 1998 by Richard Braakman <[email protected]>. 13*cf84ac9aSAndroid Build Coastguard Worker# Copyright (c) 1998-2017 The strace developers. 14*cf84ac9aSAndroid Build Coastguard Worker 15*cf84ac9aSAndroid Build Coastguard Worker# Redistribution and use in source and binary forms, with or without 16*cf84ac9aSAndroid Build Coastguard Worker# modification, are permitted provided that the following conditions 17*cf84ac9aSAndroid Build Coastguard Worker# are met: 18*cf84ac9aSAndroid Build Coastguard Worker# 1. Redistributions of source code must retain the above copyright 19*cf84ac9aSAndroid Build Coastguard Worker# notice, this list of conditions and the following disclaimer. 20*cf84ac9aSAndroid Build Coastguard Worker# 2. Redistributions in binary form must reproduce the above copyright 21*cf84ac9aSAndroid Build Coastguard Worker# notice, this list of conditions and the following disclaimer in the 22*cf84ac9aSAndroid Build Coastguard Worker# documentation and/or other materials provided with the distribution. 23*cf84ac9aSAndroid Build Coastguard Worker# 3. The name of the author may not be used to endorse or promote products 24*cf84ac9aSAndroid Build Coastguard Worker# derived from this software without specific prior written permission. 25*cf84ac9aSAndroid Build Coastguard Worker# 26*cf84ac9aSAndroid Build Coastguard Worker# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 27*cf84ac9aSAndroid Build Coastguard Worker# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 28*cf84ac9aSAndroid Build Coastguard Worker# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 29*cf84ac9aSAndroid Build Coastguard Worker# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 30*cf84ac9aSAndroid Build Coastguard Worker# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 31*cf84ac9aSAndroid Build Coastguard Worker# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 32*cf84ac9aSAndroid Build Coastguard Worker# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 33*cf84ac9aSAndroid Build Coastguard Worker# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 34*cf84ac9aSAndroid Build Coastguard Worker# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 35*cf84ac9aSAndroid Build Coastguard Worker# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 36*cf84ac9aSAndroid Build Coastguard Worker 37*cf84ac9aSAndroid Build Coastguard Workeruse strict; 38*cf84ac9aSAndroid Build Coastguard Workeruse warnings; 39*cf84ac9aSAndroid Build Coastguard Worker 40*cf84ac9aSAndroid Build Coastguard Workermy %unfinished; 41*cf84ac9aSAndroid Build Coastguard Workermy $floatform; 42*cf84ac9aSAndroid Build Coastguard Worker 43*cf84ac9aSAndroid Build Coastguard Worker# Scales for strace slowdown. Make configurable! 44*cf84ac9aSAndroid Build Coastguard Workermy $scale_factor = 3.5; 45*cf84ac9aSAndroid Build Coastguard Workermy %running_fqname; 46*cf84ac9aSAndroid Build Coastguard Worker 47*cf84ac9aSAndroid Build Coastguard Workerwhile (<>) { 48*cf84ac9aSAndroid Build Coastguard Worker my ($pid, $call, $args, $result, $time, $time_spent); 49*cf84ac9aSAndroid Build Coastguard Worker chop; 50*cf84ac9aSAndroid Build Coastguard Worker $floatform = 0; 51*cf84ac9aSAndroid Build Coastguard Worker 52*cf84ac9aSAndroid Build Coastguard Worker s/^(\d+)\s+//; 53*cf84ac9aSAndroid Build Coastguard Worker $pid = $1; 54*cf84ac9aSAndroid Build Coastguard Worker 55*cf84ac9aSAndroid Build Coastguard Worker if (s/^(\d\d):(\d\d):(\d\d)(?:\.(\d\d\d\d\d\d))? //) { 56*cf84ac9aSAndroid Build Coastguard Worker $time = $1 * 3600 + $2 * 60 + $3; 57*cf84ac9aSAndroid Build Coastguard Worker if (defined $4) { 58*cf84ac9aSAndroid Build Coastguard Worker $time = $time + $4 / 1000000; 59*cf84ac9aSAndroid Build Coastguard Worker $floatform = 1; 60*cf84ac9aSAndroid Build Coastguard Worker } 61*cf84ac9aSAndroid Build Coastguard Worker } elsif (s/^(\d+)\.(\d\d\d\d\d\d) //) { 62*cf84ac9aSAndroid Build Coastguard Worker $time = $1 + ($2 / 1000000); 63*cf84ac9aSAndroid Build Coastguard Worker $floatform = 1; 64*cf84ac9aSAndroid Build Coastguard Worker } 65*cf84ac9aSAndroid Build Coastguard Worker 66*cf84ac9aSAndroid Build Coastguard Worker if (s/ <unfinished ...>$//) { 67*cf84ac9aSAndroid Build Coastguard Worker $unfinished{$pid} = $_; 68*cf84ac9aSAndroid Build Coastguard Worker next; 69*cf84ac9aSAndroid Build Coastguard Worker } 70*cf84ac9aSAndroid Build Coastguard Worker 71*cf84ac9aSAndroid Build Coastguard Worker if (s/^<... \S+ resumed> //) { 72*cf84ac9aSAndroid Build Coastguard Worker unless (exists $unfinished{$pid}) { 73*cf84ac9aSAndroid Build Coastguard Worker print STDERR "$0: $ARGV: cannot find start of resumed call on line $."; 74*cf84ac9aSAndroid Build Coastguard Worker next; 75*cf84ac9aSAndroid Build Coastguard Worker } 76*cf84ac9aSAndroid Build Coastguard Worker $_ = $unfinished{$pid} . $_; 77*cf84ac9aSAndroid Build Coastguard Worker delete $unfinished{$pid}; 78*cf84ac9aSAndroid Build Coastguard Worker } 79*cf84ac9aSAndroid Build Coastguard Worker 80*cf84ac9aSAndroid Build Coastguard Worker if (/^--- SIG(\S+) (.*) ---$/) { 81*cf84ac9aSAndroid Build Coastguard Worker # $pid received signal $1 82*cf84ac9aSAndroid Build Coastguard Worker # currently we don't do anything with this 83*cf84ac9aSAndroid Build Coastguard Worker next; 84*cf84ac9aSAndroid Build Coastguard Worker } 85*cf84ac9aSAndroid Build Coastguard Worker 86*cf84ac9aSAndroid Build Coastguard Worker if (/^\+\+\+ killed by SIG(\S+) \+\+\+$/) { 87*cf84ac9aSAndroid Build Coastguard Worker # $pid received signal $1 88*cf84ac9aSAndroid Build Coastguard Worker handle_killed($pid, $time); 89*cf84ac9aSAndroid Build Coastguard Worker next; 90*cf84ac9aSAndroid Build Coastguard Worker } 91*cf84ac9aSAndroid Build Coastguard Worker 92*cf84ac9aSAndroid Build Coastguard Worker if (/^\+\+\+ exited with (\d+) \+\+\+$/) { 93*cf84ac9aSAndroid Build Coastguard Worker # $pid exited $1 94*cf84ac9aSAndroid Build Coastguard Worker # currently we don't do anything with this 95*cf84ac9aSAndroid Build Coastguard Worker next; 96*cf84ac9aSAndroid Build Coastguard Worker } 97*cf84ac9aSAndroid Build Coastguard Worker 98*cf84ac9aSAndroid Build Coastguard Worker ($call, $args, $result) = /(\S+)\((.*)\)\s+= (.*)$/; 99*cf84ac9aSAndroid Build Coastguard Worker if ($result =~ /^(.*) <([0-9.]*)>$/) { 100*cf84ac9aSAndroid Build Coastguard Worker ($result, $time_spent) = ($1, $2); 101*cf84ac9aSAndroid Build Coastguard Worker } 102*cf84ac9aSAndroid Build Coastguard Worker unless (defined $result) { 103*cf84ac9aSAndroid Build Coastguard Worker print STDERR "$0: $ARGV: $.: cannot parse line.\n"; 104*cf84ac9aSAndroid Build Coastguard Worker next; 105*cf84ac9aSAndroid Build Coastguard Worker } 106*cf84ac9aSAndroid Build Coastguard Worker 107*cf84ac9aSAndroid Build Coastguard Worker handle_trace($pid, $call, $args, $result, $time); 108*cf84ac9aSAndroid Build Coastguard Worker} 109*cf84ac9aSAndroid Build Coastguard Worker 110*cf84ac9aSAndroid Build Coastguard Workerdisplay_trace(); 111*cf84ac9aSAndroid Build Coastguard Worker 112*cf84ac9aSAndroid Build Coastguard Workerexit 0; 113*cf84ac9aSAndroid Build Coastguard Worker 114*cf84ac9aSAndroid Build Coastguard Workersub parse_str { 115*cf84ac9aSAndroid Build Coastguard Worker my ($in) = @_; 116*cf84ac9aSAndroid Build Coastguard Worker my $result = ""; 117*cf84ac9aSAndroid Build Coastguard Worker 118*cf84ac9aSAndroid Build Coastguard Worker while (1) { 119*cf84ac9aSAndroid Build Coastguard Worker if ($in =~ s/^\\(.)//) { 120*cf84ac9aSAndroid Build Coastguard Worker $result .= $1; 121*cf84ac9aSAndroid Build Coastguard Worker } elsif ($in =~ s/^\"//) { 122*cf84ac9aSAndroid Build Coastguard Worker if ($in =~ s/^\.\.\.//) { 123*cf84ac9aSAndroid Build Coastguard Worker return ("$result...", $in); 124*cf84ac9aSAndroid Build Coastguard Worker } 125*cf84ac9aSAndroid Build Coastguard Worker return ($result, $in); 126*cf84ac9aSAndroid Build Coastguard Worker } elsif ($in =~ s/([^\\\"]*)//) { 127*cf84ac9aSAndroid Build Coastguard Worker $result .= $1; 128*cf84ac9aSAndroid Build Coastguard Worker } else { 129*cf84ac9aSAndroid Build Coastguard Worker return (undef, $in); 130*cf84ac9aSAndroid Build Coastguard Worker } 131*cf84ac9aSAndroid Build Coastguard Worker } 132*cf84ac9aSAndroid Build Coastguard Worker} 133*cf84ac9aSAndroid Build Coastguard Worker 134*cf84ac9aSAndroid Build Coastguard Workersub parse_one { 135*cf84ac9aSAndroid Build Coastguard Worker my ($in) = @_; 136*cf84ac9aSAndroid Build Coastguard Worker 137*cf84ac9aSAndroid Build Coastguard Worker if ($in =~ s/^\"//) { 138*cf84ac9aSAndroid Build Coastguard Worker my $tmp; 139*cf84ac9aSAndroid Build Coastguard Worker ($tmp, $in) = parse_str($in); 140*cf84ac9aSAndroid Build Coastguard Worker if (not defined $tmp) { 141*cf84ac9aSAndroid Build Coastguard Worker print STDERR "$0: $ARGV: $.: cannot parse string.\n"; 142*cf84ac9aSAndroid Build Coastguard Worker return (undef, $in); 143*cf84ac9aSAndroid Build Coastguard Worker } 144*cf84ac9aSAndroid Build Coastguard Worker return ($tmp, $in); 145*cf84ac9aSAndroid Build Coastguard Worker } elsif ($in =~ s/^0x([[:xdigit:]]+)//) { 146*cf84ac9aSAndroid Build Coastguard Worker return (hex $1, $in); 147*cf84ac9aSAndroid Build Coastguard Worker } elsif ($in =~ s/^(\d+)//) { 148*cf84ac9aSAndroid Build Coastguard Worker return (int $1, $in); 149*cf84ac9aSAndroid Build Coastguard Worker } else { 150*cf84ac9aSAndroid Build Coastguard Worker print STDERR "$0: $ARGV: $.: unrecognized element.\n"; 151*cf84ac9aSAndroid Build Coastguard Worker return (undef, $in); 152*cf84ac9aSAndroid Build Coastguard Worker } 153*cf84ac9aSAndroid Build Coastguard Worker} 154*cf84ac9aSAndroid Build Coastguard Worker 155*cf84ac9aSAndroid Build Coastguard Workersub parseargs { 156*cf84ac9aSAndroid Build Coastguard Worker my ($in) = @_; 157*cf84ac9aSAndroid Build Coastguard Worker my @args = (); 158*cf84ac9aSAndroid Build Coastguard Worker my $tmp; 159*cf84ac9aSAndroid Build Coastguard Worker 160*cf84ac9aSAndroid Build Coastguard Worker while (length $in) { 161*cf84ac9aSAndroid Build Coastguard Worker if ($in =~ s/^\[//) { 162*cf84ac9aSAndroid Build Coastguard Worker my @subarr = (); 163*cf84ac9aSAndroid Build Coastguard Worker if ($in =~ s,^/\* (\d+) vars \*/\],,) { 164*cf84ac9aSAndroid Build Coastguard Worker push @args, $1; 165*cf84ac9aSAndroid Build Coastguard Worker } else { 166*cf84ac9aSAndroid Build Coastguard Worker while ($in !~ s/^\]//) { 167*cf84ac9aSAndroid Build Coastguard Worker ($tmp, $in) = parse_one($in); 168*cf84ac9aSAndroid Build Coastguard Worker defined $tmp or return undef; 169*cf84ac9aSAndroid Build Coastguard Worker push @subarr, $tmp; 170*cf84ac9aSAndroid Build Coastguard Worker unless ($in =~ /^\]/ or $in =~ s/^, //) { 171*cf84ac9aSAndroid Build Coastguard Worker print STDERR "$0: $ARGV: $.: missing comma in array.\n"; 172*cf84ac9aSAndroid Build Coastguard Worker return undef; 173*cf84ac9aSAndroid Build Coastguard Worker } 174*cf84ac9aSAndroid Build Coastguard Worker if ($in =~ s/^\.\.\.//) { 175*cf84ac9aSAndroid Build Coastguard Worker push @subarr, "..."; 176*cf84ac9aSAndroid Build Coastguard Worker } 177*cf84ac9aSAndroid Build Coastguard Worker } 178*cf84ac9aSAndroid Build Coastguard Worker push @args, \@subarr; 179*cf84ac9aSAndroid Build Coastguard Worker } 180*cf84ac9aSAndroid Build Coastguard Worker } elsif ($in =~ s/^\{//) { 181*cf84ac9aSAndroid Build Coastguard Worker my %subhash = (); 182*cf84ac9aSAndroid Build Coastguard Worker while ($in !~ s/^\}//) { 183*cf84ac9aSAndroid Build Coastguard Worker my $key; 184*cf84ac9aSAndroid Build Coastguard Worker unless ($in =~ s/^(\w+)=//) { 185*cf84ac9aSAndroid Build Coastguard Worker print STDERR "$0: $ARGV: $.: struct field expected.\n"; 186*cf84ac9aSAndroid Build Coastguard Worker return undef; 187*cf84ac9aSAndroid Build Coastguard Worker } 188*cf84ac9aSAndroid Build Coastguard Worker $key = $1; 189*cf84ac9aSAndroid Build Coastguard Worker ($tmp, $in) = parse_one($in); 190*cf84ac9aSAndroid Build Coastguard Worker defined $tmp or return undef; 191*cf84ac9aSAndroid Build Coastguard Worker $subhash{$key} = $tmp; 192*cf84ac9aSAndroid Build Coastguard Worker unless ($in =~ s/, //) { 193*cf84ac9aSAndroid Build Coastguard Worker print STDERR "$0: $ARGV: $.: missing comma in struct.\n"; 194*cf84ac9aSAndroid Build Coastguard Worker return undef; 195*cf84ac9aSAndroid Build Coastguard Worker } 196*cf84ac9aSAndroid Build Coastguard Worker } 197*cf84ac9aSAndroid Build Coastguard Worker push @args, \%subhash; 198*cf84ac9aSAndroid Build Coastguard Worker } else { 199*cf84ac9aSAndroid Build Coastguard Worker ($tmp, $in) = parse_one($in); 200*cf84ac9aSAndroid Build Coastguard Worker defined $tmp or return undef; 201*cf84ac9aSAndroid Build Coastguard Worker push @args, $tmp; 202*cf84ac9aSAndroid Build Coastguard Worker } 203*cf84ac9aSAndroid Build Coastguard Worker unless (length($in) == 0 or $in =~ s/^, //) { 204*cf84ac9aSAndroid Build Coastguard Worker print STDERR "$0: $ARGV: $.: missing comma.\n"; 205*cf84ac9aSAndroid Build Coastguard Worker return undef; 206*cf84ac9aSAndroid Build Coastguard Worker } 207*cf84ac9aSAndroid Build Coastguard Worker } 208*cf84ac9aSAndroid Build Coastguard Worker return @args; 209*cf84ac9aSAndroid Build Coastguard Worker} 210*cf84ac9aSAndroid Build Coastguard Worker 211*cf84ac9aSAndroid Build Coastguard Worker 212*cf84ac9aSAndroid Build Coastguard Workermy $depth = ""; 213*cf84ac9aSAndroid Build Coastguard Worker 214*cf84ac9aSAndroid Build Coastguard Worker# process info, indexed by pid. 215*cf84ac9aSAndroid Build Coastguard Worker# fields: 216*cf84ac9aSAndroid Build Coastguard Worker# parent pid number 217*cf84ac9aSAndroid Build Coastguard Worker# seq clones, forks and execs for this pid, in sequence (array) 218*cf84ac9aSAndroid Build Coastguard Worker 219*cf84ac9aSAndroid Build Coastguard Worker# filename and argv (from latest exec) 220*cf84ac9aSAndroid Build Coastguard Worker# basename (derived from filename) 221*cf84ac9aSAndroid Build Coastguard Worker# argv[0] is modified to add the basename if it differs from the 0th argument. 222*cf84ac9aSAndroid Build Coastguard Worker 223*cf84ac9aSAndroid Build Coastguard Workermy %pr; 224*cf84ac9aSAndroid Build Coastguard Worker 225*cf84ac9aSAndroid Build Coastguard Workersub handle_trace { 226*cf84ac9aSAndroid Build Coastguard Worker my ($pid, $call, $args, $result, $time) = @_; 227*cf84ac9aSAndroid Build Coastguard Worker my $pid_fqname = $pid . "-" . $time; 228*cf84ac9aSAndroid Build Coastguard Worker 229*cf84ac9aSAndroid Build Coastguard Worker if (defined $time and not defined $running_fqname{$pid}) { 230*cf84ac9aSAndroid Build Coastguard Worker $pr{$pid_fqname}{start} = $time; 231*cf84ac9aSAndroid Build Coastguard Worker $running_fqname{$pid} = $pid_fqname; 232*cf84ac9aSAndroid Build Coastguard Worker } 233*cf84ac9aSAndroid Build Coastguard Worker 234*cf84ac9aSAndroid Build Coastguard Worker $pid_fqname = $running_fqname{$pid}; 235*cf84ac9aSAndroid Build Coastguard Worker 236*cf84ac9aSAndroid Build Coastguard Worker if ($call eq 'execve') { 237*cf84ac9aSAndroid Build Coastguard Worker return if $result ne '0'; 238*cf84ac9aSAndroid Build Coastguard Worker 239*cf84ac9aSAndroid Build Coastguard Worker my ($filename, $argv) = parseargs($args); 240*cf84ac9aSAndroid Build Coastguard Worker my ($basename) = $filename =~ m/([^\/]*)$/; 241*cf84ac9aSAndroid Build Coastguard Worker if ($basename ne $$argv[0]) { 242*cf84ac9aSAndroid Build Coastguard Worker $$argv[0] = "$basename($$argv[0])"; 243*cf84ac9aSAndroid Build Coastguard Worker } 244*cf84ac9aSAndroid Build Coastguard Worker my $seq = $pr{$pid_fqname}{seq}; 245*cf84ac9aSAndroid Build Coastguard Worker $seq = [] if not defined $seq; 246*cf84ac9aSAndroid Build Coastguard Worker 247*cf84ac9aSAndroid Build Coastguard Worker push @$seq, ['EXEC', $filename, $argv]; 248*cf84ac9aSAndroid Build Coastguard Worker 249*cf84ac9aSAndroid Build Coastguard Worker $pr{$pid_fqname}{seq} = $seq; 250*cf84ac9aSAndroid Build Coastguard Worker } elsif ($call eq 'fork' || $call eq 'clone' || $call eq 'vfork') { 251*cf84ac9aSAndroid Build Coastguard Worker return if $result == 0; 252*cf84ac9aSAndroid Build Coastguard Worker 253*cf84ac9aSAndroid Build Coastguard Worker my $seq = $pr{$pid_fqname}{seq}; 254*cf84ac9aSAndroid Build Coastguard Worker my $result_fqname= $result . "-" . $time; 255*cf84ac9aSAndroid Build Coastguard Worker $seq = [] if not defined $seq; 256*cf84ac9aSAndroid Build Coastguard Worker push @$seq, ['FORK', $result_fqname]; 257*cf84ac9aSAndroid Build Coastguard Worker $pr{$pid_fqname}{seq} = $seq; 258*cf84ac9aSAndroid Build Coastguard Worker $pr{$result_fqname}{start} = $time; 259*cf84ac9aSAndroid Build Coastguard Worker $pr{$result_fqname}{parent} = $pid_fqname; 260*cf84ac9aSAndroid Build Coastguard Worker $pr{$result_fqname}{seq} = []; 261*cf84ac9aSAndroid Build Coastguard Worker $running_fqname{$result} = $result_fqname; 262*cf84ac9aSAndroid Build Coastguard Worker } elsif ($call eq '_exit' || $call eq 'exit_group') { 263*cf84ac9aSAndroid Build Coastguard Worker $pr{$running_fqname{$pid}}{end} = $time if defined $time and not defined $pr{$running_fqname{$pid}}{end}; 264*cf84ac9aSAndroid Build Coastguard Worker delete $running_fqname{$pid}; 265*cf84ac9aSAndroid Build Coastguard Worker } 266*cf84ac9aSAndroid Build Coastguard Worker} 267*cf84ac9aSAndroid Build Coastguard Worker 268*cf84ac9aSAndroid Build Coastguard Workersub handle_killed { 269*cf84ac9aSAndroid Build Coastguard Worker my ($pid, $time) = @_; 270*cf84ac9aSAndroid Build Coastguard Worker $pr{$pid}{end} = $time if defined $time and not defined $pr{$pid}{end}; 271*cf84ac9aSAndroid Build Coastguard Worker} 272*cf84ac9aSAndroid Build Coastguard Worker 273*cf84ac9aSAndroid Build Coastguard Workersub straight_seq { 274*cf84ac9aSAndroid Build Coastguard Worker my ($pid) = @_; 275*cf84ac9aSAndroid Build Coastguard Worker my $seq = $pr{$pid}{seq}; 276*cf84ac9aSAndroid Build Coastguard Worker 277*cf84ac9aSAndroid Build Coastguard Worker for my $elem (@$seq) { 278*cf84ac9aSAndroid Build Coastguard Worker if ($$elem[0] eq 'EXEC') { 279*cf84ac9aSAndroid Build Coastguard Worker my $argv = $$elem[2]; 280*cf84ac9aSAndroid Build Coastguard Worker print "$$elem[0] $$elem[1] @$argv\n"; 281*cf84ac9aSAndroid Build Coastguard Worker } elsif ($$elem[0] eq 'FORK') { 282*cf84ac9aSAndroid Build Coastguard Worker print "$$elem[0] $$elem[1]\n"; 283*cf84ac9aSAndroid Build Coastguard Worker } else { 284*cf84ac9aSAndroid Build Coastguard Worker print "$$elem[0]\n"; 285*cf84ac9aSAndroid Build Coastguard Worker } 286*cf84ac9aSAndroid Build Coastguard Worker } 287*cf84ac9aSAndroid Build Coastguard Worker} 288*cf84ac9aSAndroid Build Coastguard Worker 289*cf84ac9aSAndroid Build Coastguard Workersub first_exec { 290*cf84ac9aSAndroid Build Coastguard Worker my ($pid) = @_; 291*cf84ac9aSAndroid Build Coastguard Worker my $seq = $pr{$pid}{seq}; 292*cf84ac9aSAndroid Build Coastguard Worker 293*cf84ac9aSAndroid Build Coastguard Worker for my $elem (@$seq) { 294*cf84ac9aSAndroid Build Coastguard Worker if ($$elem[0] eq 'EXEC') { 295*cf84ac9aSAndroid Build Coastguard Worker return $elem; 296*cf84ac9aSAndroid Build Coastguard Worker } 297*cf84ac9aSAndroid Build Coastguard Worker } 298*cf84ac9aSAndroid Build Coastguard Worker return undef; 299*cf84ac9aSAndroid Build Coastguard Worker} 300*cf84ac9aSAndroid Build Coastguard Worker 301*cf84ac9aSAndroid Build Coastguard Workersub display_pid_trace { 302*cf84ac9aSAndroid Build Coastguard Worker my ($pid, $lead) = @_; 303*cf84ac9aSAndroid Build Coastguard Worker my $i = 0; 304*cf84ac9aSAndroid Build Coastguard Worker my @seq = @{$pr{$pid}{seq}}; 305*cf84ac9aSAndroid Build Coastguard Worker my $elapsed; 306*cf84ac9aSAndroid Build Coastguard Worker 307*cf84ac9aSAndroid Build Coastguard Worker if (not defined first_exec($pid)) { 308*cf84ac9aSAndroid Build Coastguard Worker unshift @seq, ['EXEC', '', ['(anon)'] ]; 309*cf84ac9aSAndroid Build Coastguard Worker } 310*cf84ac9aSAndroid Build Coastguard Worker 311*cf84ac9aSAndroid Build Coastguard Worker if (defined $pr{$pid}{start} and defined $pr{$pid}{end}) { 312*cf84ac9aSAndroid Build Coastguard Worker $elapsed = $pr{$pid}{end} - $pr{$pid}{start}; 313*cf84ac9aSAndroid Build Coastguard Worker $elapsed /= $scale_factor; 314*cf84ac9aSAndroid Build Coastguard Worker if ($floatform) { 315*cf84ac9aSAndroid Build Coastguard Worker $elapsed = sprintf("%0.02f", $elapsed); 316*cf84ac9aSAndroid Build Coastguard Worker } else { 317*cf84ac9aSAndroid Build Coastguard Worker $elapsed = int $elapsed; 318*cf84ac9aSAndroid Build Coastguard Worker } 319*cf84ac9aSAndroid Build Coastguard Worker } 320*cf84ac9aSAndroid Build Coastguard Worker 321*cf84ac9aSAndroid Build Coastguard Worker for my $elem (@seq) { 322*cf84ac9aSAndroid Build Coastguard Worker $i++; 323*cf84ac9aSAndroid Build Coastguard Worker if ($$elem[0] eq 'EXEC') { 324*cf84ac9aSAndroid Build Coastguard Worker my $argv = $$elem[2]; 325*cf84ac9aSAndroid Build Coastguard Worker if (defined $elapsed) { 326*cf84ac9aSAndroid Build Coastguard Worker print "$lead [$elapsed] $pid @$argv\n"; 327*cf84ac9aSAndroid Build Coastguard Worker undef $elapsed; 328*cf84ac9aSAndroid Build Coastguard Worker } else { 329*cf84ac9aSAndroid Build Coastguard Worker print "$lead $pid @$argv\n"; 330*cf84ac9aSAndroid Build Coastguard Worker } 331*cf84ac9aSAndroid Build Coastguard Worker } elsif ($$elem[0] eq 'FORK') { 332*cf84ac9aSAndroid Build Coastguard Worker if ($i == 1) { 333*cf84ac9aSAndroid Build Coastguard Worker if ($lead =~ /-$/) { 334*cf84ac9aSAndroid Build Coastguard Worker display_pid_trace($$elem[1], "$lead--+--"); 335*cf84ac9aSAndroid Build Coastguard Worker } else { 336*cf84ac9aSAndroid Build Coastguard Worker display_pid_trace($$elem[1], "$lead +--"); 337*cf84ac9aSAndroid Build Coastguard Worker } 338*cf84ac9aSAndroid Build Coastguard Worker } elsif ($i == @seq) { 339*cf84ac9aSAndroid Build Coastguard Worker display_pid_trace($$elem[1], "$lead `--"); 340*cf84ac9aSAndroid Build Coastguard Worker } else { 341*cf84ac9aSAndroid Build Coastguard Worker display_pid_trace($$elem[1], "$lead +--"); 342*cf84ac9aSAndroid Build Coastguard Worker } 343*cf84ac9aSAndroid Build Coastguard Worker } 344*cf84ac9aSAndroid Build Coastguard Worker if ($i == 1) { 345*cf84ac9aSAndroid Build Coastguard Worker $lead =~ s/\`--/ /g; 346*cf84ac9aSAndroid Build Coastguard Worker $lead =~ s/-/ /g; 347*cf84ac9aSAndroid Build Coastguard Worker $lead =~ s/\+/|/g; 348*cf84ac9aSAndroid Build Coastguard Worker } 349*cf84ac9aSAndroid Build Coastguard Worker } 350*cf84ac9aSAndroid Build Coastguard Worker} 351*cf84ac9aSAndroid Build Coastguard Worker 352*cf84ac9aSAndroid Build Coastguard Workersub display_trace { 353*cf84ac9aSAndroid Build Coastguard Worker my ($startpid) = @_; 354*cf84ac9aSAndroid Build Coastguard Worker 355*cf84ac9aSAndroid Build Coastguard Worker $startpid = (keys %pr)[0]; 356*cf84ac9aSAndroid Build Coastguard Worker while ($pr{$startpid}{parent}) { 357*cf84ac9aSAndroid Build Coastguard Worker $startpid = $pr{$startpid}{parent}; 358*cf84ac9aSAndroid Build Coastguard Worker } 359*cf84ac9aSAndroid Build Coastguard Worker 360*cf84ac9aSAndroid Build Coastguard Worker display_pid_trace($startpid, ""); 361*cf84ac9aSAndroid Build Coastguard Worker} 362