7

我正在为基于 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从最终的二进制文件中删除了这个(“引导”部分不可用)。这是很自然的,因为它不依赖它ld知道,但它会导致设备无法正确启动。

所以我的问题是:强制包含此代码的最佳方法是什么?

4

5 回答 5

10

尝试添加类似:

KEEP(*(.boot))

ld链接器脚本中告诉链接器保留该.boot部分。

但是,我不确定这是否足以导致ld从该.boot部分中的存档中拉入任何对象 - 它可能根本不考虑对象,除非该对象中的某个符号导致它被拉入。如果这是一个问题,指定_start为入口点(-e _start在 ld 命令行上使用或ENTRY(_start)在链接器脚本中使用)可能是解决方案。

于 2010-04-23T05:47:31.987 回答
4

我认为您想将--no-gc-sections选项传递给链接器。来自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'.
于 2010-04-21T13:51:52.740 回答
2

链接器只会从档案中提取解析显式引用符号所需的那些对象。您的启动代码没有被显式引用,因为它是通过重置向量调用的。

如果您的引导代码包含多个模块,您应该使用 ld 和-r / --relocatable选项创建一个部分链接的目标文件,这会将对象组合成一个对象,而无需解析所有符号(例如 main() for例子)。然后可以在与您的应用程序代码的完整链接中使用它。如果它只是一个目标文件,那么在任何情况下创建存档都没有真正的优势(并且您发现它不起作用)。

请注意,传统上 GNU C 运行时启动是在一个名为 crt0.o 的文件(不是存档)中提供的,大概是出于同样的原因。

于 2010-04-21T21:28:49.153 回答
2

您可以--whole-archive在链接时使用,但它是一把大象枪。手册页声称:

对于 --whole-archive 选项后命令行中提到的每个存档,在链接中包含存档中的每个目标文件,而不是在存档中搜索所需的目标文件。

于 2011-04-21T16:45:41.627 回答
1

您可以使用 ld --whole-archive 选项来提取未引用的符号。此 ld 选项页面包含整个存档 --whole-archive

对于 --whole-archive 选项后命令行中提到的每个存档,在链接中包含存档中的每个目标文件,而不是在存档中搜索所需的目标文件。这通常用于将存档文件转换为共享库,强制将每个对象包含在生成的共享库中。此选项可以多次使用。
从 gcc 使用此选项时有两个注意事项:首先,gcc 不知道此选项,因此您必须使用 -Wl,-whole-archive。其次,不要忘记在您的档案列表之后使用 -Wl,-no-whole-archive,因为 gcc 会将它自己的档案列表添加到您的链接中,您可能不希望这个标志也影响这些。

另请参阅有关堆栈溢出的此问题,使用整体存档选项

于 2010-04-23T04:56:37.967 回答