2019年1月31日木曜日

gccで指定したアーキテクチャのバイナリをコンパイルする方法



自作エミュレータで学ぶx86アーキテクチャ コンピュータが動く仕組みを徹底理解!
という本を買って、はじめの部分を読んでいると実機と本とで出力される内容が違った部分にいきなり出くわしたので、その解決法をメモしていく。

注意点


原因はこちらが使っているCPU(x86_64)のアーキテクチャが本が想定しているもの(i386)と違うのが原因なので、本が誤っているわけではないので注意!


解決法


gccとldそれぞれにi386で処理してくれとオプションを指定することで解決できた。

gcc -c -o xxx.o input-file.c ..なんか色々なオプション.. -m32 -fno-pie
ld ..なんか色々なオプション.. -m elf_i386 --oformat=binary

GCC

gccのオプション-m32を指定することで、32bit環境のコードを生成してくれるようになる。
-m32のドキュメントはこちら

ただこれだけだと、 ldコマンドで

undefined reference to `_GLOBAL_OFFSET_TABLE_'

とエラー起きたので、 -fno-pieも追加で指定する必要がある。

gccはデフォルトでposition-independent executables (PIE)と呼ばれるプログラムコードが実際に動作するPC上のメモリの好きなところに配置されても正しく実行できるようにしている。

が、その分余分なコードを生成するのだが、今回は勉強のためなのでそのような仕組みはいらず、-fno-picを指定して上げる必要があった。

ld

ldでも-mオプションでエミュレートしたい環境を指定する。指定できるものはld -Vで確認できる。

今回は32bit環境なので、ld -Vにあったelf_i386を指定した。

--oformatオプションは出力されるオブジェクトファイルのバイナリフォーマットを指定するものだ。

指定できるものはobjdump -iで確認できる。binaryは何でもいいよ的なもの。



0 件のコメント:

コメントを投稿