2013-03-24 8 views
8

Mi sto legando per utilizzare objcopy per includere un modulo binario di un file di testo in un file eseguibile. (A runtime ho bisogno del file come stringa). Funziona bene finché il linker non ha bisogno di trovare i riferimenti dai nomi dei simboli. Il problema è che objcopy antepone i nomi dei simboli con il percorso al file. Dal momento che sto usando GNU Autotools per spedire il pacchetto, questo nome di percorso predefinito cambia e non so quale simbolo del linker esterno usare nel programma C/C++.objcopy antepone il nome di percorso di directory al nome di simbolo

nm libtest.a |grep textfile 
textfile.o: 
00001d21 D _binary__home_git_textfile_end 
00001d21 A _binary__home_git_textfile_size 
00000000 D _binary__home_git_textfile_start 

libtest.a è stato prodotto con (estratto da Makefile.am):

SUFFIXES = .txt 
.txt.$(OBJEXT): 
    objcopy --input binary --output elf32-i386 --binary-architecture i386 $< [email protected] 

Come posso dire a objcopy solo noi lo stelo del nome del file come simboli del linker? O c'è un altro modo per aggirare il problema?

risposta

0

Una soluzione semplice consiste nel trasformare il file di testo in ciò che potrebbe essere utilizzato per inizializzare un array di caratteri. Quindi, otterresti 0x41,0x42,0x43,0x30,0x31,0x32 per "ABC012". Puoi quindi # include questa sequenza di byte. È anche possibile escape tutti i caratteri non ASCII invece di convertire tutto in byte in modo che la maggior parte del testo sia ancora leggibile nel file di inclusione generato.

+0

Utilizzare 'stdin' e' extern' per evitare di memorizzare la fonte. – Alex

+0

@Alex Non sono sicuro di capire cosa intendi. –

+0

usando '-x ' e '-' come input per' gcc'/'g ++' – Alex

7

Un po 'ironicamente è possibile utilizzare objcopy per risolvere il problema tramite l'opzione --redefine-sym che consente la ridenominazione di simboli ...

Se uso objcopy per creare un file oggetto da un PNG in un'altra directory :

$ objcopy -I binary -O elf64-x86-64 -B i386 --rename-section .data=.rodata,alloc,load,data,contents,readonly ../../resources/test.png test_png.o 

L'oggetto risultante presenta i seguenti simboli:

$readelf -s test_png.o -W 

Symbol table '.symtab' contains 5 entries: 
    Num: Value   Size Type Bind Vis  Ndx Name 
    0: 0000000000000000  0 NOTYPE LOCAL DEFAULT UND 
    1: 0000000000000000  0 SECTION LOCAL DEFAULT 1 
    2: 0000000000000000  0 NOTYPE GLOBAL DEFAULT 1 _binary_______resources_test_png_start 
    3: 0000000000003aaa  0 NOTYPE GLOBAL DEFAULT 1 _binary_______resources_test_png_end 
    4: 0000000000003aaa  0 NOTYPE GLOBAL DEFAULT ABS _binary_______resources_test_png_size 

Questi possono poi essere rinominato:

$objcopy --redefine-sym _binary_______resources_test_png_start=_binary_test_png_start test_png.o 
$objcopy --redefine-sym _binary_______resources_test_png_size=_binary_test_png_size test_png.o 
$objcopy --redefine-sym _binary_______resources_test_png_end=_binary_test_png_end test_png.o 

risultanti in un oggetto con i nomi dei simboli che objcopy sarebbe generato se il PNG era stato localizzato nella directory corrente:

$readelf -s test_png.o -W 

Symbol table '.symtab' contains 5 entries: 
    Num: Value   Size Type Bind Vis  Ndx Name 
    0: 0000000000000000  0 NOTYPE LOCAL DEFAULT UND 
    1: 0000000000000000  0 SECTION LOCAL DEFAULT 1 
    2: 0000000000000000  0 NOTYPE GLOBAL DEFAULT 1 _binary_test_png_start 
    3: 0000000000003aaa  0 NOTYPE GLOBAL DEFAULT 1 _binary_test_png_end 
    4: 0000000000003aaa  0 NOTYPE GLOBAL DEFAULT ABS _binary_test_png_size 
+0

La menzione di '--redefine-sym' è buona, ma sembra insufficiente: in che modo il chiamante di objcopy dovrebbe sapere come formare il simbolo" originale " nome? Prendo atto che se il file di input su objcopy è qualcosa come '../../ foo/bar.txt' il nome del simbolo è qualcosa di orribile come' _binary ________ foo_bar_txt_start'. Dovendo codificare la logica per trasformare punti, barre e forse altri personaggi (quali?) In caratteri di sottolineatura sembra piuttosto sciocco. E stranamente, l'opzione '--wildcard' di objcopy potrebbe aiutarci, ma sembra non avere alcun effetto con' --redefine-sym' (suppongo che lo intendano per altri usi). –

+3

@JohnZwinck: Devi solo essere in grado di ricostruire la parte non di directory, quindi eseguire l'objdump dei nomi e controllare quali terminano con il nome desiderato, quindi utilizzarlo per la ridenominazione. – PlasmaHH

+0

Guardando il codice, tutti i caratteri non alfanumerici vengono convertiti in '_'. Quindi il seguente converte il nome del file 'echo -n" $ nomefile "| tr -c '[A-Za-z0-9]' '_''. Prependa '_binary_' e aggiungi' _start' e altri. – Mitar

7

Generico il metodo per includere dati grezzi in ELF è supportato dalla direttiva assembler .incbin.

Il trucco è quello di creare template .S di file che potrebbe assomigliare a questo:

 .global foo_start 
foo_start: 
     .incbin "foo.raw" 

     .global foo_end 
foo_end:  

Questo file viene pre-elaborata tramite cpp quindi non c'è bisogno di codificare il nome del file lì, ad es. possiamo scrivere:

 .incbin __raw_file_path__ 

... e poi passarlo durante la compilazione:

gcc -D__raw_file_path__='"data/foo.png"' foo.S -c -o data/foo.o 

Infine, mentre ci prepariamo il file .S noi stessi possiamo aggiungere alcuni dati e/o informazioni aggiuntive.Se si include "file di testo" prime e desidera che questi siano disponibili come stringhe C è possibile aggiungere '0' byte solo dopo che i dati grezzi:

 .global foo_start 
foo_start: 
     .incbin "foo.raw" 

     .global foo_end 
foo_end:  
     .byte 0 

     .global foo_size 
foo_size: 
     .int foo_end - foo_start 

Se si desidera la flessibilità in piena regola, si può ovviamente pre- elaborare manualmente il file per modificare qualsiasi parte di esso, ad es.

.global @[email protected]_start 
@[email protected]_start: 
     .incbin "@[email protected]" 
     .global @[email protected]_end 
@[email protected]_end: 

... e quindi compilarlo:

sed -e "s,@[email protected],passwd,g" -e "s,@[email protected],/etc/passwd," <foo.S.in | gcc -x assembler-with-cpp - -o passwd.o -c 
4

Un'altra alternativa che ho usato è quello di cd alla directory di origine e poi dare objcopy il nome base della fonte. In bash, questo sarebbe:

cd $(dirname $SOURCE) 
objcopy ... $(basename $SOURCE) $TARGET 

questo modo i simboli generati sono sempre _binary_file_name_xxx senza il percorso.

Problemi correlati