Bug 50348

Summary: -fvisibility=hidden doesn't hide stl implementation details.
Product: gcc Reporter: Pawel Sikora <pawel_sikora>
Component: libstdc++Assignee: Not yet assigned to anyone <unassigned>
Status: RESOLVED DUPLICATE    
Severity: normal CC: jason, vincenzo.innocente
Priority: P3    
Version: 4.6.2   
Target Milestone: ---   
Host: Target:
Build: Known to work:
Known to fail: Last reconfirmed:

Description Pawel Sikora 2011-09-10 15:58:56 UTC
$ cat x.hpp
#ifndef x_hpp
#define x_hpp

#include <vector>
struct X { void foo(); };
typedef std::vector< X > VX;
VX bar() __attribute((visibility( "default" )));

#endif

$ cat x.cpp
#include "x.hpp"
VX bar() { return VX(); }


$ g++ -fvisibility=hidden -fvisibility-inlines-hidden -fPIC x.cpp -Wall -shared -o libx.so -s
$ readelf -sW libx.so | grep -v UND | c++filt

Symbol table '.dynsym' contains 20 entries:
   Num:    Value          Size Type    Bind   Vis      Ndx Name
     2: 00000000000007b0     0 FUNC    GLOBAL DEFAULT   10 _init
     3: 00000000000009f8     0 FUNC    GLOBAL DEFAULT   13 _fini
     6: 000000000000090c    30 FUNC    GLOBAL DEFAULT   12 bar()
     7: 000000000000092a    26 FUNC    WEAK   DEFAULT   12 std::vector<X, std::allocator<X> >::vector()
     8: 000000000000092a    26 FUNC    WEAK   DEFAULT   12 std::vector<X, std::allocator<X> >::vector()
     9: 0000000000000944    26 FUNC    WEAK   DEFAULT   12 std::_Vector_base<X, std::allocator<X> >::_Vector_base()
    10: 000000000000095e    61 FUNC    WEAK   DEFAULT   12 std::_Vector_base<X, std::allocator<X> >::_Vector_impl::_Vector_impl()
    11: 000000000000095e    61 FUNC    WEAK   DEFAULT   12 std::_Vector_base<X, std::allocator<X> >::_Vector_impl::_Vector_impl()
    12: 000000000000099c    26 FUNC    WEAK   DEFAULT   12 std::allocator<X>::allocator()
    13: 00000000000009b6    10 FUNC    WEAK   DEFAULT   12 __gnu_cxx::new_allocator<X>::new_allocator()
    14: 0000000000000944    26 FUNC    WEAK   DEFAULT   12 std::_Vector_base<X, std::allocator<X> >::_Vector_base()
    15: 000000000000099c    26 FUNC    WEAK   DEFAULT   12 std::allocator<X>::allocator()
    16: 00000000000009b6    10 FUNC    WEAK   DEFAULT   12 __gnu_cxx::new_allocator<X>::new_allocator()
    17: 0000000000001dc0     0 NOTYPE  GLOBAL DEFAULT  ABS _edata
    18: 0000000000001dc0     0 NOTYPE  GLOBAL DEFAULT  ABS __bss_start
    19: 0000000000001dd0     0 NOTYPE  GLOBAL DEFAULT  ABS _end


