- libtree ist ein Tool, das die Ausgabe von
lddin einen Baum umwandelt und erklärt, wie eine Shared Library gefunden wurde oder warum sie nicht gefunden werden kann - In der Standardausgabe werden einige Standardabhängigkeiten ausgeblendet; mit
-v,-vv,-vvvlassen sich schrittweise die ausgeblendeten Bibliotheken sowie die Abhängigkeiten bereits zuvor gesehener Bibliotheken anzeigen --pathoder-pzeigt Pfade statt soname an, und mit--max-depthkann die Tiefe der rekursiven Suche begrenzt werden- Die Installation ist über v3.1.1 Prebuilt-Binaries, Fedora/RHEL/CentOS, Ubuntu 22.04+ und GNU Guix möglich
- Für den Build aus dem Quellcode wird ein C-Compiler benötigt, der C99 versteht; bei Verwendung von
makewirdLDFLAGS=-staticempfohlen
Was libtree macht
- libtree ist ein Tool, das
lddin Baumform darstellt - Es erklärt, wie Shared Libraries gefunden werden oder warum ihr Speicherort nicht ermittelt werden kann
- Im README ist ein Screenshot unter
doc/screenshot.pngenthalten
Ausgabeoptionen
- In der Standardausgabe werden einige Standardabhängigkeiten nicht angezeigt
- Detailliertere Ausgabe wird über Verbosity-Optionen gesteuert
libtree -v: zeigt Bibliotheken an, die standardmäßig übersprungen werdenlibtree -vv: zeigt auch die Abhängigkeiten der standardmäßig übersprungenen Bibliotheken anlibtree -vvv: zeigt auch die Abhängigkeiten bereits zuvor gesehener Bibliotheken an
- Das Flag
--pathoder-pzeigt Pfade statt soname an- Beispiel:
libtree -p $(which tar)
- Beispiel:
--max-depthbegrenzt die Rekursionstiefe
Installation
- Prebuilt binaries for v3.1.1: stellt vorgefertigte Binärdateien für Linux bereit
- Unter Fedora / RHEL / CentOS erfolgt die Installation mit
dnf- Bei RHEL und abgeleiteten Distributionen muss zuerst
epel-releaseaktiviert werden dnf install libtree-ldd
- Bei RHEL und abgeleiteten Distributionen muss zuerst
- Unter Ubuntu 22.04+ erfolgt die Installation mit
apt-get install libtree - Unter GNU Guix erfolgt die Installation mit
guix install libtree - Older release v2.0.0 ist ebenfalls verfügbar
Aus dem Quellcode bauen
libtreebenötigt einen C-Compiler, der C99 versteht- Das Standard-Build-Verfahren besteht darin, das Repository zu klonen und dann
makeauszuführengit clone https://github.com/haampie/libtree.gitcd libtreemake
- Bei Verwendung von
makewirdLDFLAGS=-staticempfohlen - Im README gibt es außerdem in einem separaten eingeklappten Abschnitt einen Befehl für eine unsafe quick install, der
libtree.cpercurlherunterlädt und kompiliert
2 Kommentare
Hacker-News-Kommentare
Übernimmt dieses Tool auch das unerwartete Verhalten von
ldd, bei dem einige der zu untersuchenden Libraries tatsächlich ausgeführt werden?https://catonmat.net/ldd-arbitrary-code-execution
lddführen das Ziel-Binary nicht aus.Siehe: https://manpages.debian.org/unstable/manpages/ldd.1.en.html#...
Tatsächlich scheint es ELF-Dateien direkt zu parsen und auch Abhängigkeiten rekursiv zu parsen, was ziemlich cool ist.
objdumpverwendet, gibt es die Daten so aus, wie sie in der ELF-Datei codiert sind.Dazu gehört sogar die Liste der Libraries, nach denen vdso suchen soll.
Es gibt ein ähnliches Tool namens lddtree.
https://github.com/gentoo/pax-utils/tree/master
Fehlende Abhängigkeiten mit
lddrekursiv immer wieder nachzuverfolgen ist ziemlich mühsam.Das hier wirkt daher wie eine gute Verbesserung, und beim nächsten unklaren
not foundwerde ich es ausprobieren.Im Grunde wie eine Linux-CLI-Version von depends.exe.
Besser ist stattdessen https://github.com/lucasg/Dependencies. Auch das ist nicht völlig auf dem neuesten Stand, aber …
Wenn Visual Studio installiert ist und im Installer
x64/x86 build tools (latest)ausgewählt wurde, istdumpbin /dependentsin der VS Developer Command Prompt weiterhin die verlässlichste Option.[1] https://www.dependencywalker.com/
Falls sich jemand fragt, was die Farben bedeuten: In manpage/README habe ich es nicht gefunden.
Magenta: steht auf der Ausschlussliste, wird nur bei
-v[v[v]]angezeigt.Blau: wurde zuvor bereits gesehen, sodass man mehrfach auftauchende Abhängigkeiten finden kann.
Was heißt „warum eine Library gefunden wird oder nicht“? Ist sie nicht entweder in
LD_LIBRARY_PATHoder eben nicht?Nur anhand des Screenshots verstehe ich nicht ganz, worauf sich das bezieht.
Es gibt mehrere unterschiedliche Arten, Verzeichnisse zu durchsuchen: System-Suchpfade, runpath, rpath,
LD_LIBRARY_PATHusw.Libraries werden normalerweise mit einem kurzen Namen wie
foo.sogelinkt, können aber auch über den vollständigen Pfad der Library dynamisch gelinkt werden.Außerdem sollte man
LD_LIBRARY_PATHim Allgemeinen vermeiden, wenn es geht. Das ist nicht immer möglich, aber wenn es gesetzt ist, steht es bei jeder Ausführung ganz oben in der Suchpriorität. Selbst wenn etwas dynamisch mit dem vollständigen Pfad einer Library gelinkt ist, hatLD_LIBRARY_PATHVorrang und macht die Suchlogik vollständig flach.LD_LIBRARY_PATHliegen, um gefunden zu werden.Der Punkt des Titels ist, dass libtree es einfach macht, die Pfade von einer ausführbaren Datei zu allen direkten und indirekten Abhängigkeiten zu finden. Eine der Anwendungen davon ist, Probleme mit fehlenden Abhängigkeiten besser zu verstehen.
Wenn man tatsächlich ein Paketsystem verwendet, fehlen Abhängigkeiten vermutlich eher selten; libtree wird man also wahrscheinlich aus anderen Gründen nutzen.
LD_LIBRARY_PATHliegt oder nicht; es gibt auch RPATH, das für jede Library beim Laden ausgewertet wird.Der größere Punkt ist, dass Abhängigkeiten einen Graphen bilden, der sich wie ein Baum darstellen lässt. Es ist nützlich zu wissen, wegen welcher Library, die eine bestimmte Library benötigt, diese dann nicht gefunden wurde.
LD_LIBRARY_PATHgefunden. Der Loader berücksichtigt auch mehrere andere Quellen, um Libraries zu finden.In einer normalen Konfiguration ist es eine Kombination aus den üblichen ELF-Feldern jedes geladenen Binaries und anderen dem Loader bekannten Pfaden.
Auf Systemen mit mehreren Versionen derselben Library oder mehreren Libraries mit demselben Namen kann es sehr kurzsichtig sein, sich auf
LD_LIBRARY_PATHzu verlassen. Der Loader durchsucht für jedes Binary die Pfade inLD_LIBRARY_PATHder Reihe nach und nimmt die erste passende Library. Wenn nicht auf andere Weise ein Pfad mit höherer Priorität gesetzt wurde, ist diese Library möglicherweise nicht die tatsächlich gewünschte, was zur Laufzeit zu unerwarteten Fehlern führen kann.Besser ist es, für das betreffende Binary RPATH auf den Ort der benötigten Libraries zu setzen.
Wenn Umgebung und RPATH-Einstellungen nicht konsistent sind, können sogar mehrere Versionen derselben Library gleichzeitig geladen werden. Dieses Tool hilft dabei herauszufinden, ob es ein Problem gibt und warum.
LD_LIBRARY_PATH.Da dieses Tool auf
lddbasiert, wird es vermutlich auchDYLD_LIBRARY_PATH,DYLD_FALLBACK_FRAMEWORK_PATH,DYLD_FALLBACK_LIBRARY_PATH,@executable_path,@loader_pathund@rpathinterpretieren.Wirklich nützlich. Normalerweise lese ich mit
readelfdie Sections aus, um herauszufinden, was tatsächlich benötigt wird.Reicht
LD_DEBUG=libsnicht aus?Ich weiß nicht, ob es ein Bug ist, aber im vim-Beispiel zeigen
lddund libtree unterschiedliche Libraries.Zum Beispiel steht
linux-vdso.so.1beilddganz oben in der Liste, taucht bei libtree aber gar nicht auf.linux-vdso.so.1ist keine echte Library, die man irgendwo im Dateisystem finden kann, und sie wird auch in der ELF-Datei nicht referenziert; deshalb kann libtree nichts davon wissen.Stattdessen mappt der Kernel sie automatisch in den Adressraum eines neu gestarteten Prozesses. Das ist eine Optimierung, um bei Funktionen wie
gettimeofdayden System-Call-Overhead zu vermeiden. Siehe: https://man7.org/linux/man-pages/man7/vdso.7.htmlIch hatte einmal ein chaotisches kleines Skript geschrieben, das
lddrekursiv ausführt, um herauszufinden, was man einbinden muss, damit Closed-Source-Binaries auf NixOS laufen.Wenn ich so etwas noch einmal machen muss, werde ich dieses Tool ausprobieren.
Sieht gut aus!!