When running gcc -undef file.c
, on a file containing nothing but a main
function, I get this warning from ld
:
/usr/bin/ld: warning: cannot find entry symbol _start; defaulting to 0000000000401020
There are SO questions about the same warning related to option -nostdlib and -nostartfiles, but I did not use them.
Even if I manually redefined all of the predefined symbols (retrieved using echo | gcc -dM -E -
) as #define
s and add them to my source file, running gcc -undef
on it will still produce the same warning.
The GCC documentation about -undef contains only the following:
-undef
Do not predefine any system-specific or GCC-specific macros. The standard predefined macros remain defined.
And among the predefined macros, I see nothing related to the standard C library, to main
, or to _start
. __STDC_HOSTED__
is still defined (despite -undef
). If I run gcc -undef main.c -c
, the resulting main.o
file is identical despite -undef
. So it's clearly something related to linking. But as mentioned before, GCC documentation about -undef
does not mention anything about linking, and GCC Linking Options has no -undef
option.
What is going on, and is there a way to use -undef
and still be able to compile and link a file using gcc, e.g. by adding other options?
Edit: following suggestions, I tried running gcc -Wl,-verbose
with and without -undef
, and the only difference is this:
...
/usr/bin/ld: mode elf_x86_64
+attempt to open /usr/lib/gcc/x86_64-redhat-linux/14/../../../../lib64/crt1.o succeeded
+/usr/lib/gcc/x86_64-redhat-linux/14/../../../../lib64/crt1.o
attempt to open /usr/lib/gcc/x86_64-redhat-linux/14/../../../../lib64/crti.o succeeded
...
But it's not clear to me why -undef
affects the opening of crt1.o
.
This appears to be a GCC bug. As you can see if you add the -v
option, the gcc
compiler driver passes -undef
as a command line parameter to the linker ld
, which makes no sense and causes undesired behavior. I've reported it as bug 118975.
GNU ld
has an option --undefined=sym
which causes the symbol sym
to be treated as undefined for the link (e.g. so as to pull in a library module that defines it), but not causing an error if it remains undefined. In its command line syntax, ld
also:
-undef
is equivalent to --undef
--undef
is equivalent to --undefined
=
. So --undefined sym
is equivalent to --undefined=sym
.The net effect of passing -undef
to the linker, then, is that the next parameter on the ld
command line is treated as if it were the argument of the --undefined
option. In my test, that parameter is the path to the startup code file Scrt1.o
(apparently crt1.o
on your installation), which is where the _start
symbol is defined. So that path is treated as a symbol to be undefined (harmless in itself) and not as a file to be linked. Thus Scrt1.o
is omitted from the link and you get a warning about _start
being undefined; moreover, the output executable won't work.
There's an easy workaround: compile and link the file in two steps, and don't pass -undef
when linking (as it should only affect preprocessing anyway).
gcc -c -undef main.c
gcc main.o