binutils の target
正確に binutils や gcc が許容するものを書かないといけない。たとえば、microblaze-uclinux と最初していたのだが、gcc の configure のパターンマッチングが -linux を認識するようになっていて、これにより適切な SPEC を含む linux 用のソースが選択される。したがって、microblaze-linux にしなければならない。
さらに、binutils の ld/configure は与えられた target と config.sub の target が一致したときのみ(なぜ?), EMUL を設定する。config.sub microblaze-linux とすると microblaze-unknown-linux-gnu が返ってきてしまう。だから、microblaze-
EMUL が configure で設定されると DEFAULT_EMULATION がコンパイル時に指定される。これは Makefile の EMUL をみればよい。
EMUL = elf32mb_linux EMULATION_OFILES = eelf32mb_linux.o EMUL_EXTRA_OFILES =
正しければ ld/Makefile に上のように elf32mb_linux が設定される。これが設定されていないと、コンパイル時に
microblaze-unknown-linux-gnu/bin/ld: unrecognised emulation mode: Supported emulations: elf32mb_linux
これは ld がわの emulation という変数に何も設定されていないので何を作ったらいいかわからない、ld 側が用意しているのは elf32mb_linux だといっている。説明が前後するが、emulation という変数は、環境変数(EMULATION_ENVIRON)、LD の引数、最後に default の設定を見る。MB の gcc の SPEC では明示的に何も渡していない(microblaze-*-gcc -dumpspecs で確認可能)ので結局 default が使用される。しかし、上の configure での設定で最終的に EMUL が設定されないというのがあり、このような結果になる。(日本語がわかりづらい)
target をちゃんと設定しようというのは考えてみれば当たり前の話かも、、、
でも何が正しいかは”ソースを追わないとわからない”。みんなきっといい加減にやっているんだ。
ついでにかくと、明示的に
microblaze-linux-gcc -Wl,-melf32mb_linux
なんてすると ld に emulation の設定が渡る。こうすればうまくいきそうな気もするが結果は
/opt/xtools/uclinux-uclibc/lib/gcc/microblaze-linux/4.1.2/../../../../microblaze-linux/bin/ld: /tmp/main: Not enough room for program headers (allocated 3, need 4) /opt/xtools/uclinux-uclibc/lib/gcc/microblaze-linux/4.1.2/../../../../microblaze-linux/bin/ld: final link failed: Bad value collect2: ld はステータス 1 で終了しました
となる。同じ ld を xilinx 提供の gcc で (unknown と gnu が違う、、、)
microblaze-unknown-linux-gnu-gcc -Wl,-melf32mb_linux
とするとうまくいくので gcc 側もなんか違うコードをはいているようだ。これを調べるのは馬鹿らしいから、まずは環境の作り直しということになる。
ついでのついでにかくと、xilinx の binutils/gcc のソースを現在の私の環境でコンパイルしようとすると gcc をコンパイルしているときに ar が stack over flow してしまう。どうやら sprintf でバッファーオーバーフローする模様。gcc の 4.1.? からかバッファーオーバーフロー(BOF)対策が盛り込まれてしまったおかげで、そのコンパイラでコンパイルされたオブジェクトである ar が動かなくなったのだ。バグっていてもうごけばいいのに、、、
なので、gcc の 3.4.6 を使うとうまくいく。gcc の 4系でも、もちろん BOF のチェックを ignore することもできる。
gcc -fno-stack-protector main.c -o main
こんな感じ。でもって、binutils のコンパイル時に CFLAGS="-O2 -fno-stack-protector" を与えればよかろうとおもってやってみたが、だめだった。これは私のオペミスの可能性がある。できるはずだから。原因は分かったのでそこまでする必要はなかろうと思い、gcc の 3.4.6 をインストールして使う方向で解決した。
やれやれだぜ。