Can gcc generate different size object code? - c

Which option should be enabled in gcc to generate 16-bit or 32-bit or 64-bit object code ? Are there separate options for generating each of the above object code type ?

The bitness of the generated object code is determined by the target architecture selected when gcc was built. If you want to build for a different platform, you should build a cross compiler for your desired target platform.
Note, however, that GCC does not support 16-bit x86, and that if both 32-bit and 64-bit x86 compilers are installed, as an exception, you can use -m32 or -m64 to select the desired target format.

To force gcc to generate 32-bit code you would give it the -m32 flag. To force it to generate 64-bit code you would give it the -m64 flag. I don't know of any option for 16-bit.

Related

How can i emulate an x86 32 bits program on an ARM host?

I am running a Kali Linux distribution on an arm cpu (aarch64).
I have successfully install x86_64-linux-gnux32-gcc and x86_64-linux-gnu-gcc.
I have wrote a basic c program:
#include <stdio.h>
void main()
{
printf("Hello world\n");
}
I have compiled 2 versions:
x86_64-linux-gnu-gcc test1.c -o test1_64
x86_64-linux-gnux32-gcc test1.c -o test1_32
The first binary (64 bits) works fine when i run it with this command:
qemu-x86_64-static ./test1_64
But i have an error with the second binary (32 bits):
qemu-x86_64-static ./test1_32
qemu-x86_64-static: ./test1_32: Invalid ELF image for this architecture
I have tried to force a 32 bits cpu with this command:
qemu-x86_64-static -cpu qemu32 ./test1_32
I have also tried to compile the binary with -static option. I got the same result.
How can i run my 32 bits executable ?
Thanks a lot
x86_64-linux-gnux32-gcc is not what you want for building 32-bit programs. This is actually a 64-bit compiler that targets the x32 ABI, a scheme to have 64-bit code that needs only 32 bits for pointers. It never really caught on and is fairly obscure these days, so I'm not surprised that qemu wouldn't support it.
The x86_64 target of gcc supports building 32-bit programs as well, using the -m32 option. So you ought to be able to build your 32-bit Hello World with
x86_64-linux-gnu-gcc test1.c -o test1_32 -m32
(You might have to separately install 32-bit x86 libraries to successfully cross compile.)
Then to run it, use qemu-i386 instead of qemu-x86_64.
file ./test1_32 should show you that you've still made an x86-64 executable, not i386, with a compiler for the x32 ABI as Nate noticed.
Unfortunately the file output says "ELF 32-bit LSB executable, x86-64, version 1 (SYSV), ..." so the 32-bit part could be misleading.
An actual 32-bit build has "ELF 32-bit LSB executable, Intel 80386,".
A single install of GCC/GAS can build for 32 or 64-bit x86, unlike for ARM32 vs. AArch64 where you need different builds of GCC, so I expect that was part of the confusion. GCC treats i386 and x86-64 as flavours of the same architecture, while AArch64 is treated as a totally separate architecture from ARM. (IDK if GCC did that because x86-64 machine code is similar to 32-bit, so the same assembler can pretty easily handle both. But AArch64 uses a totally different machine code format from ARM32, no point in trying to share code in the assembler between the two architectures.)
So you were probably expecting to need a GCC with 32 in its name to make 32-bit x86 executables. That is not the case.

Wrong ELF class with both 32 and 64bits lib

I am trying to solve a challenge by using LD_PRELOAD to load my own strcmp library.
I first tried to compile my library with gcc -shared -fPIC strcmp.c -o strcmp.so, but when I tried to execute my file with LD_PRELOAD=/path/to/lib/strcmp.so ltrace ./exec, I had a the error :
object '/path/strcmp.so' from LD_PRELOAD cannot be preloaded (wrong ELF class: ELFCLASS64): ignored
By comparing file /path/to/strcmp.so and file exec, I found out that my exec file was a ELF 32-bit LSB executable and that my lib was a ELF 64-bit LSB shared object.
Then I tried to compile my lib with gcc -m32 -shared -fPIC strcmp.c -o strcmp.so, but when executing I have the same error (but this time with ELFCLASS32) :
object '/path/strcmp.so' from LD_PRELOAD cannot be preloaded (wrong ELF class: ELFCLASS32): ignored
Any suggestions? How can I have the same error with both 32 and 64 bits version of my lib?
As you noticed, if you have a single 32-bit shared library, you will get that warning when 64-bit programs are run. If you have a single 64-bit library, you get that warning when you run 32-binaries. We need your system to have both 32- and 64-bit versions of your libraries, and to allow the system to choose which one to use as needed. You can accomplish that with the following changes:
Compile both a 32-bit and 64-bit version of your library, and put them in /usr/lib and /usr/lib64 respectively on RedHat-based systems. Debian uses a different library naming scheme which unfortunately is not very consistent, so I'll leave it an exercise for the reader to determine the right place to put the two libraries on Debian systems.
Change your preload to remove all paths, like so: export LD_PRELOAD=strcmp.so This will allow the system to search only the correct library directory when it looks for a 32-bit or 64-bit library.
If you want to patch only one architecture, say 32-bit, then compile a 32-bit version of your library, and then compile an empty file into a 64-bit shared library of the same name. Place them both as described above.
Note that this only works if you use the system library directories. Even /usr/local/lib and /usr/local/lib64 are not allowed.
You should run 32-bit dynamic linker directly:
ltrace /lib/ld-linux.so.2 --preload /path/to/lib/strcmp.so ./exec

Is i686 32 bit? Why does my gcc/g++ fail compiling .cpp and .c files?

