#!/usr/bin/perl -w use strict; use Getopt::Std; $Getopt::Std::STANDARD_HELP_VERSION++; my %args; getopts('f:s', \%args); sub VERSION_MESSAGE { # Nothing } sub HELP_MESSAGE { print <<EOS This program parses a linker map file, especially one produced when linking an iOS executable. Input is read from a map file provided as command-line argument By default a list of libraries used and the size of code and data linked in from each library is printed, in reverse order of size. The following options are available: -s Print a list of symbols instead. -f 'filter' Filter which libraries are handled. The filter can be a regular expression, typically several library names combined with the '|' operator. Makes sense only when -s is used too. EOS } die "The -f switch makes sense only if -s is also used\n" if defined($args{'f'}) && !defined($args{'s'}); die "Please provide one map file name\n" if !defined($ARGV[0]); die "Just one argument please\n" if defined($ARGV[1]); my $state = 0; my %libofnumber; my %sizeoflib; my %sizeofsym; open(INPUT, '<', $ARGV[0]) || die "Could not open $ARGV[0]: $!\n"; while (<INPUT>) { if ($state == 0 && m!^# Object files:!) { $state = 1; } elsif ($state == 1 && m!^\[ *([0-9]+)\] .*/([-_a-z0-9]+\.a)\(.*!i) { $libofnumber{$1} = $2; } elsif ($state == 1 && m!^# Sections:!) { $state = 2; } elsif ($state == 2 && m!^# Address\s+Size\s+File\s+Name!) { $state = 3; } elsif ($state == 3 && m!^0x[0-9A-F]+\s+(0x[0-9A-F]+)\s+\[ *([0-9]+)\] (.*)!) { my ($size,$libnum,$symbol) = ($1, $2, $3); if (defined($libofnumber{$libnum})) { $sizeoflib{$libofnumber{$libnum}} += hex($size); if (!defined($args{'f'}) || $libofnumber{$libnum} =~ /$args{'f'}/) { $sizeofsym{$symbol} = hex($size); } } } } if ($args{'s'}) { # Print symbols in reverse size order foreach (sort { $sizeofsym{$b} <=> $sizeofsym{$a} } keys(%sizeofsym)) { print $_, ": ", $sizeofsym{$_}, "\n"; } } else { # Print libraries in reverse size order foreach (sort { $sizeoflib{$b} <=> $sizeoflib{$a} } keys(%sizeoflib)) { print $_, ": ", $sizeoflib{$_}, "\n"; } }