From ac7b357d6e8460e6d6c046c21b106f6f24420839 Mon Sep 17 00:00:00 2001 From: Oliver Tappe Date: Sat, 3 Feb 2007 15:55:43 +0000 Subject: * moved slxldd from config-db to (new) bin folder as it has nothing to do with the config-db git-svn-id: http://svn.openslx.org/svn/openslx/trunk@671 95ad53e4-c205-0410-b2fa-d234c58c8868 --- bin/slxldd | 273 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 273 insertions(+) create mode 100755 bin/slxldd (limited to 'bin') diff --git a/bin/slxldd b/bin/slxldd new file mode 100755 index 00000000..9117a1aa --- /dev/null +++ b/bin/slxldd @@ -0,0 +1,273 @@ +#! /usr/bin/perl +# +# slxldd - OpenSLX-rewrite of ldd that works on multiple architectures. +# +# (c) 2006 - OpenSLX.com +# +# Oliver Tappe +# +use strict; + +my $abstract = q[ +slxldd + This script reimplements ldd in a way that should work for all + binary formats supported by the binutils installed on the host system. + + An example: if you have a folder containing an ia64 system, you can + invoke this script on a ia32-host in order to determine all the libraries + required by a binary of the ia64 target system. +]; + +use File::Glob ':globally'; +use Getopt::Long; +use Pod::Usage; + +# add the lib-folder to perl's search path for modules: +use FindBin; +use lib "$FindBin::RealBin/../lib"; + +use OpenSLX::Basics; + +my ( + $helpReq, + $manReq, + $verbose, + + $rootPath, + $versionReq, + + @filesToDo, + + @libFolders, + @libs, + %libInfo, +); + +$rootPath = '/'; +GetOptions( + 'help|?' => \$helpReq, + 'man' => \$manReq, + 'root-path=s' => \$rootPath, + 'verbose' => \$verbose, + 'version' => \$versionReq, +) or pod2usage(2); +pod2usage(-msg => $abstract, -verbose => 0, -exitval => 1) if $helpReq; +pod2usage(-verbose => 2) if $manReq; +if ($versionReq) { + system('slxversion'); + exit 1; +} + +openslxInit(); + +if (!$rootPath) { + print _tr("You need to specify the root-path!\n"); + pod2usage(2); +} + +$rootPath =~ s[/+$][]; + # remove trailing slashes + +if (!@ARGV) { + print _tr("You need to specify at least one file!\n"); + pod2usage(2); +} + +fetchLoaderConfig(); + +foreach my $file (@ARGV) { + if ($file =~ m[^/]) { + # force absolute path relative to $rootPath: + $file = "$rootPath$file"; + } + if (!-e $file) { + die _tr("slxldd: unable to find file '%s'\n", $file); + } + push @filesToDo, $file; +} + +foreach my $file (@filesToDo) { + addLibsForBinary($file); +} + +sub fetchLoaderConfigFile +{ + my $ldConfFile = shift; + + open(LDCONF, "< $ldConfFile"); + while() { + chomp; + if (/^\s*include\s+(.+?)\s*$/i) { + foreach my $incFile (<$rootPath$1>) { + fetchLoaderConfigFile($incFile); + } + next; + } + if (/\S+/i) { + s[=.+][]; + # remove any lib-type specifications (e.g. '=libc5') + push @libFolders, "$rootPath$_"; + } + } + close LDCONF; +} + +sub fetchLoaderConfig +{ + if (!-e "$rootPath/etc/ld.so.conf") { + die _tr("$rootPath/etc/ld.so.conf not found, maybe wrong root-path?\n"); + } + fetchLoaderConfigFile("$rootPath/etc/ld.so.conf"); + + # add "trusted" folders /lib and /usr/lib if not already in place: + if (!grep { m[^$rootPath/lib$]} @libFolders) { + push @libFolders, "$rootPath/lib"; + } + if (!grep { m[^$rootPath/usr/lib$] } @libFolders) { + push @libFolders, "$rootPath/usr/lib"; + } +} + +sub addLib +{ + my $lib = shift; + my $bitwidth = shift; + my $rpath = shift; + + if (!exists $libInfo{$lib}) { + push @libs, $lib; + my $libPath; + my @folders = @libFolders; + if (defined $rpath) { + # add rpath if given (explicit paths set during link stage) + push @folders, split ':', $rpath; + } + foreach my $folder (@folders) { + if (-e "$folder/$lib") { + # have library matching name, now check if the platform is ok, too: + my $libFileInfo = `file --dereference $folder/$lib 2>/dev/null`; + if ($?) { + die _tr("unable to fetch file info for $folder/$lib, giving up!\n"); + } + my $libBitwidth = ($libFileInfo =~ m[64-bit]i) ? 64 : 32; + if ($bitwidth != $libBitwidth) { + vlog 0, _tr('%s has wrong bitwidth (%s instead of %s)', + "$folder/$lib", $libBitwidth, $bitwidth) if $verbose; + next; + } + $libPath = "$folder/$lib"; + last; + } + } + if (!defined $libPath) { + die _tr("*** unable to find lib %s! ***\n", $lib); + } + print "$libPath\n"; + $libInfo{$lib} = $libPath; + push @filesToDo, $libPath; + } +} + +sub addLibsForBinary +{ + my $binary = shift; + + # first do some checks: + print STDERR "analyzing '$binary'...\n" if $verbose; + my $fileInfo = `file --dereference --brief --mime $binary 2>/dev/null`; + chomp $fileInfo; + print STDERR "\tinfo is: '$fileInfo'...\n" if $verbose; + if ($?) { + die _tr("unable to fetch file info for $binary, giving up!\n"); + } + if ($fileInfo !~ m[^application/(x-executable|x-shared)]i) { + # ignore anything that's not an executable or a shared library + print STDERR "$binary: ignored, as it isn't an executable or a shared library\n"; + next; + } + + my $bitwidth = ($fileInfo =~ m[64-bit]i) ? 64 : 32; + # determine whether binary is 32- or 64-bit platform + + # now find out about needed libs, we first try objdump... + print STDERR "\ttrying objdump...\n" if $verbose; + my $res = `objdump -p $binary 2>/dev/null`; + if (!$?) { + # find out if rpath is set for binary: + my $rpath; + if ($res =~ m[^\s*RPATH\s*(\S+)]im) { + $rpath = $1; + print STDERR "\trpath='$rpath'\n" if $verbose; + } + while($res =~ m[^\s*NEEDED\s*(.+?)\s*$]gm) { + addLib($1, $bitwidth, $rpath); + } + } else { + # ...objdump failed, so we try readelf instead: + print STDERR "\ttrying readelf...\n" if $verbose; + $res = `readelf -d $binary 2>/dev/null`; + if ($?) { + die _tr("neither objdump nor readelf seems to be installed, giving up!\n"); + } + # find out if rpath is set for binary: + my $rpath; + if ($res =~ m/Library\s*rpath:\s*\[([^\]]+)/im) { + $rpath = $1; + print STDERR "\trpath='$rpath'\n" if $verbose; + } + while($res =~ m{\(NEEDED\)[^\[]+\[(.+?)\]\s*$}gm) { + addLib($1, $bitwidth, $rpath); + } + } +} + + +__END__ + +=head1 NAME + +slxldd - OpenSLX-script to determine the libraries required by any given +binary file. + +=head1 SYNOPSIS + +slxldd [options] file [...more files] + + Options: + --help brief help message + --man show full documentation + --root-path= path to the root folder for library search + --verbose show what's going on during execution + --version show version + +=head1 OPTIONS + +=over 8 + +=item B<--help> + +Prints a brief help message and exits. + +=item B<--man> + +Prints the manual page and exits. + +=item B<--root-path=> + +Sets the root folder that is used when searching for libraries. In order to +collect the loader-settings, etc/ld.so.conf is read relative to this path and +all libraries are sought relative to this path, too (a.k.a. a virtual chroot). + +Defaults to '/'. + +=item B<--verbose> + +Prints info about the files as they are being scanned. + +=item B<--version> + +Prints the version and exits. + +=back + +=cut \ No newline at end of file -- cgit v1.2.3-55-g7522