Что определяет независимость позиции после операции переназначения памяти? - PullRequest
1 голос
/ 30 марта 2020

Я начал читать «1001 *» Миро Самека «Создание голых металлических ARM-систем с GNU» и обнаружил, что застрял в определенной точке. Что вызвало мою путаницу, можно найти в одной из заметок на стр. 10 документа PDF:

ПРИМЕЧАНИЕ. Функция low_level_init () может быть закодирована в C / C ++ со следующими ограничениями. Функция должна выполняться в состоянии ARM и не должна полагаться на инициализацию раздела .data или очистку раздела .bss. Кроме того, если переопределение памяти выполняется вообще, оно должно происходить внутри функции low_level_init (), потому что код больше не зависит от позиции после того, как эта функция вернет

Как именно код "больше не" позиционно-независимый "? Кажется, что ссылочный код (видимый на страницах 7 - 9 в PDF) по-прежнему не зависит от позиции после возврата из low_level_init / после метки _cstartup. Единственное, что кажется другим в инструкциях после метки _cstartup, это то, что они ссылаются на метки, которые определены в скрипте компоновщика (Раздел 3 руководства).

Так как именно переназначение влияет на или не следующие за ним инструкции не зависят от позиции?

1 Ответ

4 голосов
/ 31 марта 2020

Позиция не зависит от времени загрузки, а не от времени выполнения. Независимость от позиции - это качество кода, которое позволяет загружать его по любому адресу в памяти и будет по-прежнему работать, но независимость от позиции не является качеством работающей программы.

Как только мы получим стек вызовов и / или (перемещенные) данные, относящиеся к коду, мы больше не обладаем позиционной независимостью ни от кода, ни от данных и не можем их перемещать. Фактически независимость позиции исчезает, когда программа начинает выполнение (несмотря на код, независимый от позиции).

Оба адреса возврата - динамически генерируемые при вызове (например, BL) - а также указатели данных на код (векторы указателя кода ( как в vtables) и инициализированные указатели глобальных функций) уничтожают независимость позиции для работающей программы.

Предупреждающий узел автора - это способ описания исчезновения независимости позиции. Добавление к путанице заключается в том, что благодаря очень осторожной работе они позволяют фактически перемещать код, даже если его выполнение уже началось, поэтому здесь у нас есть независимость позиции, фактически продолжающаяся некоторое небольшое количество после начала выполнения.

Но Программа не может нормально функционировать (например, совершать вызовы и использовать указатели функций), не отказываясь от независимости позиции, и поэтому они решают нарисовать линию на песке в конце low_level_init.

Например, reset код очень длинен, чтобы использовать нестандартный вызов для вызова low_level_init - предоставляя ему значение lr без использования либо BL, либо mov lr,pc (который будет захватывать предварительно преобразованный (ROM) адрес из cstartup.) Предоставленное значение lr является адресом (1022 *), на который low_level_init «вернется»!

    (10) LDR r0,=_reset /* pass the reset address as the 1st argument */
    (11) LDR r1,=_cstartup /* pass the return address as the 2nd argument */
    (12) MOV lr,r1 /* set the return address after the remap */
    (13) LDR sp,=__stack_end__ /* set the temporary stack pointer */
    (14) B low_level_init /* relative branch enables remap */
_cstartup:

Это B в сочетании с MOV lr,r1 это вызов.

...