GCC output file's size seems too big - c

I have the following code(file.c):
int main() {}
I go gcc file.c, and the output file file.exe is 26.5KB
I also tried with -O2, -Ofast, -Os but the size stays the same. I have included no headers, nothing; I even tried putting int main(void) {}.
Shouldn't the output file be roughly 1KB? [I am using Windows 10 - GCC 4.8.1]
Context:
I am trying to understand how PE files work in windows, and so far, I think I have a great grasp of the concept, so I wanted to run some tests because I want to be able to take code from another file, lets say file2.exe, and try to sneak it inside file.exe with OllyDBG. But since this pretty much NULL code yields a freaking 26.5KB, I really dont know what to do...

there are a LOT of items that get added to a file to make it executable.
In the following example, on Linux 16.04
gcc version: gcc (Ubuntu 5.4.0-6ubuntu1~16.04.9) 5.4.0 20160609
I wrote the following source in a
file named untitled2.c
int main(void)
{
}
Then compiled it into untitled2.o
gcc -ggdb -Wall -Wextra -Wconversion -std=gnu11 -pedantic -Wmissing-prototypes -c untitled2.c -o untitled2.o -I.
then linked it into untitleed2
gcc -ggdb -std=gnu11 -o untitled2 untitled2.o
Here are the results.
-rw-r--r-- 1 rkwill root 22 Mar 21 20:41 untitled2.c
-rw-rw-r-- 1 rkwill rkwill 2608 Mar 21 20:41 untitled2.o
-rwxrwxr-x 1 rkwill rkwill 16904 Mar 21 20:41 untitled2
I.E. the original source file is 22 bytes. The compiled file is 2608 bytes (no optimization parameters) the executable file is 16904 bytes
striping the file (removing the debug info) would reduce the file size slightly, but not enough to eliminate the significant difference in size.

Related

backtrace.dll works with gcc 8 but not gcc 12

I have some C code that is used to print backtrace in console.
I am compiling it using this command:
set PATH = %PATH%;D:\gcc-12.1.0\mingw32\bin
D:\gcc-12.1.0\mingw32\bin\gcc -O2 -shared -Wall -ID:\gcc-12.1.0\mingw32\include backtrace.c -static -o backtrace.dll -L. -lbfd -lz -liberty -limagehlp
The dll compiles with both GCC 8 and GCC 12, but does not load when using GCC 12. It works with GCC 8 regardless of which version was used to compile it.
I can post the code if required.
This is the intended behavior when running with gcc 8
Running with GCC 12
And the abnormal ending happens on line 56
I have tried with different flags, doesn't seem to make a difference, compilation is not the issue, only loading the dll.
Thanks!

Compiling 32-bit app on x86_64 gcc increases app size drastically compared to x32 gcc

I have a small C program that was is intended to be 32-bit app for compatibility. Later I changed my gcc to x86_64 from x32. And now my program compiles in 64-bit app, which I don't won't to be.
I made it compile with -m32 and windres -f 386pe to force 32-bit, but the application size went up from 47 kB to 303 kB. I don't understand why the app became so big even though it's supposed to be the same, or I am doing something wrong with it?
My make file is pretty simple (for old 32 bit gcc):
all: gcc-test
gcc-test: gcc-test.o icon.o
gcc gcc-test.o icon.o -o gcc-test.exe
gcc-test.o: gcc-test.c
gcc -c gcc-test.c
icon.o: icon.rc
windres icon.rc -o icon.o
Now I converted it to x64_86 gcc:
all: gcc-test
gcc-test: gcc-test.o icon.o
gcc -m32 gcc-test.o icon.o -o gcc-test.exe
gcc-test.o: gcc-test.c
gcc -m32 -c gcc-test.c
icon.o: icon.rc
windres -F pe-i386 icon.rc -o icon.o
And when I am doing the already converted makefile for x86_64 on 32-bit gcc it still becomes 47 kB as it's supposed to be. I think that I forgot to pass something else, it may just allocate a lot of memory for x64, while it's not x64 and not required?
I am pretty sure that's very bad, and it shouldn't be so, how do I make it previous size?

Using gcc with multiple files

