【问题标题】:GNU ld removes sectionGNU ld 删除部分
【发布时间】:2011-02-10 13:33:11
【问题描述】:

我正在为基于 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 不知道对它的依赖,但它会导致设备无法正确启动。

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

【问题讨论】:

    标签: linker embedded arm ld gnu-assembler


    【解决方案1】:

    尝试添加类似的内容:

    KEEP(*(.boot))
    

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

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

    【讨论】:

      【解决方案2】:

      我认为您想将 --no-gc-sections 选项传递给链接器。来自GNU ld documentation

      --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'.
      

      【讨论】:

        【解决方案3】:

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

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

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

        【讨论】:

          【解决方案4】:

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

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

          【讨论】:

            【解决方案5】:

            您可以使用 ld --whole-archive 选项来提取未引用的符号。这个ld options page 有这个用于整个存档 --whole-archive

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

            另请参阅有关堆栈溢出的此问题,uses of whole-archive option

            【讨论】:

              猜你喜欢
              • 2021-12-11
              • 1970-01-01
              • 2018-12-11
              • 2012-02-10
              • 2018-09-08
              • 2012-01-08
              • 2023-03-12
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多