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