imho the std::vector details shouldn't have default visiblity in this case.
Comment 1 Paolo Carlini 2011-09-11 15:18:14 UTC
I'm not an expert here, but I have an hard time believing this is a library issue. I can see that we have been doing, for a lot of time:

  namespace std _GLIBCXX_VISIBILITY(default)
  {

Is this wrong?!? Jason?
Comment 2 Paolo Carlini 2011-09-22 00:29:43 UTC
Jason, could you please help me triaging this PR? Should the library do something else here? Thanks!
Comment 3 vincenzo Innocente 2011-09-22 11:05:21 UTC
I did a small test removing the visibily just in stl_vector.h
grep namespace /afs/cern.ch/user/i/innocent/w2/lib/gcc/x86_64-unknown-linux-gnu/4.7.0/../../../../include/c++/4.7.0/bits/stl_vector.h
namespace std /* _GLIBCXX_VISIBILITY(default) */
and got
++ -fvisibility=hidden -fvisibility-inlines-hidden -fPIC bha.cc -Wall -shared -o libx.so 
[vinavx0] ~/public/ctest $ readelf -sW libx.so | grep -v UND | sed 's/.local/ .local/g' | c++filt

Symbol table '.dynsym' contains 14 entries:
   Num:    Value          Size Type    Bind   Vis      Ndx Name
     2: 0000000000000540     0 FUNC    GLOBAL DEFAULT    9 _init
     3: 0000000000000758     0 FUNC    GLOBAL DEFAULT   12 _fini
     6: 000000000000066c    30 FUNC    GLOBAL DEFAULT   11 bar()
     7: 00000000000006fc    26 FUNC    WEAK   DEFAULT   11 std::allocator<X>::allocator()
     8: 00000000000006fc    26 FUNC    WEAK   DEFAULT   11 std::allocator<X>::allocator()
     9: 0000000000000716    10 FUNC    WEAK   DEFAULT   11 __gnu_cxx::new_allocator<X>::new_allocator()
    10: 0000000000000716    10 FUNC    WEAK   DEFAULT   11 __gnu_cxx::new_allocator<X>::new_allocator()
    11: 0000000000001ae8     0 NOTYPE  GLOBAL DEFAULT  ABS _edata
    12: 0000000000001ae8     0 NOTYPE  GLOBAL DEFAULT  ABS __bss_start
    13: 0000000000001af8     0 NOTYPE  GLOBAL DEFAULT  ABS _end

Symbol table '.symtab' contains 39 entries:
   Num:    Value          Size Type    Bind   Vis      Ndx Name
     1: 00000000000005a0     0 FUNC    LOCAL  DEFAULT   11 call_gmon_start
     2: 0000000000000000     0 FILE    LOCAL  DEFAULT  ABS crtstuff.c
     3: 0000000000001ac0     0 OBJECT  LOCAL  DEFAULT   19 __CTOR_LIST__
     4: 0000000000001ad0     0 OBJECT  LOCAL  DEFAULT   20 __DTOR_LIST__
     5: 0000000000001ae0     0 OBJECT  LOCAL  DEFAULT   21 __JCR_LIST__
     6: 00000000000005c0     0 FUNC    LOCAL  DEFAULT   11 __do_global_dtors_aux
     7: 0000000000001ae8     1 OBJECT  LOCAL  DEFAULT   22 completed.5901
     8: 0000000000001af0     8 OBJECT  LOCAL  DEFAULT   22 dtor_idx.5903
     9: 0000000000000640     0 FUNC    LOCAL  DEFAULT   11 frame_dummy
    10: 0000000000000000     0 FILE    LOCAL  DEFAULT  ABS bha.cc
    11: 0000000000000000     0 FILE    LOCAL  DEFAULT  ABS crtstuff.c
    12: 0000000000001ac8     0 OBJECT  LOCAL  DEFAULT   19 __CTOR_END__
    13: 0000000000000840     0 OBJECT  LOCAL  DEFAULT   13 __FRAME_END__
    14: 0000000000001ae0     0 OBJECT  LOCAL  DEFAULT   21 __JCR_END__
    15: 0000000000000720     0 FUNC    LOCAL  DEFAULT   11 __do_global_ctors_aux
    16: 0000000000001ab8     0 OBJECT  LOCAL  HIDDEN    18 __dso_handle
    17: 000000000000068a    26 FUNC    LOCAL  HIDDEN    11 std::vector<X, std::allocator<X> >::vector()
    18: 000000000000068a    26 FUNC    LOCAL  HIDDEN    11 std::vector<X, std::allocator<X> >::vector()
    19: 00000000000006a4    26 FUNC    LOCAL  HIDDEN    11 std::_Vector_base<X, std::allocator<X> >::_Vector_base()
    20: 00000000000006a4    26 FUNC    LOCAL  HIDDEN    11 std::_Vector_base<X, std::allocator<X> >::_Vector_base()
    21: 00000000000006be    61 FUNC    LOCAL  HIDDEN    11 std::_Vector_base<X, std::allocator<X> >::_Vector_impl::_Vector_impl()
    22: 00000000000006be    61 FUNC    LOCAL  HIDDEN    11 std::_Vector_base<X, std::allocator<X> >::_Vector_impl::_Vector_impl()
    23: 0000000000001ad8     0 OBJECT  LOCAL  HIDDEN    20 __DTOR_END__
    24: 0000000000001880   496 OBJECT  LOCAL  HIDDEN    15 _DYNAMIC
    25: 0000000000001a88    48 OBJECT  LOCAL  HIDDEN    17 _GLOBAL_OFFSET_TABLE_
    27: 0000000000000540     0 FUNC    GLOBAL DEFAULT    9 _init
    28: 0000000000000758     0 FUNC    GLOBAL DEFAULT   12 _fini
    31: 000000000000066c    30 FUNC    GLOBAL DEFAULT   11 bar()
    32: 00000000000006fc    26 FUNC    WEAK   DEFAULT   11 std::allocator<X>::allocator()
    33: 00000000000006fc    26 FUNC    WEAK   DEFAULT   11 std::allocator<X>::allocator()
    34: 0000000000000716    10 FUNC    WEAK   DEFAULT   11 __gnu_cxx::new_allocator<X>::new_allocator()
    35: 0000000000000716    10 FUNC    WEAK   DEFAULT   11 __gnu_cxx::new_allocator<X>::new_allocator()
    36: 0000000000001ae8     0 NOTYPE  GLOBAL DEFAULT  ABS _edata
    37: 0000000000001ae8     0 NOTYPE  GLOBAL DEFAULT  ABS __bss_start
    38: 0000000000001af8     0 NOTYPE  GLOBAL DEFAULT  ABS _end

if I add -flto visibility of the "local symbols is turned again to DEFAULT, not sure if relevant though
g++ -fvisibility=hidden -fvisibility-inlines-hidden -fPIC bha.cc -Wall -shared -o libx.so -flto
[vinavx0] ~/public/ctest $ readelf -sW libx.so | grep -v UND | sed 's/.local/ .local/g' | c++filt

Symbol table '.dynsym' contains 10 entries:
   Num:    Value          Size Type    Bind   Vis      Ndx Name
     2: 0000000000000430     0 FUNC    GLOBAL DEFAULT    9 _init
     3: 0000000000000628     0 FUNC    GLOBAL DEFAULT   12 _fini
     6: 000000000000053c    30 FUNC    GLOBAL DEFAULT   11 bar()
     7: 00000000000019a8     0 NOTYPE  GLOBAL DEFAULT  ABS _edata
     8: 00000000000019a8     0 NOTYPE  GLOBAL DEFAULT  ABS __bss_start
     9: 00000000000019b8     0 NOTYPE  GLOBAL DEFAULT  ABS _end

Symbol table '.symtab' contains 36 entries:
   Num:    Value          Size Type    Bind   Vis      Ndx Name
     1: 0000000000000470     0 FUNC    LOCAL  DEFAULT   11 call_gmon_start
     2: 0000000000000000     0 FILE    LOCAL  DEFAULT  ABS crtstuff.c
     3: 0000000000001980     0 OBJECT  LOCAL  DEFAULT   19 __CTOR_LIST__
     4: 0000000000001990     0 OBJECT  LOCAL  DEFAULT   20 __DTOR_LIST__
     5: 00000000000019a0     0 OBJECT  LOCAL  DEFAULT   21 __JCR_LIST__
     6: 0000000000000490     0 FUNC    LOCAL  DEFAULT   11 __do_global_dtors_aux
     7: 00000000000019a8     1 OBJECT  LOCAL  DEFAULT   22 completed.5901
     8: 00000000000019b0     8 OBJECT  LOCAL  DEFAULT   22 dtor_idx.5903
     9: 0000000000000510     0 FUNC    LOCAL  DEFAULT   11 frame_dummy
    10: 0000000000000000     0 FILE    LOCAL  DEFAULT  ABS ccT50cVU.ltrans0.o
    11: 000000000000055a    26 FUNC    LOCAL  DEFAULT   11 std::vector<X, std::allocator<X> >::vector() .local.0.2256
    12: 000000000000055a    26 FUNC    LOCAL  DEFAULT   11 std::vector<X, std::allocator<X> >::vector() .local.1.2253
    13: 0000000000000574    26 FUNC    LOCAL  DEFAULT   11 std::_Vector_base<X, std::allocator<X> >::_Vector_base() .local.3.2259
    14: 000000000000058e    61 FUNC    LOCAL  DEFAULT   11 std::_Vector_base<X, std::allocator<X> >::_Vector_impl::_Vector_impl() .local.4.2265
    15: 000000000000058e    61 FUNC    LOCAL  DEFAULT   11 std::_Vector_base<X, std::allocator<X> >::_Vector_impl::_Vector_impl() .local.5.2262
    16: 00000000000005cc    26 FUNC    LOCAL  DEFAULT   11 std::allocator<X>::allocator() .local.7.2268
    17: 00000000000005e6    10 FUNC    LOCAL  DEFAULT   11 __gnu_cxx::new_allocator<X>::new_allocator() .local.9.2272
    18: 0000000000000000     0 FILE    LOCAL  DEFAULT  ABS crtstuff.c
    19: 0000000000001988     0 OBJECT  LOCAL  DEFAULT   19 __CTOR_END__
    20: 0000000000000710     0 OBJECT  LOCAL  DEFAULT   13 __FRAME_END__
    21: 00000000000019a0     0 OBJECT  LOCAL  DEFAULT   21 __JCR_END__
    22: 00000000000005f0     0 FUNC    LOCAL  DEFAULT   11 __do_global_ctors_aux
    23: 0000000000001978     0 OBJECT  LOCAL  HIDDEN    18 __dso_handle
    24: 0000000000001998     0 OBJECT  LOCAL  HIDDEN    20 __DTOR_END__
    25: 0000000000001750   496 OBJECT  LOCAL  HIDDEN    15 _DYNAMIC
    26: 0000000000001958    32 OBJECT  LOCAL  HIDDEN    17 _GLOBAL_OFFSET_TABLE_
    28: 0000000000000430     0 FUNC    GLOBAL DEFAULT    9 _init
    29: 0000000000000628     0 FUNC    GLOBAL DEFAULT   12 _fini
    32: 000000000000053c    30 FUNC    GLOBAL DEFAULT   11 bar()
    33: 00000000000019a8     0 NOTYPE  GLOBAL DEFAULT  ABS _edata
    34: 00000000000019a8     0 NOTYPE  GLOBAL DEFAULT  ABS __bss_start
    35: 00000000000019b8     0 NOTYPE  GLOBAL DEFAULT  ABS _end


I think that, unless not imposed by the standard (why??) the visibility of "namespace std" SHALL NOT BE forced to default
Comment 4 Pawel Sikora 2011-09-22 11:23:14 UTC
(In reply to comment #3)

> I think that, unless not imposed by the standard (why??) the visibility of
> "namespace std" SHALL NOT BE forced to default

part of the std:: (exceptions typeinfo symbols) must be visible-by-default
for proper throw-catch/dynamic_cast working across shared libs boundaries.
Comment 5 vincenzo Innocente 2011-09-22 11:49:29 UTC
indeed
and in "exception" header-file is a place where visibility is correctly handled
#pragma GCC visibility push(default)
extern "C++" {

namespace std
{
}
#pragma GCC visibility pop


I would have preferred specific __attribute((visibility( "default" )))
on each exception class though (push and pop and error-prone)
Comment 6 Jonathan Wakely 2011-09-22 12:26:56 UTC
dup of PR 36022 ?
Comment 7 Paolo Carlini 2011-09-22 13:23:41 UTC
Seems so, thanks Jon. The older one also includes some rationale from Benjamin.
Comment 8 Jonathan Wakely 2011-09-22 13:45:10 UTC
I think before the default visibility was added everywhere it was pretty easy to cause segfaults by using -fvisibility=hidden
Comment 9 Paolo Carlini 2011-09-22 14:42:38 UTC
Duplicate.

*** This bug has been marked as a duplicate of bug 36022 ***