OSDN Git Service

* speclib: Initial stab at cleaning up temp files. More work needed.
authorcgf <cgf>
Sun, 12 Apr 2009 05:11:07 +0000 (05:11 +0000)
committercgf <cgf>
Sun, 12 Apr 2009 05:11:07 +0000 (05:11 +0000)
* mkimport: Ditto.

winsup/cygwin/ChangeLog
winsup/cygwin/mkimport [new file with mode: 0755]
winsup/cygwin/speclib

index db1e19e..8069d64 100644 (file)
@@ -1,5 +1,10 @@
 2009-04-12  Christopher Faylor  <me+cygwin@cgf.cx>
 
+       * speclib: Initial stab at cleaning up temp files.  More work needed.
+       * mkimport: Ditto.
+
+2009-04-12  Christopher Faylor  <me+cygwin@cgf.cx>
+
        * Makefile.in (clean): Clean globals.h.
        (LIBCOS): Depend on globals.h.
 
diff --git a/winsup/cygwin/mkimport b/winsup/cygwin/mkimport
new file mode 100755 (executable)
index 0000000..99d8ef0
--- /dev/null
@@ -0,0 +1,82 @@
+#!/usr/bin/perl
+use strict;
+use File::Temp qw'tempdir';
+use File::Spec;
+use Getopt::Long;
+my $dir = tempdir(CLEANUP => 1);
+
+my ($ar, $as, $nm, $objcopy, %replace);
+GetOptions('ar=s'=>\$ar, 'as=s'=>\$as,'nm=s'=>\$nm, 'objcopy=s'=>\$objcopy, 'replace=s'=>\%replace);
+
+# Args::
+#   1) import lib to create
+#   2) input dll
+#   3...) extra objects to add
+
+$_ = File::Spec->rel2abs($_) for @ARGV;
+
+my $libdll = shift;
+my $inpdll = shift;
+
+open my $nm_fd, '-|', $nm, '-Apg', '--defined-only', $inpdll;
+my %text = ();
+my %import = ();
+my %symfile = ();
+while (<$nm_fd>) {
+    chomp;
+    my ($fn, $type, $sym) = /^$inpdll:(.*?):\S+\s+(\S)\s+(\S+)$/o;
+    next unless $fn;
+    $text{$fn} = $sym if $type eq 'T';
+    $import{$fn} = $sym if $type eq 'I';
+    $symfile{$sym} = $fn;
+}
+close $nm_fd or exit 1;
+
+for my $sym (keys %replace) {
+    my $fn;
+    my $_sym = '_' . $sym;
+    if (!defined($fn = $symfile{$_sym})) {
+       $fn = "$sym.o";
+       $text{$fn} = $_sym;
+    }
+    my $imp_sym = '__imp__' . $replace{$sym};
+    $import{$fn} = $imp_sym;
+}
+
+for my $f (keys %text) {
+    my $imp_sym = delete $import{$f};
+    my $glob_sym = $text{$f};
+    if (!defined $imp_sym) {
+       delete $text{$f};
+    } elsif ($imp_sym eq '__imp__') {
+       $text{$f} = 0;
+    } else {
+       $text{$f} = 1;
+       open my $as_fd, '|-', $as, '-o', "$dir/t-$f", "-";
+       print $as_fd <<EOF;
+       .extern $imp_sym
+       .global $glob_sym
+$glob_sym:
+       jmp     *$imp_sym
+EOF
+       close $as_fd or exit 1;
+    }
+}
+
+chdir $dir or die "$0: couldn't cd to $dir - $!\n";
+system $ar, 'x', $inpdll;
+exit 1 if $?;
+
+for my $f (keys %text) {
+    if (!$text{$f}) {
+       unlink $f;
+    } else {
+       system $objcopy, '-R', '.text', $f and exit 1;
+       system $objcopy, '-R', '.bss', '-R', '.data', "t-$f" and exit 1;
+    }
+}
+
+unlink $libdll;
+system $ar, 'crus', $libdll, glob('*.o'), @ARGV;
+unlink glob('*.o');
+exit 1 if $?;
index b26644a..8074408 100755 (executable)
@@ -1,6 +1,6 @@
 #!/usr/bin/perl
 use Getopt::Long;
-use File::Temp qw'tempdir';
+use File::Temp;
 use File::Basename;
 use File::Spec;
 use strict;
@@ -8,46 +8,49 @@ use strict;
 sub dllname($;$);
 
 my $static;
-my $exclude;
+my $inverse;
+my @exclude;
 
-GetOptions('static!'=>\$static, 'v|exclude!'=>\$exclude);
+my ($ar, $as, $nm, $objcopy);
+GetOptions('exclude=s'=>\@exclude, 'static!'=>\$static, 'v!'=>\$inverse,
+          'ar=s'=>\$ar, 'as=s'=>\$as,'nm=s'=>\$nm, 'objcopy=s'=>\$objcopy);
 
-my $nm = shift;
-my $ar = shift;
-my $libdll = File::Spec->rel2abs(shift @ARGV);
-my $lib =  File::Spec->rel2abs(pop @ARGV);
+$_ = File::Spec->rel2abs($_) for @ARGV;
 
-open my $nm_fd, '-|', $nm, '-Ap', '--defined-only', @ARGV, $libdll or
+my $libdll = shift;
+my $lib =  pop;
+
+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/;
 while (<$nm_fd>) {
     study;
-    m%^\Q$libdll\E:([^:]*):\d+ i \.idata\$([56])% and do {
-       next;
-    };
-    m%^\Q$libdll\E:[^:]*:\d+ I (__head_.*)$% and do {
-       next;
-    };
-    next unless m%^([^:]*):([^:]*(?=:))?.* [DTI] (.*)%o;
-    if ($1 ne $libdll) {
-        $match_syms{$3} = 1;
-     } elsif ($match_syms{$3} ? !$exclude : $exclude) {
-        $extract{$2} = 1;
+    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);
+my $dir = File::Temp->newdir();
 
 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;
-exec $ar, 'crus', $lib, sort keys %extract;
+$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;