$verbose = 0;
$num_routines = 10;
$usage = "Usage: $0 [-h] -symbol-file <file> -addr-file <file>\n" .
" -symbol-file A file produced by address_query.pl containing\n" .
" address to symbol mappings.\n" .
" -addr-file An address file produced by extract-profile script.\n" .
" -num-routines <num>\n" .
" The max # of routines to dump sample info for. The\n" .
" default is $num_routines\n.";
while ($#ARGV >= 0) {
if ($ARGV[0] eq "-v") {
$verbose = 1;
} elsif ($ARGV[0] eq "-h") {
print $usage;
exit;
} elsif ($ARGV[0] eq "-num-routines") {
shift;
$num_routines = $ARGV[0];
} elsif ($ARGV[0] eq "-symbol-file") {
shift;
$SYMBOL_FILE = $ARGV[0];
unless (-f "$SYMBOL_FILE") {
die "No file $SYMBOL_FILE\n";
}
} elsif ($ARGV[0] eq "-addr-file") {
shift;
$ADDRESS_FILE = $ARGV[0];
unless (-f "$ADDRESS_FILE") {
die "No file $ADDRESS_FILE\n";
}
}
else {
print $usage;
exit;
}
shift;
}
if (!defined($SYMBOL_FILE) || !defined($ADDRESS_FILE)) {
print $usage;
exit;
}
%addr_to_symbol = ();
%symbol_hits = ();
%addr_to_srcline = ();
%srcline_hits = ();
$find_symbol = 0;
open(SYMBOL_FILE, "< $SYMBOL_FILE") or die "Error opening $SYMBOL_FILE\n";
while (<SYMBOL_FILE>) {
chop($_);
if ($verbose) {
print STDERR "Process $.: <$_>\n";
}
if (/^[0x]??([\d|a-f]+):/) {
$address = $1;
if ($verbose) {
print STDERR "Match for addr $address\n";
}
$find_symbol = 1;
if ( !($_ = <SYMBOL_FILE>) ) {
print STDERR "ERROR -- unexpectedly out of data!\n";
exit;
}
chop($_);
if (/^\(/) {
} else {
if ($verbose) {
print STDERR "Src line is $_\n";
}
if (/^(\w+)\.(\w+)\((\d+)\)/) {
$srcline = "$1.$2:$3";
$addr_to_srcline{$address} = $srcline;
$srcline_hits{$srcline} = 0;
if ($verbose) {
print STDERR "Addr $address -> $addr_to_srcline{$address}\n";
}
}
if ( !($_ = <SYMBOL_FILE>) ) {
print STDERR "ERROR -- out of data, expecting src info!\n";
exit;
}
chop($_);
}
if ($verbose) {
print STDERR "Symbol line is $_\n";
}
if (/^\(([\d|a-f]+)\)[ ]+dynamorio!(\w+)/) {
$addr_to_symbol{$address} = $2;
$symbol_hits{$2} = 0;
if ($verbose) {
print STDERR "Addr $address -> $addr_to_symbol{$address}\n";
}
$find_symbol = 0;
} else {
print STDERR "ERROR -- out of data at line $., expecting symbol info!: $_\n";
}
}
}
close(SYMBOL_FILE);
open(ADDRESS_FILE, "< $ADDRESS_FILE") or die "Error opening $ADDRESS_FILE\n";
$total_hits = 0;
while (<ADDRESS_FILE>) {
chop($_);
if ($verbose) {
print STDERR "Process $.: <$_>\n";
}
if (/^[0x]??([\d|a-f]+)[ ]+(\d+)+[ ]+(\d|'.')+/) {
$address = $1;
$hits = $2;
$total_hits += $hits;
if ($verbose) {
print STDERR "Match for addr $address -- $hits\n";
}
if (defined($addr_to_symbol{$address})) {
$symbol = $addr_to_symbol{$address};
$symbol_hits{$symbol} += $hits;
if ($verbose) {
print STDERR "Update $symbol ($address) to " .
" $symbol_hits{$symbol} hits\n";
}
} else {
if ($verbose) {
print STDERR "Addr $address not present in symbol file\n";
}
}
if (defined($addr_to_srcline{$address})) {
$srcline = $addr_to_srcline{$address};
$srcline_hits{$srcline} += $hits;
if ($verbose) {
print STDERR "Update $srcline ($address) to " .
" $srcline_hits{$srcline} hits\n";
}
} else {
if ($verbose) {
print STDERR "Addr $address not present in symbol file\n";
}
}
}
}
close(ADDRESS_FILE);
@array = ();
while (($key, $value) = each %symbol_hits) {
$array[$#array + 1] = "$key $value";
if ($verbose) {
printf STDERR "Symbol array[$#array] -- %s\n", $array[$#array];
}
}
sub by_hits {
($trash, $a_hits) = split / /, $a;
($trash, $b_hits) = split / /, $b;
$b_hits <=> $a_hits;
}
@sorted_symbols = sort by_hits @array;
if ($#sorted_symbols > 0) {
printf "\n\tHottest symbols\n\n";
printf "%30s %15s %8s\n", "Symbol name", "Hits", "%-age";
printf "%30s %15s %8s\n", "===========", "====", "=====";
for ($i = 0; $i <= $#sorted_symbols; $i++) {
if ($i > $num_routines) {
last;
}
($symbol, $hits) = split / /, $sorted_symbols[$i];
printf "%30s %15d %8.2f\n", $symbol, $hits, 100 * $hits / $total_hits;
}
}
@array = ();
while (($key, $value) = each %srcline_hits) {
$array[$#array + 1] = "$key $value";
if ($verbose) {
printf STDERR "Srcline array[$#array] -- %s\n", $array[$#array];
}
}
@sorted_srclines = sort by_hits @array;
if ($#sorted_srclines > 0) {
printf "\n\tHottest src lines\n\n";
printf "%30s %15s %8s\n", "Src line", "Hits", "%-age";
printf "%30s %15s %8s\n", "=========", "====", "=====";
for ($i = 0; $i <= $#sorted_srclines; $i++) {
if ($i > $num_routines) {
last;
}
($srcline, $hits) = split / /, $sorted_srclines[$i];
printf "%30s %15d %8.2f\n", $srcline, $hits, 100 * $hits / $total_hits;
}
}