Ich versuche, bestimmte Treiber innerhalb des Linux-Kernels zu kompilieren: drm ( drivers/gpu/drm/drm_drv.o
) und radeon ( drivers/gpu/drm/radeon/
) GPU-Treiber. Ich benutze LLVM für die statische Analyse (Verfolgung der Argumente in copy_to/from_user()
Aufrufe).
Bisher bin ich in der Lage, die eigentlichen Module mit dem Makefile zu kompilieren, wie unten gezeigt:
%Vor% Aber das emittiert tatsächlich keinen llvm-Bitcode - ich brauche die .bc
-Dateien, um meinen Durchlauf mit opt
zu starten.
Ich kann nur .bc
Dateien erzeugen, wenn ich clang direkt benutze (wie unten), aber nicht mit Makefiles ...
Da dies funktionierte, nahm ich die ausführliche Ausgabe der GNU-make-Operation, änderte gcc
in clang
und führte sie aus, um die .bc
-Datei zu erstellen, die auch funktionierte:
Das einzige Problem dabei ist, dass ich nur eine einzige C-Datei im Kernel-Modul gleichzeitig verarbeiten kann. Es ist auch sehr mühsam, diesen Ansatz zu machen ...
Was mich zu meiner Hauptfrage bringt: Wie würdest du llvm .bc
Bitcode-Dateien mit den Makefiles des Kernels ausgeben?
Oder, wenn die .bc
-Bitcode-Erstellung auf Dateibasis erfolgen muss, wie würde ich dann am Ende alle zusammen verknüpfen, so dass ich einen LLVM opt
-Pass auf dem Aggregat aller% ausführen kann co_de% Dateien in einem Kernelmodul?
Der beste Weg, LLVM IR in Bitcode-Form aus Clang zu bekommen, besteht darin, LTO mit dem -flto
-Befehlszeilen-Flag auszuführen.
Wenn Sie mehrere Übersetzungseinheiten haben, können Sie sie mit dem Werkzeug llvm-lto
kombinieren, um die Bitcode-Dateien zu verknüpfen. In der Regel wird Code generiert, aber Sie können das vereinigte LLVM-IR-Modul mit dem -save-merged-module
-Flag löschen.
Aber nichts davon ist wirklich eine unterstützte Schnittstelle. Wenn dies ein sehr nützlicher Arbeitsablauf ist, sollten Sie mit den LLVM-Entwicklern darüber sprechen, etwas zu unterstützen, das dem von ld -r
ähnlich ist.
Ich benutzte clang, um das ext2-Modul zu instrumentieren. Es gibt 3 Dinge, die du machen willst: 1) Konvertiere .c in .bc 2) Führen Sie Ihren Optimierer in der .bc-Datei aus und erstellen Sie eine ext2-opt.o-Datei 3) Erstellen Sie die Datei ext2-instrumented.ko aus der Datei ext2-opt.o.
Außerdem benötigen Sie eine Linux-Version, die mit clang kompiliert wird. Ich könnte Linux 4.17 kompiliert mit clang Version 3.8.1 nach dem Deaktivieren einiger Module. Sie können es hier
bekommenLasst uns jetzt zu Schritt 1 gehen - wie bereits erwähnt, führe Make im ausführlichen Modus aus
%Vor%und greifen Sie alle Optionen, die von Makefile ausgespuckt werden. Der Standardcompiler wird gcc sein. Ersetzen Sie gcc durch clang, fügen Sie den Befehl --emit-llvm hinzu und ersetzen Sie .o durch .bc. Der resultierende Kompilierungsbefehl auf meinem Rechner sieht so aus:
%Vor%Dadurch wird eine .bc-Datei für Sie erstellt. Beachten Sie, dass ich das resultierende .bc-Code-Verzeichnis in ext2_instrumented geändert habe, d. h. meine BC-Datei wird nicht in fs / ext2 erstellt, sondern in einem anderen Ordner namens fs / ext2_instrumented. Das ist mein Arbeitsordner. Ich möchte, dass dieser Ordner keine .c-Dateien, sondern nur .bc-Dateien enthält. Ich brauche das, weil das Standard-KBuild-System nach .c-Dateien in einem Ordner sucht. Mehr dazu später.
Schritt 2: Führen Sie alle Optimierungsdurchläufe für die resultierende ext2-instrumentierte.bc-Datei mit dem opt-Befehl wie folgt aus:
opt -load $ (DIR) /build/FSlice.so -constprop -sccp -mergereturn -sink -lic -reg2mem all.bc -o all.inst.bc llvm-link -o all.inst2.bc $ (DIR) /build/libFSlice.bc all.inst.bc clang -mcmodel = kernel -c all.inst2.bc -o all.o
Dies führt zu einer .o-Datei, die wir im nächsten Schritt in eine .ko-Datei kompilieren werden:
Schritt 3:
%Vor%Das Kbuild-System ist schwer zu verstehen und noch schwieriger zu modifizieren. Ich würde empfehlen, diesen 2-Ordner-Hack zu verwenden (1. Ordner zum Erstellen einer .bc-Datei und zweiten Ordner zum Erstellen von .o und .ko-Dateien). Um es zusammenzufassen, hier ist mein resultierendes Makefile in ext2_instrumented Ordner:
%Vor%Tags und Links llvm clang linux-kernel makefile