Issue
Say I'm trying to create an executable binary from:
// main.c
#include <stdio.h>
int main() {
printf("Hello, world!");
return 0;
}
I can just run gcc main.c
and I get the executable binary a.out
that prints `Hello, world!", as desired.
I've been told that gcc
did two things here:\
- Compiled
main.c
to a object code, and - Linked that code with the stardard library so that
printf
works.\
How can I manually accomplish these two steps manually, one-by-one?
I start compiling main.c
to object code by running gcc -c main.c
, creating the object file main.o
. Now I'd like to do the linking step. It seems I can do this, also with gcc
, by simply running gcc main.o
, producing the executable binary a.out
.
I've read that this second invocation of gcc
is actually running the linker ld
under the hood. How can I do this with ld
directly, instead of with a second invocation of gcc
? If I run ld main.o
, I get a warning and an error:
ld: warning: cannot find entry symbol _start; defaulting to 00000000004000b0
ld: main.o: in function `main':
main.c:(.text+0x10): undefined reference to `printf'
The error seems to suggest that I need to tell it to link to the C standard library so I can use printf
. I can with the -lc
flag ld main.o -lc
. This produces a.out
, but I still get the warning:
ld: warning: cannot find entry symbol _start; defaulting to 00000000004002e0
And when I run a.out
, it prints Hello, world!
all over the screen, forever:
Hello, world!Hello, world!Hello, world!Hello, world!Hello, world!Hello, world!Hello, world!Hello, world!Hello, world!Hello, world!Hello, world!Hello, world!Hello, world!Hello, world!Hello, world!Hello,
What's the correct way to invoke ld
here to eliminate the warning and get the correct executable?
Solution
What's the correct way to invoke ld here to eliminate the warning and get the correct executable?
The only correct way to link a user-space C binary is by using the appropriate compiler front end: gcc main.o
.
Using ld
directly is never correct.
You can see what gcc
actually does by invoking gcc -v main.o
. Note however that the resulting ld
(or collect2
command):
- may differ depending on how your
gcc
was configured - may differ between different OS releases
- may differ depending on which
libc
is being used
TL;DR: you are welcome to learn how gcc
invokes ld
on your system, but you should not put the result into any Makefile
or a build script.
Answered By - Employed Russian Answer Checked By - Willingham (WPSolving Volunteer)