我试图允许在输出二进制文件中指定特定符号的位置,而不放弃ld的垃圾收集功能。例如:如果我在MyInclude.h
#ifndef MY_INCLUDE_H_
#define MY_INCLUDE_H_
void CalledFunc(void);
void UncalledFunc(void);
#endif
和一个主程序:
#include "MyInclude.h"
int main(void)
{
CalledFunc();
return 0;
}
使用带有ffunction-sections -fdata-sections
的gcc进行编译,并在地图文件中显示--gc-sections
已删除的.text.UncalledFunc
。
我现在需要将某些功能放在不同的部分。在这个例子中,如果恰好调用UncalledFunc()
,我希望它在一个特殊的部分。我有一个链接器参数文件,如下所示:
MEMORY
{
FLASH (rx) : ORIGIN = 0x10000000, LENGTH = 512K
}
SECTIONS
{
.text.myregion ORIGIN(FLASH):
{
*(.text.myregion)
*(.text.myregion*)
} >FLASH
ASSERT ( . <= 0x10010000, "Too much stuff in myregion!")
.text :
{
*(.text)
*(.text*)
} >FLASH
}
UncalledFunc()
和CalledFunc()
定义为:
void CalledFunc(void) __attribute__ ((section (".text.myregion")))
{
/* ... */
}
void UncalledFunc(void) __attribute__ ((section (".text.myregion")))
{
/* ... */
}
在这种情况下,似乎函数属性会覆盖发送到GCC的每个函数段参数。因此,由于两个函数都在相同的输入部分中,因此它们都出现在输出图像中。有没有办法告诉链接器UncalledFunc()
如果被调用.text.myregion
但仍然删除它?如上所示,myregion
的空间有限,最好不要在那里放置任何不必要的东西。
答案 0 :(得分:2)
编译器正在做它所说的;你要求它把那个功能放在那个部分,那还有什么呢?
然后链接器会在一个部分中看到所有函数,因此垃圾收集不是很有帮助。
我没试过这个,但我想可以简单地为每个函数分配不同的手册名称来解决问题:
void CalledFunc(void) __attribute__ ((section (".text.myregion.CalledFunc")))
{
/* ... */
}
void UncalledFunc(void) __attribute__ ((section (".text.myregion.UncalledFunc")))
{
/* ... */
}
但是,如果这是大量输入(或者如果你使用宏来应用属性),那么它可能会更好:
#define STRINGIFY(S) #S
#define TOSTRING(S) STRINGIFY(S)
#define NAME __FILE__ "." TOSTRING(__LINE__)
void CalledFunc(void) __attribute__ ((section (".text.myregion." NAME)))
{
/* ... */
}
这样你可以通过搜索和替换来完成它,并且每个函数仍然具有唯一的部分名称。 (有必要使用宏,因为__LINE__
是一个整数值,但我们需要一个字符串,而#
“stringify”运算符只能在宏内部使用。显然没有间接性的间接原因__LINE__
将被评估为实际行号。)
可能是__FUNCTION__
宏有效,但鉴于这不在函数体之内,我不自信。
答案 1 :(得分:0)
如果您使用链接时优化,编译器应该能够删除未使用的函数,即使您将所有函数放入公共部分。
所以保留模块(比方说include.c include.h test.c),但是这样构建:
gcc -c -Os -flto include.c -o include.o
gcc -c -Os -flto test.c -o test.o
gcc -flto -Os test.o include.o -o test
这可能(取决于实际代码)内联使用的函数并删除未使用的函数(除非你使用属性noinline。