public inbox for gcc-help@gcc.gnu.org
 help / color / mirror / Atom feed
* -fvisibility-inlines-hidden not hiding inline methods?
@ 2009-07-10 14:00 Lassi Tuura
  2009-07-10 14:51 ` Ian Lance Taylor
  0 siblings, 1 reply; 4+ messages in thread
From: Lassi Tuura @ 2009-07-10 14:00 UTC (permalink / raw)
  To: gcc-help; +Cc: Peter Elmer, Giulio Eulisse

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@GLIBCXX_3.4 (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@GLIBC_2.2.5 (3)
     10: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND  
memmove@GLIBC_2.2.5 (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@GLIBCXX_3.4 (2)
     15: 0000000000001260     0 NOTYPE  GLOBAL DEFAULT  ABS _edata
     16: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND  
__gxx_personality_v0@CXXABI_1.3 (4)
     17: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND  
_Znwm@GLIBCXX_3.4 (2)
     18: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND  
_Unwind_Resume@GCC_3.0 (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>

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: -fvisibility-inlines-hidden not hiding inline methods?
  2009-07-10 14:00 -fvisibility-inlines-hidden not hiding inline methods? Lassi Tuura
@ 2009-07-10 14:51 ` Ian Lance Taylor
  2009-07-10 15:25   ` Lassi Tuura
  0 siblings, 1 reply; 4+ messages in thread
From: Ian Lance Taylor @ 2009-07-10 14:51 UTC (permalink / raw)
  To: Lassi Tuura; +Cc: gcc-help, Peter Elmer, Giulio Eulisse

Lassi Tuura <lat@cern.ch> writes:

> 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.

-fvisibility-inlines-hidden only affects inline methods.  It does not
affect inline functions which are not methods.  E.g., your test cases
uses std::sort, but std::sort is not an inline method of any class.  In
general -fvisibility-inlines-hidden does not apply to template
instantiations, since that would break explicit instantiations.

Ian

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: -fvisibility-inlines-hidden not hiding inline methods?
  2009-07-10 14:51 ` Ian Lance Taylor
@ 2009-07-10 15:25   ` Lassi Tuura
  2009-07-10 19:35     ` Ian Lance Taylor
  0 siblings, 1 reply; 4+ messages in thread
From: Lassi Tuura @ 2009-07-10 15:25 UTC (permalink / raw)
  To: Ian Lance Taylor; +Cc: gcc-help, Peter Elmer, Giulio Eulisse

Hi,

> -fvisibility-inlines-hidden only affects inline methods.  It does not
> affect inline functions which are not methods.  E.g., your test cases
> uses std::sort, but std::sort is not an inline method of any  
> class.  In
> general -fvisibility-inlines-hidden does not apply to template
> instantiations, since that would break explicit instantiations.

Thanks. We do see this happening for members as well such as  
std::vector<T>::_M_insert_aux. Do I understand you correctly the  
option only applies to non-template inline member functions? That  
would be unfortunate as we have by far more template-generated inline  
goo than other origins :-/

Is there any way to override the above restriction to apply to all  
inlines - or at least templates and out-of-class free functions  
included - and/or would a patch to enable such behaviour be accepted?  
Should one expect any major drawbacks for such a change on pretty bog  
standard C++ use, such as standard library or boost?

Is different visibility for template specialisations common for those  
that use the option? I couldn't think of any construct in our code  
that would call for it, and was wondering if there were examples of  
how it's used elsewhere so that I don't misunderstand this feature.

Lassi


^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: -fvisibility-inlines-hidden not hiding inline methods?
  2009-07-10 15:25   ` Lassi Tuura
@ 2009-07-10 19:35     ` Ian Lance Taylor
  0 siblings, 0 replies; 4+ messages in thread
From: Ian Lance Taylor @ 2009-07-10 19:35 UTC (permalink / raw)
  To: Lassi Tuura; +Cc: gcc-help, Peter Elmer, Giulio Eulisse

Lassi Tuura <lat@cern.ch> writes:

>> -fvisibility-inlines-hidden only affects inline methods.  It does not
>> affect inline functions which are not methods.  E.g., your test cases
>> uses std::sort, but std::sort is not an inline method of any  class.
>> In
>> general -fvisibility-inlines-hidden does not apply to template
>> instantiations, since that would break explicit instantiations.
>
> Thanks. We do see this happening for members as well such as
> std::vector<T>::_M_insert_aux. Do I understand you correctly the
> option only applies to non-template inline member functions? That
> would be unfortunate as we have by far more template-generated inline
> goo than other origins :-/
> 
> Is there any way to override the above restriction to apply to all
> inlines - or at least templates and out-of-class free functions
> included - and/or would a patch to enable such behaviour be accepted?
> Should one expect any major drawbacks for such a change on pretty bog
> standard C++ use, such as standard library or boost?
>
> Is different visibility for template specialisations common for those
> that use the option? I couldn't think of any construct in our code
> that would call for it, and was wondering if there were examples of
> how it's used elsewhere so that I don't misunderstand this feature.

I think you understand me correctly.  The problem with templates is that
changing the visibility will break explicit instantiation--that is,
-fvisibility-inlines-hidden will always work as long as you don't
compare function pointers.  I think it would be OK to have an option
which says that you also promise not to use explicit instantiation.

Ian

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2009-07-10 19:35 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2009-07-10 14:00 -fvisibility-inlines-hidden not hiding inline methods? Lassi Tuura
2009-07-10 14:51 ` Ian Lance Taylor
2009-07-10 15:25   ` Lassi Tuura
2009-07-10 19:35     ` Ian Lance Taylor

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).