diff options
Diffstat (limited to 'winsup/cygwin/scripts/speclib')
-rwxr-xr-x | winsup/cygwin/scripts/speclib | 84 |
1 files changed, 84 insertions, 0 deletions
diff --git a/winsup/cygwin/scripts/speclib b/winsup/cygwin/scripts/speclib new file mode 100755 index 000000000..e6d4d8e94 --- /dev/null +++ b/winsup/cygwin/scripts/speclib @@ -0,0 +1,84 @@ +#!/usr/bin/perl +use Getopt::Long; +use File::Temp qw'tempdir'; +use File::Basename; +use File::Spec; +use strict; + +sub dllname($;$); + +my $static; +my $inverse; +my @exclude; + +my ($cpu, $ar, $as, $nm, $objcopy); +GetOptions('exclude=s'=>\@exclude, 'static!'=>\$static, 'v!'=>\$inverse, + 'cpu=s'=>\$cpu, 'ar=s'=>\$ar, 'as=s'=>\$as,'nm=s'=>\$nm, 'objcopy=s'=>\$objcopy); + +$_ = File::Spec->rel2abs($_) for @ARGV; + +my $libdll = shift; +my $lib = pop; +# FIXME? Do other (non-32 bit) arches on Windows still use symbol prefixes? +my $sym_prefix = ''; +(my $iname = basename $lib) =~ s/\.a$//o; +$iname = $sym_prefix . $iname . '_dll_iname'; + +open my $nm_fd, '-|', $nm, '-Apg', '--defined-only', @ARGV, $libdll or + die "$0: execution of $nm for object files failed - $!\n"; + +my %match_syms = (); +my $symfiles = (); +my $lastfn; +my %extract = (); +my $exclude_regex = @exclude ? join('|', @exclude) : '\\UnLiKeLy//'; +$exclude_regex = qr/$exclude_regex/; +my $dllname; +while (<$nm_fd>) { + study; + if (/ I _?(.*)_dll_iname/o) { + $dllname = $1; + } else { + my ($file, $member, $symbol) = m%^([^:]*):([^:]*(?=:))?.* T (.*)%o; + next if !defined($symbol) || $symbol =~ $exclude_regex; + if ($file ne $libdll) { + $match_syms{$symbol} = 1; + } elsif ($match_syms{$symbol} ? !$inverse : $inverse) { + $extract{$member} = 1; + } + } +} +close $nm_fd; + + +%extract or die "$0: couldn't find symbols for $lib\n"; + +my $dir = tempdir(CLEANUP => 1); + +chdir $dir; +# print join(' ', '+', $ar, 'x', sort keys %extract), "\n"; +my $res = system $ar, 'x', $libdll, sort keys %extract; +die "$0: $ar extraction exited with non-zero status\n" if $res; +unlink $lib; + +# Add a dummy .idata object for libtool so that it will think +# this library is an import library. +my $iname_o = 'd000000.o'; +$extract{$iname_o} = 1; +open my $as_fd, '|-', $as, '-R', '-o', $iname_o, "-"; +print $as_fd <<EOF; + .section .idata\$7 +.global $iname +$iname: .asciz "$dllname.dll" +EOF +close $as_fd or exit 1; +system $objcopy, '-j', '.idata$7', $iname_o; + +$res = system $ar, 'crus', $lib, sort keys %extract; +unlink keys %extract; +die "$0: ar creation of $lib exited with non-zero status\n" if $res; +exit 0; + +END { + chdir '/tmp'; # Allow $dir directory removal on Windows +} |