I am trying to generate an executable file test from a c file test.c.
test.c includes the main() function, but I also want to include functions from stuff.c. I was told to declare functions in stuff.h and then run the command gcc -Wall -std=c99 stuff.c stuff.h test.c -o test.
I know what each component of this does, but this is the first time I've tried to use gcc with multiple input files. When I try to run this command, it fails, and I get the error clang: error: cannot specify -o when generating multiple output files.
As far as I'm aware, I'm only trying to generate one output file, so I assume this command is set up incorrectly. How can I fix it?
Here are your errors
you are not suppose to compile .h files in c so try this:
gcc -Wall -std=c99 stuff.c test.c -o test
gcc depends also on environment that you run it on. On my system if I do gcc -Wall -std=c99 stuff.c stuff.h test.c -o test it will work, because compiler is set that way. On some machines it might be different. So if for some strange reason #1 does not work you have to do following:
gcc -Wall -std=c99 -c stuff.c test.c
gcc -Wall -std=c99 stuff.o test.o -o test
./test
But your error clang: error: cannot specify -o when generating multiple output files is due to some code error, perhaps header file problems. So post your code
The difference seems to be due to a difference of behavior between gcc and clang as shown in the following example.
~/test $ ls -ltr
total 4
-rw-rw-r-- 1 arusaha arusaha 0 Apr 3 13:19 b.h
-rw-rw-r-- 1 arusaha arusaha 0 Apr 3 13:19 b.c
-rw-rw-r-- 1 arusaha arusaha 14 Apr 3 13:20 a.c
~/test $ clang -Wall -std=c99 b.c b.h a.c -o ab
clang: error: cannot specify -o when generating multiple output files
~/test $ gcc -Wall -std=c99 b.c b.h a.c -o ab
~/test $ ls -ltr
total 16
-rw-rw-r-- 1 arusaha arusaha 0 Apr 3 13:19 b.h
-rw-rw-r-- 1 arusaha arusaha 0 Apr 3 13:19 b.c
-rw-rw-r-- 1 arusaha arusaha 14 Apr 3 13:20 a.c
-rwxrwxr-x 1 arusaha arusaha 8576 Apr 3 13:21 ab
~/test $
Compiling multiple files is supported in gcc, see http://www.network-theory.co.uk/docs/gccintro/gccintro_11.html
I was curious how gcc command can throw a clang error and that turned out to be a clue :). It is possible that OP's gcc is pointing to clang (and that can be confusing).
From gcc manpage at http://man7.org/linux/man-pages/man1/gcc.1.html
-o file
Place output in file file. This applies to whatever sort of
output is being produced, whether it be an executable file, an
object file, an assembler file or preprocessed C code.
If -o is not specified, the default is to put an executable file
in a.out, the object file for source.suffix in source.o, its
assembler file in source.s, a precompiled header file in
source.suffix.gch, and all preprocessed C source on standard
output.
From clang manpage at https://clang.llvm.org/docs/CommandGuide/clang.html
-o <file> Write output to file.
To me, the difference of behavior is not exactly clear by just reading the man page but I could be wrong.

Why does compiling a header file with a D option result in a much bigger file than using a C wrapper for the header?

