GNU ld удаляет раздел - PullRequest
       109

GNU ld удаляет раздел

7 голосов
/ 21 апреля 2010

Я пишу загрузочный скрипт для устройства на базе ARM-Cortex M3. Если я скомпилирую загрузочный скрипт на ассемблере и код приложения C, а затем объединю объектные файлы и перенесу их на мое устройство, все будет работать.

Однако, если я использую ar для создания архива (libboot.a) и объединяю этот архив с приложением C, возникает проблема:

Я поместил загрузочный код в раздел:

    .section    .boot, "ax"
    .global     _start

_start:
    .word       0x10000800  /* Initial stack pointer (FIXME!) */
    .word       start
    .word       nmi_handler
    .word       hard_fault_handler
    ... etc ...

Я обнаружил, что ld удаляет это из окончательного двоичного файла (раздел «boot» недоступен). Это вполне естественно, поскольку от него не зависит ld, но это приводит к неправильной загрузке устройства.

Итак, мой вопрос: каков наилучший способ заставить этот код быть включенным?

Ответы [ 5 ]

10 голосов
/ 23 апреля 2010

Попробуйте добавить что-то вроде:

KEEP(*(.boot))

в сценарии компоновщика ld, чтобы сообщить компоновщику о сохранении раздела .boot.

Однако я не уверен, достаточно ли этого, чтобы ld извлек любые объекты из архива, которые находятся в разделе .boot - он может вообще не рассматривать объект, если только какой-либо символ в этом объекте вызывает его. Если это проблема, решением проблемы может быть указание _start в качестве точки входа (использование -e _start в командной строке ld или использование ENTRY(_start) в сценарии компоновщика).

3 голосов
/ 21 апреля 2010

Я думаю, вы хотите передать компоновщику параметр - no-gc-section . Из документации GNU ld :

--gc-sections
--no-gc-sections

Enable garbage collection of unused input sections.

`--gc-sections' decides which input sections are used
by examining symbols and relocations. The section
containing the entry symbol and all sections containing symbols
undefined on the command-line will be kept, as will sections
containing symbols referenced by dynamic objects.
Note that when building shared libraries, the linker must
assume that any visible symbol is referenced. Once this initial
set of sections has been determined, the linker recursively marks
as used any section referenced by their relocations.
See `--entry' and `--undefined'.
2 голосов
/ 21 апреля 2011

Вы можете использовать --whole-archive при связывании, но это большой пистолет слона Страница man утверждает:

Для каждого архива, упомянутого в командной строке после параметра --whole-archive, включайте каждый объектный файл в архиве в ссылку, а не ищите в архиве требуемые объектные файлы.

2 голосов
/ 22 апреля 2010

Компоновщик извлекает из архива только те объекты, которые необходимы для разрешения явно обозначенных символов. На ваш стартовый код явно не ссылаются, потому что он вызывается через вектор сброса.

Если ваш загрузочный код состоит из нескольких модулей, вы должны создать частично связанный объектный файл, используя ld и параметр -r / --relocatable , это объединит объекты в один объект без необходимости разрешения всех символов (например, main ()). Это может быть использовано в полной ссылке с кодом вашего приложения. Если это всего лишь один объектный файл, то в любом случае нет никакого реального преимущества в создании архива (и, как вы обнаружили, он не будет работать).

Обратите внимание, что традиционно запуск среды выполнения GNU C предоставляется в файле с именем crt0.o (не в архиве), предположительно по той же причине.

1 голос
/ 23 апреля 2010

Вы можете использовать опцию ld --whole-archive для добавления символов без ссылок. На этой странице настроек ld есть это для всего архива - весь архив

Для каждого архива, указанного на командная строка после --whole-архива включите каждый объектный файл в архив в ссылке, а не поиск в архиве необходимого объектные файлы. Это обычно используется для превратить архивный файл в общий библиотека, заставляя каждый объект быть включены в итоговый общий библиотека. Эта опция может быть использована более чем один раз.
Два замечания при использовании этой опции от gcc: во-первых, gcc не знает об этой опции, поэтому вы должны использовать -Wl, -whole-архив. Во-вторых, не забудьте использовать -Wl, -no-whole-archive после вашего списка архивов, потому что gcc добавит свой список архивов на вашу ссылку, и вы не можете этого флаг, чтобы повлиять на них.

Также смотрите этот вопрос о переполнении стека, использует опцию всего архива

...