skip to Main Content

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

Answers


  1. 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().

    Login or Signup to reply.
  2. 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.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search