Hi,
We are using GCC 4.3.2 + binutils 2.19.1 on a RHEL4-derived system.
We're testing -fvisibility-inlines-hidden, and don't quite understand
what it does. We are seeing some but not all inline functions getting
emitted out-of-line as public weak symbols and calls to them going
via the PLT; the documentation seems to indicate this would not happen.
I've stared at this for a while and fail to see the logic by which
something is emitted as hidden or as a (weak) default visibility
symbols. We use several libraries beyond the standard library, and in
any shared library we may have 2/3rds declared default and 1/3rd
declared hidden for example (e.g. for boost).
I've made below a very simple example using a std::vector and
std::sort. As you can see from the readelf and objdump outputs
attached below, calls to local inlined functions have default
visibility and go via PLT, so it seems -fvisibility-inlines-hidden
didn't really achieve its purpose here.
Have we misunderstood the intended behaviour or is there a bug or
incompatibility here somewhere?
Regards,
Lassi
$ cat foo.cc
#include <vector>
#include <algorithm>
int foo(int *a, int *b)
{
std::vector<int> x(a, b);
std::sort(x.begin(), x.end());
return x[0];
}
$ c++ -v
Using built-in specs.
Target: x86_64-unknown-linux-gnu
Configured with: ../configure --prefix=/build/31c/slc4_amd64_gcc432/
external/gcc/4.3.2 --enable-languages=c,c++,fortran --with-gmp=/build/
31c/slc4_amd64_gcc432/external/gcc/4.3.2/tmp/gmp --with-mpfr=/build/
31c/slc4_amd64_gcc432/external/gcc/4.3.2/tmp/mpfr --enable-shared
Thread model: posix
gcc version 4.3.2 (GCC)
$ as --version
GNU assembler (GNU Binutils) 2.19.1
Copyright 2007 Free Software Foundation, Inc.
This program is free software; you may redistribute it under the
terms of
the GNU General Public License version 3 or later.
This program has absolutely no warranty.
This assembler was configured for a target of `x86_64-unknown-linux-
gnu'.
$ ld --version
GNU ld (GNU Binutils) 2.19.1
Copyright 2007 Free Software Foundation, Inc.
This program is free software; you may redistribute it under the
terms of
the GNU General Public License version 3 or (at your option) a later
version.
This program has absolutely no warranty.
$ c++ -shared -o libfoo.so -fPIC -fvisibility-inlines-hidden -O2 -W -
Wall foo.cc
$ readelf -Ws libfoo.so | awk '/dynsym/,/^$/ {print}{}'
Symbol table '.dynsym' contains 20 entries:
Num: Value Size Type Bind Vis Ndx Name
0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND
1: 00000000000007a0 0 SECTION LOCAL DEFAULT 8
2: 0000000000000a80 242 FUNC WEAK DEFAULT 10
_ZSt13__adjust_heapIN9__gnu_cxx17__normal_iteratorIPiSt6vectorIiSaIiEEEE
liEvT_T0_S8_T1_
3: 0000000000000940 314 FUNC GLOBAL DEFAULT 10 _Z3fooPiS_
4: 0000000000000000 0 NOTYPE WEAK DEFAULT UND
__gmon_start__
5: 0000000000000000 0 NOTYPE WEAK DEFAULT UND
_Jv_RegisterClasses
6: 0000000000000000 0 FUNC GLOBAL DEFAULT UND
_ZdlPv@xxxxxxxxxxx (2)
7: 0000000000000dc8 0 FUNC GLOBAL DEFAULT 11 _fini
8: 0000000000000b80 365 FUNC WEAK DEFAULT 10
_ZSt16__introsort_loopIN9__gnu_cxx17__normal_iteratorIPiSt6vectorIiSaIiE
EEElEvT_S7_T0_
9: 0000000000000000 0 FUNC WEAK DEFAULT UND
__cxa_finalize@xxxxxxxxxxx (3)
10: 0000000000000000 0 FUNC GLOBAL DEFAULT UND
memmove@xxxxxxxxxxx (3)
11: 0000000000001260 0 NOTYPE GLOBAL DEFAULT ABS __bss_start
12: 0000000000001270 0 NOTYPE GLOBAL DEFAULT ABS _end
13: 0000000000000cf0 155 FUNC WEAK DEFAULT 10
_ZSt16__insertion_sortIN9__gnu_cxx17__normal_iteratorIPiSt6vectorIiSaIiE
EEEEvT_S7_
14: 0000000000000000 0 FUNC GLOBAL DEFAULT UND
_ZSt17__throw_bad_allocv@xxxxxxxxxxx (2)
15: 0000000000001260 0 NOTYPE GLOBAL DEFAULT ABS _edata
16: 0000000000000000 0 FUNC GLOBAL DEFAULT UND
__gxx_personality_v0@xxxxxxxxxx (4)
17: 0000000000000000 0 FUNC GLOBAL DEFAULT UND
_Znwm@xxxxxxxxxxx (2)
18: 0000000000000000 0 FUNC GLOBAL DEFAULT UND
_Unwind_Resume@xxxxxxx (5)
19: 00000000000007a0 0 FUNC GLOBAL DEFAULT 8 _init
$ objdump -j .plt -d libfoo.so
libfoo.so: file format elf64-x86-64
Disassembly of section .plt:
00000000000007b8
<_ZSt13__adjust_heapIN9__gnu_cxx17__normal_iteratorIPiSt6vectorIiSaIiEEE
EliEvT_T0_S8_T1_@plt-0x10>:
7b8: ff 35 3a 0a 00 00 pushq 0xa3a(%rip) # 11f8
<_GLOBAL_OFFSET_TABLE_+0x8>
7be: ff 25 3c 0a 00 00 jmpq *0xa3c(%rip) # 1200
<_GLOBAL_OFFSET_TABLE_+0x10>
7c4: 0f 1f 40 00 nopl 0x0(%rax)
00000000000007c8
<_ZSt13__adjust_heapIN9__gnu_cxx17__normal_iteratorIPiSt6vectorIiSaIiEEE
EliEvT_T0_S8_T1_@plt>:
7c8: ff 25 3a 0a 00 00 jmpq *0xa3a(%rip) # 1208
<_GLOBAL_OFFSET_TABLE_+0x18>
7ce: 68 00 00 00 00 pushq $0x0
7d3: e9 e0 ff ff ff jmpq 7b8 <_init+0x18>
00000000000007d8 <_ZdlPv@plt>:
7d8: ff 25 32 0a 00 00 jmpq *0xa32(%rip) # 1210
<_GLOBAL_OFFSET_TABLE_+0x20>
7de: 68 01 00 00 00 pushq $0x1
7e3: e9 d0 ff ff ff jmpq 7b8 <_init+0x18>
00000000000007e8
<_ZSt16__introsort_loopIN9__gnu_cxx17__normal_iteratorIPiSt6vectorIiSaIi
EEEElEvT_S7_T0_@plt>:
7e8: ff 25 2a 0a 00 00 jmpq *0xa2a(%rip) # 1218
<_GLOBAL_OFFSET_TABLE_+0x28>
7ee: 68 02 00 00 00 pushq $0x2
7f3: e9 c0 ff ff ff jmpq 7b8 <_init+0x18>
00000000000007f8 <__cxa_finalize@plt>:
7f8: ff 25 22 0a 00 00 jmpq *0xa22(%rip) # 1220
<_GLOBAL_OFFSET_TABLE_+0x30>
7fe: 68 03 00 00 00 pushq $0x3
803: e9 b0 ff ff ff jmpq 7b8 <_init+0x18>
0000000000000808 <memmove@plt>:
808: ff 25 1a 0a 00 00 jmpq *0xa1a(%rip) # 1228
<_GLOBAL_OFFSET_TABLE_+0x38>
80e: 68 04 00 00 00 pushq $0x4
813: e9 a0 ff ff ff jmpq 7b8 <_init+0x18>
0000000000000818
<_ZSt16__insertion_sortIN9__gnu_cxx17__normal_iteratorIPiSt6vectorIiSaIi
EEEEEvT_S7_@plt>:
818: ff 25 12 0a 00 00 jmpq *0xa12(%rip) # 1230
<_GLOBAL_OFFSET_TABLE_+0x40>
81e: 68 05 00 00 00 pushq $0x5
823: e9 90 ff ff ff jmpq 7b8 <_init+0x18>
0000000000000828 <_ZSt17__throw_bad_allocv@plt>:
828: ff 25 0a 0a 00 00 jmpq *0xa0a(%rip) # 1238
<_GLOBAL_OFFSET_TABLE_+0x48>
82e: 68 06 00 00 00 pushq $0x6
833: e9 80 ff ff ff jmpq 7b8 <_init+0x18>
0000000000000838 <_Znwm@plt>:
838: ff 25 02 0a 00 00 jmpq *0xa02(%rip) # 1240
<_GLOBAL_OFFSET_TABLE_+0x50>
83e: 68 07 00 00 00 pushq $0x7
843: e9 70 ff ff ff jmpq 7b8 <_init+0x18>
0000000000000848 <_Unwind_Resume@plt>:
848: ff 25 fa 09 00 00 jmpq *0x9fa(%rip) # 1248
<_GLOBAL_OFFSET_TABLE_+0x58>
84e: 68 08 00 00 00 pushq $0x8
853: e9 60 ff ff ff jmpq 7b8 <_init+0x18>
$ objdump -j .text -d libfoo.so | grep "callq.*@plt"
8a1: e8 52 ff ff ff callq 7f8 <__cxa_finalize@plt>
975: e8 be fe ff ff callq 838 <_Znwm@plt>
98b: e8 78 fe ff ff callq 808 <memmove@plt>
9c0: e8 23 fe ff ff callq 7e8
<_ZSt16__introsort_loopIN9__gnu_cxx17__normal_iteratorIPiSt6vectorIiSaIi
EEEElEvT_S7_T0_@plt>
9d5: e8 3e fe ff ff callq 818
<_ZSt16__insertion_sortIN9__gnu_cxx17__normal_iteratorIPiSt6vectorIiSaIi
EEEEEvT_S7_@plt>
a29: e8 aa fd ff ff callq 7d8 <_ZdlPv@plt>
a3b: e8 d8 fd ff ff callq 818
<_ZSt16__insertion_sortIN9__gnu_cxx17__normal_iteratorIPiSt6vectorIiSaIi
EEEEEvT_S7_@plt>
a50: e8 d3 fd ff ff callq 828
<_ZSt17__throw_bad_allocv@plt>
a65: e8 6e fd ff ff callq 7d8 <_ZdlPv@plt>
a6d: e8 d6 fd ff ff callq 848 <_Unwind_Resume@plt>
a75: e8 ce fd ff ff callq 848 <_Unwind_Resume@plt>
c34: e8 af fb ff ff callq 7e8
<_ZSt16__introsort_loopIN9__gnu_cxx17__normal_iteratorIPiSt6vectorIiSaIi
EEEElEvT_S7_T0_@plt>
c7e: e8 45 fb ff ff callq 7c8
<_ZSt13__adjust_heapIN9__gnu_cxx17__normal_iteratorIPiSt6vectorIiSaIiEEE
EliEvT_T0_S8_T1_@plt>
cb3: e8 10 fb ff ff callq 7c8
<_ZSt13__adjust_heapIN9__gnu_cxx17__normal_iteratorIPiSt6vectorIiSaIiEEE
EliEvT_T0_S8_T1_@plt>
d6d: e8 96 fa ff ff callq 808 <memmove@plt>