Subject: Re: Purging old library versions
To: Simon Burge <simonb@telstra.com.au>
From: Dave Sainty <dave@dtsp.co.nz>
List: current-users
Date: 08/24/1998 00:47:17
Simon Burge writes:

> 
> On Sat, 22 Aug 1998 17:23:31 -0700 (PDT)  Paul Goyette wrote:
> 
> > Having followed -current for a long time now, I notice that I've got a
> > few old versions of shared object libraries in /usr/lib.  Is there some
> > relatively easy way to find out which executables I might still have
> > lying around linked to these older versions of libedit, libkvm (likely
> > not very many here), and libstdc++?  I know I could just find all the
> > executables and try to run them, but there must be an easier way to
> > check which libraries they're linked against?
> 
> I got this ages ago (1994!) and haven't used it in quite a while, so I
> don't even know if it works on -current (or anything recent).  A quick
> glance doesn't show any obvious problems.  Have a look and let us know
> how you go.

I always meant to write one of these, but never got around to it. :)

Here it is again with some fixes for NetBSD-current, and an extra
feature to list all files on the system that require missing shared
libraries.  And a few panics in case the output of these utilities
changes again. :)

------------------------------

#!/usr/bin/perl
# hey emacs, this is a -*-perl-*- script!

# A little script to build a reference listing for dynamic libraries.
# This should help you to get rid of unused ones and find the binaries
# you need to update before removing old lib revisions.

# Martin Husemann, martin@euterpe.owl.de, 25-Apr-1994
#
# D.Sainty@dtsp.co.nz - Updated for NetBSD-current as at: 24/8/1998

# Synopsis:
#   libref [-a]
#
# Description:
#   Lists usage count for all known shared libraries
#
# Options:
#   -a	 gives a complete reference table

undef $ENV{"LD_LIBRARY_PATH"};

$doRef = $ARGV[0] eq "-a";	# yes, it may use getopt...

# First ask ldconfig for a list of all shared libs and initialize the
# reference and statistics table
open(LIBS, "ldconfig -r |") || die("could not run ldconfig: $!\n");
while (<LIBS>) {
    chop;
    next if /^(\S*ld.so.hints:|\s*search directories:.*)$/;
    m/^.*=> (\S+)(|\s.*)$/ || die("parsing $_");
    $reference{$1} = "";
    $count{$1} = 0;
}
close(LIBS);

# now lookup every dynamically linked executable on the whole disk
open(FILES, "find / -type f -print |") || die("could not run find: $!\n");
while (defined($file = <FILES>)) {
    chop $file;
    if ( -x $file ) {
	$whatis=`file $file`;
	if ($whatis =~ /dynamically linked/) {
	    open(LIBS, "ldd $file |") || die("could not run ldd: $!\n");
	    @libs = <LIBS>;
	    close(LIBS);
	    shift(@libs);
	    foreach (@libs) {
		chop;
		m/^.*=> (\S.+\S)\s+\(0x[0-9a-f]+\)\s*$/ || die("parsing $_ in file $file");

		if ($1 eq "not found") {
		    push(@unresolvables, $file);
		    last;
		}
		
		die("lib? $_ in file $file") if !defined $count{$1};
		
		$count{$1}++;
		$reference{$1} .= " $file" if ($doRef);
	    }
	}
    }
}
close(FILES);

# sort statistics
sub ByUsage {
    $count{$a} <=> $count{$b};
}
@sorted = sort ByUsage keys(%count);

# and finaly report statistics...
print "Shared library usage counts\n\n" if ($doRef);
foreach (@sorted) {
    printf "%8d	 %s\n", $count{$_}, $_;
}

# and the cross reference
if ($doRef) {
    print "\n\nShared library cross reference\n\n";
    foreach $lib (sort(keys(%reference))) {
	print "$lib:$reference{$lib}\n";
    }
}

print "\n\nFiles with unresolved libraries:\n\n";
foreach $file (@unresolvables) {
    print "$file\n";
}

exit 0;