diff options
author | Christopher Faylor <me@cgf.cx> | 2009-04-12 07:19:52 +0400 |
---|---|---|
committer | Christopher Faylor <me@cgf.cx> | 2009-04-12 07:19:52 +0400 |
commit | edd090a2704aaf538c41cc97619c1d473b4916b2 (patch) | |
tree | 844ddc3a55e17cffac03a1342e30c9e15acf1453 /winsup/cygwin/mkimport | |
parent | 370a1171d8e7f3e93062815f53734f74a35ac817 (diff) |
* mkimport: New script to perform all operations necessary to create
libcygwin.a.
* rmsym: Delete.
* newsym: Delete.
* Makefile.in (toolopts): New variable which holds options relating to
binutils/gcc tools.
(speclib): Use toolopts. Add symbols to avoid copying to special libraries.
(OBSOLETE_FUNCTIONS): Delete.
(NEW_FUNCTIONS): Change to represent an argument to new mkimport script.
(libcygwin.a): Use only new mkimport script to create libcygwin.a. Only rely
on ${LIBCOS}.
(*/lib*.a): Simplify speclib dependencies.
(speclib): Accept toolchain options. Convert every argument to absolute path.
Simplify parsing of nm output. Accommodate new exclude option.
Diffstat (limited to 'winsup/cygwin/mkimport')
-rwxr-xr-x | winsup/cygwin/mkimport | 80 |
1 files changed, 80 insertions, 0 deletions
diff --git a/winsup/cygwin/mkimport b/winsup/cygwin/mkimport new file mode 100755 index 000000000..58c604180 --- /dev/null +++ b/winsup/cygwin/mkimport @@ -0,0 +1,80 @@ +#!/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; +exec $ar, 'crus', $libdll, glob('*.o'), @ARGV; |