Bug 36022 - stl templates exported as weak symbols though visibility hidden is used
Summary: stl templates exported as weak symbols though visibility hidden is used
Status: RESOLVED INVALID
Alias: None
Product: gcc
Classification: Unclassified
Component: libstdc++ (show other bugs)
Version: 4.3.0
: P3 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords:
: 50348 (view as bug list)
Depends on:
Blocks:
 
Reported: 2008-04-23 06:27 UTC by Mike Hommey
Modified: 2011-09-22 14:42 UTC (History)
2 users (show)

See Also:
Host: x86_64-linux-gnu
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed:


Attachments
remove visibility attribute with -D_GLIBCXX_VISIBILITY=0, run testuite with it and -fvisibility-hidden (702 bytes, patch)
2009-01-30 20:56 UTC, Benjamin Kosnik
Details | Diff
add key functions to classes in stdexcept (995 bytes, patch)
2010-11-01 01:32 UTC, Andrew Dixie
Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Mike Hommey 2008-04-23 06:27:37 UTC
With the following foo.cpp sample:
#include <algorithm>

__attribute__((visibility("default"))) void foo() {
  int array[] = { 23, 5, -10, 0, 0, 321, 1, 2, 99, 30 };
  int elements = sizeof(array) / sizeof(array[0]); 
  std::sort(array, array + elements);
}

Building with the following command line:
g++-4.3 -shared -fPIC -fvisibility=hidden -fvisibility-inlines-hidden -o foo.so foo.cpp

Leads to internals being exposed, which is unexpected:
objdump -T -C test2.so | grep std
000000000000136d  w   DF .text	000000000000003a  Base        void std::__unguarded_insertion_sort<int*>(int*, int*)
0000000000001b18  w   DF .text	0000000000000057  Base        void std::sort<int*>(int*, int*)
000000000000147f  w   DF .text	000000000000000e  Base        std::__niter_base<int*, false>::__b(int*)
000000000000190b  w   DF .text	0000000000000021  Base        std::__lg(long)
0000000000001324  w   DF .text	0000000000000049  Base        void std::__unguarded_linear_insert<int*, int>(int*, int)
000000000000141f  w   DF .text	0000000000000060  Base        int* std::__unguarded_partition<int*, int>(int*, int*, int)
0000000000001674  w   DF .text	0000000000000088  Base        void std::make_heap<int*>(int*, int*)
0000000000001400  w   DF .text	000000000000001f  Base        void std::iter_swap<int*, int*>(int*, int*)
00000000000013b5  w   DF .text	000000000000002c  Base        void std::swap<int>(int&, int&)
00000000000016fc  w   DF .text	0000000000000054  Base        void std::__pop_heap<int*>(int*, int*, int*)
00000000000019bc  w   DF .text	000000000000004f  Base        int* std::__copy_move_backward_a2<false, int*, int*>(int*, int*, int*)
0000000000001a4b  w   DF .text	0000000000000079  Base        void std::__insertion_sort<int*>(int*, int*)
0000000000001a0b  w   DF .text	0000000000000040  Base        int* std::copy_backward<int*, int*>(int*, int*, int*)
0000000000001750  w   DF .text	000000000000005d  Base        void std::__heap_select<int*>(int*, int*, int*)
0000000000001284  w   DF .text	00000000000000a0  Base        int const& std::__median<int>(int const&, int const&, int const&)
00000000000017ad  w   DF .text	000000000000002b  Base        void std::pop_heap<int*>(int*, int*)
000000000000152e  w   DF .text	0000000000000146  Base        void std::__adjust_heap<int*, long, int>(int*, long, long, int)
00000000000013a7  w   DF .text	000000000000000e  Base        std::__miter_base<int*, false>::__b(int*)
000000000000180f  w   DF .text	0000000000000034  Base        void std::partial_sort<int*>(int*, int*, int*)
00000000000017d8  w   DF .text	0000000000000037  Base        void std::sort_heap<int*>(int*, int*)
0000000000001991  w   DF .text	000000000000002b  Base        int* std::__copy_move_backward_a<false, int*, int*>(int*, int*, int*)
0000000000001ac4  w   DF .text	0000000000000054  Base        void std::__final_insertion_sort<int*>(int*, int*)
0000000000001843  w   DF .text	00000000000000c8  Base        void std::__introsort_loop<int*, long>(int*, int*, long)
000000000000192c  w   DF .text	0000000000000065  Base        int* std::__copy_move_backward<false, true, std::random_access_iterator_tag>::__copy_move_b<int>(int const*, int const*, int*)
00000000000013e1  w   DF .text	000000000000001f  Base        void std::__iter_swap<true>::iter_swap<int*, int*>(int*, int*)
000000000000148d  w   DF .text	00000000000000a1  Base        void std::__push_heap<int*, long, int>(int*, long, long, int)


FYI: g++-4.3 -v
Using built-in specs.
Target: x86_64-linux-gnu
Configured with: ../src/configure linux gnu
Thread model: posix
gcc version 4.3.1 20080401 (prerelease) (Debian 4.3.0-3) 

(it also happens with g++-4.2 from debian (4.2.3))
Comment 1 Andrew Pinski 2008-05-05 05:27:10 UTC
The std:: namespace is supposed to be exposed and is marked as such in the libstdc++ headers.

