aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristopher Faylor <me@cgf.cx>2009-01-02 06:57:14 +0000
committerChristopher Faylor <me@cgf.cx>2009-01-02 06:57:14 +0000
commit944c817a60697a4dcfc05ee51ac9490208f86d53 (patch)
tree8aa705514d320beda7d0dd32a8f56e4209b2e2d8
parentfeb2075569076a0f9fb42932f2d63c6431803444 (diff)
downloadnewlib-944c817a60697a4dcfc05ee51ac9490208f86d53.zip
newlib-944c817a60697a4dcfc05ee51ac9490208f86d53.tar.gz
newlib-944c817a60697a4dcfc05ee51ac9490208f86d53.tar.bz2
* speclib: Rewrite completely in perl. Avoid multiple nm calls.
-rw-r--r--winsup/cygwin/ChangeLog4
-rwxr-xr-xwinsup/cygwin/speclib141
2 files changed, 94 insertions, 51 deletions
diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog
index cd518c5..30e6ddd 100644
--- a/winsup/cygwin/ChangeLog
+++ b/winsup/cygwin/ChangeLog
@@ -1,3 +1,7 @@
+2009-01-02 Christopher Faylor <me+cygwin@cgf.cx>
+
+ * speclib: Rewrite completely in perl. Avoid multiple nm calls.
+
2008-12-31 Christopher Faylor <me+cygwin@cgf.cx>
* include/cygwin/version.h: Bump CYGWIN_VERSION_API_MINOR to 191.
diff --git a/winsup/cygwin/speclib b/winsup/cygwin/speclib
index 6642414..31c7113 100755
--- a/winsup/cygwin/speclib
+++ b/winsup/cygwin/speclib
@@ -1,52 +1,91 @@
-#!/bin/sh -x
-# speclib - Make a special version of the cygwin import library.
-#
-# Copyright 2001, 2002 Red Hat, Inc.
-#
-# This file is part of Cygwin.
-#
-# This software is a copyrighted work licensed under the terms of the
-# Cygwin license. Please consult the file "CYGWIN_LICENSE" for
-# details.
-
-case "$1" in
- -v) shift; v() { :; } ;;
- *) v() { /bin/false; } ;;
-esac
-lib=$1; shift
-nm=$1; shift
-ar=$1; shift
-libdll=$1; shift
-cp /dev/null /tmp/$$.objs
-trap "cd /tmp; /bin/rm -rf $lib.bak /tmp/$$.dir /tmp/$$.syms /tmp/$$.objs /tmp/$$.raw" 0 1 2 15
-$nm --extern-only --defined-only $* | sed -n -e 's%^.* [TD] \(.*\)$%/ \1\$/p%p' > /tmp/$$.syms
-v || $nm -Ap --extern-only --defined-only $libdll | egrep ' I __head| I _.*_iname' | awk -F: '{print $2}' > /tmp/$$.objs
-$nm -Ap --extern-only --defined-only $libdll | sed -n -f /tmp/$$.syms | awk -F: '{print $2}' >> /tmp/$$.objs
-sort -o /tmp/$$.objs -u /tmp/$$.objs
-
-[ -s /tmp/$$.objs ] || { echo "speclib: couldn't find symbols for $lib" 1>&2; exit 1; }
-
-/bin/rm -rf /tmp/$$.dir
-mkdir /tmp/$$.dir
-cd /tmp/$$.dir
-if v; then
- $ar x $libdll
- /bin/rm -f `cat /tmp/$$.objs`
-else
- $ar x $libdll `cat /tmp/$$.objs`
-fi
-/bin/rm -f $lib
-$ar crus $lib *.o
-export lib;
-perl -pi.bak -- - $lib << 'EOF'
-BEGIN {
- binmode STDIN;
- binmode STDOUT;
- $lib = ($ENV{lib} =~ m!/([^/]+)$!o)[0] || $ENV{lib};
- $lib =~ s/\.a//o;
- my $pad = length('cygwin1_dll') - length($lib);
- die "speclib: library name too long (" . length($lib) . ")\n" if $pad < 0;
- $lib = "__head_$lib" . "\0" x $pad;
+#!/usr/bin/perl
+use Getopt::Long;
+use File::Temp qw'tempdir';
+use File::Basename;
+use strict;
+
+sub dllname($;$);
+
+my $verbose;
+my $static;
+my $exclude;
+
+GetOptions('static!'=>\$static, 'v|exclude!'=>\$exclude);
+
+my $lib = shift;
+my $nm = shift;
+my $ar = shift;
+my $libdll = shift;
+
+open my $nm_fd, '-|', $nm, '-Ap', '--defined-only', @ARGV, $libdll or
+ die "$0: execution of $nm for object files failed - $!\n";
+
+my %match_syms = ();
+my $symfiles = ();
+my $lastfn;
+my @headtail = ();
+my %extract = ();
+my $libdllname;
+while (<$nm_fd>) {
+ study;
+ m%^\Q$libdll\E:([^:]*):\d+ i \.idata\$([56])% and do {
+ if ($2 eq 5) {
+ push @headtail, $1;
+ } else {
+ pop @headtail;
+ }
+ next;
+ };
+ m%^\Q$libdll\E:[^:]*:\d+ I (__head_.*)$% and do {
+ $libdllname = $1;
+ next;
+ };
+ next unless m%^([^:]*):([^:]*(?=:))?.* [DTI] (.*)%o;
+ if ($1 ne $libdll) {
+ $match_syms{$3} = 1;
+ } elsif ($match_syms{$3} ? !$exclude : $exclude) {
+ $extract{$2} = 1;
+ }
+}
+close $nm_fd;
+
+%extract or die "$0: couldn't find symbols for $lib\n";
+defined($libdllname) or die "$0: couldn't determine __head_<NAME> - malformed import archive?\n";
+for (@headtail) {
+ $extract{$_} = 1;
+}
+
+my $dir = tempdir();
+
+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;
+$res = system $ar, 'crus', $lib, sort keys %extract;
+die "$0: $ar creation exited with non-zero status\n" if $res;
+
+open my $lib_fd, '<', $lib or die "$0: couldn't open $lib for input - $!\n";
+binmode $lib_fd;
+
+my $libname = dllname($lib, 'lib');
+my $pad = length($libdllname) - length($libname);
+die "$0: library name too long (" . length($libname) . ")\n" if $pad < 0;
+$libname .= "\0" x $pad;
+
+$res = sysread($lib_fd, $_, -s $lib);
+close $lib_fd;
+
+die "$0: couldn't read $lib - $!\n" if $res != -s _;
+0 while s/$libdllname/$libname/sog;
+
+open $lib_fd, '>', $lib or die "$0: couldn't open $lib for output - $!\n";
+syswrite($lib_fd, $_) == length($_) or die "$0: write to $lib failed - $!\n";
+close $lib_fd;
+exit 0;
+
+sub dllname($;$) {
+ my $x = basename($_[0], '.a');
+ $x =~ s/^lib//o;
+ return '__head_' . $_[1] . $x;
}
- s/__head_cygwin1_dll/$lib/g;
-EOF