1

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

1
  • Message is clear. OS expected _main, you named it _start Commented Jan 25, 2020 at 1:09

2 Answers 2

3

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.

Sign up to request clarification or add additional context in comments.

2 Comments

You can just list all of the options and arguments to pass to the linker with a single -Wl: clang -Wl,-e,_start.
Great explanation and answer overall , seems that this also works with gcc with -e switch.Thank you
0

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

1 Comment

You are right on this one as gcc -c nomain.c does produce an object file, whats weird is that it compiled and linked just fine on Linux...

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.