Finden Sie heraus, wo in einem Live-System ein Symbol für eine gemeinsam genutzte Bibliothek definiert ist, und listen Sie alle in ein System exportierten Symbole auf


21

Grundsätzlich sind dies zwei Fragen in einer - denn wenn ich alle innerhalb eines Systems exportierten Symbole zusammen mit ihrem gemeinsamen Bibliothekspfad auflisten kann, könnte ich einfach grepdiese Ausgabe machen.

Bei Kernel-Symbolen ist es wahrscheinlich etwas einfacher - weil wir immer cat /proc/kallsymseine Liste aller Symbole dieser Module erhalten können, die in den Speicher geladen sind. Anschließend sudo cat /proc/moduleswird eine Liste der geladenen Module mit ihren Adressen angezeigt, jedoch nicht die Pfade, aus denen Module geladen wurden (wenn sie als separate, nicht in Baumstruktur befindliche .ko-Objekte erstellt wurden).

Zum Beispiel versuche ich das Programm zu verfolgen kstmit ltrace:

$ ltrace kst2
...
_ZNK13QGraphicsItem10parentItemEv(0xa1ccdb4, 0, 0xbfe631a8, 0x823652b, 0xbfe63298) = 0xa1ce854
__dynamic_cast(0xa1ce854, 0x839ff00, 0x8306b80, 84, 0xbfe63298)     = 0xa1ce800
_ZNK13QGraphicsItem10parentItemEv(0xa1ccdb4, 0x839ff00, 0x8306b80, 84, 0xbfe63298) = 0xa1ce854
__dynamic_cast(0xa1ce854, 0x839ff00, 0x8306b80, 84, 0xbfe63298)     = 0xa1ce800
...

... und ich würde gerne wissen, wo sich das _ZNK13QGraphicsItem10parentItemEvbefindet.

Was tun mit Symbolen für gemeinsam genutzte Bibliotheken? Durchlesen von [gcc-help] Re: Finden der Bibliothek, in der das Symbol definiert ist. ; Ich habe so etwas ausprobiert:

$ find /usr/lib -name '*.so*' -exec nm --print-file-name --defined-only --dynamic {} \; | grep "QGraphicsItem"
...
/usr/lib/libQtGui.so.4.7.2:00766d70 T _Zls6QDebugN13QGraphicsItem16GraphicsItemFlagE
/usr/lib/libQtGui.so.4.7.2:00766aa0 T _Zls6QDebugN13QGraphicsItem18GraphicsItemChangeE
/usr/lib/libQtGui.so.4.7.2:00767e80 T _Zls6QDebugP13QGraphicsItem
...

... aber das gibt mir zusätzliche Probleme: Ich kenne nicht wirklich alle Pfade, die auf meinem System nach gemeinsam genutzten Bibliotheken durchsucht werden. Als ich das erste Mal versuchte find /lib ..., fand ich nichts. Ich finde das Erraten von Verzeichnissen lästig, genauso wie die Alternative: das findDurchsuchen des gesamten Root-Dateisystems mit ... Und außerdem stoße ich auf * .soos, die nicht geöffnet werden können nm(vielleicht weil sie Symlinks sind?), Welche gibt eine ganze Reihe von Fehlermeldungen aus (die ich auch nicht mag).

Die Sache ist, dass - ldd(oder ld?) Wahrscheinlich einen Teil dieser Suche nach Symbolen durchführt, aber ich habe die entsprechenden Hilfeseiten ausprobiert, und ich kann keinen Weg finden, ein Symbol von der Befehlszeile aus zu "finden", ohne eine Art ausführbare Datei als Streit. Nebenfrage - gibt es eine Möglichkeit, diese Tools dafür zu verwenden?

Also, was ich für ein Kommandozeilen-Tool suche, das sich ungefähr so ​​verhält (Pseudocode):

$ ./findsymbol '_Zls6QDebugN13QGraphicsItem16GraphicsItemFlagE'
symbol found in:
    /usr/lib/libQtGui.so.4.7.2:00766d70 T _Zls6QDebugN13QGraphicsItem16GraphicsItemFlagE
...

... wo ich keine zu durchsuchenden Verzeichnisse spezifiziere - die aber auch handhaben würden, zB LD_PRELOADoder LD_LIBRARY_PATH; sag wenn ich tue:

$ LD_PRELOAD="/path/to/mylib.so" ./findsymbol '*mylib_print*'

... dann würde ich bekommen, /path/to/mylib.sowo das gegebene Symbol definiert wurde (vorausgesetzt, dass ein solches Symbol in den Standardbibliotheken nicht existieren würde) - und würde sonst "nicht gefunden" ausgeben. Andernfalls kann ./findsymbol --dumpalleine Liste aller verfügbaren Symbole und ihrer Positionen erstellt werden, die in einer bestimmten Umgebung (z. B. einer bestimmten bashShell) angezeigt werden.

Gibt es ein solches Tool für Linux?

Antworten:


16

Die Pfade, in denen nach Bibliotheken gesucht werden soll, werden in der Datei /etc/ld.so.conf, der Umgebungsvariablen LD_LIBRARY_PATHund allen in der ELF-Binärdatei codierten RPATHs aufgelistet. Das Programm lddteilt Ihnen mit, welche Bibliotheken von einer bestimmten Anwendung geladen werden.

Sobald Sie ein Symbol haben, auf das Sie neugierig sind, können Sie mit dem Programm nmSymbole von .ound .aDateien sowie readelfSymbole von einer .sooder mehreren ausführbaren Elfen sichern.

Beispiele:

nm -g /usr/lib/blah.a
readelf -Ws /usr/lib/blah.so

Und schließlich, mit diesem Hintergrund beiseite, hier ist dein heiliger Gral:

_ZN6Kopete6Global10PropertiesC2EvWo ist das mit einem Symbol ?

scanelf -l -s _ZN6Kopete6Global10PropertiesC2Ev | grep _ZN6Kopete6Global10PropertiesC2Ev

was ergibt:

ET_DYN _ZN6Kopete6Global10PropertiesC2Ev /usr/lib64/libkopete.so.4.11.4

Die -lFlagge sagt, dass nach dirs gesucht werden soll /etc/ld.so.confund -sgibt das zu suchende Symbol an.


Dies ist unvollständig: Einige Programme laden Bibliotheken aus anwendungsspezifischen Verzeichnissen.
Gilles 'SO- hör auf böse zu sein'

2
Mit @Gilles scanelfkönnen Sie bestimmte Verzeichnisse für die Suche angeben und die rekursive Suche unterstützen, um die Suchpfade zu -roptimieren oder das gesamte System ohne große Probleme zu durchsuchen. Zum Beispiel scanelf -r -s SYMBOL /lib/* /usr/* /opt/*werden die meisten Orte gefunden, an denen sich Bibliotheken verstecken.
Casey

7

Auf GNU-Systemen (wenn Sie den dynamischen Linker von GNU libc verwenden) können Sie Ihr Programm wie folgt ausführen:

LD_DEBUG=bindings kst2

Finden, wohin sich die Symbole auflösen.


0

Ich bin mehrmals darauf gestoßen und habe versucht, Code von einem Linux-System auf ein anderes zu portieren. Normalerweise greife ich einfach alle Standardverzeichnisse durch. Ich konnte nichts googeln finden. Also hier ist ein kurzes Skript:

edt11x / findinsharedlibs

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.