Lekensteyn
Lekensteyn

Reputation: 66415

How can I find the full file path given a library name like libfoo.so.1?

Without implementing a linker or using ldd, how can I find the full path to a library? Is there a standard library available for that on Linux? (POSIX maybe?)

Using ldd and grep on a file that is knowingly using libGL.so.1, it looks like:

$ ldd /usr/bin/glxinfo | grep libGL
libGL.so.1 => /usr/lib/libGL.so.1 (0x00007f34ff796000)

Given a library name like libGL.so.1, how can I find the full path /usr/lib/libGL.so.1?. Preferably accepting an option for finding 32-bit and 64-bit libraries. If no library does that, does a program exist to do this? Something like find-library-path libGL.so.1. The locate libGL.so.1 command does not count.

I don't want to actually load the library using dlopen or something if it executes code from that library.

Upvotes: 42

Views: 67823

Answers (5)

Albert
Albert

Reputation: 68160

I implemented such a script here:

#!/usr/bin/env python3

"""
Like `type` but for libs.
"""

import sys
import os
from argparse import ArgumentParser
from glob import glob


def parse_ld_conf_file(fn):
    paths = []
    for l in open(fn).read().splitlines():
        l = l.strip()
        if not l:
            continue
        if l.startswith("#"):
            continue
        if l.startswith("include "):
            for sub_fn in glob(l[len("include "):]):
                paths.extend(parse_ld_conf_file(sub_fn))
            continue
        paths.append(l)
    return paths


def get_ld_paths():
    # To be very correct, see man-page of ld.so.
    # And here: http://unix.stackexchange.com/questions/354295/what-is-the-default-value-of-ld-library-path/354296
    # Short version, not specific to an executable, in this order:
    # - LD_LIBRARY_PATH
    # - /etc/ld.so.cache (instead we will parse /etc/ld.so.conf)
    # - /lib, /usr/lib (or maybe /lib64, /usr/lib64)
    paths = []
    if "LD_LIBRARY_PATH" in os.environ:
        paths.extend(os.environ["LD_LIBRARY_PATH"].split(":"))
    paths.extend(parse_ld_conf_file("/etc/ld.so.conf"))
    paths.extend(["/lib", "/usr/lib", "/lib64", "/usr/lib64"])
    return paths


def main():
    arg_parser = ArgumentParser()
    arg_parser.add_argument("lib")
    args = arg_parser.parse_args()

    paths = get_ld_paths()
    for p in paths:
        fn = "%s/%s" % (p, args.lib)
        if os.path.exists(fn):
            print(fn)
            return

    print("Did not found %r in %r." % (args.lib, paths), file=sys.stderr)
    sys.exit(1)


if __name__ == "__main__":
    main()

Upvotes: 1

saaj
saaj

Reputation: 25224

For systems with GNU libc and Python the following is the closest I found. It uses LD_DEBUG (described in the man page of ld.so(8)).

LD_DEBUG=libs python3 -c "import ctypes; ctypes.CDLL('libssl.so.1.0.0')" 2>&1 | \
    grep -A 1000 "initialize program: python" | grep -A 3 "find library"

The output (for libssl.so.1.0.0) is the following:

 15370: find library=libssl.so.1.0.0 [0]; searching
 15370:  search cache=/etc/ld.so.cache
 15370:   trying file=/lib/x86_64-linux-gnu/libssl.so.1.0.0
 15370: 
 15370: find library=libcrypto.so.1.0.0 [0]; searching
 15370:  search cache=/etc/ld.so.cache
 15370:   trying file=/lib/x86_64-linux-gnu/libcrypto.so.1.0.0
 15370: 

Upvotes: 1

cLupus
cLupus

Reputation: 563

Expanding on Honky Tonk's answer, the command echo "$(ldconfig -p | grep libGL.so.1 | tr ' ' '\n' | grep /)" will give you the path alone.

Upvotes: 21

HonkyTonk
HonkyTonk

Reputation: 2019

Use ldconfig which is the tool that manages link space.

The -p flag lets you browse all available linkable libraries.

Upvotes: 27

R.. GitHub STOP HELPING ICE
R.. GitHub STOP HELPING ICE

Reputation: 215257

If you don't mind actually loading the library and using some nonstandard but widely-available functions, calling dladdr on any symbol from the library will return information containing the full pathname that was loaded.

Upvotes: 2

Related Questions