2013-03-24 6 views
8

objcopyを使用して、バイナリ形式のテキストファイルを実行可能ファイルに含めることにしています。 (実行時にファイルが文字列として必要です)。これは、リンカがシンボル名から参照を見つける必要があるまでうまく動作します。問題は、objcopyがシンボル名の前にファイルのパス名を付加することです。私はGNU Autotoolsを使ってパッケージを出荷しているので、この前置きパス名が変更され、C/C++プログラムで使用する外部リンカシンボルは分かりません。objcopyはシンボル名の前にディレクトリパス名を付加します

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(Makefile.amからの抽出物)を製造した。

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

はどのようなリンカーシンボルとしてファイル名の私たちだけステムにobjcopyを伝えることができますか?あるいは、問題の周りに別の方法がありますか?

答えて

0

単純な解決策の1つは、テキストファイルをcharの配列を初期化するために使用できるものに変換することです。したがって、 "ABC012"には0x41,0x42,0x43,0x30,0x31,0x32が表示されます。 #この一連のバイトを#includeできます。 すべての文字をバイトに変換するのではなく、すべての非ASCII文字をエスケープして、生成されたインクルードファイルでほとんどのテキストを読み込めるようにすることもできます。

+0

'stdin'と' extern'を使ってソースを保存しないでください。 – Alex

+0

@Alexあなたが何を意味するのか分かりません。 –

+0

'gcc' /' g ++ 'の入力として '-x 'と '-'を使用しています – Alex

7

私は別の ディレクトリ内のPNGからオブジェクトファイルを作成するためにobjcopyを使用する場合はやや皮肉なことに、あなたは...シンボルの名前を変更することができます--redefine-symオプションを使用して問題を解決するために

objcopyを使用することができます。

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

得られたオブジェクトは次の記号があります

$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 

これらはその後、名前を変更することができます。

objcopyをはPNGが現在のディレクトリに置かれていた場合 が生成されなければならないシンボル名を持つオブジェクトに結果の
$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 

$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

'--redefine-sym'の記述は良いですが、それは不十分なようです:objcopyの呼び出し元はどのようにして"元の "シンボルを形成するかを知っていますか?名? objcopyへの入力ファイルが '../../ foo/bar.txt'のようなものであれば、シンボル名は' _binary ________ foo_bar_txt_start'のように恐ろしいものです。ドット、スラッシュ、およびおそらく他の文字(?)をアンダースコアに変換するロジックをエンコードすることはかなりばかげているようです。そして奇妙なことに、objcopyの '--wildcard'オプションは私たちを助けてくれるかもしれませんが、' --redefine-sym'では何の効果もないようです(他の用途に使うと思います)。 –

+3

@JohnZwinck:ディレクトリ以外の部分を再構築し、名前をobjdumpして目的の名前で終わるかどうかを確認し、名前を変更するためにそれを使うだけでよい。 – PlasmaHH

+0

コードを見ると、英数字以外の文字はすべて「_」に変換されます。したがって、以下はファイル名 'echo -n" $ filename "| tr -c '[A-Za-z0-9]' '' '。 '_binary_'の前に' _start'などを追加します。 – Mitar

7

ジェネリックELFに生データを含める方法は、.incbinアセンブラ指示文でサポートされています。

トリックは、このようになります。テンプレート.Sファイルを作成することです:

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

     .global foo_end 
foo_end:  

我々は例えば、そこにファイル名をハードコーディングする必要はありませんので、このファイルは、CPPを経由して前処理されています。コンパイル中

 .incbin __raw_file_path__ 

を...そして、それを渡します:私たちは書くことができます

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

最後に、我々は.Sは、私たち自身をファイルの準備として、我々はいくつかの余分なデータおよび/または情報を追加することができます。あなたは生の「テキストファイル」を含め、これらはあなたが追加することができますC文字列として使用できるようにしたい場合は「0」バイトだけで生のデータの後:

 .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 

あなたは本格的な柔軟性が必要な場合は、当然のことができます前プロセスファイルを手動で変更して、その一部を変更します。

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

...そして、それをコンパイルします。

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

私が使用している別の代替ソースディレクトリにcdにあり、その後objcopyにソースのベース名を与えます。 bashでは、これは次のようになります。

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

この方法では、生成されたシンボルは、パスなしで常に_binary_file_name_xxxです。

関連する問題