Linux上でgccを使い32bitプログラムを生成する
gcc -m32だけではコンパイルできない
gccには-m32というオプションがあり、これを使うと32bitコードを生成してくれます。
最近のIntel CPUはみんな64bitで、C言語でlongで宣言したものは64bit長になります。
稀に特殊な事情、あるいは32bit時代に作成されたソースコードで64bitだと上手く動作しないものがあり、32bitバイナリを生成したい場合があります。
#include <stdio.h> int main(int argc,char *argv[]) { printf("Hello World!!\n"); return 0; }
これはお馴染みのHello Worldですが、これを
$ gcc -m32 hello.c -o hello32
とやると32bitでコンパイルするはずですが、実際にUbuntu18.04LTS上でやってみると、
$ gcc -m32 hello.c -o hello32 In file included from hello.c:1:0: /usr/include/stdio.h:27:10: fatal error: bits/libc-header-start.h: No such file or directory #include <bits/libc-header-start.h> ^~~~~~~~~~~~~~~~~~~~~~~~~~ compilation terminated.
こんな感じでエラーが出ました。
32bit版の開発ライブラリをインストールする
色々調べると32bit版の開発ライブラリをインストールする必要がある様です。
$ sudo apt install libc6-dev-i386
を実行します。
この後、コンパイルすると下記の様にコンパイルに成功します。
$ gcc -m32 hello.c -o hello32 $ ./hello32 Hello World!!
これだけだと32bitか否か判らないので、少しソースを弄ります。
#include <stdio.h> int main(int argc,char *argv[]) { printf("Hello World!!\n"); printf("sizeof(long) = %ld\n",sizeof(long)); printf("sizeof(int ) = %ld\n",sizeof(int)); return 0; }
これを64bitと32bitでコンパイルしてそれぞれ実行します。
32bitでコンパイルする際、printf()のフォーマット文字列で警告が出ますが無視。
$ gcc hello.c -o hello64 $ gcc -m32 hello.c -o hello32 hello.c: In function ‘main’: hello.c:6:27: warning: format ‘%ld’ expects argument of type ‘long int’, but argument 2 has type ‘unsigned int’ [-Wformat=] printf("sizeof(long) = %ld\n",sizeof(long)); ~~^ %d hello.c:7:27: warning: format ‘%ld’ expects argument of type ‘long int’, but argument 2 has type ‘unsigned int’ [-Wformat=] printf("sizeof(int ) = %ld\n",sizeof(int)); ~~^ %d $ ./hello64 Hello World!! sizeof(long) = 8 sizeof(int ) = 4 $ ./hello32 Hello World!! sizeof(long) = 4 sizeof(int ) = 4
こんな感じで、longのバイト数が64bitは8byte,32bitは4byteでコンパイルされました。
ちなみにCentOSやRed Hat Linuxだとインストールするパッケージ名が異なっていて、下記らしいですが動作確認はしていません。
$ yum -y install glibc-devel.i686 glibc-devel libstdc++-devel.i686