1
votes

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

2
Message is clear. OS expected _main, you named it _start - Jon Chesterfield

2 Answers

3
votes

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.

0
votes

I'm pretty sure you can compile any C-source without main().

The problem will be with the linker trying to create an executable, which won't work without main().