2010-09-01 15 views
14

Ich möchte eine Datei erzeugen, die ich in den Speicher laden kann (zum Beispiel mit mmap) und dann zum Anfang dieses Speichers springen, um den Code auszuführen.Wie kann gcc nur Maschinencode erzeugen, der direkt in den Speicher geladen und ausgeführt werden kann?

Idealerweise würde ich gerne die Option haben, entweder den Code verschiebbar zu machen (was ineffizient sein könnte) oder eine explizite Adresse anzugeben, bei der der Code geladen werden soll (was ein Schmerz ist), aber beides würde wahrscheinlich funktionieren gut für sich.

+0

ist das nicht was eine Objektdatei ist? – aaronasterling

+1

Nein, zumindest enthalten Objektdateien Informationen darüber, welche Symbole sie exportieren (zur Verwendung durch den Linker) –

+2

Gibt es einen bestimmten Grund, warum Sie keine dll/shared library stattdessen verwenden möchten? Es gibt eine Menge Fallstricke mit rohen Binärdateien. – snemarch

Antwort

14

Sie können dies tun, aber Sie müssen durch das Objektdateiformat gehen. Insbesondere kann der Befehl objcopy eine ausführbare Datei in eine "flache" Binärdatei umwandeln (abhängig von Ihrer Zielplattform). Vielleicht so etwas wie diese:

gcc -o test test.c 
objcopy -O binary test test.bin 

Siehe man objcopy auf Ihrer Plattform für weitere Details.

+0

+1, ich wusste, dass da etwas war, das das tat .Weißt du, ob ich das an einer bestimmten Adresse laden muss? –

+0

Ja, das wirst du. Es wird die Adresse sein, zu der der Linker angewiesen wurde, eine Verbindung herzustellen. Beachten Sie, dass Sie die Steuerungsdatei des Linkers normalerweise nicht sehen, so dass Sie möglicherweise nicht wissen, wo das ist. – RBerteig

+0

Wo finde ich die Steuerungsdatei? –

6

Sie möchten über das Dienstprogramm objcopy wissen, das normalerweise zusammen mit GCC verfügbar ist. Es ist eine Komponente des Tools binutils, dessen sichtbarstes Mitglied der Linker ld ist.

Der Prozess besteht darin, dass Sie Ihre Quelldatei (en) kompilieren und im Allgemeinen wie gewohnt verknüpfen. Das gibt Ihnen eine fertige ausführbare Datei in elf (oder einem anderen verschiebbaren plattformabhängigen Binärformat). Sie verwenden dann objcopy, um die ausführbare Datei in ein flaches Binärbild umzuwandeln.

Dies ist am nützlichsten für die Vorbereitung von Code aus dem ROM ausgeführt werden, wo Sie sicherstellen möchten, dass Sie eine geeignete C-Laufzeitbibliothek für Ihre Zielplattform verwenden, und wahrscheinlich müssen die Linker-Skriptdatei anpassen und bereitstellen Ihr eigener C-Runtime-Startup-Code.

Wenn es Ihr Ziel ist, etwas wie eine .so-Datei zu erhalten, die in einen vorhandenen Prozess geladen werden soll, dann beachten Sie, dass ein Teil der Arbeit des Shared Library-Loaders das Verknüpfen dieser Symbole beendet in der .so-Datei, die sich auf Adressen in der Hauptdatei (oder anderen .so-Dateien) beziehen, werden beim Laden aufgelöst. Die Verwendung von objcopy wird dies nicht tun, und daher kann es für auf diese Weise geladene Funktionen schwierig sein, die vorhandene C-Laufzeitbibliothek und die von ihr verwalteten Objekte wie offene Dateien ordnungsgemäß zu verwenden.

Unabhängig von Ihren Zielen müssen Sie die Kontrolle über den Linker ergreifen, um Ihre Binärdatei an einer bekannten Adresse zu finden. Um dies zu tun, müssen Sie ein Linker-Skript erstellen. Dokumentation für die Skriptsprache ist in the binutils manual. Sie werden hauptsächlich an den Abschnitten ".text *" interessiert sein und möglicherweise auch an den Abschnitten ".rodata *", wenn Sie über initialisierte globale Variablen verfügen. Die Vorbereitung für diese Initialisierung bleibt dem Leser als Übung überlassen.

Insgesamt ist dies nur die Spitze eines sehr großen Eisbergs. Ich würde vorschlagen, etwas Zeit mit einem Cross-Compiler-Build zu verbringen, um zu sehen, wie diese Dinge in der Praxis verwendet werden. Die AVR- und MSP430-Communities verwenden GCC, haben aktive Teilnahme und kostengünstige (und oft sogar Open Source) Hardware, um loszulegen.