Bug 21405 - Can't give symbol versions to templates
Summary: Can't give symbol versions to templates
Status: RESOLVED INVALID
Alias: None
Product: gcc
Classification: Unclassified
Component: libstdc++ (show other bugs)
Version: 3.4.2
: P2 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2005-05-05 21:49 UTC by Mike Hearn
Modified: 2012-01-11 14:00 UTC (History)
9 users (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Mike Hearn 2005-05-05 21:49:34 UTC
See http://gcc.gnu.org/ml/libstdc++/2005-04/msg00173.html

If you have code like:

std::string b = "bee";
std::string c = "see";

std::string a = b + c;

Then the string + operator overload will appear in the final ELF image with
GLOBAL WEAK visibility, meaning it can be bound to the wrong version of the
symbol at runtime (ie symbol versioning is ignored).

This is serious as it means you can't mix libraries that use different C++ ABIs
into the same image even if they only interact via C ABIs, something that the
GCC docs explicitly say will work!
Comment 1 Andrew Pinski 2005-05-05 22:27:01 UTC
I don't know if this is really a vaild bug, as the standard requires the inline function as the same so it 
would be undefined if they are different.
Comment 2 Mike Hearn 2005-05-05 22:39:57 UTC
I don't understand what you mean. There's definitely a bug here because a
configuration that the docs say should work, causes mysterious crashes due to
mis-binds of symbols. I suspect building with -fvisibility-inlines-hidden can
resolve this problem but why is it not the default?
Comment 3 Andrew Pinski 2005-05-05 22:40:50 UTC
So here is the story really global templates have aways global visibility in C++ so this is not a bug in 
GCC or binutils.  This is a bug in how you think that you can use two different versions. 
Comment 4 Mike Hearn 2005-05-06 00:17:47 UTC
No, there is very definitely a bug here even if it's just in the documentation.

The GCC docs say in very clear and unambiguous terms that this will work, by
design. Not by accident, by design. That's the whole point of applying symbol
versions to the standard C++ library.

It only affects methods that have been inlined into the headers. Methods that
are defined as external work correctly. So either:

a) No methods should be inlined

or

b) GCC should not emit them as GLOBAL WEAK so they can be overridden by other
definitions elsewhere in the image

The latter is what the new -fvisibility-inlines-hidden switch does. So why is it
not on by default?
Comment 5 Chris Jefferson 2005-05-08 12:18:05 UTC
Out of interest, where do the docs say that? (I'm not being sarcastic, just interested)
Comment 6 Mike Hearn 2005-05-08 12:38:36 UTC
http://gcc.gnu.org/onlinedocs/libstdc++/abi.html

See the "testing multi-abi binaries" section at the bottom:

<quote>

A "C" application, dynamically linked to two shared libraries, liba, libb. The
dependent library liba is C++ shared library compiled with gcc-3.3.x, and uses
io, exceptions, locale, etc. The dependent library libb is a C++ shared library
compiled with gcc-3.4.x, and also uses io, exceptions, locale, etc.

[ ... snip ... ]

This resulting binary, when executed, will be able to safely use code from both
liba, and the dependent libstdc++.so.6, and libb, with the dependent libstdc++.so.5.

</quote>

A C++ program linked indirectly (via a C library) against another C++ library is
exactly the same scenario. This is the whole point of symbol versioning.
Comment 7 Benjamin Kosnik 2005-05-25 22:49:36 UTC
Changing this to libstdc++, so we remember to track this.
Comment 8 Mike Hearn 2005-05-31 13:23:19 UTC
Reopening the bug, as Benjamin wishes to track it.
Comment 9 Giovanni Bajo 2005-05-31 15:10:34 UTC
You can't use -fvisibility-inlines-hidden or otherwise you'll get linker errors 
if the compiler later decides not to inline those functions. I don't think you 
can win.
Comment 10 Mike Hearn 2005-06-01 11:56:33 UTC
So this feature is basically terminally broken and never worked in the first place?

How about if GCC supported a new attribute or something that made it emit
inlines for that class with a specific symbol version?
Comment 11 Andrew Pinski 2005-12-30 18:20:35 UTC
There is an one defintion rule in C++ unlike most other languages which have weak symbols.  And if you are working around it by using hidden symbols well you are asking to run into troubles.
Comment 12 Cristian Petrescu-Prahova 2006-03-20 17:07:37 UTC
(In reply to comment #11)
> There is an one defintion rule in C++ unlike most other languages which have
> weak symbols.  And if you are working around it by using hidden symbols well
> you are asking to run into troubles.

I don't believe that C++ has to say (should say) anything that pertains to shared libraries. Moreover, symbol versions were added as workarounds for problems created by the ELF format semantics. This is a platform specific problem, not a pure C++ problem. However, to have the gnu toolchain to properly support C++ on ELF platforms, adding proper versioning for *all* symbols, including template-originated symbols is a must. I'm not sure if this is a task for g++ of for the linker or for both, but someone should eventually acknowledge that there is a problem and start looking for solutions...
Comment 13 H.J. Lu 2006-03-20 17:30:51 UTC
FWIW, the current GNU binutils and glibc treat the weak definition in
shared libraries as strong. There is even a whole set of testsuite for
this in the GNU binutils.
Comment 14 Cristian Petrescu-Prahova 2006-03-20 18:32:35 UTC
The problem is not how the dynamic linker treats 'weak' symbols. The problem is that template originating functions having no version numbers. It just happen that template originating functions are also marked as weak (if I understand correctly). In other words, if I have a regular C/C++ function, I can attach version strings to it, whereas it I have a C++ template function I cannot attach version strings to it, or more precisely to instances of it. I don't really care whether symbols are 'weak' or 'strong', I only care of proper versioning for *all* C++ symbols.

I believe that this situation was clearly described by the original bug reporter 10 months ago. For some reason nobody seems to acknowledge that there is a problem, the main line of reasoning so far being that 'C++ standard says only unique (weak) names are valid'. However, that flies in the face of the whole synmbol versioning mechanism, weak symbols or not. Afterall, versioning for symbols was introduced precisely to allow multiple instances of the same symbol to be valid in a shared object context.

Please feel free to correct me on any g++ internal details on which I am no expert. However, the root problem is there and is a show-stopper for any attempt of distributing pre-compiled C++ shared object binaries.
Comment 15 Pawel Sikora 2006-03-20 19:34:25 UTC
see PR19664, PR20218, PR20297.
Comment 16 Pawel Sikora 2006-03-20 19:35:31 UTC
(In reply to comment #15)
> see PR19664, PR20218, PR20297.

ops, this is the note for C#10.
Comment 17 Benjamin Kosnik 2006-03-22 04:51:25 UTC
see the solution in 24660
Comment 18 Cristian Petrescu-Prahova 2006-03-22 19:10:57 UTC
(In reply to comment #17)
> see the solution in 24660

I'm not sure I understand correctly: are all C++ template libraries supposed to add 24660-style machinery?
Comment 19 Jason Merrill 2006-06-20 18:12:59 UTC
Changed the summary to clarify, and remove "visibility"
Comment 20 Richard Biener 2012-01-11 14:00:52 UTC
For DSOs you need to avoid re-exporting libstdc++ symbols without versions.
Use a linker script to assign versions and/or restrict what you export
via visibility attributes and/or use -fvisbility-default=hidden.

To pick up properly versioned symbols for UNDEFs in DSOs you have to
link the DSO against the proper libstdc++.

This is not a bug (but easy to get wrong).