combine two GCC compiled .o object files into a third .o file - gcc

How does one combine two GCC compiled .o object files into a third .o file?
$ gcc -c a.c -o a.o
$ gcc -c b.c -o b.o
$ ??? a.o b.o -o c.o
$ gcc c.o other.o -o executable
If you have access to the source files the -combine GCC flag will merge the source files before compilation:
$ gcc -c -combine a.c b.c -o c.o
However this only works for source files, and GCC does not accept .o files as input for this command.
Normally, linking .o files does not work properly, as you cannot use the output of the linker as input for it. The result is a shared library and is not linked statically into the resulting executable.
$ gcc -shared a.o b.o -o c.o
$ gcc c.o other.o -o executable
$ ./executable
./executable: error while loading shared libraries: c.o: cannot open shared object file: No such file or directory
$ file c.o
c.o: ELF 32-bit LSB shared object, Intel 80386, version 1 (SYSV), dynamically linked, not stripped
$ file a.o
a.o: ELF 32-bit LSB relocatable, Intel 80386, version 1 (SYSV), not stripped

Passing -relocatable or -r to ld will create an object that is suitable as input of ld.
$ ld -relocatable a.o b.o -o c.o
$ gcc c.o other.o -o executable
$ ./executable
The generated file is of the same type as the original .o files.
$ file a.o
a.o: ELF 32-bit LSB relocatable, Intel 80386, version 1 (SYSV), not stripped
$ file c.o
c.o: ELF 32-bit LSB relocatable, Intel 80386, version 1 (SYSV), not stripped
For an in-depth explanation see MaskRay's Relocatable linking article.

If you want to create an archive of two or more .o files (i.e.. a static library) use the ar command:
ar rvs mylib.a file1.o file2.o

Related

How to link multiple mach-o files with terminal on MacOS

I created two files: a.c and b.c, they are both *.c file;
Then I use terminal to compile both with command:
gcc -c a.c
gcc -c b.c
I got two mach-o files: a.o and b.o;
So what can I do to link them and generate a linked object file like ab.o ?
I tried the following:
ld a.o b.o -e main -o ab
But it turned me down with the following:
ld: warning: No version-min specified on command line
ld: dynamic main executables must link with libSystem.dylib for inferred architecture x86_64
So what should be done next ?
Just feed them back to gcc:
gcc -o ab a.o b.o
Side note: you might wanna call the resulting file ab.out or ab without suffix, but probably not ab.o, since that usually implies an unlinked object file.
enter image description here
why link a.o and b.o to ab ,but a.o and b.o text size is not ab.o text size
0000005c != 0000002e + 0000002c

How to link 2 files with different starting addresses with ld

