Почему функция выполняется от того же адреса памяти каждый раз?

Я демонтирую исполняемый файл:

(gdb) disas main
Dump of assembler code for function main:
0x004012d0 <main+0>:    push   %ebp
0x004012d1 <main+1>:    mov    %esp,%ebp
...

Каждый раз адрес памяти является тем же:0x004012d0.

Разве адрес памяти не должен быть динамично присвоен ОС?

ОБНОВЛЕНИЕ

Теперь я вижу, что это - виртуальное пространство, и это может быть рандомизировано на некоторых платформах.

Кто-то может отправить дамп gdb, который изменяется?

10
задан Earlz 31 March 2010 в 20:22
поделиться

7 ответов

Почему ОС выбирает другой адрес?

Когда ОС выполняет процесс, она загружает исполняемый файл в пространство виртуальной памяти. По пути он разрешит любые относительные и/ или символические ссылки. Предполагая, что у вас один и тот же исполняемый файл и те же разделяемые библиотеки, и вы запускаете его так же, как и в предыдущий раз, было бы очень странно, если бы ОС решила загрузить исполняемый файл другим способом.

-3
ответ дан 4 December 2019 в 02:25
поделиться

Я думаю, что проблема здесь (по крайней мере, в Linux) может быть в том, что gdb пытается помочь, из документации:

set disable-randomization

set disable-randomization on

Эта опция (включена по умолчанию в gdb) отключает встроенную рандомизацию в виртуальном адресном пространстве запущенной программы. виртуального адресного пространства запущенной программы. Эта опция полезна для нескольких отладочных чтобы сделать выполнение более воспроизводимым, а адреса памяти - многократно используемыми в разных сеансах отладки. сеансах отладки.

Эта возможность реализована только в gnu/Linux. Вы можете получить такое же поведение, используя

 (gdb) set exec-wrapper setarch `uname -m` -R

http://sourceware.org/gdb/current/onlinedocs/gdb/Starting.html

UPDATE: Я проверил это и, похоже, это действительно так для меня (под управлением Linux 2.6.28). Составьте простую программу Hello World и запустите gdb без args командной строки (мы не хотим загружать программу до переопределения настройки disable-randomization), а затем введите:

(gdb) set disable-randomization off
(gdb) file ./a.out
(gdb) break main
(gdb) run
(gdb) disas printf

Адрес printf отличается при каждом запуске программы.

3
ответ дан 4 December 2019 в 02:25
поделиться

Это зависит от ОС. Чаще всего адрес двоичного файла остается неизменным. Это важно для эксплуатации ошибок манипулирования памятью, таких как переполнения буфера. Адрес слинкованных библиотек в Linux всегда будет отличаться из-за ASLR. В Windows Vista и Windows 7 пространство виртуальной памяти двоичного файла также рандомизируется при каждом его выполнении, поэтому адрес функции будет отличаться при каждом запуске.

3
ответ дан 4 December 2019 в 02:25
поделиться

Перемещение исполняемого файла

Некоторые исполняемые файлы настроены так, что они всегда загружаются по одному и тому же адресу. Некоторые установлены таким образом, что их можно "перемещать". Параметр, управляющий этим в компоновщике Visual Studio, называется / FIXED. Даже такие исполняемые файлы чаще всего загружаются по предпочтительному адресу. Более новые ОС (Win7, Vista) рандомизируют адрес загрузки для некоторых исполняемых файлов для повышения безопасности (процесс атаки, загруженный по неизвестному адресу, сложнее) - это называется ASLR . Примечание. Даже исполняемый файл, помеченный как / FIXED: NO, не считается подходящим для ASLR. Разработчик должен явно разрешить ASLR для исполняемого файла.

Виртуальное адресное пространство

Примечание: важно понимать, что процесс владеет всем адресным пространством. У нескольких процессов есть собственное адресное пространство, поэтому, если вы запускаете один и тот же исполняемый файл несколько раз, нет причин, по которым он не может загружаться по одному и тому же адресу каждый раз.

2
ответ дан 4 December 2019 в 02:25
поделиться

И да, и нет. Физическая память выделяется ОС, и только ОС знает, где находится ваша программа в физической оперативной памяти. Ваша программа видит только виртуальный адрес, который всегда будет одним и тем же, если все загружается в одном и том же порядке.

2
ответ дан 4 December 2019 в 02:25
поделиться

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

0
ответ дан 4 December 2019 в 02:25
поделиться

Это виртуальный адрес. Физический адрес известен ОС, но каждый процесс имеет собственное виртуальное адресное пространство. Перемещаемый образ, вероятно, будет каждый раз получать одно и то же сопоставление, особенно основной исполняемый файл. Но это не гарантируется. Примером являются библиотеки DLL. Библиотеки DLL могут загружаться в разном порядке, что приводит к разным виртуальным адресам между запусками, потому что по мере загрузки DLL 1 DLL 2 не может быть загружена в этот виртуальный адрес и должна получить свой собственный адрес.

1
ответ дан 4 December 2019 в 02:25
поделиться
Другие вопросы по тегам:

Похожие вопросы: