Из readelf мы знаем, что точкой входа исполняемого файла ELF является "_start" в Android (32-разрядная версия ARM), а "_start" определено в crtbegin_dynamic.S для динамического связанные исполняемые файлы.
Вопрос: как система сборки гарантирует, что раздел ".text" в crtbegin_dynamic.o идет первым в окончательном исполняемом образе (так что "_start" идет первым в раздел ".text" в финальном образе исполняемого файла)?
Ответ 1 · рейтинг 1 · auselen
Это решает компоновщик (ld), который может неявно вызываться при создании исполняемого файла с gcc.
Сначала вы должны проверить документацию ld по точке входа.
Первая инструкция, которую необходимо выполнить в программе, называется точкой входа.
...
Существует несколько способов установки точки входа. Компоновщик установит точку входа, попробовав каждый из следующих методов по порядку и остановившись, когда один из них окажется успешным:
- параметр командной строки `-e';
- команда ENTRY(symbol) в скрипте компоновщика;
- значение целевого конкретного символа, если оно определено; Для многих целей это начало, ...
- адрес первого байта раздела `.text', если он присутствует;
- Адрес 0.
Вы можете попробовать поиграть с опцией -e компоновщика через -Wl,-eXXX
$ echo "int main(void) {return 42;}" | gcc -Wl,-efoo -xc - -o t42
/usr/bin/ld: warning: cannot find entry symbol foo; defaulting to 00000000004003d0
$ readelf -a t42|grep 4003d0
59: 00000000004003d0 0 FUNC GLOBAL DEFAULT 13 _start
Ответ 2 · рейтинг 1 · Igor Skochinsky
Неважно, произойдет ли _start первым, последним или в середине .text. Компоновщик использует e_entry в заголовке ELF, чтобы указать фактический адрес после ссылки.
Однако crtbegin_dynamic.o по-прежнему должен быть первым, а crtend.o должен быть последним, потому что они определяют начало и конец массивов конструкторов/деструкторов, и CRT/динамический компоновщик полагается на это. Драйвер компилятора gcc или g++ гарантирует это, помещая эти объекты в соответствующие места в списке объектных файлов при вызове компоновщика. Вы можете увидеть полную командную строку, передав -v в gcc/g++.