I am trying to build a small os. I have an asm file that puts the processor in 64 bit mode with paging enabled. After this, i am jumping to my C code. I want the C code and asm code to be linked into the same file but the C code to have base address at 0xFFFFFF8000000000 and the asm file at 0x5000. How can I do this with ld.
This is what I have so far:
nasm -f elf64 os_init.asm -o ../bin/os_init.o
gcc -c -Os -nostdlib -nostartfiles -nodefaultlibs -fno-builtin vga/*.c utils/*.c *.c memory_management/*.c
ld -Ttext 0x5000 ../bin/os_init.o *.o -o ../bin/kernel.out
objcopy -S -O binary ../bin/kernel.out ../bin/kernel.bin
Currently both files are linked at 0x5000

What is the difference between ar/nm and gcc-ar/gcc-nm?

ar, nm, and ranlib are provided by the binutils package. gcc-ar, gcc-nm, and gcc-ranlib are provided by the GCC package. I read somewhere that the gcc-ar, gcc-nm, and gcc-ranlib are "effectively wrappers" around the ar, nm, and ranlib binaries respectively.
What is the technical difference between the gcc-ar, gcc-nm, and gcc-ranlib vs. ar, nm, and ranlib? There must be a reason why GCC provides these binaries in its builds.
When should a build system of a userland package use one vs. the other? If the toolchain being used to build a userland package is GCC based, does it matter which one you use (e.g., ar vs gcc-ar, nm vs gcc-nm)?
gcc-ar is a wrapper for GNU ar such that a command:
gcc-ar ...
is equivalent to:
ar --plugin=/path/to/liblto_plugin.so ...
On my present system, Ubuntu 17.10, GCC 7.2, that would be e.g:
ar --plugin=/usr/lib/gcc/x86_64-linux-gnu/7/liblto_plugin.so
There is just the same relationship between nm and gcc-nm.
The --plugin option of the binutils ar and nm enables them to dynamically
load a recognizer/analyser for some non-default format of object file that
they have to deal with.
The shared library liblto_plugin.so is one that enables them to deal with the
IR (intermediate representation) object files produced and consumed in link-time-optimized
builds.
So, if you would do your plain old build like this:
$ gcc -c main.c foo.c bar.c
$ ar cr libfoobar.a foo.o bar.o
$ gcc -o prog main.o -L. -lfoobar
then you'd do your link-time-optimized build like:
$ gcc -flto -c main.c foo.c bar.c
$ gcc-ar cr libfoobar.a foo.o bar.o
$ gcc -flto -o prog main.o -L. -lfoobar
In recent releases of binutils - I don't know which was the first; within the
last 3 or 4 years - liblto_plugin.so has been loaded by default by ar
and nm; so in fact:
$ gcc -flto -c main.c foo.c bar.c
$ ar cr libfoobar.a foo.o bar.o
$ gcc -flto -o prog main.o -L. -lfoobar
will work fine; and nm foo.o will work fine. But the gcc-* versions still serve a purpose in being
independently shipped with GCC, since your regular ar and nm might not
support that default, and if not then that last build, for instance,
would fail in the linkage with undefined references, since ar would fail
to insert in the archive a true symbol table for foo.o and bar.o.

Can I tell gcc/ld to exclude unused modules?

I would like to know if I can tell gcc/ld to omit unused modules from being put into the output file.
Suppose I have modules a.c, b.c and c.c. a.c and b.c depend on each other, one of them contains a main(), and due to whatever reasons, no parts of c.c are referenced.
gcc -c a.c
gcc -c b.c
gcc -c c.c
If I bundle the stuff together into a library, no code from c.c won't be in the output:
ar rcs abc.a a.o b.o c.o
gcc abc.a
But if I give the .o files directly to gcc, the code from c.c resp. c.o is included.
gcc a.o b.o c.o
Can I, by any way, tell gcc to leave out unused modules without putting them into a library?
I am programming an AVR µC and use AVR Studio, which doesn't allow the creation of libraries, but would like to omit the source files which are not used, depending on the build configuration.
I don't know if it's possible on AVR, but you could ask GCC to put each symbols in its own section using -ffunction-sections -fdata-sections at compile time. Then at link step, you could use -Wl,--gc-sections to ask ld to remove unused sections.

is it possible to create an object file from other object files in gcc?

I was trying to do something like this in a makefile:
program.exe: ui.o main.o
gcc ......etc
ui.o: window1.o window2.o
gcc -c window1.o window2.o -o ui.o #this doesn't want to work
window1.o: window1.c window1.h window1_events.c window1_controls.c ...
gcc -c window1.c window1_events.c window1_controls.c... -o window1.o
window2.o: ...
gcc ...
main.o: ...
gcc ...
but when I compile like this, it gives the error "input file unused because linking not done," and then I get a bunch of unresolved externs, etc--problems which are resolved by changing
program.exe: ui.o main.o
gcc ...
to
program.exe: window1.o window2.o main.o
gcc ...
so is it possible to just link object files together, to avoid having mile-long lines in a makefile and break down the build process a little more?
Yes: to merge several object files into one, use ld -r or ld -Ur:
From "man ld" on Linux:
-r
--relocatable
Generate relocatable output---i.e., generate an output file that can
in turn serve as input to ld. This is often called partial linking.
As a side effect, in environments that support standard Unix magic
numbers, this option also sets the output file’s magic number to
"OMAGIC".
If this option is not specified, an absolute file is produced.
When linking C++ programs, this option will not resolve references to
constructors; to do that, use -Ur.
You could also do this with gcc:
gcc -Wl,-r foo.o bar.o -o foobar.o -nostdlib
Merging object files like this has some advantages over using an archive library: if merged files change very infrequently (compared to say main.c), your final executable links will be faster.
OTOH, with archived library, the linker will only use what it needs, so your executable may end up being smaller if e.g. window2.c ends up not being necessary.
I bunch of object files is a library. You can create a library with the ar
utility. The following example creates a library called mylib.a containing the files foo.o and bar.o
ar rvs mylib.a foo.o bar.o
You can then link with it by using it on the compiler command line:
gcc -o myexe main.c mylib.a
To create a library:
ar rvs somelib.a file1.o file2.o file3.o
To link it:
gcc -o program.exe file4.o somelib.a

Resources