[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

[SCM] Debian package checker branch, master, updated. 2.5.9-18-g610970f



The following commit has been merged in the master branch:
commit 610970f61893323862a37894cefc198e09476026
Author: Niels Thykier <niels@thykier.net>
Date:   Tue Jun 26 13:21:16 2012 +0200

    coll/objdump-info: Use xargs + a new helper
    
    Signed-off-by: Niels Thykier <niels@thykier.net>

diff --git a/collection/objdump-info b/collection/objdump-info
index 4e86481..4a61998 100755
--- a/collection/objdump-info
+++ b/collection/objdump-info
@@ -26,6 +26,8 @@
 use strict;
 use warnings;
 
+use Cwd qw(realpath);
+
 use lib "$ENV{'LINTIAN_ROOT'}/lib/";
 use Lintian::Collect;
 use Lintian::Command qw(spawn reap);
@@ -33,7 +35,7 @@ use Lintian::Util qw(fail);
 
 my ($pkg, $type, $dir) = @ARGV;
 my $info = Lintian::Collect->new ($pkg, $type, $dir);
-my $failed = 0;
+my $helper = realpath("$0-helper");
 
 if ( -e "$dir/objdump-info" ) {
     unlink "$dir/objdump-info" or fail "unlink objdump-info: $!"
@@ -45,154 +47,27 @@ if ( -e "$dir/objdump-info.gz" ) {
 
 my $file_info = $info->file_info;
 
+chdir ("$dir/unpacked")
+    or fail ("unable to chdir to unpacked: $!\n");
+
 my %opts = ( pipe_in => FileHandle->new,
              out => "$dir/objdump-info.gz",
              fail => 'error' );
-spawn(\%opts, ['gzip', '-9c'] );
+spawn(\%opts, ['xargs', '-0r', $helper], '|', ['gzip', '-9c'] );
 $opts{pipe_in}->blocking(1);
 
-chdir ("$dir/unpacked")
-    or fail ("unable to chdir to unpacked: $!\n");
-
 foreach my $bin ($info->sorted_index) {
     my $finfo = $file_info->{$bin};
 
     if ($finfo =~ m/^\bELF\b/) {
-
-        print {$opts{pipe_in}} "-- $bin\n";
-
-        system("head \Q$bin\E | grep -q 'packed.*with.*UPX'");
-        print {$opts{pipe_in}} "objdump: $bin: Packed with UPX" if $? == 0;
-
-        my @sections;
-        my @symbol_versions;
-        my @dyn_symbols;
-        my $truncated = 0;
-
-        if (open(PIPE, '-|', "readelf -W -l -t -d -V -s \Q$bin\E 2>&1")) {
-            my $section = '';
-            my %program_headers;
-
-            while(<PIPE>) {
-                chomp;
-                if (m/^readelf: Error: Unable to read in 0x[0-9a-fA-F]+ bytes of/) {
-                    print {$opts{pipe_in}} "objdump: $bin: File truncated\n" unless $truncated++;
-                    next;
-                } elsif (m/^Program Headers:/) {
-                    $section = 'PH';
-                    print {$opts{pipe_in}} "$_\n";
-                } elsif (m/^Section Headers:/) {
-                    $section = 'SH';
-                    print {$opts{pipe_in}} "$_\n";
-                } elsif (m/^Dynamic section at offset .*:/) {
-                    $section = 'DS';
-                    print {$opts{pipe_in}} "$_\n";
-                } elsif (m/^Version symbols section /) {
-                    $section = 'VS';
-                } elsif (m/^Symbol table '.dynsym'/) {
-                    $section = 'DS';
-                } elsif (m/^Symbol table/) {
-                    $section = '';
-                } elsif (m/^\s*$/) {
-                    $section = '';
-                } elsif (m/^\s*(\S+)\s*(?:(?:\S+\s+){4})\S+\s(...)/
-                         and $section eq 'PH') {
-                    my ($header, $flags) = ($1, $2);
-                    $header =~ s/^GNU_//g;
-                    next if $header eq 'Type';
-
-                    my $newflags = '';
-                    $newflags .= ($flags =~ m/R/) ? 'r' : '-';
-                    $newflags .= ($flags =~ m/W/) ? 'w' : '-';
-                    $newflags .= ($flags =~ m/E/) ? 'x' : '-';
-
-                    $program_headers{$header} = $newflags;
-                    print {$opts{pipe_in}} "  $header off 0x0 X 0x0 X 0x0\n  flags $newflags\n";
-                } elsif (m/^\s*\[(\d+)\]\s*(\S+)(?:\s|\Z)/
-                         and $section eq 'SH') {
-                    $sections[$1] = $2;
-                    # We need sections as well (i.e. for incomplete stripping)
-                    # - The 0 0 0 0 2**3 is just there to make it look like objdump output
-                    #   (supposedly we don't even check for those extra fields in
-                    #    L::Collect::Binary)
-                    print {$opts{pipe_in}} " $1 $2   0 0 0 0 2**3\n";
-                } elsif (m/^\s*0x(?:[0-9A-F]+)\s+\((.*?)\)\s+(\S.*)\Z/i
-                         and $section eq 'DS') {
-                    my ($type, $value) = ($1, $2);
-
-                    if ($type eq 'RPATH') {
-                        $value =~ s/.*\[//;
-                        $value =~ s/\]\s*$//;
-                    }
-                    $value =~ s/^(?:Shared library|Library soname): \[(.*)\]/$1/;
-                    print {$opts{pipe_in}} "  $type   $value\n";
-                } elsif (m/^\s*[0-9A-F]+: \s+ \S+ \s* (?:\(\S+\))? (?:\s|\Z)/xi
-                         and $section eq 'VS') {
-                    while (m/([0-9A-F]+h?)\s*(?:\((\S+)\))?(?:\s|\Z)/gci) {
-                        my ($vernum, $verstring) = ($1, $2);
-                        $verstring ||= '';
-                        if ($vernum =~ m/h$/) {
-                            $verstring = "($verstring)";
-                        }
-                        push @symbol_versions, $verstring;
-                    }
-                } elsif (m/^\s*(\d+):\s*[0-9a-f]+\s+\d+\s+(?:(?:\S+\s+){3})(\S+)\s+(.*)\Z/
-                         and $section eq 'DS') {
-                    # We (somtimes) need to read the "Version symbols section" first to
-                    # use this data and readelf tends to print after this section, so
-                    # save for later.
-                    push @dyn_symbols, [$1, $2, $3, '']
-
-                } elsif (m/^There is no dynamic section in this file/
-                         and exists $program_headers{DYNAMIC}) {
-                    # The headers declare a dynamic section but it's
-                    # empty. Generate the same error as objdump,
-                    # the checks scripts special-case the string.
-                    print {$opts{pipe_in}} "\n\nobjdump: $bin: Invalid operation\n";
-                }
-            }
-            close PIPE;
-        }
-
-        if (@dyn_symbols) {
-            print {$opts{pipe_in}} "DYNAMIC SYMBOL TABLE:\n";
-            foreach my $dynsym (@dyn_symbols) {
-                my ($symnum, $seg, $sym, $ver) = @$dynsym;
-
-                    if ($sym =~ m/^(.*)@(.*) \(.*\)$/) {
-                        $sym = $1;
-                        $ver = $2;
-                    } elsif (@symbol_versions == 0) {
-                        # No versioned symbols...
-                        $ver = '';
-                    } else {
-                        $ver = $symbol_versions[$symnum];
-
-                        if ($ver eq '*local*' or $ver eq '*global*') {
-                            if ($seg eq 'UND') {
-                                $ver = '   ';
-                            } else {
-                                $ver = 'Base';
-                            }
-                        } elsif ($ver eq '()') {
-                            $ver = '(Base)';
-                        }
-                    }
-
-                    if ($seg =~ m/^\d+$/ and defined $sections[$seg]) {
-                        $seg = $sections[$seg];
-                    }
-
-                    print {$opts{pipe_in}} "00      XX $seg  000000  $ver  $sym\n";
-            }
-        }
+        printf {$opts{pipe_in}} "%s\0", $bin;
     }
 }
 
 close $opts{pipe_in} or fail "cannot write objdump-info.gz: $!";
 reap(\%opts);
 
-exit $failed;
+exit 0;
 
 # Local Variables:
 # indent-tabs-mode: nil
diff --git a/collection/objdump-info-helper b/collection/objdump-info-helper
new file mode 100755
index 0000000..e816bb1
--- /dev/null
+++ b/collection/objdump-info-helper
@@ -0,0 +1,207 @@
+#!/usr/bin/perl
+# objdump-info-helper -- lintian collection script
+
+# Most of it is taken from objdump-info (Lintian 2.5.9), which had the
+# following copyright/license statements:
+#
+# The original shell script version of this script is
+# Copyright (C) 1998 Christian Schwarz
+# 
+# This version, including support for etch's binutils, is
+# Copyright (C) 2008 Adam D. Barratt
+# 
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+# 
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+# 
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, you can find it on the World Wide
+# Web at http://www.gnu.org/copyleft/gpl.html, or write to the Free
+# Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
+# MA 02110-1301, USA.
+
+use strict;
+use warnings;
+
+my @sections;
+my @symbol_versions;
+my @dyn_symbols;
+my $truncated = 0;
+my $section = '';
+my %program_headers;
+my $bin;
+
+# it would have been nice to do open '-|', "readelf ... 2>&1" but
+# then we have to escape the args and that puts us over the
+# argument limit in some cases...
+my $pid = open my $readelf, '-|';
+
+if (not defined $pid) {
+    die "fork: $!";
+}
+if (not $pid) {
+    # child - re-direct standerr and exec
+    open STDERR, '>&', STDOUT or die "redirect STDERR: $!";
+    exec 'readelf', '-WltdVs', @ARGV;
+}
+
+if (scalar @ARGV == 1) {
+    # Special case - readelf will not prefix the output with "File:
+    # $name" if it only gets one file argument, so act as if it did...
+    # - In fact, if readelf always emitted that File: header, we could
+    #   simply use xargs directly on readelf and just parse its output
+    #   in the loop below.
+    $bin = $ARGV[0];
+    print "-- $bin\n";
+
+    system ("head \Q$bin\E | grep -q 'packed.*with.*UPX'");
+    print "objdump: $bin: Packed with UPX" if $? == 0;
+}
+
+while ( my $line = <$readelf> ) {
+
+    chomp $line;
+
+    if ($line =~ m/^File: (.+)$/) {
+        my $file = $1;
+        finish_file();
+
+        $bin = $file;
+        print "-- $bin\n";
+
+        system ("head \Q$bin\E | grep -q 'packed.*with.*UPX'");
+        print "objdump: $bin: Packed with UPX" if $? == 0;
+    } elsif ($line =~ m/^readelf: Error: Unable to read in 0x[0-9a-fA-F]+ bytes of/) {
+        print "objdump: $bin: File truncated\n" unless $truncated++;
+        next;
+    } elsif ($line =~ m/^Program Headers:/) {
+        $section = 'PH';
+        print "$line\n";
+    } elsif ($line =~ m/^Section Headers:/) {
+        $section = 'SH';
+        print "$line\n";
+    } elsif ($line =~ m/^Dynamic section at offset .*:/) {
+        $section = 'DS';
+        print "$line\n";
+    } elsif ($line =~ m/^Version symbols section /) {
+        $section = 'VS';
+    } elsif ($line =~ m/^Symbol table '.dynsym'/) {
+        $section = 'DS';
+    } elsif ($line =~ m/^Symbol table/) {
+        $section = '';
+    } elsif ($line =~ m/^\s*$/) {
+        $section = '';
+    } elsif ($line =~ m/^\s*(\S+)\s*(?:(?:\S+\s+){4})\S+\s(...)/
+             and $section eq 'PH') {
+        my ($header, $flags) = ($1, $2);
+        $header =~ s/^GNU_//g;
+        next if $header eq 'Type';
+
+        my $newflags = '';
+        $newflags .= ($flags =~ m/R/) ? 'r' : '-';
+        $newflags .= ($flags =~ m/W/) ? 'w' : '-';
+        $newflags .= ($flags =~ m/E/) ? 'x' : '-';
+
+        $program_headers{$header} = $newflags;
+        print "  $header off 0x0 X 0x0 X 0x0\n  flags $newflags\n";
+    } elsif ($line =~ m/^\s*\[(\d+)\]\s*(\S+)(?:\s|\Z)/
+                 and $section eq 'SH') {
+        $sections[$1] = $2;
+        # We need sections as well (i.e. for incomplete stripping)
+        # - The 0 0 0 0 2**3 is just there to make it look like objdump output
+        #   (supposedly we don't even check for those extra fields in
+        #    L::Collect::Binary)
+        print " $1 $2   0 0 0 0 2**3\n";
+    } elsif ($line =~ m/^\s*0x(?:[0-9A-F]+)\s+\((.*?)\)\s+(\S.*)\Z/i
+                 and $section eq 'DS') {
+        my ($type, $value) = ($1, $2);
+
+        if ($type eq 'RPATH') {
+            $value =~ s/.*\[//;
+            $value =~ s/\]\s*$//;
+        }
+        $value =~ s/^(?:Shared library|Library soname): \[(.*)\]/$1/;
+        print "  $type   $value\n";
+    } elsif ($line =~ m/^\s*[0-9A-F]+: \s+ \S+ \s* (?:\(\S+\))? (?:\s|\Z)/xi
+                 and $section eq 'VS') {
+        while ($line =~ m/([0-9A-F]+h?)\s*(?:\((\S+)\))?(?:\s|\Z)/gci) {
+            my ($vernum, $verstring) = ($1, $2);
+            $verstring ||= '';
+            if ($vernum =~ m/h$/) {
+                $verstring = "($verstring)";
+            }
+            push @symbol_versions, $verstring;
+        }
+    } elsif ($line =~ m/^\s*(\d+):\s*[0-9a-f]+\s+\d+\s+(?:(?:\S+\s+){3})(\S+)\s+(.*)\Z/
+                 and $section eq 'DS') {
+        # We (somtimes) need to read the "Version symbols section" first to
+        # use this data and readelf tends to print after this section, so
+        # save for later.
+        push @dyn_symbols, [$1, $2, $3, ''];
+
+    } elsif ($line =~ m/^There is no dynamic section in this file/
+                 and exists $program_headers{DYNAMIC}) {
+        # The headers declare a dynamic section but it's
+        # empty. Generate the same error as objdump,
+        # the checks scripts special-case the string.
+        print "\n\nobjdump: $bin: Invalid operation\n";
+    }
+}
+
+# Finish the last file
+finish_file ();
+
+close $readelf;
+
+exit 0;
+
+sub finish_file {
+
+    if (@dyn_symbols) {
+        print "DYNAMIC SYMBOL TABLE:\n";
+        foreach my $dynsym (@dyn_symbols) {
+            my ($symnum, $seg, $sym, $ver) = @$dynsym;
+
+            if ($sym =~ m/^(.*)@(.*) \(.*\)$/) {
+                $sym = $1;
+                $ver = $2;
+            } elsif (@symbol_versions == 0) {
+                # No versioned symbols...
+                $ver = '';
+            } else {
+                $ver = $symbol_versions[$symnum];
+
+                if ($ver eq '*local*' or $ver eq '*global*') {
+                    if ($seg eq 'UND') {
+                        $ver = '   ';
+                    } else {
+                        $ver = 'Base';
+                    }
+                } elsif ($ver eq '()') {
+                    $ver = '(Base)';
+                }
+            }
+
+            if ($seg =~ m/^\d+$/ and defined $sections[$seg]) {
+                $seg = $sections[$seg];
+            }
+
+            print "00      XX $seg  000000  $ver  $sym\n";
+        }
+    }
+
+    # reset variables
+    @sections = ();
+    @symbol_versions = ();
+    @dyn_symbols = ();
+    $truncated = 0;
+    $section = '';
+    %program_headers = ();
+    $bin = '';
+}
diff --git a/debian/changelog b/debian/changelog
index 27b6c4e..d83e38c 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -22,6 +22,10 @@ lintian (2.5.10) UNRELEASED; urgency=low
       by file(1).
   * collection/objdump-info:
     + [NT] Only call readelf once per binary.
+    + [NT] Use xargs + a new helper to reduce the number of
+      readelf calls even further.
+  * collection/objdump-info-helper:
+    + [NT] New file.
 
   * debian/control:
     + [NT] Add (Build-)Dependency on libarchive-zip-perl.

-- 
Debian package checker


Reply to: