Расположение глобальных переменных без -PPIC - PullRequest
0 голосов
/ 05 февраля 2019

Хотя существуют некоторые сообщения об эффекте -fPIC (см., Например, этот пост ), большинство из них неясны.Я написал чрезвычайно простой пример и до сих пор не могу понять, что происходит без -fPIC относительно расположения глобальных переменных.Вот мой файл C:

$ cat main.c
#include <stdio.h>
int var1 = 94;
int var2 = 76;

int main(int argc, char **argv)
{
    int var1Loc = (int) &var1;
    int var2Loc = (int) &var2;
    printf("var1 address is: %d\n",var1Loc);
    printf("var2 address is: %d\n",var2Loc);
    printf("diff         is: %d\n",var2Loc-var1Loc);

    return var1+var2;
}

Затем я компилирую его с -fPIC и запускаю его дважды:

$ gcc -Wno-pointer-to-int-cast -O0 -g -o main main.c
$ ./main
var1 address is: -2019672048
var2 address is: -2019672044
diff         is: 4
$ ./main
var1 address is: 1441697808
var2 address is: 1441697812
diff         is: 4

Когда я делаю то же самое без -fPIC Я получаю похожие результаты.Я думал, что без -fPIC адреса должны быть одинаковыми для всех прогонов нет?

1 Ответ

0 голосов
/ 05 февраля 2019

В аббревиатуре (или инициализм ): ASLR - рандомизация размещения адресного пространства.

Википедия о ASLR говорит:

ASLR случайным образом упорядочивает позиции адресного пространства ключевых областей данных процесса, включая базу исполняемого файла и позиции стека, кучи и библиотек.

Это описывает то, что вы видите.Впоследствии вы обнаружили, что использование:

 echo 0 | sudo tee /proc/sys/kernel/randomize_va_space

для выключения ASLR означало, что адреса одинаковы при выполнении, либо с -fPIC, либо без него, подтверждая тем самым, что ASLR был причиной изменения адреса.

Обратите внимание, что при печати вашего адреса, вероятно, должны использоваться аргументы формата %p и void * (хотя вы можете потенциально усечь преобразование данных, когда применяете приведение (int) к адресам - но формат является правильным дляиспользуйте %d).Модификатор типа t предназначен для ptrdiff_t, разница между двумя указателями.

#include <stdio.h>

int var1 = 94;
int var2 = 76;

int main(void)
{
    void *var1Loc = &var1;
    void *var2Loc = &var2;
    printf("var1 address is: %p\n", var1Loc);
    printf("var2 address is: %p\n", var2Loc);
    printf("diff         is: %td\n", &var2 - &var1);

    return 0;
}
...