1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
|
#!/usr/bin/perl
use strict;
use warnings;
die "Usage: $0 script.ver dllname build.def import.def\n" if @ARGV != 4;
my ($verfile, $dllname, $builddef, $importdef) = @ARGV;
open my $verfh, '<', $verfile or die "Cannot open input file $verfile: $!\n";
my $input = join '', <$verfh>;
close $verfh;
my @syms;
my (%cnt, %last, %ords);
$input =~ s/\/\*.*?\*\///sg; # Remove C comments
while ($input =~ m/(\S+)\s*\{((?:[^\{\}]|\{(?2)\})+)\}\s*;/sg) { # Split {...}
my ($ver, $block) = ($1, $2);
while ($block =~ s/(\S+)\s*:((?:[^\{\}:]|\{(?2)\})+)$//sg) { # Split section:
my ($section, $syms) = ($1, $2);
next if $section ne 'global';
$syms =~ s/\s+//g;
foreach (split /;\s*/, $syms) { # Split symbols
$cnt{$_}++;
$last{$_} = $ver;
push @syms, [$_, $ver];
}
}
}
open my $importfh, '>', $importdef or die "Cannot open output file $importdef: $!\n";
open my $buildfh, '>', $builddef or die "Cannot open output file $builddef: $!\n";
print $importfh "LIBRARY \"$dllname\"\n";
print $importfh "EXPORTS\n";
print $buildfh "EXPORTS\n";
my $ord = 1;
foreach (@syms) {
my ($sym, $ver) = @{$_};
print $importfh "\"$sym\@$ver\" \@$ord\n";
if ($last{$sym} ne $ver) {
print $buildfh "\"$sym\@$ver\" \@$ord\n";
} else {
$ords{$sym} = $ord;
print $buildfh "\"$sym\@$ver\" = " . (($cnt{$sym} > 1) ? "\"$sym\@\@$ver\"" : $sym) . " \@$ord\n"
}
$ord++;
}
# GNU dlltool has broken calculation of ordinals for aliased symbols, so specify ordinals explicitly
# GNU LD prior 2.21 has broken handling of symbols with dot character
# Operator == for defining symbol alias is supported since GNU dlltool 2.21
print $importfh "$_ \@$ords{$_} == \"$_\@$last{$_}\"\n" foreach sort keys %last;
close $importfh;
close $buildfh;
|