Search code examples
linuxprocessspaceelf

Why .text section is not near by "Entry point address"?


My main.c is:

#include <stdio.h>
#include <stdlib.h>
int bss_var;
int data_var0 = 1;
int main()
{
    // stack
    printf("_____________________________________\n");
    printf("stack section:\n");
    int stack_var = 3;
    printf("\t%p\n",&stack_var);
    printf("_____________________________________\n");

    // heap
    printf("heap section:\n");
    char *p = (char*)malloc(10);
    printf("\t%p\n",p);
    printf("_____________________________________\n");

    // .bss
    printf(".bss section:\n");
    printf("\t%p\n",&bss_var);
    printf("_____________________________________\n");

    // .data
    printf(".data section:\n");
    static int data_var1 = 4;
    printf("\t%p\n",&data_var1);
    printf("\t%p\n",&data_var0);
    printf("_____________________________________\n");

    // .text
    printf(".text section:\n");
    printf("\t%p\n",main);
    printf("_____________________________________\n");

    return 0;
}

And the result is:

stack section: 0x7fffffffe1ec
heap section:  0x555555756670
.bss section:  0x55555575501c
.data section: 0x555555755014
.text section: 0x55555555473a

$ readelf -h a.out:

Entry point address: 0x630

Why the "Entry point address" at 0x630 is not near by ".text section" at 0x55555555473a ?

My environment is: x86_64, linux-4.15.0


Solution

  • The entry point is near the address of the .text section.

    The entry point that you see with $ readelf -h a.out is the nominal address statically assigned by the linker, before the program is loaded and relocated.

    The address of the .text section is not the address of main, as your program assumes, it is the address of the symbol __executable_start, and furthermore what the program prints at runtime is not the nominal address assigned by the linker but the virtual address after the program is loaded and relocated. See:

    $ cat main.c
    #include <stdio.h>
    
    extern char __executable_start;
    extern char _start;
    
    int main(void)
    {
        printf("%p: address of `.text` section\n", &__executable_start);
        printf("%p: address of `_start` \n", &_start);
        printf("%p: address of `main` \n", &main);
        return 0;
    }
    
    $ gcc -Wall main.c 
    
    $ readelf -s a.out | egrep -w '(main|_start|__executable_start)'
        34: 0000000000000000     0 FILE    LOCAL  DEFAULT  ABS main.c
        49: 0000000000000000     0 NOTYPE  GLOBAL DEFAULT  ABS __executable_start
        57: 0000000000000540    43 FUNC    GLOBAL DEFAULT   14 _start
        59: 000000000000064a    83 FUNC    GLOBAL DEFAULT   14 main
    

    The nominal address of the .text section is 0000000000000000. The entry point is the address of _start, at offset 0x540 bytes in the .text section and main is at offset 0x64a. The entry point as reported by:

    $ readelf -h a.out | grep 'Entry point'
    Entry point address:               0x540
    

    is the same. And running the program:

    $ ./a.out 
    0x564c5d350000: address of `.text` section
    0x564c5d350540: address of `_start` 
    0x564c5d35064a: address of `main`
    

    shows the symbols at the same offsets from virtual base address 0x564c5d350000.