2 # objdump-info -- maemian collection script
4 # The original shell script version of this script is
5 # Copyright (C) 1998 Christian Schwarz
7 # This version, including support for etch's binutils, is
8 # Copyright (C) 2008 Adam D. Barratt
10 # This program is free software; you can redistribute it and/or modify
11 # it under the terms of the GNU General Public License as published by
12 # the Free Software Foundation; either version 2 of the License, or
13 # (at your option) any later version.
15 # This program is distributed in the hope that it will be useful,
16 # but WITHOUT ANY WARRANTY; without even the implied warranty of
17 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 # GNU General Public License for more details.
20 # You should have received a copy of the GNU General Public License
21 # along with this program. If not, you can find it on the World Wide
22 # Web at http://www.gnu.org/copyleft/gpl.html, or write to the Free
23 # Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
29 unless (-f "fields/package") {
30 print STDERR "error: collection script called in wrong directory!\n";
36 open (FILES, '<', "file-info")
37 or fail("cannot open file-info: $!");
39 open (OUT, '>', "objdump-info")
40 or fail("cannot open objdump-info: $!");
42 open(PIPE, '-|', "dpkg-query -W -f='\${Version}\n' binutils")
43 or fail("unable to run dpkg-query: $!");
44 my $binutils_version = <PIPE>;
45 chomp $binutils_version;
49 or fail ("unable to chdir to unpacked: $!\n");
52 if (m/^(.+?):\s.*ELF/) {
55 print OUT "-- $bin\n";
57 system("head $bin | grep -q 'packed.*with.*UPX'");
58 print OUT "objdump: $bin: Packed with UPX" if $? == 0;
60 if (open(PIPE, '-|', "readelf -l $bin 2>&1")) {
67 system("objdump -T $bin >/dev/null 2>&1");
69 # Seems happy so slurp the full output
70 if (open(PIPE, '-|', "objdump --headers --private-headers -T $bin 2>&1")) {
80 if (open(PIPE, '-|', "objdump --headers --private-headers -T $bin 2>&1")) {
83 if (m/Invalid operation$/) {
86 } elsif (m/File format not recognized$/) {
88 } elsif (m/File truncated$/) {
97 if ($invalidop or $binutils_version !~ m/^2\.17/) {
98 # If we're using a binutils newer than etch's then either
99 # "invalid operation" or "file format not recognized"
100 # are simply passed through to the checks scripts
101 # which handle the output themselves
103 # If objdump returned "invalid operation" and we are
104 # using etch's binutils then the readelf code will tend
105 # to produce false positives so we just return the
106 # objdump output and let the scripts handle it
108 print OUT $objdumpout;
109 } elsif (system("readelf -l $bin 2>&1 | grep -q 'Error: Not an ELF file'") == 0) {
110 print OUT "objdump: $bin: File format not recognized\n";
112 # We're using etch's binutils so attempt to build an output
113 # file in the expected format without using objdump; we lose
114 # some data but none that our later checks actually use
119 if (open(PIPE, '-|', "readelf -W -l -t -d -V $bin")) {
125 if (m/^Program Headers:/) {
128 } elsif (m/^Section Headers:/) {
131 } elsif (m/^Dynamic section at offset .*:/) {
134 } elsif (m/^Version symbols section /) {
138 } elsif (m/^\s*(\S+)\s*(?:(?:\S+\s+){4})\S+\s(...)/
139 and $section eq 'PH') {
140 my ($header, $flags) = ($1, $2);
141 $header =~ s/^GNU_//g;
142 next if $header eq 'Type';
145 $newflags .= ($flags =~ m/R/) ? 'r' : '-';
146 $newflags .= ($flags =~ m/W/) ? 'w' : '-';
147 $newflags .= ($flags =~ m/E/) ? 'x' : '-';
149 $program_headers{$header} = $newflags;
151 print OUT " $header off 0x0 X 0x0 X 0x0\n flags $newflags\n";
152 } elsif (m/^\s*\[(\d+)\]\s*(\S+)(?:\s|\Z)/
153 and $section eq 'SH') {
155 } elsif (m/^\s*0x(?:[0-9A-F]+)\s+\((.*?)\)\s+(\S.*)\Z/i
156 and $section eq 'DS') {
157 my ($type, $value) = ($1, $2);
159 $value =~ s/^(?:Shared library|Library soname): \[(.*)\]/$1/;
160 print OUT " $type $value\n";
161 } elsif (m/^\s*[0-9A-F]+:\s+(\S+)\s*(?:\((\S+)\))?(\s|\Z)/i
162 and $section eq 'VS') {
163 while (m/([0-9A-F]+h?)\s*(?:\((\S+)\))?(\s|\Z)/gci) {
164 my ($vernum, $verstring) = ($1, $2);
166 if ($vernum =~ m/h$/) {
167 $verstring = "($verstring)";
169 push @symbol_versions, $verstring;
171 } elsif (m/^There is no dynamic section in this file/
172 and exists $program_headers{DYNAMIC}) {
173 # The headers declare a dynamic section but it's
174 # empty. Generate the same error as objdump,
175 # the checks scripts special-case the string.
176 print OUT "\n\nobjdump: $bin: Invalid operation\n";
182 if (open(PIPE, '-|', "readelf -W -s -D $bin")) {
183 print OUT "DYNAMIC SYMBOL TABLE:\n";
186 last if m/^Symbol table of/;
188 if (m/^\s*(\d+)\s+\d+:\s*[0-9a-f]+\s+\d+\s+(?:(?:\S+\s+){3})(\S+)\s+(.*)\Z/) {
189 my ($symnum, $seg, $sym, $ver) = ($1, $2, $3, '');
191 if ($sym =~ m/^(.*)@(.*)$/) {
194 } elsif (@symbol_versions == 0) {
195 # No versioned symbols...
198 $ver = $symbol_versions[$symnum];
200 if ($ver eq '*local*' or $ver eq '*global*') {
206 } elsif ($ver eq '()') {
211 if ($seg =~ m/^\d+$/ and defined $sections[$seg]) {
212 $seg = $sections[$seg];
215 print OUT "00 XX $seg 000000 $ver $sym\n";
233 print STDERR "internal error: $_[0]\n";
235 print STDERR "internal error: $!\n";
237 print STDERR "internal error.\n";