Посмотрите на скрипт компоновщика, который ld
использует:
ld -verbose
Формат задокументирован по адресу: https://sourceware.org/binutils/docs-2.25/ld/Scripts.html
Он определяет в основном все о том, каким будет исполняемый файл.Генерируемый.
В 64-битной версии Binutils 2.24 Ubuntu 14.04 он содержит строку:
ENTRY(_start)
, которая устанавливает точку входа в символ _start
(идет к заголовку ELF, как упоминалосьctn)
А затем:
. = SEGMENT_START("text-segment", 0x400000) + SIZEOF_HEADERS;
, который устанавливает адрес первых заголовков равным 0x400000
+ SIZEOF_HEADERS
.
Я изменил этот адрес на 0x800000
, передал свой пользовательский скрипт с ld -T
, и он заработал: readelf -s
говорит, что _start
находится по этому адресу.
Другой способизменить его - использовать опцию -Ttext-segment=0x800000
.
Причина использования 0x400000
= 4Mb = getconf PAGE_SIZE
состоит в том, чтобы начать в начале второй страницы, как указано по адресу: ПочемуВиртуальный адрес точки входа исполнения ELF в форме 0x80xxxxx, а не ноль 0x0?
Вопрос описывает, как установить _start
из командной строки: Почему точка входа ELF 0x8048000 не изменяетсяс опцией "ld -e"?
SIZEOF_HEADERS
- это размер заголовков программы ELF +, которые находятся в начале файла ELF.Эти данные загружаются в самое начало пространства виртуальной памяти Linux (почему TODO?). В минимальном мире приветствия Linux x86-64 с 2 заголовками программ это стоит 0xb0
, так что символ _start
имеет значение 0x4000b0.