9

我想获取程序结尾的地址,并在编译/链接器时检查我是否有足够的空间,在代码之后,在执行时放置一些随机数据。

但是由于 PROVIDE 关键字提供的符号就像 C 代码中的普通变量一样,我无法在编译时验证它。

在链接器脚本中,我有符号:

PROVIDE (__data_end_rom   = _etext + SIZEOF (.data));

所以我可以使用这个符号来获取我的代码末尾的地址:

extern u16 __data_end_rom;

如果我假设结束地址为 0xffff,我可以计算可用内存:

#define AVAILABLE_MEM (0Xffff - &__data_end_rom)

我正在考虑使用 gcc 4.6 中提供的 _Static_assert(cond, message) 检查可用内存

_Static_assert(SIZE_I_WANT_TO_ASSURE <= AVAILABLE_MEM, "NOT ENOUGH MEMORY!!!");

我的问题是:宏 AVAILABLE_MEM 不是在编译时计算的,所以我得到了错误:

error: expression in static assertion is not constant

有没有办法直接在标签中或以其他方式提供 __data_end_rom 地址?

我知道我无法在编译时得到它,因为符号只会在链接器时被链接,所以有什么方法可以让链接器失败?

我可以直接在链接器脚本中检查这一点,但我不喜欢这样做,因为 SIZE_I_WANT_TO_ASSURE 是从配置头中的其他宏计算的另一个宏。

4

3 回答 3

7

您可以创建一个包含断言的自定义链接描述文件。看这里

http://sourceware.org/binutils/docs/ld/Miscellaneous-Commands.html

您想使用“断言”机制。

于 2013-11-16T12:29:00.147 回答
7
_Static_assert(SIZE_I_WANT_TO_ASSURE <= AVAILABLE_MEM, "NOT ENOUGH MEMORY!!!");

error: expression in static assertion is not constant

这里的问题是您试图在需要编译时间常量的表达式中比较在构建的链接阶段生成的“常量”(即编译器在编译期间知道的东西)。

#define AVAILABLE_MEM (0Xffff - &__data_end_rom)

编译器不知道 的地址__data_end_rom,只有链接器知道。

不幸的是,我认为在编译时没有办法做到这一点,让编译器告诉你数据太大。另一方面,读取二进制文件的附加脚本(例如size yourprog与一点点awk或其他东西结合使用)应该能够在makefile或类似的东西中提供相关信息。

于 2013-05-30T12:00:25.487 回答
2

您可以在链接脚本本身中执行此操作,如下所示:

/* minimum amount of data required at end of .text */
_Min_Data_Left 0Xffff;

.text : 
{
... all the usual stuff ...
PROVIDE (__data_end_rom  = . );
. = . + _Min_Data_Left;
. = ALIGN(4);
} >FLASH

链接器现在会告诉您,如果您超出限制,则 FLASH 已溢出 - 编译将失败,我知道这就是您想要的。

这是一种常用的方法来确保最小数量的堆栈和堆可用。这是一个版本 - 查找 _Min_Heap_Size 和 _Min_Stack_Size:https ://github.com/pingdynasty/OwlWare/blob/master/Source/flash.ld

出于好奇,您将如何处理 .text 中的额外空间 - 我假设这是在 Flash 中?

于 2015-05-25T23:34:58.407 回答