I have this C file that serves as a wrapper for a header file:
#define SOME_CONTROL_FLAG
#include "thefile.h"
If I compile with this:
gcc -I. -c -o thefile.o thefile.c
I get a 9 kB object file. However, if I do this instead:
gcc -I. -c -D SOME_CONTROL_FLAG -o thefile.o thefile.h
I get a 3 MB object file! That's ~300 times larger. Aren't those two command lines supposed to yield the same thing?
In general, compilation with different symbols compiled different code
Consider the following code. If FOOBAR is defined, then there's more code in the file to compile (after the preprocessor preprocesses it):
#ifdef FOOBAR
int foo(int bar) {
return bar + bar;
}
#endif
int bar(int baz) {
return 1+baz;
}
Compiling with FOOBAR defined changes the size of the output. Without FOOBAR, it's 1232, and with FOOBAR, it's 1328. That's not a huge difference, but it is a difference.
$ gcc -c code.c -o code.o
$ ls -l code.o
-rw-rw-r-- 1 user user 1232 Oct 29 13:19 code.o
$ gcc -DFOOBAR -c code.c -o code.o
$ ls -l code.o
-rw-rw-r-- 1 user 1328 Oct 29 13:19 code.o
If there's lots of conditional code, this could be very significant. For instance, defining symbols might cause lots of platform specific code to be included, and not defining symbols might leave function implementations as stubs.
Compiling different types of code produces different code sizes
Note: this portion is based on Urhixidur's (the OP's) answer. I felt that a bit more elaboration on it was in order.
Another aspect that can lead to different compiled object sizes is what GCC is actually compiling. In your example
gcc -I. -c -D SOME_CONTROL_FLAG -o thefile.o thefile.h
a header file is being compiled, and GCC detects that it's compiling with the c-header language based on the file extension. However, the fact that you're compiling a header file and producing a .o file suggests that you want to compile this as C, in which case you should use GCC's -x option. About it the man page says:
-x language
Specify explicitly the language for the following input files (rather than letting the compiler choose a default based on the file name suffix). This option applies to all
following input files until the next -x option. Possible values for language are:
c c-header cpp-output
c++ c++-header c++-cpp-output
objective-c objective-c-header objective-c-cpp-output
objective-c++ objective-c++-header objective-c++-cpp-output
assembler assembler-with-cpp
ada
f77 f77-cpp-input f95 f95-cpp-input
go
java
-x none
Turn off any specification of a language, so that subsequent files are handled according to their file name suffixes (as they are if -x has not been used at all).
Based on this, and the code I used in the first section, we can observe the drastic size difference that happens when we compile your code as c or as c-header:
$ gcc -c code.h -o code.o # as a header
$ ls -l code.o
-rw-rw-r-- 1 user user 1470864 Oct 29 14:04 code.o
$ gcc -c -x c code.h -o code.o # as c code
$ ls -l code.o
-rw-rw-r-- 1 user user 1232 Oct 29 14:04 code.o
Note that compiling (as a header) doesn't seem to be affected by the symbol definition though:
$ gcc -c code.h -o code.o
$ ls -l code.o
-rw-rw-r-- 1 user user 1470864 Oct 29 14:06 code.o
$ gcc -DFOOBAR -c code.h -o code.o
$ ls -l code.o
-rw-rw-r-- 1 user user 1470864 Oct 29 14:06 code.o
Because gcc decides what to do with the input based on its extension, silly me. The true equivalent compilation line is:
gcc -I. -c -D SOME_CONTROL_FLAG -x c -o thefile.o thefile.h
Where -x c tells gcc to treat the .h as a .c
The resulting object files are identical save for one byte, because the file's name is included (in the debug info, I suppose).

How to compile a APR test script

Its a long time since I've used C but now I'm trying to compile a short script that gets server-stats from the Apache-Portable-Runtime (APR).
Header files located at /usr/include/apr-1/apr*.h and libs are located at /usr/lib64/libapr-1.*
Source files can be found on the official APR site http://apr.apache.org/docs/apr/1.3/files.html.
/* test.c */
#include <stdio.h>
#include <stdlib.h>
#include <apr_general.h>
#include <apr_time.h>
int main(int argc, const char *argv[])
{
apr_time_t t;
t = apr_time_now();
printf("The current time: %" APR_TIME_T_FMT "[us]\n", t);
return 0;
}
When I try and compile I get the following error (which I believe is a linking issue):
~> gcc -Wall $(apr-1-config --cflags --cppflags --includes --link-ld) test.c -o test.bin
/tmp/cc4DYD2W.o: In function `main':
test.c:(.text+0x10): undefined reference to `apr_time_now'
collect2: ld returned 1 exit status
My environment is gentoo:
~> uname -a
Linux alister 2.6.32.21-grsec-gt-r2 #1 SMP Tue Sep 7 23:54:49 PDT 2010\
x86_64 Intel(R) Xeon(R) CPU L5640 # 2.27GHz GenuineIntel GNU/Linux`
~> gcc -v
gcc version 4.3.4 (Gentoo 4.3.4 p1.1, pie-10.1.5)
~> emerge --search "%#^dev-lib.*apr"
* dev-libs/apr
Latest version installed: 1.3.9
* dev-libs/apr-util
Latest version installed: 1.3.9
Does anyone with more experience with C on Linux have any suggestions for me to get this working?
As always thanks in advance.
gcc -Wall -I/usr/include/apr-1 -L/usr/lib64 -lapr-1 test.c -o test.bin
-l specifies which shared library to link to, while -L specifies where to look for shared libraries.
APR provides a tool to make this easier, apr-1-config. Something like this should work:
gcc -Wall $(apr-1-config --cflags --cppflags --includes --link-ld) test.c -o test.bin
I finally got around to looking into this.
gcc mentions -l twice in different contexts:
Linker Options
object-file-name -llibrary ...
Directory Options
... -Idir -Ldir ...
so I moved the -llib after the object name (to get the 2nd context) and it compiled!
APR_CFG=$(apr-1-config --cflags --cppflags --includes --link-ld)
gcc -Wall test.c -o test.bin $APR_CFG
./test.bin
The current time: 1332999950442660[us]
I'm not fully sure I understand the linking order and why it didn't work before (if someone could shed some light on that it would be fantastic) but for now I have enough to continue.

Resources