【发布时间】: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 ),我会得到相同的结果,该修复对我来说仍然是“治疗症状”,但这是区分原因的一个很好的标准: 输入部分无关紧要。