Ich habe ein gemeinsames Objekt geschrieben, das die Argumente für die Funktionen FT_Load_Glyph
und FT_Render_Glyph
von FreeType ändert, indem es mit LD_PRELOAD
und dlsym
verknüpft wird.
Das funktioniert gut, aber ich bin neugierig, ob es eine Möglichkeit gibt, diese Änderungen vorzunehmen:
LD_PRELOAD
auf alle Programme auf dem Host anzuwenden; Die einzigen zwei "Lösungen", die ich mir vorstellen konnte, sind hässliche Hacks:
LD_PRELOAD
alle Programme, die ganze Zeit, die langsam und zerbrechlich erscheint; oder libfreetype.so.6.12.3
bis libxxxxtype.so.6.12.3
; dann
libxxxxtype.so.6.12.3
auf libxxxxtype.so.6
; libxxxxtype.so.6
; und libfreetype.so.6.999
. Ich möchte im Wesentlichen transparent einige Funktionen in einem gemeinsamen Objekt patchen, während ich die restlichen Funktionen durchlasse, ohne notwendigerweise Zugriff auf die Quelle des gemeinsamen Objekts oder die Programme zu haben, die es benutzen, aber wenn ich a mache gefälschtes geteiltes Objekt mit dem Soname libfreetype.so.6
, ich kann keine saubere Methode sehen, um es mit (oder dlopen
) mit dem echten libfreetype.so.6
zu verknüpfen.
Dies ist mein erstes wirkliches Experiment mit Shared Libraries, also bitte ertragen Sie mich, wenn diese Frage einige falsche Annahmen macht oder einfach keinen Sinn ergibt.
Können Sie versuchen, uprobes
zu verwenden, um die Steuerung einiger Funktionen dynamisch zu stehlen?
Überprüfen Ссылка
%Vor%uprobes: Dynamische Ablaufverfolgung auf Benutzerebene, die zu Linux 3.5 hinzugefügt und in Linux 3.14 verbessert wurde. Sie können Funktionen auf Benutzerebene verfolgen. Zum Beispiel die Rückgabe der Funktion readline () von allen laufenden Bash-Shells mit der zurückgegebenen Zeichenfolge:
Und Ссылка
Es gab auch andere Lösungen zum Verfolgen von User-Space-Funktionen, wie ftrace, systemtap, dtrace, lttng. Einige von ihnen müssen neu kompiliert werden und Tracing-Punkte statisch im Programm definieren. und uprobes sind "user-level dynamic tracing".
Einige Links über Uprobes:
Es gibt handler
von uprobes mit pt_regs
. Wie im letzten Link gesagt: " Uprobes implementiert somit einen Mechanismus, mit dem eine Kernel-Funktion aufgerufen werden kann, wenn ein Prozess eine bestimmte Befehlsstelle ausführt. " und schlägt vor, dass uprobes einige ptrace / gdb-basierte Lösungen ersetzen können ; es besteht also die Möglichkeit, die Ausführung eines Programms zu ändern, das den aktiven Modus anspricht, indem das eip / rip (PC) -Register geändert wird.
Sie können auch andere dynamische Instrumentierungswerkzeuge wie pin
oder dyninst
; aber sie sind für die pro-Prozess-Nutzung ausgelegt.
Eine andere Lösung wäre, systemweit "overlay" für lib zu machen, mit benutzerdefiniertem libfreetype und dann unprofessionell unmodifizierter Methoden zu reell lib.
Sie müssen die benutzerdefinierte Lib mit der echten lib kompatibel machen. Das kannst du mit dlopen
mit absoluter Pfad (zB dlopen("/usr/lib64/libfreetype.so.6")
),
Kopieren von Definitionen von reellen, exportierten Funktionen und deren Proxy mit dlsym
.
Sie denken, dass zur einfacheren Wartung Sie können proxied Argumenttypen durch einfache void*
ersetzen. Sie müssen nur Änderungen vornehmen, wenn sich Freetype-Funktionen ändern (Argumente zählen, Funktionsnamen).
Um lib "overlay" zu erstellen, könnten Sie benutzerdefinierte Lib in zB installieren. "/opt/myapp/lib64/libfreetype.so.6", dann fügen Sie diesen Pfad zu Laufzeitpfaden dynamischer Linker hinzu. Sie müssen möglicherweise Symlinks für andere Versionen erstellen oder neue benutzerdefinierte Bibliotheken kompilieren, wenn sich die ursprüngliche Implementierung ändert. Was auch immer benötigt wird, um Real-Lib zu beschatten und andere Apps in Betrieb zu halten :)
Google sagt, dass man, um Laufzeitladepfade auf Debian zu ändern, einfach /etc/ld.so.conf
bearbeiten muss. Fügen Sie /opt/myapp/lib64
path am Anfang hinzu, so dass es zuerst überprüft wird.
Jetzt sollte jede App, die nach Freetype sucht, deine lib laden, du kannst sie mit ldd <path to app>
überprüfen.
Ich kann nur an einen Fall denken, wenn diese Lösung nicht funktioniert: wenn die App gebündelten libfreetype lädt oder sie nach dem vollständigen Pfad lädt, nicht nach dem Namen.
zu LD_PRELOAD alle Programme, die ganze Zeit, die langsam und zerbrechlich scheint
Das ist eine gute Lösung (für was Sie wollen). Ich sehe keinen besseren.
Es ist nicht fragil. Es stellt dem Runtime-Linker auf dokumentierte Weise Informationen bereit. Du nimmst nichts an und tust so, als wäre etwas nicht das, was es ist. Sie ändern nur die Präferenzhierarchie für die Auflösung von Funktionsnamen.
Es ist nicht langsam. Der Linker muss irgendwann etwas tun. Es muss überprüft werden, ob LD_PRELOAD
definiert ist, was in jedem Fall eine User-Space-Operation ist. Also wird es diesem Pfad folgen und deine Bibliothek laden, bevor du eine Menge anderer Arbeit verrichtest. Ich wäre erstaunt, wenn die Zeit unter normalen Umständen überhaupt messbar wäre.
Es gibt zwei Bedenken, die ich haben würde, aber sie sind orthogonal zur Technik. Der Code muss in jedem Fall funktionieren, und Sie müssen ein wenig in das Prozess-Erzeugungs-Framework eintauchen, um sicherzustellen, dass LD_PRELOAD
wirklich überall definiert ist . Darüber hinaus definiert Id.so seine Umgebungsvariablen genau für Ihre beabsichtigte Verwendung. Wer soll streiten?
Tags und Links linux shared-libraries function-interposition