Tuesday, June 24, 2008

How can I call main() function

This article gives you some basic idea: what happens when user application/program starts.
Why I am saying "some basic idea" since here I am not considering dynamic linking/loading of shared libraries.
If you want to know in depth of what happens when user application/program starts, please
read my Linker and Loader blog:
http://bhushanverma.blogspot.com/search/label/ELF%2FLinker%2FLoader%2Flibc%2FCompiler

Whenever user runs any user application, its get loaded in memory by Operating System/Loader.
Now Operating System/Loader calls user application _start entry point.
User application starts running at _start.
_start calls the user program's main function,then it calls the exit(0)system call, which cleans up the process.

User application starts running at _start as follows:

_start(args) {
ret = main(args);
exit(ret);
}

when main() returns, os calls exit() which destroy the process and returns all its resources.
Most of the above code is written in assembly.

Now lets take an example to undestand this:

$ cat main.c
#include

_start ()
{
int ret;
ret = main ();
exit (ret);
}

int
main (void)
{
printf ("hello world");
return 0;
}

Now build this c program:
$ gcc -c main.c
$ ld -main main.o -lc
$ ./main
hello world

If the above commands not works try as follows:
$ gcc -o main -nostdlib main.c -lc
$ ./main
hello world

Yes, we did it.

1 comment:

woja said...

Hello Mr Bhushan,

I am interested in a program that should be able to run stand alone
but should also be integrated as a library into a larger program.
Precisely, it is some sort of debugger, dbx and gdb and their clients
serve as the prototypes of the approach. In contrast to dbx and gdb
the client will not run as separate process. The client is
the program that should be able to run stand alone as well
should be callable from the debugger, and I have no control about the
design of the client (at best I can force the creation of a shared
library instead of an executable).

So I'm very interested in the work you did (in fact it seems to be
rather singular, a Google search did not offer more proposals).
The Sun version works very well but not the Linux version,
probably your version from 2008 did not follow all developments of Linux.

Here is the output when running your example on a
"Linux ubuntu 3.8.0-21-generic x86_64" platform:
bash: ./func.so: Accessing a corrupted shared library

And this is the output of "readelf -l func.so":

Elf file type is DYN (Shared object file)
Entry point 0x7e0
There are 9 program headers, starting at offset 64

Program Headers:
Type Offset VirtAddr PhysAddr
FileSiz MemSiz Flags Align
PHDR 0x0000000000000040 0x0000000000000040 0x0000000000000040
0x00000000000001f8 0x00000000000001f8 R E 8
INTERP 0x0000000000000830 0x0000000000000830 0x0000000000000830
0x0000000000000013 0x0000000000000013 R 10
[Requesting program interpreter: /lib/ld-linux.so.2]
LOAD 0x0000000000000000 0x0000000000000000 0x0000000000000000
0x00000000000008ec 0x00000000000008ec R E 200000
LOAD 0x0000000000000e00 0x0000000000200e00 0x0000000000200e00
0x0000000000000248 0x0000000000000250 RW 200000
DYNAMIC 0x0000000000000e18 0x0000000000200e18 0x0000000000200e18
0x00000000000001c0 0x00000000000001c0 RW 8
NOTE 0x0000000000000238 0x0000000000000238 0x0000000000000238
0x0000000000000024 0x0000000000000024 R 4
GNU_EH_FRAME 0x0000000000000844 0x0000000000000844 0x0000000000000844
0x0000000000000024 0x0000000000000024 R 4
GNU_STACK 0x0000000000000000 0x0000000000000000 0x0000000000000000
0x0000000000000000 0x0000000000000000 RW 8
GNU_RELRO 0x0000000000000e00 0x0000000000200e00 0x0000000000200e00
0x0000000000000200 0x0000000000000200 R 1

Section to Segment mapping:
Segment Sections...
00
01 .interp
02 .note.gnu.build-id .gnu.hash .dynsym .dynstr .gnu.version .gnu.version_r .rela.dyn .rela.plt .init .plt .text .fini .rodata .interp .eh_frame_hdr .eh_frame
03 .init_array .fini_array .jcr .dynamic .got .got.plt .data .bss
04 .dynamic
05 .note.gnu.build-id
06 .eh_frame_hdr
07
08 .init_array .fini_array .jcr .dynamic .got


So what can I do to make the example (and then my program) running?
Unfortunately, my working place is the Linux machine
(I can use the Sun as guest only) and my knowledge of the ELF syntax
and semantics is very poor.

With regards
Wolfgang Jansen