为什么内部链接的名称会出现在目标文件的符号表中?

时间:2019-03-14 02:15:28

标签: c++ elf linkage object-files

为什么内部链接的名称会出现在目标文件的符号表中?

这个问题并不重要。我只是好奇。

这是示例代码:

Default$default <- as.numeric(Default$default == "Yes")

使用GNU的namespace { static int foo() {return 10;} } static int bar() {return 20;} ,可以在目标文件的符号表中找到以下两个条目:

readelf -s foobar.o | c++filt -t

尚未要求编译器发出调试符号。

我偶然发现,如果我将 Value Size Type Bind Vis Ndx Name 00000000 11 FUNC LOCAL DEFAULT 1 (anonymous namespace)::foo() 0000000b 11 FUNC LOCAL DEFAULT 1 bar() 更改为static,这些符号就会消失。

作为参考,另请参见this answer,,它回答了一个不同的问题,解释了如何读取static inline的输出。但是,我的问题不是将Readelf工具本身视为问题,而是为什么编译器将根据我所知的需要不导出任何其他文件的符号。

2 个答案:

答案 0 :(得分:1)

打开优化器,它们就会被优化掉。

带有-O0的编译器资源管理器:https://godbolt.org/z/xyOBgN
带有-O2的编译器资源管理器:https://godbolt.org/z/OlPQu3

请注意,打开优化程序后,如何不生成程序集。

如果这些链接对您不起作用,或者您不想打开它们,则它们都具有从问题编译到使用g ++进行汇编的代码。第一个链接禁用了优化器,生成了以下程序集:

(anonymous namespace)::foo():
        push    rbp
        mov     rbp, rsp
        mov     eax, 10
        pop     rbp
        ret
bar():
        push    rbp
        mov     rbp, rsp
        mov     eax, 20
        pop     rbp
        ret

启用优化程序的程序集具有以下程序集输出:

<No assembly generated>

答案 1 :(得分:1)

  

但是,我的问题不是将Readelf工具本身视为问题,而是为什么编译器将根据我所知的需要而不导出其他文件。

编译器导出这些符号(它们具有LOCAL绑定)。

编译器只是为它们创建符号表条目,以简化调试。

  

尚未要求编译器发出调试符号。

即使没有调试符号,符号表中的(非调试)符号对于调试也很有用。考虑:

#include <stdlib.h>

namespace {
    static int foo() {abort();}
}
static int bar() {return 20 + foo();}

int main() { return bar(); }


g++ t.cc && gdb -q ./a.out


(gdb) run
Starting program: /tmp/a.out 

Program received signal SIGABRT, Aborted.
__GI_raise (sig=sig@entry=6) at ../sysdeps/unix/sysv/linux/raise.c:51
51  ../sysdeps/unix/sysv/linux/raise.c: No such file or directory.
(gdb) bt
#0  __GI_raise (sig=sig@entry=6) at ../sysdeps/unix/sysv/linux/raise.c:51
#1  0x00007ffff7a6e3fa in __GI_abort () at abort.c:89
#2  0x0000555555554653 in (anonymous namespace)::foo() ()
#3  0x000055555555465c in bar() ()
#4  0x000055555555466a in main ()

请注意第2帧和第3帧有多有用。如果您不希望发生这种情况,可以随时删除符号:

gcc t.cc -Wl,--strip-all && gdb -q ./a.out

(gdb) run
Starting program: /tmp/a.out 

Program received signal SIGABRT, Aborted.
__GI_raise (sig=sig@entry=6) at ../sysdeps/unix/sysv/linux/raise.c:51
51  ../sysdeps/unix/sysv/linux/raise.c: No such file or directory.
(gdb) bt
#0  __GI_raise (sig=sig@entry=6) at ../sysdeps/unix/sysv/linux/raise.c:51
#1  0x00007ffff7a6e3fa in __GI_abort () at abort.c:89
#2  0x0000555555554653 in ?? ()
#3  0x000055555555465c in ?? ()
#4  0x000055555555466a in ?? ()
#5  0x00007ffff7a5a2b1 in __libc_start_main (main=0x555555554661, argc=1, argv=0x7fffffffde08, init=<optimized out>, fini=<optimized out>, rtld_fini=<optimized out>, stack_end=0x7fffffffddf8)
    at ../csu/libc-start.c:291
#6  0x000055555555456a in ?? ()