So I don't think this is a bug.
Comment 2 Mike Hommey 2008-05-11 09:18:29 UTC
Usually, when you're using visibility hidden, that means you want to avoid exporting a lot of cruft symbols from a shared library... that the std:: namespace is always visibility default is an annoyance. Especially considering the set of exported symbols change with optimization, since some of these might end up inlined:

$ g++-4.3 -O3 -shared -fPIC -fvisibility=hidden -fvisibility-inlines-hidden -o foo.so foo.cpp 
$ objdump -T -C foo.so | grep std
0000000000000780  w   DF .text	00000000000002fe  Base        void std::__introsort_loop<int*, long>(int*, int*, long)

$ g++-4.3 -O2 -shared -fPIC -fvisibility=hidden -fvisibility-inlines-hidden -o foo.so foo.cpp 
$ objdump -T -C foo.so | grep std
0000000000000a40  w   DF .text	00000000000000a6  Base        void std::__insertion_sort<int*>(int*, int*)
00000000000008d0  w   DF .text	0000000000000161  Base        void std::__introsort_loop<int*, long>(int*, int*, long)
00000000000007e0  w   DF .text	00000000000000eb  Base        void std::__adjust_heap<int*, long, int>(int*, long, long, int)

$ g++-4.3 -O1 -shared -fPIC -fvisibility=hidden -fvisibility-inlines-hidden -o foo.so foo.cpp 
$ objdump -T -C foo.so | grep std
0000000000000c65  w   DF .text	0000000000000063  Base        void std::make_heap<int*>(int*, int*)
0000000000000ee0  w   DF .text	0000000000000051  Base        void std::__final_insertion_sort<int*>(int*, int*)
0000000000000b52  w   DF .text	0000000000000024  Base        void std::__unguarded_linear_insert<int*, int>(int*, int)
0000000000000b76  w   DF .text	0000000000000053  Base        void std::__push_heap<int*, long, int>(int*, long, long, int)
0000000000000b10  w   DF .text	0000000000000042  Base        int* std::__unguarded_partition<int*, int>(int*, int*, int)
0000000000000d21  w   DF .text	0000000000000053  Base        void std::sort_heap<int*>(int*, int*)
0000000000000cc8  w   DF .text	0000000000000059  Base        void std::__heap_select<int*>(int*, int*, int*)
0000000000000e72  w   DF .text	000000000000006a  Base        void std::__insertion_sort<int*>(int*, int*)
0000000000000d80  w   DF .text	00000000000000f2  Base        void std::__introsort_loop<int*, long>(int*, int*, long)
0000000000000bc9  w   DF .text	000000000000009c  Base        void std::__adjust_heap<int*, long, int>(int*, long, long, int)
Comment 3 Benjamin Kosnik 2009-01-30 20:56:01 UTC
Created attachment 17216 [details]
remove visibility attribute with -D_GLIBCXX_VISIBILITY=0, run testuite with it and -fvisibility-hidden
Comment 4 Benjamin Kosnik 2009-02-04 02:51:42 UTC
This isn't a bug, but rather part of a deliberate linkage strategy. 

For C++, types that are to be used across shared libraries have to be visible. See:

http://gcc.gnu.org/onlinedocs/gcc/Code-Gen-Options.html#Code-Gen-Options

And in particular:

Note that `-fvisibility' does affect C++ vague linkage entities. This means that, for instance, an exception class that will be thrown between DSOs must be explicitly marked with default visibility so that the `type_info' nodes will be unified between the DSOs.

Thus, the rationale for libstdc++ having namespace std have visibility "default." If you were to hack in support for allowing namespace std to have hidden visibility, and run the testsuite with -fvisibility=hidden (see attached patch) you would notice the breakdown in testresults, with mass failures. Thus, it is provided for information purposes only.

In the libstdc++ source files, anonymous namespaces are used for specific entities that have both local/hidden linkage. This use of anonymous namespaces is considered superior to attribute hidden as it uses ISO C++ and is thus more portable than vendor extensions (pragmas or attributes).

However, in libstdc++ header files, attribute hidden has been difficult to use. One might think that perhaps all the implementation details could be moved to say std::__detail, and then marked with attribute hidden. Then, many of these helper functions would be marked as hidden in your example below.

There are some pitfalls with this approach:

 1) all these implementation base types that are used by default derived classes  would have to be default
 2) same with implementation details that use static locals
 3) same with virtual functions, etc etc.
 4) thus you end up with a pretty limited set of hidden things

In addition, this may exacerbate the dlopen + RTLD_LOCAL + weak symbol issue for C++. 



Comment 5 Paolo Carlini 2010-01-09 22:56:08 UTC
I understand this can be closed as invalid, then.
Comment 6 Andrew Dixie 2010-11-01 01:32:39 UTC
Created attachment 22215 [details]
add key functions to classes in stdexcept

FWIW.  This patch an top of the patch from Benjamin Kosnik against gcc-4.4.5 gets:

                === libstdc++ Summary ===

# of expected passes            5861
# of unexpected failures        1
# of expected failures          80
# of unsupported tests          338

The one failure is abi_check which is due to the new destructor symbols not being versioned properly.

With the patch, the virtual tables and typeinfo for standard exceptions are stored once in libstdc++.so, rather than having weak/comdat definitions duplicated in every object file.
This seems beneficial in it's own right.
Comment 7 Paolo Carlini 2011-09-22 14:42:38 UTC
*** Bug 50348 has been marked as a duplicate of this bug. ***