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);

}

Reply via email to