5

I know that if I do the command ldd <name> on a binary file in /bin or /sbin I can see which libraries it uses. How do I do the reverse? I.e. do a command on a file in /lib and see what binaries are using it?

Ted Desmond
  • 111
  • 1
  • 7

4 Answers4

4

This isn't quite what you're asking for, but it will allow you to find the list of binaries using a given library. binstats generates a report on the binaries and libraries in your system, primarily to find out which binaries are missing libraries, and which libraries are no longer used at all.

In debug mode, it leaves its temporary files behind, and one of them lists all the binaries on the path (or in the folders you specify, using the -b option), with all the libraries they use. Once you have this file, you can search for the library you're interested in to determine what uses it...

So basically:

binstats -d
awk '/^\// { binary=$1 }; /libtinfo.so.5/ { print binary }' etempb.00

will list all the binaries using libtinfo.so.5. (The filename may not be etempb.00, but hopefully you get the idea...)

This will miss binaries stored in directories not on the path, e.g. in /usr/libexec, or in /sbin and /usr/sbin if you're not running as root, but you can add the relevant folders to the -b option.

Stephen Kitt
  • 411,918
  • 54
  • 1,065
  • 1,164
3

OP did not clarify; however if you want to know which currently running processes are using given libraries, lsof is useful, because (using the file-descriptors from the shared libraries), it is able to list all shared libraries currently in use along with the names of the programs which loaded them.

For instance, here is a listing (removing the first few columns) for the files in use for the text editor I am using:

cwd       DIR                8,1      4096  783366 /tmp
rtd       DIR                8,1      4096       2 /
txt       REG                8,1   1007808  659475 /usr/bin/vile
mem       REG                8,1     22664 1189463 /usr/lib/vile/vile-txt-filt.so
mem       REG                8,1     14472 1072690 /usr/lib/perl/5.14.2/auto/Tie/Hash/NamedCapture/NamedCapture.so
mem       REG                8,1     26984  717426 /usr/lib/perl/5.14.2/auto/List/Util/Util.so
mem       REG                8,1     18704  717420 /usr/lib/perl/5.14.2/auto/IO/IO.so
mem       REG                8,1     18672  717423 /usr/lib/perl/5.14.2/auto/Fcntl/Fcntl.so
mem       REG                8,1     14472  717444 /usr/lib/perl/5.14.2/auto/Cwd/Cwd.so
mem       REG                8,1     47616  914637 /lib/x86_64-linux-gnu/libnss_files-2.13.so
mem       REG                8,1     43560  914639 /lib/x86_64-linux-gnu/libnss_nis-2.13.so
mem       REG                8,1     89056  914574 /lib/x86_64-linux-gnu/libnsl-2.13.so
mem       REG                8,1     31584  914635 /lib/x86_64-linux-gnu/libnss_compat-2.13.so
mem       REG                8,1     10272  714121 /usr/lib/x86_64-linux-gnu/gconv/ISO8859-1.so
mem       REG                8,1 110939968  692851 /usr/lib/locale/locale-archive
mem       REG                8,1    530736  914572 /lib/x86_64-linux-gnu/libm-2.13.so
mem       REG                8,1     35104  914569 /lib/x86_64-linux-gnu/libcrypt-2.13.so
mem       REG                8,1    131107  913941 /lib/x86_64-linux-gnu/libpthread-2.13.so
mem       REG                8,1     14768  914571 /lib/x86_64-linux-gnu/libdl-2.13.so
mem       REG                8,1   1607696  914566 /lib/x86_64-linux-gnu/libc-2.13.so
mem       REG                8,1   1574680  717850 /usr/lib/libperl.so.5.14.2
mem       REG                8,1    167952  913960 /lib/x86_64-linux-gnu/libtinfo.so.5.9
mem       REG                8,1    136936  913944 /lib/x86_64-linux-gnu/ld-2.13.so
mem       REG                8,1     26066  714417 /usr/lib/x86_64-linux-gnu/gconv/gconv-modules.cache
  0u      CHR              136,2       0t0       5 /dev/pts/2
  1u      CHR              136,2       0t0       5 /dev/pts/2
  2u      CHR              136,2       0t0       5 /dev/pts/2
  3r      REG                8,1      6317 1197635 /usr/share/vile/perl/capture.pm
  4r      REG                8,1      1875 1197632 /usr/share/vile/perl/Vile/Manual.pm
  5r      REG                8,1      1349 1197630 /usr/share/vile/perl/plugins.pl
  6r      REG                8,1      4916 1197634 /usr/share/vile/perl/hgrep.pm
  7r      REG                8,1       652 1197643 /usr/share/vile/perl/Visit.pm
  8r      REG                8,1      1680 1197625 /usr/share/vile/perl/Glob2re.pm
  9r      REG                8,1      3986 1197638 /usr/share/vile/perl/dirlist.pm
 10r     FIFO                0,8       0t0   25311 pipe

