如何防止链接器丢弃功能? [英] how to prevent linker from discarding a function?
问题描述
我的C代码中有一个函数,该函数被隐式调用,并被链接器转储.我该如何预防这种现象?
我正在使用gcc和链接器标志-gc-sections进行编译,并且我不想从标志中排除整个文件.我尝试使用属性:"used"和"externally_visible",但都没有起作用.
void __attribute__((section(".mySec"), nomicromips, used)) func(){
...
}
在地图文件上,我可以看到该函数已编译但未链接.我使用错了吗?还有其他方法吗?
您误解了 used
属性
使用
此属性附加到函数上,意味着即使该函数似乎未被引用,也必须为该函数发出代码...
即编译器必须发出函数定义,即使函数出现 未被引用.编译器永远不会得出函数未引用的结论 如果具有外部链接.因此,在此程序中:
main1.c
static void foo(void){}
int main(void)
{
return 0;
}
编译为:
$ gcc -c -O1 main1.c
根本没有发布foo
的定义:
$ nm main1.o
0000000000000000 T main
因为在翻译单元中未引用foo
,不在外部,
因此可以进行优化.
但是在此程序中:
main2.c
static void __attribute__((used)) foo(void){}
int main(void)
{
return 0;
}
__attribute__((used))
迫使编译器发出本地定义:
$ gcc -c -O1 main2.c
$ nm main2.o
0000000000000000 t foo
0000000000000001 T main
但这并不能阻止 linker 丢弃某节
在其中定义了foo
且在-gc-sections
存在的情况下,即使foo
是是外部的,也未使用该节:
main3.c
void foo(void){}
int main(void)
{
return 0;
}
使用功能部分进行编译:
$ gcc -c -ffunction-sections -O1 main3.c
foo
的全局定义在目标文件中:
$ nm main3.o
0000000000000000 T foo
0000000000000000 T main
但是在链接之后:
$ gcc -Wl,-gc-sections,-Map=mapfile main3.o
在程序中未定义
foo
:
$ nm a.out | grep foo; echo Done
Done
并删除了定义foo
的功能部分:
地图文件
...
...
Discarded input sections
...
...
.text.foo 0x0000000000000000 0x1 main3.o
...
...
根据Eric Postpischil的评论,强制保留链接器
一个显然未使用的功能部分,您必须告诉它假定该程序
使用链接器选项 {-u|--undefined} foo
引用未使用的函数:>
main4.c
void __attribute__((section(".mySec"))) foo(void){}
int main(void)
{
return 0;
}
如果您不这样说:
$ gcc -c main4.c
$ gcc -Wl,-gc-sections main4.o
$ nm a.out | grep foo; echo Done
Done
程序中未定义
foo
.如果您告诉它:
$ gcc -c main4.c
$ gcc -Wl,-gc-sections,--undefined=foo main4.o
$ nm a.out | grep foo; echo Done
0000000000001191 T foo
Done
已定义.属性used
没有用.
I have a function in my C code that is being called implicitly, and getting dumped by the linker. how can I prevent this phenomena?
I'm compiling using gcc and the linker flag -gc-sections, and I don't want to exclude the whole file from the flag. I tried using attributes: "used" and "externally_visible" and neither has worked.
void __attribute__((section(".mySec"), nomicromips, used)) func(){
...
}
on map file I can see that the function has compiled but didn't linked. am I using it wrong? is there any other way to do it?
You are misunderstanding the used
attribute
used
This attribute, attached to a function, means that code must be emitted for the function even if it appears that the function is not referenced...
i.e the compiler must emit the function definition even the function appears to be unreferenced. The compiler will never conclude that a function is unreferenced if it has external linkage. So in this program:
main1.c
static void foo(void){}
int main(void)
{
return 0;
}
compiled with:
$ gcc -c -O1 main1.c
No definition of foo
is emitted at all:
$ nm main1.o
0000000000000000 T main
because foo
is not referenced in the translation unit, is not external,
and so may be optimised out.
But in this program:
main2.c
static void __attribute__((used)) foo(void){}
int main(void)
{
return 0;
}
__attribute__((used))
compels the compiler to emit the local definition:
$ gcc -c -O1 main2.c
$ nm main2.o
0000000000000000 t foo
0000000000000001 T main
But this does nothing to inhibit the linker from discarding a section
in which foo
is defined, in the presence of -gc-sections
, even if foo
is external, if that section is unused:
main3.c
void foo(void){}
int main(void)
{
return 0;
}
Compile with function-sections:
$ gcc -c -ffunction-sections -O1 main3.c
The global definition of foo
is in the object file:
$ nm main3.o
0000000000000000 T foo
0000000000000000 T main
But after linking:
$ gcc -Wl,-gc-sections,-Map=mapfile main3.o
foo
is not defined in the program:
$ nm a.out | grep foo; echo Done
Done
And the function-section defining foo
was discarded:
mapfile
...
...
Discarded input sections
...
...
.text.foo 0x0000000000000000 0x1 main3.o
...
...
As per Eric Postpischil's comment, to force the linker to retain
an apparently unused function-section you must tell it to assume that the program
references the unused function, with linker option {-u|--undefined} foo
:
main4.c
void __attribute__((section(".mySec"))) foo(void){}
int main(void)
{
return 0;
}
If you don't tell it that:
$ gcc -c main4.c
$ gcc -Wl,-gc-sections main4.o
$ nm a.out | grep foo; echo Done
Done
foo
is not defined in the program. If you do tell it that:
$ gcc -c main4.c
$ gcc -Wl,-gc-sections,--undefined=foo main4.o
$ nm a.out | grep foo; echo Done
0000000000001191 T foo
Done
it is defined. There's no use for attribute used
.
这篇关于如何防止链接器丢弃功能?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!