What is the use of _start() in C?

CGccStartup

C Problem Overview


I learned from my colleague that one can write and execute a C program without writing a main() function. It can be done like this:

my_main.c

/* Compile this with gcc -nostartfiles */

#include <stdlib.h>

void _start() {
  int ret = my_main();
  exit(ret); 
}

int my_main() {
  puts("This is a program without a main() function!");
  return 0; 
}

Compile it with this command:

gcc -o my_main my_main.c –nostartfiles

Run it with this command:

./my_main

When would one need to do this kind of thing? Is there any real world scenario where this would be useful?

C Solutions


Solution 1 - C

The symbol _start is the entry point of your program. That is, the address of that symbol is the address jumped to on program start. Normally, the function with the name _start is supplied by a file called crt0.o which contains the startup code for the C runtime environment. It sets up some stuff, populates the argument array argv, counts how many arguments are there, and then calls main. After main returns, exit is called.

If a program does not want to use the C runtime environment, it needs to supply its own code for _start. For instance, the reference implementation of the Go programming language does so because they need a non-standard threading model which requires some magic with the stack. It's also useful to supply your own _start when you want to write really tiny programs or programs that do unconventional things.

Solution 2 - C

While main is the entry point for your program from a programmers perspective, _start is the usual entry point from the OS perspective (the first instruction that is executed after your program was started from the OS)

In a typical C and especially C++ program, a lot of work has been done before the execution enters main. Especially stuff like initialization of global variables. Here you can find a good explanation of everything that's going on between _start() and main() and also after main has exited again (see comment below).
The necessary code for that is usually provided by the compiler writers in a startup file, but with the flag –nostartfiles you essentially tell the compiler: "Don't bother giving me the standard startup file, give me full control over what is happening right from the start".

This is sometimes necessary and often used on embedded systems. E.g. if you don't have an OS and you have to manually enable certain parts of your memory system (e.g. caches) before the initialization of your global objects.

Solution 3 - C

Here is a good overview of what happens during program startup before main. In particular, it shows that __start is the actual entry point to your program from OS viewpoint.

It is the very first address from which the instruction pointer will start counting in your program.

The code there invokes some C runtime library routines just to do some housekeeping, then call your main, and then bring things down and call exit with whatever exit code main returned.


A picture is worth a thousand words:

C runtime startup diagram


P.S: this answer is transplanted from another question which SO has helpfully closed as duplicate of this one.

Solution 4 - C

> When would one need to do this kind of thing?

When you want your own startup code for your program.

main is not the first entry for a C program, _start is the first entry behind the curtain.

Example in Linux:

_start: # _start is the entry point known to the linker
    xor %ebp, %ebp            # effectively RBP := 0, mark the end of stack frames
    mov (%rsp), %edi          # get argc from the stack (implicitly zero-extended to 64-bit)
    lea 8(%rsp), %rsi         # take the address of argv from the stack
    lea 16(%rsp,%rdi,8), %rdx # take the address of envp from the stack
    xor %eax, %eax            # per ABI and compatibility with icc
    call main                 # %edi, %rsi, %rdx are the three args (of which first two are C standard) to main

    mov %eax, %edi    # transfer the return of main to the first argument of _exit
    xor %eax, %eax    # per ABI and compatibility with icc
    call _exit        # terminate the program

>Is there any real world scenario where this would be useful?

If you mean, implement our own _start:

Yes, in most of the commercial embedded software I have worked with, we need to implement our own _start regarding to our specific memory and performance requirements.

If you mean, drop the main function and change it to something else:

No, I don't see any benefit doing that.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionSimpleGuyView Question on Stackoverflow
Solution 1 - CfuzView Answer on Stackoverflow
Solution 2 - CMikeMBView Answer on Stackoverflow
Solution 3 - CulidtkoView Answer on Stackoverflow
Solution 4 - CTrevorView Answer on Stackoverflow