ローリングコンバットピッチなう!

AIとか仮想化とかペーパークラフトとか

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でコンパイルされました。

ちなみにCentOSRed Hat Linuxだとインストールするパッケージ名が異なっていて、下記らしいですが動作確認はしていません。

$ yum -y install glibc-devel.i686 glibc-devel libstdc++-devel.i686