Tuesday, February 1, 2011

_start function (Inside C)

/usr/lib/gcc/i386-redhat-linux/4.0.0/../../../crt1.o(.text+0x18): In
function `_start':: undefined reference to `main'
collect2: ld returned 1 exit status

Above error definitely means that there is no main() definition in any of the source files of the project. To dig it further, why _start and why collect2?

_start function is the entry point of a C program which makes a call to main()
collect2 is GCC utility which is used to call various utility function during start time. like ld etc.

Going further into it, main() is the starting point of a C program from the programmer's perspective. Before calling main, a process executes a bulk of code to "clean up the room for execution".
_start is the function which gets called first, which then allocates necessary resources and then calls main() which has to be defined by the programmer.

You can override _start and tell the compiler to not to look for main by using "-nostartfiles" option.

#include
_start()
{
printf("Hello world!!\n");
_exit(0);
}

To Compile : gcc -nostartfiles sampleTest.c -o a.out

Without _exit(0); the program will compile, but there will be Segmentation fault while running it.

sample definition of _start function inside crt1.c file which is a part of c-runtime.
Notice the registration of main() function in the last line by exit().

void
__start(int argc, char **argv, char **env, struct ps_strings *ps_strings,
const struct Struct_Obj_Entry *obj __unused, void (*cleanup)(void))
{
const char *s;
environ = env;
if (argc > 0 && argv[0] != NULL) {
__progname = argv[0];
for (s = __progname; *s != '\0'; s++)
if (*s == '/')
__progname = s + 1;
}
if (ps_strings != (struct ps_strings *)0)
__ps_strings = ps_strings;
if (&_DYNAMIC != NULL)
atexit(cleanup);
else
_init_tls();
#ifdef GCRT
atexit(_mcleanup);
#endif
atexit(_fini);
#ifdef GCRT
monstartup(&eprol, &etext);
#endif
_init();
exit( main(argc, argv, env) );
}

9 comments:

  1. Thanks Kumar -- handy little article.

    ReplyDelete
  2. Replies
    1. Even don't compile. It's may be not full code. Must be correct! I don't know how at least not pure function used 3 undescribed values __ps_strings, __progname and _DYNAMIC. As to 2 fist may write extern types is clear. But _DYNAMIC is quite uncler variable... or some else. Better solution is used __attribute__((constructor)) for initialization function. You get the same results but work.

      Delete
  3. Thanks for sharing this beautiful article .

    ReplyDelete
  4. Thanks... where do __ps_strings and __progname come from and what are they used for?

    ReplyDelete
  5. is there any use of not using main in a program ? rply

    ReplyDelete
    Replies
    1. 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

      Delete
    2. This comment has been removed by the author.

      Delete