Since no-one out there seems to have one, I've written a small perl script
that reads the output of "objdump -x" run on a windows DLL and turns it into a
.spec file with all the function stubbed out (handy when you want to deal with
a DLL with over a thousand entry points).
However, I've noticed that it doesn't appear to correlate with the already
existing shell32.spec file based on a dump of the WinNT4 shell32.dll (at least
as far as ordinals go). Can anyone explain this?
David Howells
#!/usr/bin/perl -w
#
# Format:
# objdump -x <dll> | genspec.pl ><dll>.spec
# (using objdump from binutils-2.10)
#
#
# search for the beginning of the import table specification
#
while (<>)
{
chomp;
if ($_ =~ /^The Import Tables/ ) { last; }
}
#
# pull imported DLL specifications out of the import table
#
my @imports;
while (<>)
{
chomp;
if ($_ =~ /^The Export Tables/ ) { last; }
# pull out an import specification
if ($_ =~ /^\tDLL Name:/ )
{
$_ =~ s/^[^:]*[:][ ]*//;
$_ =~ y/A-Z/a-z/;
push(@imports,$_);
}
}
#
# search for the beginning of the export address table
#
$name = "";
$ordbase = 0;
while (<>)
{
chomp;
if ($_ =~ /^Export Address Table/ ) { last; }
if ($_ =~ /^Name/ ) { @_ = split; $name = $_[2]; }
if ($_ =~ /^Ordinal Base/ ) { @_ = split; $ordbase = $_[2]; }
}
#
# pull imported DLL specifications out of the import table
#
my %exportvmas;
while (<>)
{
chomp;
if ( $_ =~ /^ *$/ ) { last; }
# pull out an import specification
@_ = split("[][]");
$_[1] =~ s/ //g;
$_[4] =~ s/^ *//;
$_[4] =~ s/ .*$//;
$ord = $_[1] + $ordbase;
$exportvmas{$ord} = $_[4];
}
#
# search for the beginning of the ordinal naming table
#
while (<>)
{
chomp;
if ($_ =~ /^.Ordinal.Name Pointer. Table/ ) { last; }
}
#
# pull ordinal -> name mappings out
#
my %exportnames;
while (<>)
{
chomp;
if ( $_ =~ /^ *$/ ) { last; }
# break into bits
@_ = split("[][]");
$_[1] =~ s/ //g;
$_[2] =~ s/ //g;
$ord = $_[1] + $ordbase;
$exportnames{$ord} = $_[2];
}
###############################################################################
#
# render the spec file
#
$name =~ y/A-Z/a-z/;
$dll = $name;
$dll =~ s/.dll//;
print "name\t" . $name . "\n";
print "type\twin32\n";
print "init\t" . $dll . "LibMain\n";
print "rsrc\t" . $dll . "rsrc\n";
print "\n";
foreach (@imports)
{
print "import " . $_ . "\n";
}
print "\n";
@exports = sort {$a <=> $b} keys %exportvmas;
foreach $export (@exports)
{
$name = $exportnames{$export};
$name = defined $name ? $name . " " : $dll . "_" . $export;
printf("%4d stub %s\n",$export,$name);
}