Compiling 32-bit programme on 64-bit GCC in C & C++

Compile a 32-bit program on 64-bit GCC in C and C++
Compile a 32-bit program on 64-bit GCC in C and C++

Nowadays the compiler comes with a default 64-bit version. Sometimes we need to compile and execute code into some 32bit system. In that time, we have to use this feature. But it would lead to a problem if someone wants to run their program as a 32-bit rather than 64-bit for testing or debugging purposes. Therefore, we must have knowledge about this.

At first, we have to check the current target version of the GCC compiler. To check this, we have to type this command.

Compilers (64-Bit) for Linux: The following companies provide 64-bit compilers for Linux.

1. GCC: It provides C, C++ and Fortran compilers for AMD64 architecture-based systems running the Linux or the Sun Solaris operating systems. This application note, however, does not discuss GCC compilers for Sun Solaris; this discussion is limited to the discussion of GCC compilers for Linux. Different Linux distributions offer different versions of the GCC compilers.

 This application note focuses on the recommended compilers for the following major Linux distributions:

  • SuSE Linux Enterprise Server 8
  • SuSE Linux Enterprise Server 9
  • SuSE Linux Enterprise Server 10
  • SuSE Linux 10.1
  • SuSE Linux 10.2

GCC-V

Using built-in specs
COLLECT_GCC=gcc
COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-linux-gnu/7/lto-wrapper
OFFLOAD_TARGET_NAMES=nvptx-none
OFFLOAD_TARGET_DEFAULT=1
Target: x86_64-linux-gnu
………..
………..
………..

Hence the fourth line Target: x86_64-Linux-gnu confirms that we are running 64-bit GCC. Now in order to compile with 32-bit GCC, just add a flag -m32 in the command line of compiling the ‘C’ language program. For instance, to compile a file of geek.c through Linux terminal, you must write the following command with -m32 flag.

Sometimes, this command may generate some error like below. This indicates that the standard library of GCC is missing. In that situation, we have to install them.
In file included from test_c.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.

Now, to install the standard library for gcc, we have to write the following commands.

  • sudo apt-get install GCC-multilib
  • sudo apt-get install g++-multilib
  1. Intel: It provides C, C++ and Fortran compilers for EM64T and compatible architecture-based systems running the Linux operating systems. The current version (as of August 2007) is 10.0.
  2. PathScale: It provides C, C++ and Fortran compilers for AMD64 architecture-based systems running the Linux operating system. The current version (as of August 2007) is 3.0.
  3. PGI: The Portland Group (PGI) Toolkits are composed of high-performance C, C++ and/or Fortran Compiler(s), a debugger, and a performance profiler for 32-bit and 64-bit AMD64 and EM64T processor-based Linux. The latest PGI Edition 7 provides leading-edge application performance on AMD64 next-generation systems and supports features like auto-parallelization, OS-native multithreading, OpenMP multithreading models, and MPI programming for AMD64 architecture based multicore shared-memory and distributed-memory cluster-based systems.

Compilers (64-Bit) for Microsoft Windows

The following companies provide 64-bit compilers for Microsoft Windows.

  • Intel: It provides C/C++ and Fortran compilers for EM64T and compatible systems running the Microsoft Windows operating system.
  • Microsoft: It provides C/C++ compilers for AMD64 architecture-based systems running the Microsoft Windows operating system. The current version is Visual Studio 2008.
  • PGI: The Portland Group (PGI) Toolkits are composed of high-performance C, C++ and/or Fortran Compiler(s), a debugger and a performance profiler for 32-bit and 64-bit AMD64 and EM64T processor-based Windows platforms. The latest PGI Edition 7 provides leading-edge application performance on AMD64 next-generation systems and supports features like auto-parallelisation, OS native multithreading, OpenMP multithreading models, and MPI programming for AMD64 architecture-based multicore shared-memory and distributed-memory cluster-based systems.

