Add support for "slim", which is "stem" + removal of some exports and checking of import details
For this to work, the static_dependencies.txt file needs to contain the augmented dependency information.
To help with this, it can now consume a mixture of both rom_content.csv lines and static_dependencies.txt lines: the
best way to update the information would be something like
(edit rom_content.csv to add "slim" to XXX.dll)
findstr /i "xxx.dll" rom_content.csv > slim.txt
findstr /i "xxx.dll" static_dependencies.txt >> slim.txt
perl ..\tools\static_dependencies.pl -u static_dependencies.txt slim.txt > new_dependencies.txt
This will notice the "slim" marking for xxx.dll, and record the detailed import and export lists for
xxx.dll and everything which links to it. The new information will look something like
sys\bin\xxx.dll /epoc32/release/armv5/urel/stem_xxx.dll exports=1-98.100-102:euser[100039e5].dll
sys\bin\yyy.dll /epoc32/release/armv5/urel/yyy.dll euser[100039e5].dll:xxx[102750c7].dll@2.4-5.77.104-106:scppnwdl.dll
sys\bin\zzz.dll /epoc32/release/armv5/urel/zzz.dll euser[100039e5].dll:xxx[102750c7].dll@23.25.74-77:scppnwdl.dll
Only executables for which there is a "slim" marking will have this level of detail.
The filtering script now does the detailed cross-checking of imports to exports for "slim" executables.
In this case, it will observe the stem_xxx.dll does not export ordinal 104, and so the filtering will include
deleting sys\bin\yyy.dll (xxx.dll Missing ordinal 104)
sys\bin\zzz.dll will be acceptable, because it only uses ordinals which are still present in stem_xxx.dll
# Copyright (c) 2010 Symbian Foundation Ltd.
# All rights reserved.
# This component and the accompanying materials are made available
# under the terms of the License "Eclipse Public License v1.0"
# which accompanies this distribution, and is available
# at the URL "http://www.eclipse.org/legal/epl-v10.html".
#
# Initial Contributors:
# Symbian Foundation - initial contribution.
#
# Contributors:
#
# Description:
# This script generates a list of static dependencies for files in a ROM
use strict;
use Getopt::Long;
my $inverted_table = 0;
my $existing_file;
GetOptions(
"i|invert" => \$inverted_table, # add the inverted table
"u|update=s" => \$existing_file, # update existing file
);
my @existinglines;
if ($existing_file)
{
open EXISTING, "<$existing_file" or die("Cannot open $existing_file: $!\n");
print STDERR "Reading existing dependencies from $existing_file\n";
@existinglines = <EXISTING>;
close EXISTING;
}
my %romfiles;
my @contents;
my %need_details;
my $line;
while ($line = <>)
{
my ($romfile,$hostfile,$ibyfile,$package,$cmd,@columns) = split /,/, $line; # first 5 fields are guaranteed to be simple
next if ($romfile eq "ROM file"); # skip header line
if (!defined $hostfile)
{
# is it perhaps a static_dependencies.txt line?
my $dependencies;
my $nothing;
($romfile,$hostfile,$dependencies,$nothing) = split /\t/, $line;
next if (defined $nothing || !defined $hostfile);
$cmd = "";
}
if (lc $cmd eq "slim")
{
$need_details{lc $romfile} = 1;
$cmd = "stem"; # slim implies stem
}
if (lc $cmd eq "stem" && $hostfile !~ /stem_/)
{
push @contents, "$romfile\t$hostfile"; # calculate dependencies for the original file
$hostfile =~ s/(\/|\\)([^\\\/]+)$/$1stem_$2/; # then use stem version as well
}
push @contents, "$romfile\t$hostfile";
$romfiles{lc $romfile} = $romfile;
}
sub canonical_romfile($)
{
my ($romfile) = @_;
my $canonical = $romfiles{lc $romfile};
return $canonical if (defined $canonical);
# New romfile not seen before - add to table
$romfiles{lc $romfile} = $romfile; # set the standard for others!
return $romfile;
}
my %outputlines;
foreach my $existingline (@existinglines)
{
chomp $existingline;
my ($romfile, $hostfile, $deps) = split /\t/, $existingline;
if (defined $deps)
{
$romfile = canonical_romfile($romfile);
$outputlines{"$romfile\t$hostfile"} = "$romfile\t$hostfile\t$deps";
}
}
my %dependents;
sub print_dependency($$@)
{
my ($romfile,$hostfile,@dependencies) = @_;
$outputlines{"$romfile\t$hostfile"} = "$romfile\t$hostfile\t". join(":",@dependencies);
next unless $inverted_table;
# Create inverted table
foreach my $dependent (@dependencies)
{
next if ($dependent =~ /^sid=/);
$dependent = lc $dependent;
$dependent =~ s/^sys\\bin\\//; # no directory => sys\bin anyway
$dependent =~ s/\[\S+\]//; # ignore the UIDs for now
if (!defined $dependents{$dependent})
{
$dependents{$dependent} = $romfile;
}
else
{
$dependents{$dependent} .= "\t$romfile";
}
}
}
sub summarise_list($)
{
my ($hashref) = @_;
my @summary;
my @list = sort {$a <=> $b} keys %$hashref;
my $first = shift @list;
my $latest = $first;
foreach my $number (@list)
{
if ($number == $latest + 1)
{
# extends existing range by one
$latest = $latest + 1;
next;
}
# new range
if ($first > -1)
{
if ($latest == $first)
{
# Range with one element
push @summary, $first;
}
else
{
push @summary, "$first-$latest";
}
}
$first = $number;
$latest = $number;
}
if ($latest == $first)
{
push @summary, "$first";
}
else
{
push @summary, "$first-$latest";
}
return join(".", @summary);
}
sub generate_elftran_dependencies($$)
{
my ($romfile,$hostfile) = @_;
return if ($hostfile =~ /\/z\//); # data files in armv5\urel\z
return if ($hostfile =~ /\.sis$/); # not an e32 image file
my @elftran = `elftran $hostfile`;
my $sid;
my @imports;
my $dll;
my $importing = 0;
my %ordinals;
my %exports;
foreach my $line (@elftran)
{
# Ordinal 318: 00010f9f
if ($line =~ /Ordinal\s+(\d+):\s+(ABSENT)?/)
{
$exports{$1} = 1 unless ($2 eq "ABSENT");
next;
}
# 2 imports from backend{00010001}[102828d5].dll
# 17 imports from dfpaeabi{000a0000}.dll
if ($line =~ /(\d+) imports from (\S+)\{.{8}\}(\S+)$/)
{
$dll = $2.$3;
my $import_count = $1;
my $exename = "sys\\bin\\". lc $dll;
$exename =~ s/\[\S+\]//; # ignore the UID
if (defined $need_details{$exename})
{
# enable the tracking of the imported ordinals
$importing = $import_count;
%ordinals = ();
}
else
{
# Just report the simple reference to the imported dll
$importing = 0;
push @imports, $dll;
}
next;
}
if ($importing && $line =~ /^\s+(\d+)( offset by \d+)?$/)
{
$ordinals{$1} = 1;
$importing -= 1;
if ($importing == 0)
{
$dll = $dll. "@". summarise_list(\%ordinals);
push @imports, $dll;
}
next;
}
if ($line =~ /^Secure ID: (\S+)$/)
{
$sid = $1; # presumably owns private/$sid and various $sid.etxn files
next;
}
}
my @export_info = ();
if (scalar keys %exports && $need_details{lc $romfile})
{
push @export_info, "exports=".summarise_list(\%exports);
}
print_dependency($romfile,$hostfile, @export_info, "sid=$sid",@imports);
}
sub find_exe_names_dependencies($$)
{
my ($romfile,$hostfile) = @_;
my @strings = `$ENV{"SBS_HOME"}\\win32\\mingw\\bin\\strings $hostfile`;
my %executables;
foreach my $string (@strings)
{
if ($string =~ /^(.*\\)?([^-\\]+\.(exe|dll))$/i)
{
my $exename = $2;
$exename =~ s/^\s+//; # strip off leading whitespace (e.g.length byte before "clock.exe")
$exename = canonical_romfile("sys\\bin\\$exename"); # get the exact capitalisation
# print STDERR "Found $exename in $string";
$executables{$exename} = 1;
}
}
if (%executables)
{
print_dependency($romfile,$hostfile,sort keys %executables);
}
else
{
print STDERR "No executable names found in system statup resource $hostfile\n";
}
}
sub find_dependency_in_sys_bin($$$)
{
my ($romfile,$hostfile,$basename) = @_;
$basename = lc $basename;
foreach my $extension (".exe",".dll")
{
my $dependency = "sys\\bin\\$basename$extension";
if (defined $romfiles{$dependency})
{
print_dependency($romfile,$hostfile,$romfiles{$dependency});
return;
}
}
# grep in the contents list?
# print_dependency($romfile,$hostfile,"unmatched sys\\bin\\$basename");
}
foreach $line (@contents)
{
my ($romfile,$hostfile) = split /\t/, $line;
if ($hostfile =~ /epoc32.release.arm/i)
{
generate_elftran_dependencies($romfile,$hostfile);
next;
}
# App registration files
if ($romfile =~ /private.10003a3f.*apps\\(.*)_reg\.rsc$/i)
{
my $dependency = "sys\\bin\\$1.exe";
print_dependency($romfile,$hostfile,$dependency);
next;
}
# app resources
if ($romfile =~ /resource.apps\\(.*)(\.mif|\.mbm|\.rsc)$/)
{
my $executable = $1;
$executable =~ s/_aif$//; # xxx_aif.mif
$executable =~ s/_loc$//; # xxx_loc.rsc
find_dependency_in_sys_bin($romfile,$hostfile,$executable);
next;
}
# System state manager resource files
if ($romfile =~ /private.2000d75b\\.*\.rsc$/i)
{
find_exe_names_dependencies($romfile,$hostfile);
next;
}
# Assume that the rest don't depend on anything, and leave them out.
}
foreach my $romfile ( sort keys %outputlines)
{
print $outputlines{$romfile}, "\n";
}
if ($inverted_table)
{
print "\n";
foreach my $inverted (sort keys %dependents)
{
print "x\t$inverted\t$dependents{$inverted}\n";
}
}