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行目にCygwinWindowsと同じように処理をするように追記。
そして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のフォーマットから勉強してみるとしましょうか。