【问题标题】:GNU LD for ARM produces section alignment to unwanted bound用于 ARM 的 GNU LD 生成与不需要的边界的部分对齐
【发布时间】:2021-03-15 19:38:16
【问题描述】:

我正在使用工具链 GNU Tools for STM32 为 STM32 微控制器构建嵌入式软件,我需要没有间隙的二进制输出。

链接器会在 .text 和 .rodata 部分之间产生间隙。问题是.rodata 部分的对齐方式。使用适用于 STM32 版本 9-2020-q2-update 的 GNU 工具会出现此问题。我以前使用的版本(7-2018-q2-update)没有产生这个问题。

链接描述文件的摘录(对于两个 GNU 工具版本都是一样的):

SECTIONS
{
  .text :
  {
    . = ALIGN(4);
    *(.text)           /* .text sections (code) */
    *(.text*)          /* .text* sections (code) */
    *(.glue_7)         /* glue arm to thumb code */
    *(.glue_7t)        /* glue thumb to arm code */
    *(.eh_frame)

    KEEP (*(.init))
    KEEP (*(.fini))

    . = ALIGN(4); /* PaulV: change that to ALIGN(8) eliminates the gap */
  } >FLASH

  /* Constant data into "FLASH" Rom type memory */
  .rodata :
  {
    . = ALIGN(4);
    *(.rodata)         /* .rodata sections (constants, strings, etc.) */
    *(.rodata*)        /* .rodata* sections (constants, strings, etc.) */
    . = ALIGN(4);
  } >FLASH
}

更多细节:

版本 7-2018-q2-update 产生的输出没有间隙。

.lst 文件(注意 .rodata 部分与边界 4 对齐):

K4_G1.elf:     file format elf32-littlearm

Sections:
Idx Name          Size      VMA       LMA       File off  Algn
          ....
  3 .text         0001a20c  08100800  08100800  00010800  2**4
                  CONTENTS, ALLOC, LOAD, READONLY, CODE
  4 .rodata       00009b54  0811aa0c  0811aa0c  0002aa0c  2**2
                  CONTENTS, ALLOC, LOAD, READONLY, DATA

和.map 文件(非空部分.fini.rodata 之间没有间隙):

 .fini          0x000000000811aa04        0x8 c:/st/stm32cubeide_1.4.0/stm32cubeide/plugins/com.st.stm32cube.ide.mcu.externaltools.gnu-tools-for-stm32.7-2018-q2-update.win32_1.5.0.202011040924/tools/bin/../lib/gcc/arm-none-eabi/7.3.1/thumb/v7e-m/fpv5/hard/crtn.o
                0x000000000811aa0c                . = ALIGN (0x4)
                0x000000000811aa0c                _etext = .

.vfp11_veneer   0x000000000811aa0c        0x0
 .vfp11_veneer  0x000000000811aa0c        0x0 linker stubs

.v4_bx          0x000000000811aa0c        0x0
 .v4_bx         0x000000000811aa0c        0x0 linker stubs

.iplt           0x000000000811aa0c        0x0
 .iplt          0x000000000811aa0c        0x0 c:/st/stm32cubeide_1.4.0/stm32cubeide/plugins/com.st.stm32cube.ide.mcu.externaltools.gnu-tools-for-stm32.7-2018-q2-update.win32_1.5.0.202011040924/tools/bin/../lib/gcc/arm-none-eabi/7.3.1/thumb/v7e-m/fpv5/hard/crtbegin.o

.rodata         0x000000000811aa0c     0x9b54
                0x000000000811aa0c                . = ALIGN (0x4)
 *(.rodata)
 .rodata        0x000000000811aa0c       0x8c Src/app_composer/init.o

版本 9-2020-q2-update 产生输出 with 差距。

.lst 文件(注意 .rodata 部分与边界 8 对齐,但为什么呢?):

K4_G1.elf:     file format elf32-littlearm

Sections:
Idx Name          Size      VMA       LMA       File off  Algn
          ...
  3 .text         0001923c  08100800  08100800  00010800  2**4
                  CONTENTS, ALLOC, LOAD, READONLY, CODE
  4 .rodata       000061f0  08119a40  08119a40  00029a40  2**3
                  CONTENTS, ALLOC, LOAD, READONLY, DATA

