Enthält der vmlinux-Header die Länge des Kernel-Images?

Enthält der vmlinux-Header die Länge des Kernel-Images?

Ich versuche, eine zusammengesetzte Datei zu zerlegen, die aus mehreren Teilen besteht, von denen einer ein unkomprimierter Kernel ist, der zwischen mehreren anderen Dateien eingebettet ist. Ich versuche, die genaue Länge des Kernel-Teils zu ermitteln, was sich als schwierig erweist.

Gibt es im VMlinux-Header einen Hinweis darauf, wie viele Daten der Bootloader vor der Ausführung lesen soll, oder wird davon ausgegangen, dass der gesamte Inhalt der VMlinux-Datei bei der Übergabe vom Bootloader geladen werden soll?

Antwort1

Die kurze Antwort lautet „nein“, aber wenn es sich um ein ELF-Image handelt, können Sie mit etwas Hacken wahrscheinlich den Kernel finden. Siehe den readelfHack unten.

Der Bootloader ist dafür verantwortlich, das Format der Datei zu kennen, in der sich der Kernel und das Root-Dateisystem befinden. Dazu gehört auch, die Größe der Kerneldatei zu kennen, egal in welchem ​​Format sie vorliegt. Auf PowePC und Blackfin ist der Bootloader dafür verantwortlich, den gesamten Kernel zu dekomprimieren, wenn er komprimiert ist, und ihn an seinen endgültigen Speicherort im RAM zu schreiben. Auf ARM könnte der Kernel selbstdekomprimierend sein und der Bootloader muss nur die rohe Kerneldatei an einen geeigneten Ort im RAM kopieren und die Ausführung starten.

Wenn der Kernel selbstdekomprimierend ist, können die Symbole, die die Größe der komprimierten Kerneldatei angeben, je nach verwendetem Dekomprimierungsalgorithmus irgendwo im Dekomprimierungscode am Anfang der Datei stehen oder auch nicht. Ohne eine Linker-Map für den jeweiligen Kernel-Build können Sie das jedoch nicht wissen. Der Bootloader hat jedenfalls keine Möglichkeit, das herauszufinden.

Der unkomprimierte Kernelcode selbst ist von zwei Symbolen _stextund umgeben _end, deren Adressen den Anfang und das Ende des Kernels selbst darstellen, aber nicht den Umfang eines enthaltenen Initramfs umfassen, falls ein Initramfs in die Kernel-Binärdatei eingebunden wurde. Der Umfang des Initramfs wird vom Linker in zwei Kernelsymbolen __initramfs_startund festgelegt __initramfs_end. Bootloader können die Kernelsymboltabelle im Allgemeinen nicht lesen (sie befindet sich in der System.mapDatei) und ohne diese Fähigkeit hätten sie keine Möglichkeit zu wissen, wo sich die Symbole _endund __initrams_endin der Kerneldatei befinden. Das heißt, die Position der Symbole ist kein fester Offset vom Anfang der Binärdatei. Sie wird zur Linkzeit bestimmt und kann je nach Konfiguration des Kernel-Builds variieren.

Bei einem unkomprimierten Kernel im ELF-Format können Sie den Anfang der vmlinux-Datei wahrscheinlich identifizieren, indem Sie nach dem ELF-Header suchen ( 177 E L Fim od -cDump der zusammengesetzten Datei). Sie können dann von diesem Punkt aus readelf -eoder objdump -hauf den Rest der Datei anwenden, um den Abschnitt mit dem höchsten Dateioffset ( .shstrtab) zu finden. Fügen Sie diesem Offset die Abschnittsgröße hinzu und Sie gelangen zum Ende von vmlinux. Ich habe diese Methode mit einem ungestrippten PPC vmlinux getestet und eine Größe erhalten, die genau der Größe der eigenständigen vnlinux-Datei entsprach. Nach dem Strippen des Kernels lieferte diese Methode ein Ergebnis, das 1283 Bytes unter der gestrippten Bildgröße lag.

Eingebettete Systeme verwenden normalerweise ein Dateiformat wie mkimagezum Packen des Kernels, des Root-Dateisystems, des Gerätebaums und anderer Komponenten. U-Boot ist beispielsweise mkimage-fähig, weiß also, wo die Kernel-Binärdatei in der mkimage-Datei beginnt und endet, und weiß, ob der Kernel komprimiert ist oder nicht und an welche RAM-Adresse die Kernel-Datei geschrieben werden soll.

verwandte Informationen