GNU 链接器 ARM - 为什么我的部分重叠?
GNU linker ARM - why my sections overlap?
我需要添加一个小堆以在 TM4C ARM 微控制器上使用标准库函数(_sbrk
需要 end
符号)。
这是我的 linker 脚本(带有微控制器演示):
/* Entry Point */
ENTRY(Reset_Handler)
HEAP_SIZE = 1024;
MEMORY
{
FLASH (rx) : ORIGIN = 0x00000000, LENGTH = 0x00100000
SRAM (rwx) : ORIGIN = 0x20000000, LENGTH = 0x00040000
}
SECTIONS
{
.text :
{
_text = .;
KEEP(*(.isr_vector))
*(.text*)
*(.rodata*)
_etext = .;
} > FLASH
.data : AT(ADDR(.text) + SIZEOF(.text))
{
_data = .;
_ldata = LOADADDR (.data);
*(vtable)
*(.data*)
_edata = .;
} > SRAM
.bss :
{
_bss = .;
*(.bss*)
*(COMMON)
_ebss = .;
} > SRAM
.heap : AT(ADDR(.bss) + SIZEOF(.bss))
{
. = ALIGN(8);
__end__ = .;
PROVIDE(end = .);
__HeapBase = .;
. += HEAP_SIZE;
__HeapLimit = .;
} > SRAM
}
我只在 .bss 之后添加了 .heap 类似于 .data/.text 但我得到 link 错误:
ld: section .init loaded at [000126b4,000126bf] overlaps section .data loaded at [000126b4,00012f8f]
collect2: error: ld returned 1 exit status
当我删除 AT(ADDR(.bss) + SIZEOF(.bss))
时也会发生这种情况。当我删除 .heap 并调用 libc 函数时,一切都会编译并且 links,输出二进制文件运行正确。
我应该如何调整脚本以在 bss 之后正确放置堆?
事实证明我的堆和 bss 是正确的,但是在链接标准库函数时添加了名为 .init 和 .fini 的新部分 - 它们与 .data 冲突。这是我更正后的链接描述文件:
/* Entry Point */
ENTRY(Reset_Handler)
HEAP_SIZE = 1024;
MEMORY
{
FLASH (rx) : ORIGIN = 0x00000000, LENGTH = 0x00100000
SRAM (rwx) : ORIGIN = 0x20000000, LENGTH = 0x00040000
}
SECTIONS
{
.text :
{
_text = .;
KEEP(*(.isr_vector))
*(.text*)
*(.rodata*)
KEEP (*(.init))
KEEP (*(.fini))
_etext = .;
} > FLASH
.ARM.extab :
{
*(.ARM.extab* .gnu.linkonce.armextab.*)
} > FLASH
.ARM :
{
__exidx_start = .;
*(.ARM.exidx*)
__exidx_end = .;
} > FLASH
__end_code = .;
.data : AT(__end_code)
{
_data = .;
_ldata = LOADADDR (.data);
*(vtable)
*(.data*)
_edata = .;
} > SRAM
.bss :
{
_bss = .;
*(.bss*)
*(COMMON)
_ebss = .;
} > SRAM
.heap : AT(_ebss)
{
. = ALIGN(8);
__end__ = .;
PROVIDE(end = .);
__HeapBase = .;
. += HEAP_SIZE;
__HeapLimit = .;
} > SRAM
}
我添加了行 KEEP (*(.init))
、KEEP (*(.fini))
和 .ARM
部分(来自另一个 MCU 链接描述文件)。现在一切都链接并运行良好。
如果您使用的是 TivaWare 库,我建议您使用在 Code Composer 中创建相应项目时生成的链接描述文件。您可以将其复制到您的项目中。例如,对于 tm4c123glx launchpad 评估板上的处理器,名称将为 tm4C123gh6pm.lds。我会把它贴在这里:
/******************************************************************************
*
* Default Linker script for the Texas Instruments TM4C123GH6PM
*
* This is derived from revision 15071 of the TivaWare Library.
*
*****************************************************************************/
MEMORY
{
FLASH (RX) : ORIGIN = 0x00000000, LENGTH = 0x00040000
SRAM (WX) : ORIGIN = 0x20000000, LENGTH = 0x00008000
}
REGION_ALIAS("REGION_TEXT", FLASH);
REGION_ALIAS("REGION_BSS", SRAM);
REGION_ALIAS("REGION_DATA", SRAM);
REGION_ALIAS("REGION_STACK", SRAM);
REGION_ALIAS("REGION_HEAP", SRAM);
REGION_ALIAS("REGION_ARM_EXIDX", FLASH);
REGION_ALIAS("REGION_ARM_EXTAB", FLASH);
SECTIONS {
PROVIDE (_intvecs_base_address = 0x0);
.intvecs (_intvecs_base_address) : AT (_intvecs_base_address) {
KEEP (*(.intvecs))
} > REGION_TEXT
PROVIDE (_vtable_base_address = 0x20000000);
.vtable (_vtable_base_address) : AT (_vtable_base_address) {
KEEP (*(.vtable))
} > REGION_DATA
.text : {
CREATE_OBJECT_SYMBOLS
*(.text)
*(.text.*)
. = ALIGN(0x4);
KEEP (*(.ctors))
. = ALIGN(0x4);
KEEP (*(.dtors))
. = ALIGN(0x4);
__init_array_start = .;
KEEP (*(.init_array*))
__init_array_end = .;
*(.init)
*(.fini*)
} > REGION_TEXT
PROVIDE (__etext = .);
PROVIDE (_etext = .);
PROVIDE (etext = .);
.rodata : {
*(.rodata)
*(.rodata*)
} > REGION_TEXT
.data : ALIGN (4) {
__data_load__ = LOADADDR (.data);
__data_start__ = .;
*(.data)
*(.data*)
. = ALIGN (4);
__data_end__ = .;
} > REGION_DATA AT> REGION_TEXT
.ARM.exidx : {
__exidx_start = .;
*(.ARM.exidx* .gnu.linkonce.armexidx.*)
__exidx_end = .;
} > REGION_ARM_EXIDX
.ARM.extab : {
*(.ARM.extab* .gnu.linkonce.armextab.*)
} > REGION_ARM_EXTAB
.bss : {
__bss_start__ = .;
*(.shbss)
*(.bss)
*(.bss.*)
*(COMMON)
. = ALIGN (4);
__bss_end__ = .;
} > REGION_BSS
.heap : {
__heap_start__ = .;
end = __heap_start__;
_end = end;
__end = end;
KEEP(*(.heap))
__heap_end__ = .;
__HeapLimit = __heap_end__;
} > REGION_HEAP
.stack : ALIGN(0x8) {
_stack = .;
__stack = .;
KEEP(*(.stack))
} > REGION_STACK
}
然后确保您的启动代码初始化了正确的部分(您还将获得一个名为 tm4c123gh6pm_startup_ccs_gcc.c 的文件,其中包含启动代码,或者用作- 是或作为指南。
您会注意到它们在初始化各个部分所需的变量方面做得很好。避免了 user2162550 提出的问题。
顺便说一句 - 我注意到当使用 -O2 链接器错误编译时有点混淆 - 如果你的代码适合关闭它,直到你得到你想要的一切。
我需要添加一个小堆以在 TM4C ARM 微控制器上使用标准库函数(_sbrk
需要 end
符号)。
这是我的 linker 脚本(带有微控制器演示):
/* Entry Point */
ENTRY(Reset_Handler)
HEAP_SIZE = 1024;
MEMORY
{
FLASH (rx) : ORIGIN = 0x00000000, LENGTH = 0x00100000
SRAM (rwx) : ORIGIN = 0x20000000, LENGTH = 0x00040000
}
SECTIONS
{
.text :
{
_text = .;
KEEP(*(.isr_vector))
*(.text*)
*(.rodata*)
_etext = .;
} > FLASH
.data : AT(ADDR(.text) + SIZEOF(.text))
{
_data = .;
_ldata = LOADADDR (.data);
*(vtable)
*(.data*)
_edata = .;
} > SRAM
.bss :
{
_bss = .;
*(.bss*)
*(COMMON)
_ebss = .;
} > SRAM
.heap : AT(ADDR(.bss) + SIZEOF(.bss))
{
. = ALIGN(8);
__end__ = .;
PROVIDE(end = .);
__HeapBase = .;
. += HEAP_SIZE;
__HeapLimit = .;
} > SRAM
}
我只在 .bss 之后添加了 .heap 类似于 .data/.text 但我得到 link 错误:
ld: section .init loaded at [000126b4,000126bf] overlaps section .data loaded at [000126b4,00012f8f]
collect2: error: ld returned 1 exit status
当我删除 AT(ADDR(.bss) + SIZEOF(.bss))
时也会发生这种情况。当我删除 .heap 并调用 libc 函数时,一切都会编译并且 links,输出二进制文件运行正确。
我应该如何调整脚本以在 bss 之后正确放置堆?
事实证明我的堆和 bss 是正确的,但是在链接标准库函数时添加了名为 .init 和 .fini 的新部分 - 它们与 .data 冲突。这是我更正后的链接描述文件:
/* Entry Point */
ENTRY(Reset_Handler)
HEAP_SIZE = 1024;
MEMORY
{
FLASH (rx) : ORIGIN = 0x00000000, LENGTH = 0x00100000
SRAM (rwx) : ORIGIN = 0x20000000, LENGTH = 0x00040000
}
SECTIONS
{
.text :
{
_text = .;
KEEP(*(.isr_vector))
*(.text*)
*(.rodata*)
KEEP (*(.init))
KEEP (*(.fini))
_etext = .;
} > FLASH
.ARM.extab :
{
*(.ARM.extab* .gnu.linkonce.armextab.*)
} > FLASH
.ARM :
{
__exidx_start = .;
*(.ARM.exidx*)
__exidx_end = .;
} > FLASH
__end_code = .;
.data : AT(__end_code)
{
_data = .;
_ldata = LOADADDR (.data);
*(vtable)
*(.data*)
_edata = .;
} > SRAM
.bss :
{
_bss = .;
*(.bss*)
*(COMMON)
_ebss = .;
} > SRAM
.heap : AT(_ebss)
{
. = ALIGN(8);
__end__ = .;
PROVIDE(end = .);
__HeapBase = .;
. += HEAP_SIZE;
__HeapLimit = .;
} > SRAM
}
我添加了行 KEEP (*(.init))
、KEEP (*(.fini))
和 .ARM
部分(来自另一个 MCU 链接描述文件)。现在一切都链接并运行良好。
如果您使用的是 TivaWare 库,我建议您使用在 Code Composer 中创建相应项目时生成的链接描述文件。您可以将其复制到您的项目中。例如,对于 tm4c123glx launchpad 评估板上的处理器,名称将为 tm4C123gh6pm.lds。我会把它贴在这里:
/******************************************************************************
*
* Default Linker script for the Texas Instruments TM4C123GH6PM
*
* This is derived from revision 15071 of the TivaWare Library.
*
*****************************************************************************/
MEMORY
{
FLASH (RX) : ORIGIN = 0x00000000, LENGTH = 0x00040000
SRAM (WX) : ORIGIN = 0x20000000, LENGTH = 0x00008000
}
REGION_ALIAS("REGION_TEXT", FLASH);
REGION_ALIAS("REGION_BSS", SRAM);
REGION_ALIAS("REGION_DATA", SRAM);
REGION_ALIAS("REGION_STACK", SRAM);
REGION_ALIAS("REGION_HEAP", SRAM);
REGION_ALIAS("REGION_ARM_EXIDX", FLASH);
REGION_ALIAS("REGION_ARM_EXTAB", FLASH);
SECTIONS {
PROVIDE (_intvecs_base_address = 0x0);
.intvecs (_intvecs_base_address) : AT (_intvecs_base_address) {
KEEP (*(.intvecs))
} > REGION_TEXT
PROVIDE (_vtable_base_address = 0x20000000);
.vtable (_vtable_base_address) : AT (_vtable_base_address) {
KEEP (*(.vtable))
} > REGION_DATA
.text : {
CREATE_OBJECT_SYMBOLS
*(.text)
*(.text.*)
. = ALIGN(0x4);
KEEP (*(.ctors))
. = ALIGN(0x4);
KEEP (*(.dtors))
. = ALIGN(0x4);
__init_array_start = .;
KEEP (*(.init_array*))
__init_array_end = .;
*(.init)
*(.fini*)
} > REGION_TEXT
PROVIDE (__etext = .);
PROVIDE (_etext = .);
PROVIDE (etext = .);
.rodata : {
*(.rodata)
*(.rodata*)
} > REGION_TEXT
.data : ALIGN (4) {
__data_load__ = LOADADDR (.data);
__data_start__ = .;
*(.data)
*(.data*)
. = ALIGN (4);
__data_end__ = .;
} > REGION_DATA AT> REGION_TEXT
.ARM.exidx : {
__exidx_start = .;
*(.ARM.exidx* .gnu.linkonce.armexidx.*)
__exidx_end = .;
} > REGION_ARM_EXIDX
.ARM.extab : {
*(.ARM.extab* .gnu.linkonce.armextab.*)
} > REGION_ARM_EXTAB
.bss : {
__bss_start__ = .;
*(.shbss)
*(.bss)
*(.bss.*)
*(COMMON)
. = ALIGN (4);
__bss_end__ = .;
} > REGION_BSS
.heap : {
__heap_start__ = .;
end = __heap_start__;
_end = end;
__end = end;
KEEP(*(.heap))
__heap_end__ = .;
__HeapLimit = __heap_end__;
} > REGION_HEAP
.stack : ALIGN(0x8) {
_stack = .;
__stack = .;
KEEP(*(.stack))
} > REGION_STACK
}
然后确保您的启动代码初始化了正确的部分(您还将获得一个名为 tm4c123gh6pm_startup_ccs_gcc.c 的文件,其中包含启动代码,或者用作- 是或作为指南。
您会注意到它们在初始化各个部分所需的变量方面做得很好。避免了 user2162550 提出的问题。
顺便说一句 - 我注意到当使用 -O2 链接器错误编译时有点混淆 - 如果你的代码适合关闭它,直到你得到你想要的一切。