和.map文件(非空部分.fini.rodata之间有间隙):

 .fini          0x0000000008119a34        0x8 c:/st/stm32cubeide_1.4.0/stm32cubeide/plugins/com.st.stm32cube.ide.mcu.externaltools.gnu-tools-for-stm32.9-2020-q2-update.win32_1.5.0.202011040924/tools/bin/../lib/gcc/arm-none-eabi/9.3.1/thumb/v7e-m+dp/hard/crtn.o

.vfp11_veneer   0x0000000008119a3c        0x0
 .vfp11_veneer  0x0000000008119a3c        0x0 linker stubs

.v4_bx          0x0000000008119a3c        0x0
 .v4_bx         0x0000000008119a3c        0x0 linker stubs

.iplt           0x0000000008119a3c        0x0
 .iplt          0x0000000008119a3c        0x0 c:/st/stm32cubeide_1.4.0/stm32cubeide/plugins/com.st.stm32cube.ide.mcu.externaltools.gnu-tools-for-stm32.9-2020-q2-update.win32_1.5.0.202011040924/tools/bin/../lib/gcc/arm-none-eabi/9.3.1/thumb/v7e-m+dp/hard/crtbegin.o

.rodata         0x0000000008119a40     0x61f0
                0x0000000008119a40                . = ALIGN (0x4)
 *(.rodata)
 .rodata        0x0000000008119a40       0x96 Src/app_composer/init.o

2021 年 3 月 16 日编辑

输入对象文件中没有部分 *(.rodata) 具有 在边界上对齐 8 或更大。

将部分名称 .rodata 更改为名称 .text 可以消除 间隙(如果我将部分 .text 和 .rodata 内容加入到 单个 .text 部分):

SECTIONS
{
  .text :
  {
    . = ALIGN(4);
    *(.text)           /* .text sections (code) */

    /* ... */

    . = ALIGN(4);
  } >FLASH

  /* Constant data into "FLASH" Rom type memory */
  .text : /* <-- the same name as the previous section instead of .rodata */
  {
    . = ALIGN(4);
    *(.rodata)         /* .rodata sections (constants, strings, etc.) */
    *(.rodata*)        /* .rodata* sections (constants, strings, etc.) */
    . = ALIGN(4);
  } >FLASH
}

两种变体的源代码和构建设置也相同。

问题的原因可能是什么?如何解决?我错过了什么吗?

附:当然,我可以将.text 部分末尾的对齐方式更改为 8。那将是治标不治本,但我想了解原因。

提前感谢您的帮助!

【问题讨论】:

  • 部分名称(在冒号之前)是任意的,您可以将它们称为 .bob 和 .ted 而不是 .text 和 .rodata,这也意味着如果您希望这是一大块东西,那么只有一个节头。将 .rodata 内容移动到 .text 部分,去掉所有其他不使用的垃圾(胶水等)
  • 现在.text 的大小是多少,如果添加或删除一些东西,aligh 8 是否仍然“修复”它?
  • @old_timer。你是对的:如果我将输出部分 .text 和 .rodata “合并”到单个 .text 输出部分中,差距就会消失。如果我将 name.rodata 更改为 .text (在链接器脚本中有两个“部分” .text ),我会得到相同的结果,该修复对我来说仍然是“治疗症状”,但这是区分原因的一个很好的标准: 输入部分无关紧要。

标签: gcc arm stm32 ld


【解决方案1】:

在输入对象文件上运行objdump -h。我怀疑您会发现编译器在输入 .rodata 部分之一上放置了 8 的最小对齐。然后链接器将输出对齐设置为输入节的最大值。

【讨论】:

  • 这也是我的第一个怀疑。我浏览了所有输入的 .o 文件,发现只有一些 .text、.debug 部分和一个 .bss 部分在 8 边界上对齐或大于(实际上仅在 8 上)。所有输入的 .rodata 节在 1 或 2 或 4 上对齐。以前版本的 GNU 工具链生成的目标文件是相似的(除了边界 8 上没有对齐的 .bss 节)。
猜你喜欢
  • 2011-01-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-02-10
  • 2018-12-11
  • 2021-12-11
  • 1970-01-01
  • 2015-07-07
相关资源
最近更新 更多