Как arm-eabi-gcc гарантирует, что раздел .text в crtbegin_dynamic.o будет первым в финальном динамически подключаемом исполняемом файле?

Из readelf мы знаем, что точкой входа исполняемого файла ELF является «_start» в Android (32-разрядная версия ARM), а «_start» определено в crtbegin_dynamic.S для динамического связанные исполняемые файлы.

Вопрос: как система сборки гарантирует, что раздел ".text" в crtbegin_dynamic.o идет первым в окончательном исполняемом образе (так что "_start" идет первым в раздел ".text" в финальном образе исполняемого файла)?


person CodingNow    schedule 26.08.2014    source источник


Ответы (2)


Это решает компоновщик (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
person auselen    schedule 26.08.2014

Неважно, произойдет ли _start первым, последним или в середине .text. Компоновщик использует e_entry в заголовке ELF, чтобы указать фактический адрес после ссылки.

Однако crtbegin_dynamic.o по-прежнему должен быть первым, а crtend.o должен быть последним, потому что они определяют начало и конец массивов конструкторов/деструкторов, и CRT/динамический компоновщик полагается на это. Драйвер компилятора gcc или g++ гарантирует это, помещая эти объекты в соответствующие места в списке объектных файлов при вызове компоновщика. Вы можете увидеть полную командную строку, передав -v в gcc/g++.

person Igor Skochinsky    schedule 26.08.2014