GASと疑似命令
Gnu Tarが1.22になって、Jオプションというかxz圧縮に対応した。
tarでJオプションを試そうとすると、どうも内部ではxzコマンドを呼び出しているらしい。
そこで、cygwin上でxz 4.999.8betaをコンパイルしようとしたところ、コンパイルエラーが起きた。
原因
makeしてみると、以下のようなメッセージが発生する
/bin/sh ../../../libtool --mode=compile gcc -std=gnu99 -DHAVE_CONFIG_H -I. -I. ./../.. -I../../../src/liblzma/api -I../../../src/liblzma/common -g -O2 -MT l ibcheck_la-crc32_x86.lo -MD -MP -MF .deps/libcheck_la-crc32_x86.Tpo -c -o libche ck_la-crc32_x86.lo `test -f 'crc32_x86.S' || echo './'`crc32_x86.S gcc -std=gnu99 -DHAVE_CONFIG_H -I. -I../../.. -I../../../src/liblzma/api -I../. ./../src/liblzma/common -g -O2 -MT libcheck_la-crc32_x86.lo -MD -MP -MF .deps/li bcheck_la-crc32_x86.Tpo -c crc32_x86.S -DDLL_EXPORT -DPIC -o .libs/libcheck_la- crc32_x86.o crc32_x86.S: Assembler messages: crc32_x86.S:73: Warning: .type pseudo-op used outside of .def/.endef ignored. crc32_x86.S:73: Error: junk at end of line, first unrecognized character is `_' crc32_x86.S:276: Warning: .size pseudo-op used outside of .def/.endef ignored. crc32_x86.S:276: Error: junk at end of line, first unrecognized character is `_' make[4]: *** [libcheck_la-crc32_x86.lo] Error 1 make[4]: Leaving directory `/usr/local/src/xz/xz-4.999.8beta/src/liblzma/check' make[3]: *** [all-recursive] Error 1 make[3]: Leaving directory `/usr/local/src/xz/xz-4.999.8beta/src/liblzma' make[2]: *** [all-recursive] Error 1 make[2]: Leaving directory `/usr/local/src/xz/xz-4.999.8beta/src' make[1]: *** [all-recursive] Error 1 make[1]: Leaving directory `/usr/local/src/xz/xz-4.999.8beta' make: *** [all] Error 2
gccでコンパイルしているので、アセンブラ部分はGASで処理される。
問題が発生しているのは73行目
.type LZMA_CRC32, @function
と276行目、
.size LZMA_CRC32, .-LZMA_CRC32
の部分。
pseudo-opとは、疑似命令の事だからして、どうやらtype疑似命令とsize疑似命令が問題のようだ。
defineされた中身はどうなっているのだろう
実際にプリプロセッサを展開した後はどうなるのか、一つ前の助言を参考にしつつ、確認。
.globl _lzma_crc32 .type _lzma_crc32, @function .align 16 _lzma_crc32:
(空行は省略しました)
正常に出ているくさいが、ダメだという。
そもそも、Bunutils - as .type疑似命令の解説を見ると、
.type name , type description (ELF version)
となっている。
.size疑似命令の解説でも、
.size name , expression (ELF version)
となっており、このELF用の利用法を選択しているのが問題なのだろう。
つまり「(ELF version)」と書いているところから、Cygwin用ではない。
Cygwinが出力するバイナリはCOFFだからして、「#if defined(__CYGWIN__)」などとして正しい定義をすればいいのだろう。
一難去ってまた一難
以上を見てみて、Windowsと同じ形式にすればよさそうということで、コードに変更を加えてみた。
src/liblzma/check/crc32_x86.S の 72行目と270行目にCygwinもWindowsと同じように処理をするように追記。
そしてmakeすると
/usr/lib/gcc/i686-pc-cygwin/3.4.4/../../../../i686-pc-cygwin/bin/as: BFD (GNU Binutils) 2.18.50.20080625 assertion fail /netrel/src/binutils-20080624-2/bfd/coff-i386.c:579 crc32_x86.S: Assembler messages: crc32_x86.S:117: Error: cannot represent relocation type BFD_RELOC_386_GOTPC make: *** [libcheck_la-crc32_x86.lo] Error 1
またコンパイルエラーで落ちてしまった。
解決できず
BFDで再配置が云々といわれているけど、メモリ上の再配置の話だろうか。
あいにくこの周りの知識はほとんどない。
そもそも、上のWindowsと同じ処理にして合っているのかどうかも分からない。
ん〜。とりあえずCOFFのフォーマットから勉強してみるとしましょうか。