#!/usr/bin/perl -w ## sort-addresses.pl ## by Mike Melanson (mike at multimedia.cx) ## This Perl script takes an file with a list of addresses and any number of ## function files indicating function boundaries, and sorts the addresses ## into the function boundaries. ## ## Usage: ## sort-addresses.pl [function-file-2 ... ## ... function-file-n] use strict; my @original_address_bins; my @address_bins; my @sorted_address_bins; my @addresses; my @sorted_addresses; my $i; my $j; my $address_filename = shift; my $function_filename; my @function_filenames; while ($function_filename = shift) { $function_filenames[++$#function_filenames] = $function_filename; } sub sort_bins { $b->{'count'} <=> $a->{'count'}; } if (!defined $address_filename || !defined $function_filenames[0]) { print < [function-file-2 ... function-file-n] This script requires an address file followed by at least one function file. Any number of additional function files may be specified adterwards. EOM exit; } print "loading known function information...\n"; for ($i = 0; $i <= $#function_filenames; $i++) { open (FUNCTIONFILE, $function_filenames[$i]) or die "could not open $function_filenames[$i]\n"; while (($_ = )) { if (/^function: ([0-9A-Fa-f]{8}) -> ([0-9A-Fa-f]{8}): (.+)/) { # small hole right now: disregard the function whose last address is FFFFFFFF if ($2 ne "FFFFFFFF") { $#original_address_bins++; $original_address_bins[$#original_address_bins]->{'name'} = $3; $original_address_bins[$#original_address_bins]->{'first_address'} = $1; $original_address_bins[$#original_address_bins]->{'last_address'} = $2; $original_address_bins[$#original_address_bins]->{'count'} = 0; } } } } # let the last bin count everything above the last bin $original_address_bins[$#original_address_bins]->{'last_address'} = "FFFFFFFF"; close (FUNCTIONFILE); print "loading addresses...\n"; open (ADDRESSFILE, $address_filename) or die "could not open $address_filename\n"; while ($_ = ) { if (/START PROFILE/) { $_ =~ s/^START PROFILE: (.*)$//; print <{'name'} = $original_address_bins[$i]->{'name'}; $address_bins[$i]->{'first_address'} = $original_address_bins[$i]->{'first_address'}; $address_bins[$i]->{'last_address'} = $original_address_bins[$i]->{'last_address'}; $address_bins[$i]->{'count'} = 0; } my $count = 0xFFFFFFFF; # my $count = 5000; # good for debugging since it takes a lot less time while (($_ = ) && ($_ !~ /STOP PROFILE/) && ($count-- > 0)) { if (/^:/) { $_ =~ s/^:(.*)$//; $addresses[++$#addresses] = $1; } } print <{'last_address'}) { $i++; # next bin; loop again } else { # add the address to this bin's count and move to the next address $address_bins[$i]->{'count'}++; $j++; } } @sorted_address_bins = sort sort_bins @address_bins; for ($i = 0; $i <= $#sorted_address_bins; $i++) { if ($sorted_address_bins[$i]->{'count'} > 0) { print "$sorted_address_bins[$i]->{'name'}: $sorted_address_bins[$i]->{'first_address'} -> $sorted_address_bins[$i]->{'last_address'}, count = $sorted_address_bins[$i]->{'count'} (" . $sorted_address_bins[$i]->{'count'} / $#sorted_addresses * 100 . "%)\n"; } } } } close (ADDRESSFILE);