LLVM 链接器将堆栈放在错误的位置
LLVM linker places stack in the wrong place
我正在尝试 link 使用 clang + lld 的 Cortex-M4 固件。 gcc 构建工作正常。我正在使用 stock CMSIS linker 脚本,仅调整了 RAM 和 ROM 大小(基本相同)。脚本开头(无注释):
__ROM_BASE = 0x00000000;
__ROM_SIZE = 0x00040000; /* 256 KB */
__RAM_BASE = 0x20000000;
__RAM_SIZE = 0x00010000; /* 64 KB */
__STACK_SIZE = 0x00000400;
__HEAP_SIZE = 0x00000C00;
MEMORY
{
FLASH (rx) : ORIGIN = __ROM_BASE, LENGTH = __ROM_SIZE
RAM (rwx) : ORIGIN = __RAM_BASE, LENGTH = __RAM_SIZE
}
在脚本最后的断言 ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed with stack")
上链接失败。如果我删除断言,二进制 link 没问题,但堆栈地址错误。它最终出现在闪存中(堆也在错误的位置)。来自 nm
的输出:
200018a8 B __bss_end__
200000d8 B __bss_start__
00004568 R __copy_table_end__
0000455c R __copy_table_start__
200000d4 D __data_end__
20000000 D __data_start__
00000000 ? __end__
00004570 A __etext
0000455c R __exidx_end
0000454c T __exidx_start
00000c00 A __HEAP_SIZE
00000c00 ? __HeapLimit
200000d4 d __init_array_end
200000d0 d __init_array_start
w __libc_fini_array
00000445 T __libc_init_array
200000d0 d __preinit_array_end
200000d0 d __preinit_array_start
20000000 A __RAM_BASE
00010000 A __RAM_SIZE
00000000 A __ROM_BASE
00040000 A __ROM_SIZE
00000400 ? __stack
00000400 A __STACK_SIZE
00000000 ? __StackLimit
00000400 ? __StackTop
在 Cortex-M 上尝试 运行 时,代码当然会崩溃。我找到了this ticket。如果我将 .stack
部分更改为:
.stack (COPY) :
{
. = ORIGIN(RAM) + LENGTH(RAM) - __STACK_SIZE;
__StackLimit = .;
. = . + __STACK_SIZE;
. = ALIGN(8);
__StackTop = .;
} > RAM
PROVIDE(__stack = __StackTop);
然后我收到溢出错误:
ld.lld: error: section '.stack' will not fit in region 'RAM': overflowed by 536879272 bytes
那个巨大的数字是 0x200020A8 所以 lld
可能正确地得到了结束地址,但不是起点。
如何修复 linker 脚本以将堆栈正确放置在 RAM 顶部?感谢帮助
我通过删除 COPY
并将 NOLOAD
添加到堆栈部分来修复它。它使用 gcc 和 clang 构建和运行良好。
.stack (ORIGIN(RAM) + LENGTH(RAM) - __STACK_SIZE) (NOLOAD) :
{
. = ALIGN(8);
__StackLimit = .;
. = . + __STACK_SIZE;
. = ALIGN(8);
__StackTop = .;
} > RAM
PROVIDE(__stack = __StackTop);
我正在尝试 link 使用 clang + lld 的 Cortex-M4 固件。 gcc 构建工作正常。我正在使用 stock CMSIS linker 脚本,仅调整了 RAM 和 ROM 大小(基本相同)。脚本开头(无注释):
__ROM_BASE = 0x00000000;
__ROM_SIZE = 0x00040000; /* 256 KB */
__RAM_BASE = 0x20000000;
__RAM_SIZE = 0x00010000; /* 64 KB */
__STACK_SIZE = 0x00000400;
__HEAP_SIZE = 0x00000C00;
MEMORY
{
FLASH (rx) : ORIGIN = __ROM_BASE, LENGTH = __ROM_SIZE
RAM (rwx) : ORIGIN = __RAM_BASE, LENGTH = __RAM_SIZE
}
在脚本最后的断言 ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed with stack")
上链接失败。如果我删除断言,二进制 link 没问题,但堆栈地址错误。它最终出现在闪存中(堆也在错误的位置)。来自 nm
的输出:
200018a8 B __bss_end__
200000d8 B __bss_start__
00004568 R __copy_table_end__
0000455c R __copy_table_start__
200000d4 D __data_end__
20000000 D __data_start__
00000000 ? __end__
00004570 A __etext
0000455c R __exidx_end
0000454c T __exidx_start
00000c00 A __HEAP_SIZE
00000c00 ? __HeapLimit
200000d4 d __init_array_end
200000d0 d __init_array_start
w __libc_fini_array
00000445 T __libc_init_array
200000d0 d __preinit_array_end
200000d0 d __preinit_array_start
20000000 A __RAM_BASE
00010000 A __RAM_SIZE
00000000 A __ROM_BASE
00040000 A __ROM_SIZE
00000400 ? __stack
00000400 A __STACK_SIZE
00000000 ? __StackLimit
00000400 ? __StackTop
在 Cortex-M 上尝试 运行 时,代码当然会崩溃。我找到了this ticket。如果我将 .stack
部分更改为:
.stack (COPY) :
{
. = ORIGIN(RAM) + LENGTH(RAM) - __STACK_SIZE;
__StackLimit = .;
. = . + __STACK_SIZE;
. = ALIGN(8);
__StackTop = .;
} > RAM
PROVIDE(__stack = __StackTop);
然后我收到溢出错误:
ld.lld: error: section '.stack' will not fit in region 'RAM': overflowed by 536879272 bytes
那个巨大的数字是 0x200020A8 所以 lld
可能正确地得到了结束地址,但不是起点。
如何修复 linker 脚本以将堆栈正确放置在 RAM 顶部?感谢帮助
我通过删除 COPY
并将 NOLOAD
添加到堆栈部分来修复它。它使用 gcc 和 clang 构建和运行良好。
.stack (ORIGIN(RAM) + LENGTH(RAM) - __STACK_SIZE) (NOLOAD) :
{
. = ALIGN(8);
__StackLimit = .;
. = . + __STACK_SIZE;
. = ALIGN(8);
__StackTop = .;
} > RAM
PROVIDE(__stack = __StackTop);