Почему раздел .text не находится рядом с адресом точки входа? - PullRequest
0 голосов
/ 02 марта 2019

Мой main.c:

#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;
}

И результат:

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

$ readelf -h a.out:

Entry point address: 0x630

Почему«Адрес точки входа» в 0x630 не находится рядом с «.text section» в 0x55555555473a?

Моя среда: x86_64, linux-4.15.0

Ответы [ 2 ]

0 голосов
/ 04 марта 2019

Точкой входа является рядом с адресом секции .text.

Точкой входа, которую вы видите с помощью $ readelf -h a.out, является номинальный адрес, статически назначенный компоновщиком допрограмма загружена и перемещена.

Адрес раздела .text не является адресом main, как предполагает ваша программа, это адрес символа __executable_start, и более тогоПрограмма печатает во время выполнения не номинальный адрес, назначенный компоновщиком, а виртуальный адрес после загрузки и перемещения программы.См .:

$ 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

Номинальный адрес секции .text - 0000000000000000. Точкой входа является адрес _start, со смещением 0x540 байтов в секции .text, а main - по адресусмещение 0x64a.Точка входа, о которой сообщают:

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

, совпадает.И работает программа:

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

показывает символы с одинаковыми смещениями от виртуального базового адреса 0x564c5d350000.

0 голосов
/ 02 марта 2019

В исполняемом файле, не зависящем от позиции, адрес точки входа относительно базового адреса отображения.По умолчанию базовый адрес сопоставления определяется случайным образом ядром для каждого запуска программы.На x86-64 он обычно равен 0x555555550000.

. Вы можете связать свою программу с -no-pie, чтобы создать зависимый от позиции исполняемый файл (тип ELF ET_EXEC вместо ET_DYN).

...