Issue
So I am trying to compile ,link and run a program without the main function.This is the code:
#include <stdio.h>
#include <stdlib.h>
int my_main()
{
printf("Hello world!\n");
return 0;
}
void _start()
{
exit(my_main());
}
Tried to compile with the command : gcc -nostartfiles nomain.c . While it does compile and produces the a.out file on a Debian vm, I am unable to compile it in my macOS Catalina v10.15.2. I am using the latest version of gcc. The message I am receiving when trying to compile is :
Undefined symbols for architecture x86_64: "_main", referenced from: implicit entry/start for main executable ld: symbol(s) not found for architecture x86_64 collect2: error: ld returned 1 exit status
So far I have tried to change _start to start but still getting the same result. As I understand the compilation process is different depending on the OS.
Note: There is no problem I am trying to solve here , just curiosity.
Thank you in advance
Solution
On macOS 10.14.6 with Xcode 11.3, the code in the question compiles and links with the command:
clang -Wl,-e, -Wl,__start <Name of Your Source File>
The resulting executable appears to work. However, since it bypasses the startup code for the C environment, you should not expect that using routines from the C library or other C features will work properly.
Note that two underscores are needed before start
in the above command because the source code contains one and another is added by the C compiler. If the code is changed to use start
instead of _start
, then the command would use one underscore:
clang -Wl,-e, -Wl,_start <Name of Your Source File>
The switches -Wl,-e, -Wl,_start
pass -e _start
to the linker, which tells it to use _start
as the address of the initial code to execute. It is not clear to me why this bypasses the default loading of the C-run-time-startup object module, which also defines _start
. I would have preferred to use a linker switch that tells it not to load that module, but I did not find one in the man page for ld
. Experimentation suggests that, by default, ld
loads the default object module, and it refers to main
, which results in a link error, but, when -e _start
is used, the linker sets the program’s _start
symbol as the startup address and does not load the default object module.
Answered By - Eric Postpischil