Compilers (32-Bit) for Linux: The following companies provide 32-bit compilers for x86 Linux. These compilers also run on 64-bit Linux Operating systems, running on AMD Athlon 64 processor-based platforms, AMD Opteron™ processor-based platforms, or AMD Family 10h processor-based platforms.

  • GCC: The GCC provides C, C++ and Fortran compilers for x86 Linux and Sun Solaris. This application note, however, does not discuss the GCC compilers for Sun Solaris; it discusses only GCC compilers for Linux. Different Linux distributions offer different versions of the GCC compiler. This application note focuses on the recommended compilers for the following major Linux distributions for workstations and servers—SuSE Linux Enterprise Server 8, SuSE Linux Enterprise Server 9, SuSE Linux Enterprise Server 10, SuSE Linux 10.1, SuSE Linux 10.2, Red Hat Enterprise Linux 3 and Red Hat Enterprise Linux 4. This application note also briefly discusses the GCC 4.2 compiler, which is the current GCC version from the Free Software Foundation (FSF).
  • Intel: It provides C, C++ and Fortran compilers for x86 Linux. This document also talks about two previous versions of the compiler, 9.1 and 8.1, because they are comparable in performance to the current version (when running on AMD platforms) and are still in use.
  • PathScale: It provides C, C++ and Fortran compilers for x86 Linux.

Compilers (32-Bit) for Microsoft Windows: The following companies provide 32-bit compilers for Microsoft Windows.

  • Intel: It provides C, C++ and Fortran compilers for x86 Microsoft Windows. This document also talks about two previous versions of the compiler, 9.1 and 8.1, because they are comparable in performance to the current version and are still in use.
  • Microsoft: It provides C/C++ compilers for x86 Microsoft Windows.
  • PGI: The Portland Group (PGI) Toolkits are composed of high-performance C, C++ and/or Fortran Compiler(s), a debugger, and a performance profiler for 32-bit and 64-bit AMD64 and EM64T processor-based Windows platforms. The latest PGI Edition 7 provides leading-edge application performance on AMD64 next-generation systems and supports features like auto-parallelization, OS native multithreading, OpenMP multithreading models, and MPI programming for AMD64 architecture-based multicore shared-memory and distributed-memory cluster-based systems.

How to check whether a program is compiled with 32-bit after adding a “-m32” flag?
We can easily check this by the following programme.

filter_none
edit
play_arrow

brightness_5
// C program to demonstrate difference
// in output in 32-bit and 64-bit gcc
// File name: geek.c

#include<stdio.h>

int main()
{
printf(“Size = %lu”, sizeof(size_t));
}

Compile the above program in Linux by these two different commands, Default 64-bit compilation.

Input: gcc -m64 geek.c -o out
Output: ./out
Size = 8
Forced 32-bit compilation,

Input: gcc -m32 geek.c -o out
Output: ./out
Size = 4

Some Other Methods Are:

This really depends on the application and how it has been coded. Some code can just be recompiled with a 64-bit compiler and it will just work, but usually, this only happens if the code has been designed with portability in mind.

If the code has a lot of assumptions about the size of native types and pointers, if it has a lot of bit packing hacks or of it talks to an external process using a byte specified protocol but using some assumptions about the size of native types then it may require some, or a lot, of work to get a clean compile.

Pretty much every cast and compiler warning is a red flag that needs checking out. If the code wasn’t “warning clean” to start with then that is also a sign that a lot of work may be required.

Well, fundamentally, the number of changes are fairly small, but it’ll still be a major task if the application isn’t carefully written to be somewhat portable to begin with.

The main difference is that pointers are 64 bit wide, but most other data types are unchanged. An int is still 32 bit and a long is probably also still 32 bit. So if your code casts between ints and pointers, that’s going to break. Similarly, any struct or similar which depends on a specific offset to a member may break because other members may now be bigger, and so change the offset.

To read more about C++, click here.

By Akhil Sharma