2010-09-01 4 views
14

Vorrei produrre un file che posso caricare in memoria (ad esempio con mmap) e quindi saltare all'inizio di quella memoria per eseguire il codice.Come far generare gcc solo il codice macchina che può essere caricato direttamente in memoria ed eseguito?

Idealmente, mi piacerebbe l'opzione di rendere il codice rilocabile (che potrebbe essere inefficiente) o specificare un indirizzo esplicito che il codice si aspetta di caricare (che è un dolore), ma uno probabilmente funzionerebbe bene da solo.

+0

non è questo un file oggetto? – aaronasterling

+1

no, perlomeno i file oggetto contengono informazioni su quali simboli esportano (per essere utilizzati dal linker) –

+2

Qualche ragione specifica per cui non si desidera utilizzare una libreria dll/condivisa? C'è un sacco di insidie ​​con i binari grezzi. – snemarch

risposta

14

È possibile farlo ma è necessario passare attraverso il formato del file oggetto. In particolare, il comando objcopy può trasformare un file eseguibile in un file binario "piatto" (a seconda della piattaforma di destinazione). Forse qualcosa di simile:

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

Vedi man objcopy sulla vostra piattaforma per maggiori dettagli.

+0

+1, sapevo che c'era qualcosa che faceva questo .Sai se ho bisogno di caricarlo a un indirizzo specifico? –

+0

Sì, lo farai. Sarà l'indirizzo a cui è stato detto al linker di collegarsi. Nota che normalmente non vedi il file di controllo del linker, quindi potresti non sapere dove si trova ... – RBerteig

+0

Dove trovo il file di controllo? –

6

Si desidera conoscere l'utilità objcopy, che di solito è disponibile insieme a GCC. È un componente del pacchetto di strumenti binutils, il cui membro più visibile è il linker, ld.

Il processo consiste nel compilare i file di origine e collegarli generalmente come al solito. Questo ti dà un eseguibile finito in formato elf (o un altro binario rilocabile in base alla piattaforma). Quindi si usa objcopy per trasformare l'eseguibile in un'immagine binario piatta.

Questo è molto utile per preparare il codice da eseguire dalla ROM, dove si vorrebbe assicurarsi di utilizzare una libreria di runtime C adatta per la piattaforma di destinazione, e probabilmente è necessario personalizzare il file di script del linker e fornire il proprio codice di avvio del runtime C.

Se il tuo obiettivo è ottenere qualcosa di simile a un file .so, da caricare in un processo esistente, tieni presente che parte del lavoro del caricatore di librerie condivise è terminare effettivamente il collegamento in modo che i simboli nel file .so che fa riferimento agli indirizzi nell'eseguibile principale (o altri file .so) vengono risolti al momento del caricamento. L'uso di objcopy non lo farà, e quindi potrebbe essere difficile per le funzioni caricate in questo modo utilizzare correttamente la libreria di runtime C esistente e gli oggetti che mantiene come i file aperti.

Indipendentemente dai tuoi obiettivi, dovrai prendere il controllo del linker per individuare il tuo binario a un indirizzo conosciuto. Per fare ciò, dovrai creare uno script linker. La documentazione per il linguaggio di script è the binutils manual. Sarai interessato principalmente alle sezioni ".text *" e possibilmente nelle sezioni ".rodata *" se prevedi di avere variabili globali inizializzate. In realtà organizzare quell'inizializzazione è lasciato come esercizio per il lettore.

Nel complesso, questa è solo la punta di un iceberg molto grande. Suggerirei di passare un po 'di tempo con un compilatore cross build per vedere come queste cose vengono utilizzate nella pratica. Le comunità AVR e MSP430 utilizzano GCC, hanno una partecipazione attiva e hardware economico (e spesso anche open source) per iniziare.

Problemi correlati