not sure how relevant is in practice BUT in the example below one may notice that the visibility of "bar" is turned to DEFAULT by lto no lto 17: 0000000000000597 11 FUNC LOCAL HIDDEN 11 bar() lto 11: 0000000000000597 11 FUNC LOCAL DEFAULT 11 bar() .2238 cat vislto.cc void ext(); void bar() __attribute((visibility( "hidden" ))); void foo() __attribute((visibility( "default" ))); void foo() { bar();} void bar() { ext();} g++ -fPIC vislto.cc -Wall -shared -o libvislto.so [vinavx0] ~/public/ctest $ readelf -sW libvislto.so | grep -v UND | sed 's/\./ \./g' | c++filt Symbol table ' .dynsym' contains 11 entries: Num: Value Size Type Bind Vis Ndx Name 2: 0000000000000478 0 FUNC GLOBAL DEFAULT 9 _init 3: 00000000000005e8 0 FUNC GLOBAL DEFAULT 12 _fini 6: 000000000000058c 11 FUNC GLOBAL DEFAULT 11 foo() 8: 00000000000018d0 0 NOTYPE GLOBAL DEFAULT ABS _edata 9: 00000000000018d0 0 NOTYPE GLOBAL DEFAULT ABS __bss_start 10: 00000000000018e0 0 NOTYPE GLOBAL DEFAULT ABS _end Symbol table ' .symtab' contains 31 entries: Num: Value Size Type Bind Vis Ndx Name 1: 00000000000004c0 0 FUNC LOCAL DEFAULT 11 call_gmon_start 2: 0000000000000000 0 FILE LOCAL DEFAULT ABS crtstuff .c 3: 00000000000018a8 0 OBJECT LOCAL DEFAULT 19 __CTOR_LIST__ 4: 00000000000018b8 0 OBJECT LOCAL DEFAULT 20 __DTOR_LIST__ 5: 00000000000018c8 0 OBJECT LOCAL DEFAULT 21 __JCR_LIST__ 6: 00000000000004e0 0 FUNC LOCAL DEFAULT 11 __do_global_dtors_aux 7: 00000000000018d0 1 OBJECT LOCAL DEFAULT 22 completed .5901 8: 00000000000018d8 8 OBJECT LOCAL DEFAULT 22 dtor_idx .5903 9: 0000000000000560 0 FUNC LOCAL DEFAULT 11 frame_dummy 10: 0000000000000000 0 FILE LOCAL DEFAULT ABS vislto .cc 11: 0000000000000000 0 FILE LOCAL DEFAULT ABS crtstuff .c 12: 00000000000018b0 0 OBJECT LOCAL DEFAULT 19 __CTOR_END__ 13: 0000000000000650 0 OBJECT LOCAL DEFAULT 13 __FRAME_END__ 14: 00000000000018c8 0 OBJECT LOCAL DEFAULT 21 __JCR_END__ 15: 00000000000005b0 0 FUNC LOCAL DEFAULT 11 __do_global_ctors_aux 16: 00000000000018a0 0 OBJECT LOCAL HIDDEN 18 __dso_handle 17: 0000000000000597 11 FUNC LOCAL HIDDEN 11 bar() 18: 00000000000018c0 0 OBJECT LOCAL HIDDEN 20 __DTOR_END__ 19: 0000000000001670 496 OBJECT LOCAL HIDDEN 15 _DYNAMIC 20: 0000000000001878 40 OBJECT LOCAL HIDDEN 17 _GLOBAL_OFFSET_TABLE_ 22: 0000000000000478 0 FUNC GLOBAL DEFAULT 9 _init 23: 00000000000005e8 0 FUNC GLOBAL DEFAULT 12 _fini 26: 000000000000058c 11 FUNC GLOBAL DEFAULT 11 foo() 28: 00000000000018d0 0 NOTYPE GLOBAL DEFAULT ABS _edata 29: 00000000000018d0 0 NOTYPE GLOBAL DEFAULT ABS __bss_start 30: 00000000000018e0 0 NOTYPE GLOBAL DEFAULT ABS _end [vinavx0] ~/public/ctest $ g++ -fPIC vislto.cc -Wall -shared -o libvislto.so -flto [vinavx0] ~/public/ctest $ readelf -sW libvislto.so | grep -v UND | sed 's/\./ \./g' | c++filt Symbol table ' .dynsym' contains 11 entries: Num: Value Size Type Bind Vis Ndx Name 2: 0000000000000478 0 FUNC GLOBAL DEFAULT 9 _init 3: 00000000000005e8 0 FUNC GLOBAL DEFAULT 12 _fini 6: 000000000000058c 11 FUNC GLOBAL DEFAULT 11 foo() 8: 00000000000018d0 0 NOTYPE GLOBAL DEFAULT ABS _edata 9: 00000000000018d0 0 NOTYPE GLOBAL DEFAULT ABS __bss_start 10: 00000000000018e0 0 NOTYPE GLOBAL DEFAULT ABS _end Symbol table ' .symtab' contains 31 entries: Num: Value Size Type Bind Vis Ndx Name 1: 00000000000004c0 0 FUNC LOCAL DEFAULT 11 call_gmon_start 2: 0000000000000000 0 FILE LOCAL DEFAULT ABS crtstuff .c 3: 00000000000018a8 0 OBJECT LOCAL DEFAULT 19 __CTOR_LIST__ 4: 00000000000018b8 0 OBJECT LOCAL DEFAULT 20 __DTOR_LIST__ 5: 00000000000018c8 0 OBJECT LOCAL DEFAULT 21 __JCR_LIST__ 6: 00000000000004e0 0 FUNC LOCAL DEFAULT 11 __do_global_dtors_aux 7: 00000000000018d0 1 OBJECT LOCAL DEFAULT 22 completed .5901 8: 00000000000018d8 8 OBJECT LOCAL DEFAULT 22 dtor_idx .5903 9: 0000000000000560 0 FUNC LOCAL DEFAULT 11 frame_dummy 10: 0000000000000000 0 FILE LOCAL DEFAULT ABS cclww4iv .ltrans0 .o 11: 0000000000000597 11 FUNC LOCAL DEFAULT 11 bar() .2238 12: 0000000000000000 0 FILE LOCAL DEFAULT ABS crtstuff .c 13: 00000000000018b0 0 OBJECT LOCAL DEFAULT 19 __CTOR_END__ 14: 0000000000000650 0 OBJECT LOCAL DEFAULT 13 __FRAME_END__ 15: 00000000000018c8 0 OBJECT LOCAL DEFAULT 21 __JCR_END__ 16: 00000000000005b0 0 FUNC LOCAL DEFAULT 11 __do_global_ctors_aux 17: 00000000000018a0 0 OBJECT LOCAL HIDDEN 18 __dso_handle 18: 00000000000018c0 0 OBJECT LOCAL HIDDEN 20 __DTOR_END__ 19: 0000000000001670 496 OBJECT LOCAL HIDDEN 15 _DYNAMIC 20: 0000000000001878 40 OBJECT LOCAL HIDDEN 17 _GLOBAL_OFFSET_TABLE_ 22: 0000000000000478 0 FUNC GLOBAL DEFAULT 9 _init 23: 00000000000005e8 0 FUNC GLOBAL DEFAULT 12 _fini 26: 000000000000058c 11 FUNC GLOBAL DEFAULT 11 foo() 28: 00000000000018d0 0 NOTYPE GLOBAL DEFAULT ABS _edata 29: 00000000000018d0 0 NOTYPE GLOBAL DEFAULT ABS __bss_start 30: 00000000000018e0 0 NOTYPE GLOBAL DEFAULT ABS _end
Honza?
Btw, I consistently do _not_ see HIDDEN here. BFD issue?
So what is happening is bar is being coming localized to the newly produced assembly file which is the same as being hidden really. If we do: void bar() __attribute((visibility( "hidden" ), externally_visible)); The new assembly file in both cases produces: .globl _Z3barv .hidden _Z3barv Without the externally_visible, the function does not have a .globl to it. This is also why in both with and without -flto dynsym does not have the symbol there. There is no bug to be fixed, LTO is doing the localizing rather than the linker doing it.
Note I looked at both with and without the LTO plugin too to make sure it would work in both cases.