Exploring The Main Function
Exploring The Main Function
#include<stdio.h>
int main()
{
return 0;
}
#include<stdio.h>
int main(int argc, char **argv)
{
return 0;
}
#include<stdio.h>
void main()
{
}
#include<stdio.h>
void main(int argc, char **argv)
{
}
What is that one particular function that needs to be present for a c program to run.
Yes, It’s the main() function.
When you run the program, the start-up code gets executed and then the kernel will call the main
function where you define how it should work.
What does the kernel do when you press enter after the ./a.out ?
And these are the operations performed when the process begins and when it ends
(Started another process hence address change from here, just keep in mind the function names seen
above as you will be seeing in depth about it)
From the readelf –headers ./sample , we see that the entry point is 0x1060
In the above you can see the dump of the functions _init and __cxa_finalize@plt
That’s a lot of info to check. No worries, we wont be checking everything, as we are going after main.
This is where you can find the answer for the question, what invokes main?
The (__libc_start_main)libc-start.c initializes and invokes the main. The libc-start.c is executed for
statically linked binaries, for dynamically linked, it would be in libc.so and this comes under startup
code. Before this the ELF startup code is run: https://codebrowser.dev/glibc/glibc/csu/init-
first.c.html#__libc_init_first
In line 173, we can see that, for static executables, the mentioned code is run.
GNU HURD is a collection of microkernel servers that are written as a part of the GNU project.
Note: The startup process is different for statically linked programs and dynamically lined programs
Statically-linked program
• The ELF headers points program start at _start.
• _start (sysdeps/mach/hurd/i386/static-start.S) calls _hurd_stack_setup
• _hurd_stack_setup (sysdeps/mach/hurd/i386/init-first.c) calls first_init which
calls __mach_init to initialize enough to run RPCs, then runs
the _hurd_preinit_hook hooks, which initialize global variables of libc.
• _hurd_stack_setup (sysdeps/mach/hurd/i386/init-first.c) calls _hurd_startup.
• _hurd_startup (hurd/hurdstartup.c) gets hurdish information from servers and
calls its main parameter.
• the main parameter was actually doinit (in sysdeps/mach/hurd/i386/init-first.c),
which mangles the stack and calls doinit1 which calls init.
• init sets threadvars, tries to initialize threads (and perhaps switches to the
new stack) and gets to call init1.
• init1 gets the Hurd block, calls _hurd_init on it
• _hurd_init (hurd/hurdinit.c) initializes initial ports, starts the signal thread,
runs the _hurd_subinit hooks (init_dtable hurd/dtable.c notably initializes the FD
table and the _hurd_fd_subinit hooks, which notably checks std*).
• We are back to _start, which jumps to _start1 which is the normal libc startup
which calls __libc_start_main
• __libc_start_main (actually called LIBC_START_MAIN in csu/libc-start.c) initializes
libc, tls, libpthread, atexit
• __libc_start_main calls initialization function given as parameter __libc_csu_init,
• __libc_csu_init (csu/elf-init.c) calls preinit_array_start functions
• __libc_csu_init calls _init
• _init (sysdeps/i386/crti.S) calls PREINIT_FUNCTION, (actually libpthread on
Linux, __gmon_start__ on hurd)
• back to __libc_csu_init calls init_array_start functions
• back to __libc_start_main, it calls calls application's main, then exit.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~