自己完結型のソースファイルからフラットなバイナリファイルを生成するようにgccを説得するコマンドラインオプションのセットはありますか?たとえば、foo.cの内容が次のようになっているとします。
static int f(int x)
{
int y = x*x;
return y+2;
}
外部参照はなく、リンカーにエクスポートするものもありません。この関数のマシン命令だけで、他の装飾なしで小さなファイルを取得したいと思います。 32ビットプロテクトモードを除いて、(DOS).COMファイルのようなものです。
これを試してみてください:
$ cc -c test.c
$ objcopy -O binary test.o binfile
objdump
で正しいことを確認できます:
$ objdump -d test.o
test.o: file format pe-i386
Disassembly of section .text:
00000000 <_f>:
0: 55 Push %ebp
1: 89 e5 mov %esp,%ebp
3: 83 ec 04 sub $0x4,%esp
6: 8b 45 08 mov 0x8(%ebp),%eax
9: 0f af 45 08 imul 0x8(%ebp),%eax
d: 89 45 fc mov %eax,-0x4(%ebp)
10: 8b 45 fc mov -0x4(%ebp),%eax
13: 83 c0 02 add $0x2,%eax
16: c9 leave
17: c3 ret
そして、バイナリファイルと比較してください:
$ hexdump -C binfile
00000000 55 89 e5 83 ec 04 8b 45 08 0f af 45 08 89 45 fc |U......E...E..E.|
00000010 8b 45 fc 83 c0 02 c9 c3 |.E......|
00000018
objcopy
を使用して、.oファイルまたはa.outファイルからテキストセグメントを引き出すことができます。
$ cat q.c
f() {}
$ cc -S -O q.c
$ cat q.s
.file "q.c"
.text
.globl f
.type f, @function
f:
pushl %ebp
movl %esp, %ebp
popl %ebp
ret
.size f, .-f
.ident "GCC: (Ubuntu 4.3.3-5ubuntu4) 4.3.3"
.section .note.GNU-stack,"",@progbits
$ cc -c -O q.c
$ objcopy -O binary q.o q.bin
$ od -X q.bin
0000000 5de58955 000000c3
0000005
$ objdump -d q.o
q.o: file format elf32-i386
Disassembly of section .text:
00000000 <f>:
0: 55 Push %ebp
1: 89 e5 mov %esp,%ebp
3: 5d pop %ebp
4: c3 ret
_-Wl,<linker option>
_を使用して、オプションをリンカに直接渡すことができます。
関連するドキュメントは、以下の_man gcc
_からコピーされています。
-Wl、オプション
オプションとしてオプションをリンカーに渡します。オプションにコンマが含まれている場合、コンマで複数のオプションに分割されます。この構文を使用して、オプションに引数を渡すことができます。たとえば、-Wl、-Map、output.mapは、-Mapoutput.mapをリンカーに渡します。 GNUリンカーを使用する場合、-Wl、-Map = output.mapでも同じ効果を得ることができます。
したがって、gccでコンパイルするときに_-Wl,--oformat=binary
_を渡すと、elf形式の代わりにバイナリファイルが生成されます。ここで、_--oformat=binary
_はld
にバイナリファイルを生成するように指示します。
これにより、個別にobjcopy
する必要がなくなります。
_--oformat=binary
_は、 リンカースクリプト 内からOUTPUT_FORMAT("binary")
として表すことができることに注意してください。フラットバイナリを処理する場合は、リンカスクリプトが提供する高レベルの制御の恩恵を受ける可能性が高くなります。
他の答えは間違いなく行く方法です。ただし、出力を期待どおりにするには、objcopyに追加のコマンドライン引数を指定する必要がありました。私は64ビットマシンで32ビットコードを開発していることに注意してください。したがって、-m32
引数。また、私はintel Assembly構文の方が好きなので、引数にもそれが表示されます。
$ cat test.c
int main() { return 0; }
$ gcc -nostdinc -m32 -masm=intel -Wall -c test.c -o test.o
$ objdump --disassemble --disassembler-options intel test.o
test.o: file format elf32-i386
Disassembly of section .text:
00000000 <main>:
0: 55 Push ebp
1: 89 e5 mov ebp,esp
3: b8 00 00 00 00 mov eax,0x0
8: 5d pop ebp
9: c3 ret
わかりました。ここで、特に.textセクションのみが必要であることを指定する必要がありました。
$ objcopy --only-section=.text --output-target binary test.o test.bin
$ hexdump -C test.bin
00000000 55 89 e5 b8 00 00 00 00 5d c3 |U.......].|
0000000a
これを理解するまでに、さまざまなオプションを読んで試してみるのに約2時間かかりました。うまくいけば、これはその時間を他の誰かを救うでしょう。