| #!/usr/bin/perl |
| |
| # ********************************************************** |
| # Copyright (c) 2006-2007 VMware, Inc. All rights reserved. |
| # ********************************************************** |
| |
| # Redistribution and use in source and binary forms, with or without |
| # modification, are permitted provided that the following conditions are met: |
| # |
| # * Redistributions of source code must retain the above copyright notice, |
| # this list of conditions and the following disclaimer. |
| # |
| # * Redistributions in binary form must reproduce the above copyright notice, |
| # this list of conditions and the following disclaimer in the documentation |
| # and/or other materials provided with the distribution. |
| # |
| # * Neither the name of VMware, Inc. nor the names of its contributors may be |
| # used to endorse or promote products derived from this software without |
| # specific prior written permission. |
| # |
| # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
| # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
| # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
| # ARE DISCLAIMED. IN NO EVENT SHALL VMWARE, INC. OR CONTRIBUTORS BE LIABLE |
| # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
| # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR |
| # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER |
| # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
| # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
| # OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH |
| # DAMAGE. |
| |
| ### caller-profile.pl |
| ### author: Derek Bruening April 2006 |
| ### |
| ### Analyzes the output of crude caller profiling that |
| ### looks like this: |
| ### 0x710282fc 0x7102826c 0x710283a2 0x7103569a 242 |
| ### 0x710282fc 0x7102b25e 0x71035934 0x710299a5 31537 |
| ### 0x710282fc 0x7102826c 0x710283e3 0x710358f6 36271 |
| |
| $usage = "Usage: $0 [-build [exports/ subdir for lib]] [-base <DRdllbase>] [-dll <DRdllpath>] <callproffile>\n"; |
| |
| $bld = "lib32/debug"; |
| $DR = $ENV{'DYNAMORIO_HOME'}; |
| $DRdll = ""; |
| $infile = ""; |
| $base = 0; |
| $reloc = 0; |
| |
| # get optional params |
| while ($#ARGV >= 0) { |
| if ($ARGV[0] eq '-build') { |
| if ($#ARGV <= 0) { print $usage; exit; } |
| shift; |
| $bld = $ARGV[0]; |
| } elsif ($ARGV[0] eq '-base') { |
| if ($#ARGV <= 0) { print $usage; exit; } |
| shift; |
| $base = $ARGV[0]; |
| } elsif ($ARGV[0] eq '-dll') { |
| if ($#ARGV <= 0) { print $usage; exit; } |
| shift; |
| $DRdll = $ARGV[0]; |
| } else { |
| $infile = $ARGV[0]; |
| last; |
| } |
| shift; |
| } |
| |
| die $usage if ($infile eq ""); |
| |
| if ($DRdll eq "") { |
| $DRdll = "$DR/exports/$bld/dynamorio.dll"; |
| } |
| die "Cannot find $DRdll" unless (-f $DRdll); |
| |
| if ($base != 0) { |
| if ($DRdll =~ /dbg/ || $DRdll =~ /debug/) { |
| $normbase = 0x15000000; |
| } else { |
| $normbase = 0x71000000; |
| } |
| $reloc = $normbase - hex($base); |
| } |
| |
| open(IN, "< $infile") || die "Error: Couldn't open $infile for input\n"; |
| while (<IN>) { |
| if (/^([0-9xa-fA-F ]+) (\d+)$/) { |
| $addrs = $1; |
| if ($reloc != 0) { |
| $newaddrs = ""; |
| foreach $a (split(' ', $addrs)) { |
| $newaddrs .= sprintf("0x%08x ", hex($a) + $reloc); |
| } |
| $addrs = $newaddrs; |
| } |
| $cnt=$2; |
| $hexes[$num]=$addrs; |
| # FIXME: ensure no symbol path set that will have network delays -- |
| # perhaps even have address_query.pl clear the symbol path every time? |
| # FIXME: would be faster to batch up all addresses and then feed |
| # through a single invocation of address_query.pl |
| open(ADDR, "address_query.pl $DRdll $addrs |") || |
| die "Error running address_query.pl\n"; |
| $out[$num]=sprintf("count=$cnt\n"); |
| while (<ADDR>) { |
| $out[$num] .= $_; |
| if (/^[\w\.\/]+\((\d+)\)/) { |
| $line = $1; |
| } elsif (/^\(\w+\)\s+dynamorio!([^\+]+)/) { |
| $syms[$num] .= "$1:$line "; |
| } |
| } |
| $sortme[$num]=$num; |
| $count[$num++]=$cnt; |
| $sum+=$cnt; |
| } |
| } |
| close(IN); |
| |
| @sortme=sort({$count[$a]<=>$count[$b]} @sortme); |
| |
| # summary |
| print "Total calls: $sum\n\n"; |
| for ($i=$num-1; $i>=0; $i--) { |
| $n=$sortme[$i]; |
| printf "%5.2f%% %s\n", 100*$count[$n]/$sum, $syms[$n]; |
| } |
| |
| # details |
| for ($i=$num-1; $i>=0; $i--) { |
| $n=$sortme[$i]; |
| printf "\n--------\n%5.2f%%\n%s", 100*$count[$n]/$sum, $out[$n]; |
| } |