Оба ваших утверждения на самом деле правильно (до некоторой степени).
В случае исполняемого файла ELF компоновщик использует сценарий компоновщика для назначения адреса в виртуальном пространстве каждому символу программы (они сгруппированы в разделы, все из которых имеют начальный адрес и размер). Вы можете увидеть сценарий по умолчанию, который используется при вызове ld --verbose
. Секции двоичного кода и их адреса можно увидеть с помощью таких инструментов, как readelf
или objdump
, например. readelf -l /bin/cat
. Затем, если вы запустите cat /proc/self/maps
, вы должны указать адреса, по которым сопоставляется /bin/cat
. Таким образом, системный вызов ядра execve
выполняет следующее: замените адресное пространство текущего процесса новым, к которому сопоставляется исполняемый файл, заданный как аргумент.
Конечно, если каждому биту кода был присвоен статический адрес, вы столкнулись бы с проблемами с общими библиотеками. В общих библиотеках используется независимый от позиции код, поэтому они могут отображаться повсюду в адресном пространстве процесса. Здесь ядро принимает решение о том, как действовать.
mmap
не делает ни одно из (1) или (2), он просто отображает память или часть файла по заданному адресу адресного пространства (или пусть ядро решает, какой адрес использовать). Фактически он используется для сопоставления разделяемых библиотек, которые использует программа.Чтобы узнать, как это сделать, запустите strace /bin/true
и посмотрите, как вызывается сначала execve
, чтобы создать адресное пространство процесса из двоичного файла и как открывается файл libc, а соответствующие разделы имеют соответствующие разрешения программным загрузчиком:
execve("/bin/true", ["/bin/true"], [/* 69 vars */]) = 0
...
open("/lib/libc.so.6", O_RDONLY|O_CLOEXEC) = 3
mmap(NULL, 3804080, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7f224f351000
mprotect(0x7f224f4e8000, 2097152, PROT_NONE) = 0
mmap(0x7f224f6e8000, 24576, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x197000) = 0x7f224f6e8000
следующие статьи также могут быть стоит прочитать: