Wie finde ich den vollständigen Dateipfad bei einem Bibliotheksnamen wie libfoo.so.1?

Lesezeit: 5 Minuten

Benutzeravatar von Lekensteyn
Lekenstein

Ohne einen Linker zu implementieren oder zu verwenden ldd, wie finde ich den vollständigen Pfad zu einer Bibliothek? Gibt es dafür unter Linux eine Standardbibliothek? (POSIX vielleicht?)

Verwenden ldd und grep auf eine Datei, die wissentlich verwendet wird libGL.so.1es sieht aus wie:

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

Bei einem Bibliotheksnamen wie libGL.so.1wie finde ich den vollständigen Pfad /usr/lib/libGL.so.1?. Akzeptieren Sie vorzugsweise eine Option zum Auffinden von 32-Bit- und 64-Bit-Bibliotheken. Wenn das keine Bibliothek tut, gibt es ein Programm dafür? Etwas wie find-library-path libGL.so.1. Das locate libGL.so.1 Befehl zählt nicht.

Ich möchte die Bibliothek nicht tatsächlich mit laden dlopen oder etwas, wenn es Code aus dieser Bibliothek ausführt.

Verwenden ldconfig Dies ist das Tool, das den Linkspace verwaltet.

Das -p flag lässt Sie alle verfügbaren linkbaren Bibliotheken durchsuchen.

  • Danke für deine Antwort, aber -p druckt zwischengespeicherte Einträge aus einer Datei, nicht den aktuellen Status (Verzeichnisse in $LD_LIBRARY_PATH nicht respektiert werden)

    – Lekenstein

    31. Oktober 2012 um 14:21 Uhr


  • @Lekensteyn Wenn Sie die Bibliothek in finden möchten irgendein Ort und verlassen Sie sich nicht auf einen Mechaniker, der tatsächlich zum Verwalten von Bibliotheken verwendet wird, find oder der locate DB könnte Ihre einzige Option sein. Wie Ihre Fragen lauten, könnte es auch eine Option sein, sich die Quelle für den Loader anzusehen.

    – Honky-Tonk

    31. Oktober 2012 um 14:44 Uhr

Benutzeravatar von cLupus
cLupus

Erweitern Sie die Antwort von Honky Tonk, den Befehl echo "$(ldconfig -p | grep libGL.so.1 | tr ' ' '\n' | grep /)" wird dir den Weg allein geben.

Wenn es Ihnen nichts ausmacht, die Bibliothek tatsächlich zu laden und einige nicht standardmäßige, aber weit verbreitete Funktionen zu verwenden, rufen Sie an dladdr auf jedem Symbol aus der Bibliothek gibt Informationen zurück, die den vollständigen Pfadnamen enthalten, der geladen wurde.

  • Ich werde mir die Manpage ansehen, ich habe der Frage auch eine weitere Anforderung hinzugefügt: Die Bibliothek sollte keinen Code der Bibliothek ausführen, die überprüft wird. EDIT: So sieht es aus dladdr wird mir nicht helfen, wie es braucht dlopen Erste.

    – Lekenstein

    30. Oktober 2012 um 22:53 Uhr


  • Nun, Sie können (portabel) nicht vermeiden, globale Konstruktoren in der geladenen Bibliothek auszuführen. Es kann einige nicht-portable Hacks geben, um die Kontrolle zurückzuerlangen, bevor die Konstruktoren ausgeführt werden, indem Bibliotheksabhängigkeiten und die implementierungsspezifische Reihenfolge verwendet werden, in der Konstruktoren zum Aufrufen ausgeführt werden _exit (all dies von einem gegabelten untergeordneten Prozess aus) vorher vom Konstruktor einer anderen Bibliothek, aber ich denke, das geht in weit hergeholtes Hack-Territorium. Im Idealfall dlopen hätte ein RTLD_NOEXEC -Flag, um die Ausführung von Code in der Bibliothek zu verhindern, was für Aufgaben wie Ihre nützlich ist.

    – R.. GitHub HÖR AUF, EIS ZU HELFEN

    30. Oktober 2012 um 22:57 Uhr

  • Ja, das ist Wunschdenken. Es gibt ein RTLD_NOLOAD, aber das gibt nur NULL zurück, wenn die Bibliothek vorher nicht geladen wurde. Ich glaube nicht, dass es sogar eine Lösung gibt, die 32-Bit/64-Bit berücksichtigt (ohne ein 32-Bit- und 64-Bit-Programm zu erstellen, das dies überprüfen soll).

    – Lekenstein

    30. Oktober 2012 um 22:58 Uhr


  • Nun, es gibt noch einen hässlichen Hack – Sie könnten einen untergeordneten Prozess forken und ptrace es, und beenden Sie es auf der ersten mmap Systemaufruf getätigt. Die vorherige open Aufruf sollte Ihnen den Pfadnamen geben. 🙂 Übrigens, warum müssen Sie den Pfadnamen kennen? Ich vermute, dass es einen besseren Weg gibt, das zu erreichen, was Sie erreichen wollen.

    – R.. GitHub HÖR AUF, EIS ZU HELFEN

    30. Oktober 2012 um 23:03 Uhr

  • primus fängt GL-Aufrufe ab und trennt das Rendern vom Beschleunigen. Diese Bibliotheken müssen nicht einsitzen $LD_LIBRARY_PATHdaher kann ich nicht bestehen libGL.so.1 zum dlopen funktionieren in diesem Programm und deshalb muss ich den absoluten Pfad zu den Bibliotheken übergeben. In einem zweiten Programm möchte ich die Bibliotheken wie in der Frage angegeben nachschlagen, damit ich sie an die übergeben kann primus Programm.

    – Lekenstein

    30. Oktober 2012 um 23:18 Uhr

Für Systeme mit GNU libc und Python ist das Folgende das nächste, was ich gefunden habe. Es verwendet LD_DEBUG (beschrieben in die Manpage von 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"

Die Ausgabe (z libssl.so.1.0.0) ist das Folgende:

 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: 

Ich habe ein solches Skript implementiert hier:

#!/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()

1386770cookie-checkWie finde ich den vollständigen Dateipfad bei einem Bibliotheksnamen wie libfoo.so.1?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy