Оба ваших утверждения на самом деле верны (в некоторой степени).
В случае исполняемого ELF-файла компоновщик полагается на скрипт компоновщика для назначения адреса в виртуальном пространстве каждому символу программы (они сгруппированы в секции, все из которых имеют начальный адрес и размер). Вы можете увидеть скрипт по умолчанию, который используется, вызывая ld --verbose
. Разделы двоичного файла и их адреса можно увидеть с помощью таких инструментов, как readelf
или objdump
, например, readelf -l /bin/cat
. Затем, если вы запустите cat /proc/self/maps
, вы должны сопоставить адреса, по которым сопоставлен /bin/cat
. Таким образом, системный вызов execve
ядра делает это: заменяет адресное пространство текущего процесса новым, в которое отображается исполняемый файл, заданный в качестве аргумента.
Конечно, если бы каждому биту кода был назначен статический адрес, вы столкнулись бы с проблемами с общими библиотеками. Совместно используемые библиотеки используют независимый от позиции код, поэтому их можно отобразить повсюду в адресном пространстве процесса. Здесь ядро принимает решение о том, что делать дальше.
mmap
не выполняет ни (1), ни (2), он просто отображает память или часть файла по заданному адресу адресного пространства (или позволяет ядру решить, какой адрес использовать). На самом деле он используется для отображения общих библиотек, которые использует программа. Чтобы увидеть, как, выполните strace /bin/true
и посмотрите, как сначала вызывается execve
, чтобы создать адресное пространство процесса из двоичного файла, и как открывается файл libc, а соответствующие разделы mmap'ируются с соответствующими правами загрузчиком программы. :
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
Также стоит прочитать следующие статьи: