Почему внутренние связанные имена появляются в таблице символов моего объектного файла? - PullRequest
1 голос
/ 14 марта 2019

Почему внутренние связанные имена появляются в таблице символов моего объектного файла?

Вопрос не важен. Мне просто любопытно.

Вот пример кода:

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

Используя GNU 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 на static inline, символы исчезнут.

Для справки см. Также этот ответ, , который отвечает на другой вопрос, объясняя, как читать вывод readelf. Мой вопрос, однако, касается не инструмента Readelf как такового, а скорее того, почему компилятор экспортирует символы не из других файлов, насколько мне известно.

Ответы [ 2 ]

1 голос
/ 15 марта 2019

Мой вопрос, однако, не рассматривает инструмент 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 ?? ()
1 голос
/ 14 марта 2019

Включите оптимизатор, и они будут оптимизированы.

Проводник компилятора с -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>
...