#!/usr/bin/perl # fakeldd # # Replacement for ldd with usage of objdump # # (c) 2003-2010 Piotr Roszatycki , LGPL use strict; my @Libs = (); my %Libs = (); my $Status = 0; my $Dynamic = 0; my $Format = ''; my $Ldsodir = "/lib"; my @Ld_Library_Path = qw(/usr/lib /lib /usr/lib32 /lib32 /usr/lib64 /lib64); sub ldso { my ($lib) = @_; return if $Libs{$lib}; my $path; if ($lib =~ /^\//) { $path = $lib; } else { foreach my $dir (@Ld_Library_Path) { next unless -f "$dir/$lib"; my $badformat = 0; local *PIPE; open PIPE, "objdump -p '$dir/$lib' 2>/dev/null |"; while (my $line = ) { if ($line =~ /file format (\S*)$/) { $badformat = 1 unless $1 eq $Format; last; } } close PIPE; next if $badformat; $path = "$dir/$lib"; last; } } push @Libs, $lib; if (-f $path) { $Libs{$lib} = $path; objdump($path); } } sub objdump { my (@files) = @_; foreach my $file (@files) { local *PIPE; open PIPE, "objdump -p '$file' 2>/dev/null |"; while (my $line = ) { $line =~ s/^\s+//; if ($line =~ /file format (\S*)$/) { if (not $Format) { $Format = $1; if ($^O eq 'linux') { if ($Format =~ /^elf64-/) { push @Libs, 'linux-vdso.so.1'; $Libs{'linux-vdso.so.1'} = ''; } else { push @Libs, 'linux-gate.so.1'; $Libs{'linux-gate.so.1'} = ''; } } foreach my $lib (split /:/, $ENV{LD_PRELOAD}||'') { ldso($lib); } } else { next unless $Format eq $1; } } if (not $Dynamic and $line =~ /^Dynamic Section:/) { $Dynamic = 1; } next unless $line =~ /^ \s* NEEDED \s+ (.*) \s* $/x; my $needed = $1; if ($needed =~ /^ld(-linux)?(\.|-)/) { $needed = "$Ldsodir/$needed"; } ldso($needed); } close PIPE; } } sub load_ldsoconf { my ($file) = @_; local *FH; open FH, $file; while (my $line = ) { chomp $line; $line =~ s/#.*//; next if $line =~ /^\s*$/; if ($line =~ /^include\s+(.*)\s*/) { my $include = $1; foreach my $incfile (glob $include) { load_ldsoconf($incfile); } next; } unshift @Ld_Library_Path, $line; } close FH; } MAIN: { my @args = @ARGV; if (not @args) { print STDERR "fakeldd: missing file arguments\n"; exit 1; } if (not `which objdump`) { print STDERR "fakeldd: objdump: command not found: install binutils package\n"; exit 1; } load_ldsoconf('/etc/ld.so.conf'); unshift @Ld_Library_Path, split(/:/, $ENV{LD_LIBRARY_PATH}||''); while ($args[0] =~ /^-/) { my $arg = $args[0]; shift @ARGV; last if $arg eq "--"; } foreach my $file (@args) { %Libs = (); $Dynamic = 0; if (@args > 1) { print "$file:\n"; } if (not -f $file) { print STDERR "ldd: $file: No such file or directory\n"; $Status = 1; next; } objdump($file); if ($Dynamic == 0) { print "\tnot a dynamic executable\n"; $Status = 1; } elsif (scalar %Libs eq "0") { print "\tstatically linked\n"; } my $address = '0x' . '0' x ($Format =~ /^elf64-/ ? 16 : 8); foreach my $lib (@Libs) { if ($lib =~ /^\//) { printf "\t%s (%s)\n", $lib, $address; } elsif (defined $Libs{$lib}) { printf "\t%s => %s (%s)\n", $lib, $Libs{$lib}, $address; } else { printf "\t%s => not found\n", $lib; } } } } END { $? = $Status; }