c - 如何防止链接器丢弃函数?

标签 c gcc linker attributes

我的 C 代码中有一个函数被隐式调用,并被链接器转储。我怎样才能防止这种现象?

我正在使用 gcc 和链接器标志 -gc-sections 进行编译,我不想从标志中排除整个文件。我尝试使用属性:“used”和“externally_visible”,但都没有用。

void __attribute__((section(".mySec"), nomicromips, used)) func(){
...
}

在映射文件上,我可以看到该函数已编译但未链接。我用错了吗?还有其他方法吗?

最佳答案

您误解了 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...

编译器 必须发出函数定义,即使函数出现 未被引用。编译器永远不会断定函数未被引用 如果它有外部链接。所以在这个程序中:

ma​​in1.c

static void foo(void){}

int main(void)
{
    return 0;
}

编译:

$ gcc -c -O1 main1.c

根本没有发出 foo 的定义:

$ nm main1.o
0000000000000000 T main

因为 foo 在翻译单元中没有被引用,不是外部的, 因此可能会被优化掉。

但是在这个程序中:

ma​​in2.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

但这并不能阻止链接器丢弃一个部分 在 -gc-sections 存在的情况下定义了 foo,即使 foo 外部的,如果该部分未使用:

ma​​in3.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 的函数部分被丢弃了:

map 文件

...
...
Discarded input sections
 ...
 ...
 .text.foo      0x0000000000000000        0x1 main3.o
 ...
 ...

根据 Eric Postpischil 的评论,强制链接器保留 一个明显未使用的功能部分,您必须告诉它假设该程序 引用未使用的函数,带有链接器选项 {-u|--undefined} foo :

ma​​in4.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 属性没有用。

关于c - 如何防止链接器丢弃函数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53985290/

相关文章:

linux - Fedora 下 Firefox 未加载 XPCOM 组件

c++ - 链接器映射文件中的 __unwind$ 是什么

c++ - 在另一个命名空间中使用外部 yyin

c - memmove 和 memcpy 有什么区别?

c - 如何使用 htonl 将小端转换为大端

c - 它在 GCC 源代码的哪个位置编译成不同的汇编语言?

c++ - __restrict 指针别名,只有一个指针

c - 如何解决这个链接描述文件错误?

c - gtkmozembed 段错误

c - 在 FUSE 中更改目录时调用哪个函数?