GCC行为未解决的薄弱功能

问题描述 投票:4回答:2

考虑下面的简单程序:

__attribute__((weak)) void weakf(void);

int main(int argc, char *argv[])
{
        weakf();
}

当用gcc编译这和Linux的PC上运行它,它出现segfaults。当在ARM CM0(臂-NONE-EABI-GCC)运行它,所述接头通过一个跳转到下面的指令和NOP取代未定义的符号。

这哪里是行为记录?有可能的方式通过命令行选项来改变它呢?我公司已通过GCCLD文档,也没有这方面的消息。

如果我检查不过ARM编译器文档,this is clearly explained

c gcc arm ld weak
2个回答
1
投票

man nm

我读了一些文档,碰巧遇到了这样的相关报价:

man nm

说:

“V” “V”的符号是一个弱对象。当弱定义的符号与正常定义的符号链接,正常的定义的符号在使用时没有错误。当弱未定义的符号链接,并且不定义的符号时,弱符号的值变为零,没有错误。在某些系统中,大写字母表示默认值已指定。

“W” “W”的标志是尚未具体标记为弱对象符号的弱符号。当弱定义的符号与正常定义的符号链接,正常的定义的符号在使用时没有错误。当弱未定义的符号链接,并且不定义的符号,符号的值在系统特定的方式没有错误确定。在某些系统中,大写字母表示默认值已指定。

nm是Binutils的,这GCC引擎盖下使用的一部分,所以这应该是足够的规范。

然后,例如在你的源文件:

main.c中

__attribute__((weak)) void weakf(void);

int main(int argc, char *argv[])
{
        weakf();
}

我们的确是:

gcc -O0 -ggdb3 -std=c99 -Wall -Wextra -pedantic -o main.out main.c
nm main.out

其中包含:

w weakf

因此它是一个系统特定的值。我找不到在每个系统的行为无论如何定义。我不认为你可以做的比这里读书Binutils的源码更好。

v将被固定为0,但用于未定义的变量(其为对象):How to make weak linking work with GCC?

然后:

gdb -batch -ex 'disassemble/rs main' main.out

得到:

Dump of assembler code for function main:
main.c:
4       {
   0x0000000000001135 <+0>:     55      push   %rbp
   0x0000000000001136 <+1>:     48 89 e5        mov    %rsp,%rbp
   0x0000000000001139 <+4>:     48 83 ec 10     sub    $0x10,%rsp
   0x000000000000113d <+8>:     89 7d fc        mov    %edi,-0x4(%rbp)
   0x0000000000001140 <+11>:    48 89 75 f0     mov    %rsi,-0x10(%rbp)

5               weakf();
   0x0000000000001144 <+15>:    e8 e7 fe ff ff  callq  0x1030 <weakf@plt>
   0x0000000000001149 <+20>:    b8 00 00 00 00  mov    $0x0,%eax

6       }
   0x000000000000114e <+25>:    c9      leaveq 
   0x000000000000114f <+26>:    c3      retq   
End of assembler dump.

这意味着它得到resolved at the PLT

然后,因为我不完全理解PLT,我用实验来验证它解析为地址0和段错误:

gdb -nh -ex run -ex bt main.out

我假设同样发生在ARM,它必须只将其设置为0为好。


0
投票

在用gcc ARM这个代码不适合我(在测试的ARMv7与海湾合作委员会的Debian 4.6.3-14 + rpi1)工作。它看起来像ARM编译器工具链有不同的行为。

我没有找到有用的文档,此行为。看来,weakf等于NULL,如果是取消定义在链接时。

因此,我建议你测试一下:

if (weakf == NULL) printf ("weakf not found\n");
else weakf();
© www.soinside.com 2019 - 2024. All rights reserved.