可以在C代码中将链接器脚本符号地址作为编译时常量值吗?

时间:2013-05-30 11:52:56

标签: c gcc embedded linker-scripts bare-metal

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

但是由于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是从配置头中的其他宏计算的另一个宏。

3 个答案:

答案 0 :(得分:6)

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

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

你想使用'ASSERT'机制。

答案 1 :(得分:4)

_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中提供相关信息或类似的东西。

答案 2 :(得分:1)

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

/* 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中?