我在连接我的项目时遇到了问题。我使用来自制造商的GCC链接器脚本。
在这里,我定义了如下代码段:
MEMORY
{
// .. deleted other sections
CODE (rx ) : ORIGIN = 0x0000B000, LENGTH = 0x00074000 /* 116 page(s) */
// .. deleted other sections
}
因此,代码段开始位于0xB 000,长度为0x 74000。长度为116 x4096字节=>475136字节代码大小
我的二进制版本大小如下:
text data bss dec hex filename
432372 0 112048 522420 7f8b4 project.elf
因此,它应该链接OK,因为使用的大小432372(文本+数据)比可用空间475136小得多。
只要二进制代码大小< ~ 422 kBytes,它就可以链接,一旦它变大,链接器告诉我CODE部分溢出,无法链接。
有人能解释一下为什么吗?我看不出链接告诉我我的代码太大的原因,因为它不是!
链接脚本
MEMORY
{
// ... removed sections here .. irelevant for discussion ...
CODE (rx ) : ORIGIN = 0x0000B000, LENGTH = 0x00074000 /* 116 page(s) */
// ... removed sections here .. irelevant for discussion ...
RAM (xrw) : ORIGIN = 0x20000040, LENGTH = 20000
MEMORY_B1 (rx ) : ORIGIN = 0x60000000, LENGTH = 0K
}
/* The '__stack' definition is required by crt0, do not remove it */
__stack = ORIGIN(RAM) + LENGTH(RAM);
_estack = __stack;
__Main_Stack_Size = 2048 ;
PROVIDE ( _Main_Stack_Size = __Main_Stack_Size ) ;
__Main_Stack_Limit = __stack - __Main_Stack_Size ;
/*"PROVIDE" allows to easily override these values from an object file or the command line. */
PROVIDE ( _Main_Stack_Limit = __Main_Stack_Limit ) ;
/*
* There will be a link error if there is not this amount of
* RAM free at the end.
*/
_Minimum_Stack_Size = 2048 ;
/*
* Default heap definitions.
* The heap start immediately after the last statically allocated
* .sbss/.noinit section, and extends up to the main stack limit.
*/
/*PROVIDE ( _Heap_Begin = _end_noinit ) ; */
/*PROVIDE ( _Heap_Limit = _end_noinit ) ; */
_Min_Heap_Size = 0x100; /* required amount of heap (256 bytes) */
_Min_Stack_Size = 0x400; /* required amount of stack (1kByte) */
ENTRY(Reset_Handler)
SECTIONS
{
.text :
{
KEEP(*(.vectors))
__Vectors_End = .;
__Vectors_Size = __Vectors_End - __Vectors;
__end__ = .;
*(.text*)
KEEP(*(.init))
KEEP(*(.fini))
/* .ctors */
*crtbegin.o(.ctors)
*crtbegin?.o(.ctors)
*(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors)
*(SORT(.ctors.*))
*(.ctors)
/* .dtors */
*crtbegin.o(.dtors)
*crtbegin?.o(.dtors)
*(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors)
*(SORT(.dtors.*))
*(.dtors)
*(.rodata*)
KEEP(*(.eh_frame*))
} > CODE
.ARM.extab :
{
*(.ARM.extab* .gnu.linkonce.armextab.*)
} > CODE
__exidx_start = .;
.ARM.exidx :
{
*(.ARM.exidx* .gnu.linkonce.armexidx.*)
} > CODE
__exidx_end = .;
/* To copy multiple ROM to RAM sections,
* uncomment .copy.table section and,
* define __STARTUP_COPY_MULTIPLE in startup_ARMCMx.S */
/*
.copy.table :
{
. = ALIGN(4);
__copy_table_start__ = .;
LONG (__etext)
LONG (__data_start__)
LONG (__data_end__ - __data_start__)
LONG (__etext2)
LONG (__data2_start__)
LONG (__data2_end__ - __data2_start__)
__copy_table_end__ = .;
} > CODE
*/
/* To clear multiple BSS sections,
* uncomment .zero.table section and,
* define __STARTUP_CLEAR_BSS_MULTIPLE in startup_ARMCMx.S */
/*
.zero.table :
{
. = ALIGN(4);
__zero_table_start__ = .;
LONG (__bss_start__)
LONG (__bss_end__ - __bss_start__)
LONG (__bss2_start__)
LONG (__bss2_end__ - __bss2_start__)
__zero_table_end__ = .;
} > CODE
*/
__etext = .;
.data : AT (__etext)
{
__data_start__ = .;
*(vtable)
*(.data*)
. = ALIGN (4);
*(.ram)
. = ALIGN(4);
/* preinit data */
PROVIDE_HIDDEN (__preinit_array_start = .);
KEEP(*(.preinit_array))
PROVIDE_HIDDEN (__preinit_array_end = .);
. = ALIGN(4);
/* init data */
PROVIDE_HIDDEN (__init_array_start = .);
KEEP(*(SORT(.init_array.*)))
KEEP(*(.init_array))
PROVIDE_HIDDEN (__init_array_end = .);
. = ALIGN(4);
/* finit data */
PROVIDE_HIDDEN (__fini_array_start = .);
KEEP(*(SORT(.fini_array.*)))
KEEP(*(.fini_array))
PROVIDE_HIDDEN (__fini_array_end = .);
KEEP(*(.jcr*))
. = ALIGN(4);
/* All data end */
__data_end__ = .;
} > RAM
.bss :
{
. = ALIGN(4);
__bss_start__ = .;
*(.bss*)
*(COMMON)
. = ALIGN(4);
__bss_end__ = .;
} > RAM
.heap (COPY):
{
__HeapBase = .;
__end__ = .;
end = __end__;
_end = __end__;
KEEP(*(.heap*))
__HeapLimit = .;
} > RAM
/* .stack_dummy section doesn't contains any symbols. It is only
* used for linker to calculate size of stack sections, and assign
* values to stack symbols later */
.stack_dummy (COPY):
{
KEEP(*(.stack*))
} > RAM
/* Set stack top to end of RAM, and stack limit move down by
* size of stack_dummy section */
__StackTop = ORIGIN(RAM) + LENGTH(RAM);
__StackLimit = __StackTop - SIZEOF(.stack_dummy);
PROVIDE(__stack = __StackTop);
/* Check if data + heap + stack exceeds RAM limit */
ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed with stack")
/* Check if CODE usage exceeds CODE size */
ASSERT( LENGTH(CODE) >= (__etext + SIZEOF(.data)), "CODE memory overflowed !")
}
在最后一行,我Assert代码大小:
/* Check if CODE usage exceeds CODE size */
ASSERT( LENGTH(CODE) >= (__etext + SIZEOF(.data)), "CODE memory overflowed !")
__etext应该是文本(代码)使用的实际大小,.data应该为零
1条答案
按热度按时间hgncfbus1#
有人能解释一下为什么吗?
查看链接器脚本:
CODE (rx ) : ORIGIN = 0x0000B000, LENGTH = 0x00074000 /* 116 page(s) */
0x 74000十六进制是475136十进制,或464 KB。
__etext应该是文本(代码)使用的实际大小,.data应该为零
不是根据链接器脚本。在发布的脚本中,__etext是代码段的结束地址。或者简单地说,代码段的大小加上它的起始地址(非零)。
换句话说,最后一个ASSERT()编码错误,过早地释放了0xB 000字节。0x 74000 - 0xB 000 = 0x 69000(或430080十进制)。