NetBSD-Users archive

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

Re: libstdc++.so.7 is missing



On Sun 20 Jan 2019 at 08:58:55 -0500, Greg Troxel wrote:
> From that find the root cause, which is something that directly includes
> it, vs including a library that includes it.  ldd makes this not that
> easy.

FreeBSD's ldd has an option to show just the libraries that are required
directly (and recurses, so it shows it more nicely separated). I made a
perl script that does more or less the same, but it also prints the
reverse relationships, the search path of each library, and any
conflicts between different versions of the same library.

#!/usr/pkg/bin/perl
#
# A ldd-replacement which clearly indicates which libraries are needed 
# by which object.
#

my %map;
my %needed_by;
my @todo;

sub do_one_file {
    my $file = shift;
    my @needed;
    my @path;

    open OBJDUMP, "objdump -x $file |";

    while (<OBJDUMP>) {
	chomp;
	if (/NEEDED/) {
	    s/\s*NEEDED\s*//;
	    push @needed, $_;
	}

	if (/RPATH/) {
	    s/\s*RPATH\s*//;
	    @path = split /:/;
	    print "path = @path\n";
	    break;
	}
    }
    close OBJDUMP;

    push @path, "/usr/lib";
    push @path, "/lib";

    print "$file needs:\n";

    for my $lib (@needed) {
	# Find $lib in @path
	my $found = 0;
	PATH:
	for my $dir (@path) {
	    my $candidate = $dir."/".$lib;

	    if (-e $candidate) {
		print "\t$lib => $candidate\n";
		$found = 1;
		if (exists $map{$lib}) {
		    # $candidate was already processed before
		} else {
		    push @todo, $candidate;
		    $map{$lib} = $candidate;
		}
		if (!exists $needed_by{$candidate}) {
		    $needed_by{$candidate} = undef;
		    # then the next push will use autovivivication
		}
		push @{$needed_by{$candidate}}, $file;
		last PATH;
	    }
	}
	if (!$found) {
	    print "\t$lib not found\n";
	}
    }

    if (@needed == 0) {
	print "\t(nothing)\n";
    }

    print "\n";
}

push @todo, @ARGV;

while (@todo) {
    do_one_file(pop @todo);
}

# Dump reverse requirements:

my %fullib;

for my $lib (sort keys %needed_by) {
    print "$lib <=\n";
    for my $by (@{$needed_by{$lib}}) {
	print "\t$by\n";
    }
    print "\n";

    # Create a mapping of short lib name to full file name
    # to detect potential conflicts
    my $short = $lib;
    $short =~ s=.*/==;
    $short =~ s=\.so[.0-9]*==;
    if (!exists $fullib{$short}) {
	$fullib{$short} = undef;
	# then the next push will use autovivivication
    }
    push @{$fullib{$short}}, $lib;
}

# Dump conflicts

print "Conflicting libraries:\n";

for my $lib (sort keys %fullib) {
    my @longnames = @{$fullib{$lib}};
    if (@longnames > 1) {
	print "$lib ==\n";
	for my $longname (@longnames) {
	    print "\t", $longname, "\n";
	    for my $by (@{$needed_by{$longname}}) {
		print "\t\t$by\n";
	    }
	    print "\n";
	}
    }
}

Attachment: signature.asc
Description: PGP signature



Home | Main Index | Thread Index | Old Index