2009年8月12日水曜日

Assembler messages: Error: suffix or operands invalid for `push'

特殊な状況ですが・・・



  • かなり古いkernel-2.4系のi386なLinuxマシンで、pkgsrcでgccをビルドしてあった


  • (ちょっと古いけど)x86_64なLinuxマシン上で、上記gccを用いて、


  • とりあえずこんなサンプルプログラムを、コンパイル


% cat hello.c
#include <stdio.h>



int
main( int argc, char* argv[] )
{
    printf("hello world\n");
    return 0;
}



gccでコンパイルしてみると



% gcc hello.c
/tmp//ccMnfFZA.s: Assembler messages:
/tmp//ccMnfFZA.s:9: Error: suffix or operands invalid for `push'



というようなエラーメッセージが出ました。



ここで使っているgccは、冒頭で述べたように、i386な環境でビルドしたgcc。



% which gcc
/usr/pkg/gcc34/bin/gcc



どうも、

Error: suffix or operands invalid for `push'

というメッセージが出るのは、32bit環境のgccで生成されたアセンブラコードが、64bit環境のアセンブラで処理されて、エラーとなっている・・・らしいです。





とりあえずの解決方法



謎のオプションをつけます。



% gcc -m32 -Wa,--32 hello.c
/usr/bin/ld: skipping incompatible /usr/lib64/libc.so when searching for -lc
/usr/bin/ld: skipping incompatible /usr/lib64/libc.a when searching for -lc



なにやらメッセージが出ていますが、これはエラーではないようなので、無視してよさそうです。



% ./a.out
hello world



というわけで、コンパイルしてできたバイナリも、一応動きました。



  • 「-m32」は、32bitコードを生成しなさい、のオプション


  • 「-Wa」は、アセンブラ(GNU as)へ渡すオプションを指定するもので、asに「--32」が渡る


  • 「--32」は、i386において、32bit用で処理する、みたいな意味のオプションらしい。as --helpでは表示されないけど、asのinfoには掲載されている




別の解決方法を考えて見ました。

そもそも



  • pkgsrcのgcc


  • OSのas


という、素性の異なるものを混在して使っているのが気持ち悪いです。

じゃあ、ってことで

/usr/pkgsrc/devel/binutils

をインストールしてみました。pkgsrcのデフォルト設定のままでは、

/usr/pkg/bin/gnu-addr2line  /usr/pkg/bin/gnu-ld       /usr/pkg/bin/gnu-readelf
/usr/pkg/bin/gnu-ar         /usr/pkg/bin/gnu-nm       /usr/pkg/bin/gnu-size
/usr/pkg/bin/gnu-as         /usr/pkg/bin/gnu-objcopy  /usr/pkg/bin/gnu-strings
/usr/pkg/bin/gnu-c++filt    /usr/pkg/bin/gnu-objdump  /usr/pkg/bin/gnu-strip
/usr/pkg/bin/gnu-gprof      /usr/pkg/bin/gnu-ranlib

という名前で、一連のツールがインストールされました。gnu-asがgccから実行されるようにしなくちゃなりません。

「gcc -v hello.c」とかやると気がつきますが、

/usr/pkg/gcc34/lib/gcc/i686-pc-linux-gnu/3.4.6/specs

というようなファイルがあって、その中に、アセンブラを起動する方法が指定されています。そこを、こんな風に変更します。asをgnu-asに置き換えただけです。

*invoke_as:
%{!S:-o %|.s |
gnu-as %(asm_options) %|.s %A }

システム全体で使われているファイルを直接書き換えてしまうのも気持ち悪いので、別のファイル(たとえば/tmp/specs)にしておいて、

% gcc -specs=/tmp/specs hello.c

みたいに使わせることもできます。

これで、「-m32 -Wa,--32」が不要になりました。

「-v」オプションをつけて、

gcc -v -specs=/tmp/specs hello.c

と実行すれば、たくさん表示されるメッセージの中に、

GNU C version 3.4.6 (i686-pc-linux-gnu)
        compiled by GNU C version 3.4.6.
GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072
gnu-as -V -Qy -o /tmp//ccg6llBp.o /tmp//ccxsSXGL.s
GNU assembler version 2.17 (i386-debian-linux) using BFD version 2.17

というメッセージもあって、gnu-asが使われているのを発見できます。



0 件のコメント:

コメントを投稿