I am trying to compile a helloworld.c code
#include<stdio.h>
int main(){
printf("Hello World");
return 0;
}
on a Linux machine. Below is the uname- a result for the machine, which states that the machine is 64 bit.
uname-a : Linux pascal 2.6.32-358.23.2.el6.x86_64 #1 SMP Sat Sep 14 05:32:37 EDT 2013 x86_64 x86_64 x86_64 GNU/Linux
On running the gcc command I am getting the following errors:
[pascal]/user/gasharma/workspaceC++:/>gcc -c helloworld.c
/tmp/ccpg1Atk.s: Assembler messages:
/tmp/ccpg1Atk.s:11: Error: suffix or operands invalid for `push'
/tmp/ccpg1Atk.s:12: Error: suffix or operands invalid for `push'
/tmp/ccpg1Atk.s:14: Error: suffix or operands invalid for `push'
/tmp/ccpg1Atk.s:20: Error: suffix or operands invalid for `pop'
/tmp/ccpg1Atk.s:21: Error: suffix or operands invalid for `pop'
Here is the output for gcc -v:
[pascal]/user/gasharma/workspaceC++:/>gcc -v
Using built-in specs.
Target: i686-pc-linux-gnu
Configured with: ../gcc-4.2.4/configure --prefix=/usr/local --with-gmp=/usr/local --with-mpfr=/usr/local
Thread model: posix
gcc version 4.2.4
On closer inspection of the above, I do see that the target is i686 (which I am not sure is 32 or 64 bit). My strong guess is that it is 32 bit. I Googled for sometime and results indicated that the problem could be with the 32 bit compiler on 64 bit machine. However, some results also pointed at use of -m32 and -m64 options to execute a successful compile run.
I did a gcc run with -m64 and it resulted in the below error.
[pascal]/user/gasharma/workspaceC++:/>gcc -c -m64 helloworld.c
helloworld.c:1: sorry, unimplemented: 64-bit mode not compiled in
I have six questions here:
1) i686 in the target represents 32 or 64 bit machine? How can I make that distinction? Generally i386 refers to 32bit and x86_64 to 64 bit.
2) How can I run a simple helloworld.c in my case? When, why and how do I use -m32 and -64 options?
3) Does this have something to do with the assembler or compiler?
4) What does "sorry, unimplemented: 64-bit mode not compiled in" imply?
5) What is the meaning of "Configured with: ../gcc-4.2.4/configure --prefix=/usr/local --with-gmp=/usr/local --with-mpfr=/usr/local"?
6) Why the target machine is not x86_64 under the gcc when I am running 64 bit machine?
I will really appreciate someone taking time and answering my above questions. Thanks in advance!
i686 is a reference to the Intel CPU architecture used for the the Pentium Pro and Pentium II processors. It also means that the target is 32-bit x86 code instead of 64-bit x86 code.
You need to fix your installation, as the installed compiler is incompatible with the installed assembler. You don't need to use either -m32 or -m64 option to compile a hello world program.
The problem is that your compiler isn't compatible with your assembler. Your compiler is only capable of generating 32-bit code, but your assembler assumes 64-bit code by default. Your compiler incorrectly assumes that your assembler defaults to 32-bit and so doesn't pass the necessary option that would allow the assembler to work with 32-bit code.
It means that your compiler isn't capable of generating 64-bit code.
The first step of of building GCC, the compiler you're using, is to run the configure script included with the source code. This line shows how that configure script was run, including what arguments were used.
Because the installed version of GCC on your computer was built to only target 32-bit. It will run on a x86_64 CPU in 32-bit mode, and, with a compatible assembler, it can generate code that will run on a x86_64 CPU in 32-bit mode.
I have no idea why your compiler and/or assembler were installed incorrectly or how to fix it.

Format for setting Optimization flags in cBench

I am new to Compiler related work. I want to analyse some source code before and after optimising with -O1, -O2, -O3 flags. I am using Intel's PIN tool for analysis purposes. I am using source code from cBench Benchmark suite. But I am not getting that how to set optimization option in that.
Tutorial of cBench mentions following statement.
use __compile batch script with compiler name as the first parameter to compile the benchmark with a specific compiler, i.e. gcc, open64, pathscale or intel. In the second parameter you can specify optimization flags.
So I compile every source code with these three optimization flags as follows
./__compile gcc -O3
./__compile gcc -O2
./__compile gcc -O1
But when I analyse the object file in PIN tool, I am not able to find any difference in any of the 24 program set of cBench.
What is the point where I am missing.?

GCC m68k pc-relative

I was using a Microtek toolchain to generate an executable binary with relocatable code (pc-relative) and data from a fixed address (Absolute data). Today, this toolchain does not work on Windows 7 64 bits. The idea is to replace Microtek toolchain for 68000 with the GNU toolchain (GCC 4.8.0).
But I can not find the same options on the gcc compiler:
Microtec compiler "MCC68K" with:
"-Mcp": Directs the compiler to use PC-relative addressing for all code references.
"-Mda": Directs the compiler to use absolute addressing for all data references.
Gcc (m68k-elf-gcc) with:
-mpcrel
Unable to build with gcc relocatable code with no relocatable data as the Microteck compiler. With "-mpcrel", all is relocatable (code and data).
do you have an idea?
Sorry for my bad english.
Thanks.
As far as I know, there is no way to achieve the same result with the GNU m68k toolchain.
-mpcrel will generate fully position-independent code with
pc-relative adressing for code as well as for data, resulting in a
limited program/data size (pc-relative offsets cannot exceed 16 bits).
-fpic and -fPIC will generate position independent code with
relocatable binaries but will require a special loader that does the in-place relocation
From gcc docs
-fpic Generate position-independent code (PIC) suitable for use in a shared library,...
-fPIC If supported for the target machine, emit position-independent code, suitable for dynamic linking and avoiding any limit on the size
of the global offset table.
Also try to search

Resources