diff options
Diffstat (limited to 'strip_and_check_elf_files')
-rwxr-xr-x | strip_and_check_elf_files | 91 |
1 files changed, 91 insertions, 0 deletions
diff --git a/strip_and_check_elf_files b/strip_and_check_elf_files new file mode 100755 index 0000000..7b9d28a --- /dev/null +++ b/strip_and_check_elf_files @@ -0,0 +1,91 @@ +#!/usr/bin/perl +# $Id$ +# Strip files + +use strict; +use warnings; +use File::Find; + +my $buildroot = $ENV{RPM_BUILD_ROOT}; +die "No build root defined" unless $buildroot; +die "Invalid build root" unless -d $buildroot; +# normalize build root +$buildroot =~ s|/$||; + +my (@shared_libs, @executables, @static_libs); +find(\&keep_wanted, $buildroot); + +strip_files() if !$ENV{DONT_STRIP}; +check_missing_or_unused_libs(); + +sub strip_files { + my $exclude_pattern = join('|', + map { '(:?' . quotemeta($_) . ')' } + $ENV{EXCLUDE_FROM_STRIP} ? split(' ', $ENV{EXCLUDE_FROM_STRIP}) : (), + '/usr/lib/debug' + ); + my @to_strip = grep { !/$exclude_pattern/ } @shared_libs, @executables; + + system( + "strip", + "--remove-section=.comment", + "--remove-section=.note", + $_) foreach @to_strip; +} + +sub check_missing_or_unused_libs { + foreach my $f (@shared_libs, @executables) { + my (undef, undef, @l) = `ldd -u -r $f 2>/dev/null`; + @l or next; + my $f_ = substr($f, length($buildroot)); + print STDERR "Warning: unused libraries in $f_: ", join(' ', map { basename($_) } @l), "\n"; + } + foreach my $f (@shared_libs) { + my @l = `ldd -r $f 2>&1 >/dev/null` or next; + my $f_ = substr($f, length($buildroot)); + print STDERR "Warning: undefined symbols in $f_: ", join(' ', map { /undefined symbol: (\S+)/ ? $1 : () } @l), "\n"; + } +} + +# TODO: we should write a binding for libfile... +sub expensive_test { + my ($file) = @_; + my $type = `file -- $file`; +} + +# Check if a file is an elf binary, shared library, or static library, +# for use by File::Find. It'll fill the following 3 arrays with anything +# it finds: +sub keep_wanted() { + # skip symlinks + return if -l $_; + # skip directories + return if -d $_; + + # Does its filename look like a shared library? + if (m/\.so/) { + # Ok, do the expensive test. + if (expensive_test($_) =~ m/ELF.*shared/) { + push @shared_libs, $File::Find::name; + return; + } + } + + # Is it executable? -x isn't good enough, so we need to use stat. + my (undef, undef, $mode, undef) = stat(_); + if ($mode & 0111) { + # Ok, expensive test. + if (expensive_test($_) =~ m/ELF.*executable/) { + push @executables, $File::Find::name; + return; + } + } + + # Is it a static library, and not a debug library? + if (m/lib.*\.a/ && ! m/_g\.a/) { + push @static_libs, $File::Find::name; + return; + } +} + +sub basename { local $_ = shift; s|/*\s*$||; s|.*/||; $_ } |