2015/02/09(月)データファイルをバイナリに埋め込みたい
バイナリファイルをデータ配列として取り込むことが可能です。
binary utilityのobjcopyコマンドのヘルプを見ると、入出力フォーマットにbinaryやhexといった指定ができることが判ります。
実際にファイルを吐かせてfileコマンドやreadelfコマンドを使って、試行錯誤した後でビルドできる状態にできたので、
メモとして記しておきます。しっかりとマニュアルを読めば試行錯誤は不要だとは思います...(無力
結合したいファイルを作る
$ echo -ne "1234567890\0" > foo.txt $ objcopy -Ibinary -Bi386 -Oelf64-x86-64 foo.txt foo.o
- Iは入力フォーマット。テキストファイルを作っていますが、バイナリファイルでも同様です。
- Bはアーキテクチャですが、入力ファイルからアーキテクチャが推定できない場合のみ有効だそうです。
- Oは出力フォーマット。ビルドする際に結合したいオブジェクトファイルに合わせて選択します。
サンプルコード
結果からの後付になりますが、変換した後のファイルをシンボルダンプするとソレらしいものがあります。実際にオブジェクトファイルの内容と易化の出力とを照らしあわせていくとなんとなくイメージがわきます。
変数に型は与えていないので、適当な型の変数としてextern宣言しておきます。
シンボルのアドレス情報がデータ本体のアドレスになるので、&演算子でアドレスを得ます。
start/endはそれで納得しますが、sizeも&で取得する必要があります。
値を保持する変数を用意してくれているわけではなく、値はシンボルのアドレス情報として格納されているようです。
$ cat sample.c #include <stdio.h> main() { extern char _binary_foo_txt_start; extern char _binary_foo_txt_end; extern char _binary_foo_txt_size; printf("%16x\n%16x\n%16x\n%s\n", &_binary_foo_txt_start, &_binary_foo_txt_end, &_binary_foo_txt_size, &_binary_foo_txt_start); }
$ gcc -c sample.c -o sample.o $ gcc sample.o foo.o -o sample $ ./sample 601040 60104b b 1234567890 $
検証
生成していたオブジェクトファイルのヘッダ情報を参照しておきましょう..リンクに失敗する場合には 整合性がとれているか確認していきます.
シンボルが見つからない時も これで探すと良いでしょう.
$ readelf -a sample | grep _binary_ 51: 000000000000000b 0 NOTYPE GLOBAL DEFAULT ABS _binary_foo_txt_size 54: 000000000060104b 0 NOTYPE GLOBAL DEFAULT 24 _binary_foo_txt_end 55: 0000000000601040 0 NOTYPE GLOBAL DEFAULT 24 _binary_foo_txt_start $ readelf -h sample.o ELF Header: Magic: 7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00 Class: ELF64 Data: 2's complement, little endian Version: 1 (current) OS/ABI: UNIX - System V ABI Version: 0 Type: REL (Relocatable file) Machine: Advanced Micro Devices X86-64 Version: 0x1 Entry point address: 0x0 Start of program headers: 0 (bytes into file) Start of section headers: 328 (bytes into file) Flags: 0x0 Size of this header: 64 (bytes) Size of program headers: 0 (bytes) Number of program headers: 0 Size of section headers: 64 (bytes) Number of section headers: 13 Section header string table index: 10 $ readelf -h foo.o ELF Header: Magic: 7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00 Class: ELF64 Data: 2's complement, little endian Version: 1 (current) OS/ABI: UNIX - System V ABI Version: 0 Type: REL (Relocatable file) Machine: Advanced Micro Devices X86-64 Version: 0x1 Entry point address: 0x0 Start of program headers: 0 (bytes into file) Start of section headers: 112 (bytes into file) Flags: 0x0 Size of this header: 64 (bytes) Size of program headers: 0 (bytes) Number of program headers: 0 Size of section headers: 64 (bytes) Number of section headers: 5 Section header string table index: 2
対応フォーマット
objcopyのビルド方法やバイナリパッケージの場合はディストリに依存するかもしれません。"--info"オプションでリストアップすることができました。
これに気づくのが後になってロスが大きかったです。
Display a list showing all architectures and object formats available.
$ objcopy --info BFD header file version (GNU Binutils for Ubuntu) 2.24 elf64-x86-64 (header little endian, data little endian) i386 elf32-i386 (header little endian, data little endian) i386 elf32-x86-64 (header little endian, data little endian) i386 a.out-i386-linux (header little endian, data little endian) i386 pei-i386 (header little endian, data little endian) i386 pei-x86-64 (header little endian, data little endian) i386 elf64-l1om (header little endian, data little endian) l1om elf64-k1om (header little endian, data little endian) k1om elf64-little (header little endian, data little endian) i386 l1om k1om plugin elf64-big (header big endian, data big endian) i386 l1om k1om plugin elf32-little (header little endian, data little endian) i386 l1om k1om plugin elf32-big (header big endian, data big endian) i386 l1om k1om plugin pe-x86-64 (header little endian, data little endian) i386 pe-i386 (header little endian, data little endian) i386 plugin (header little endian, data little endian) srec (header endianness unknown, data endianness unknown) i386 l1om k1om plugin symbolsrec (header endianness unknown, data endianness unknown) i386 l1om k1om plugin verilog (header endianness unknown, data endianness unknown) i386 l1om k1om plugin tekhex (header endianness unknown, data endianness unknown) i386 l1om k1om plugin binary (header endianness unknown, data endianness unknown) i386 l1om k1om plugin ihex (header endianness unknown, data endianness unknown) i386 l1om k1om plugin elf64-x86-64 elf32-i386 elf32-x86-64 a.out-i386-linux pei-i386 i386 elf64-x86-64 elf32-i386 elf32-x86-64 a.out-i386-linux pei-i386 l1om ------------ ---------- ------------ ---------------- -------- k1om ------------ ---------- ------------ ---------------- -------- plugin ------------ ---------- ------------ ---------------- -------- pei-x86-64 elf64-l1om elf64-k1om elf64-little elf64-big i386 pei-x86-64 ---------- ---------- elf64-little elf64-big l1om ---------- elf64-l1om ---------- elf64-little elf64-big k1om ---------- ---------- elf64-k1om elf64-little elf64-big plugin ---------- ---------- ---------- elf64-little elf64-big elf32-little elf32-big pe-x86-64 pe-i386 plugin srec symbolsrec i386 elf32-little elf32-big pe-x86-64 pe-i386 ------ srec symbolsrec l1om elf32-little elf32-big --------- ------- ------ srec symbolsrec k1om elf32-little elf32-big --------- ------- ------ srec symbolsrec plugin elf32-little elf32-big --------- ------- ------ srec symbolsrec verilog tekhex binary ihex i386 verilog tekhex binary ihex l1om verilog tekhex binary ihex k1om verilog tekhex binary ihex plugin verilog tekhex binary ihex