ldd, by the way, is not universally available; lsof is used on most Unix-like platforms.

Here is an example script, which generates a report for all libraries in the currently running system (if arguments are given, it matches those against the library names):

#!/usr/bin/perl -w
# $Id: lsof-libs,v 1.2 2016/05/28 13:59:33 tom Exp $
#
# Process the output from "lsof", obtaining a list of binaries by library path.

use strict;

open( FP, "lsof|" ) || do {
    print STDERR "Can't open lsof: $!\n";
    return;
};
my (@input) = <FP>;
close(FP);

my $program = "";
my $library = "";
my %libs;
for my $n ( 0 .. $#input ) {
    my @fields = split /\s+/, $input[$n];
    next if ( $#fields < 8 );
    next unless ( $fields[8] =~ /^\// );
    my $pathname = $fields[8];
    if ( $fields[3] eq "txt" ) {
        $program = $pathname;
    }
    elsif ( $fields[3] eq "mem" ) {
        next unless ( $pathname =~ /\/lib[^\/]/ );
        $library = $pathname;
        my $found = ( $#ARGV < 0 );
        if ( $#ARGV >= 0 ) {
            for my $a ( 0 .. $#ARGV ) {
                if ( $ARGV[$a] eq $library ) {
                    $found = 1;
                    last;
                }
            }
        }
        if ($found) {
            my %obj;
            %obj = %{ $libs{$library} } if ( $libs{$library} );
            $obj{$program}  = 1;
            $libs{$library} = \%obj;
        }
    }
}
for my $lib ( sort keys %libs ) {
    printf "%s\n", $lib;
    my %obj = %{ $libs{$lib} };
    for my $prog ( sort keys %obj ) {
        printf "\t%s\n", $prog;
    }
}
1;

Further reading:

Thomas Dickey
  • 75,040
  • 9
  • 171
  • 268
2

As long as you stick to binaries provided by your distribution, it keeps track of this through package dependencies.

  1. Determine the package containing that library file.
  2. List the packages that depend on this library package.
  3. List executables in those packages.

Of course this won't tell you about programs that are not installed through your distribution's packaging mechanism. This will also list extra executables when a package contains more than one executable. On the flip side, for many purposes, the package is the information you need, rather than the executable.

How to perform each of these steps depends on the package manager used by your distribution. The pacman rosetta has a table of package management commands on popular distributions. For example, on Debian, Ubuntu, Linux Mint, elementary OS, and other dpkg/apt-based distributions:

dpkg -S /path/to/library.so   # which package contains this library?
aptitude search "~i ~Dlibrary-package" # which installed packages depend on this library?
dpkg -L $(aptitude search -F %p "~i ~D$(dpkg -S /path/to/library.so | sed 's/:.*//')") | grep /bin
Gilles 'SO- stop being evil'
  • 807,993
  • 194
  • 1,674
  • 2,175
1

When in doubt, use brute force:

#!/bin/bash
# $1 -- target library
IFS=:
find $PATH -maxdepth 1 -executable -type f -o -type l 2>/dev/null | 
while read b; do
  ldd "$b" 2>/dev/null | grep -q -F "$1" &&  echo "$b"
done

It takes about a minute to go through all my PATH executables (~ 4K ) on my system.

Petr Skocik
  • 28,176
  • 14
  • 81
  • 141