This is the mail archive of the
binutils@sources.redhat.com
mailing list for the binutils project.
Symbol versioning in C++ (two ld bugs)
- From: Phil Edwards <phil at jaj dot com>
- To: binutils at sources dot redhat dot com
- Cc: bkoz at redhat dot com, rth at redhat dot com
- Date: Mon, 11 Feb 2002 16:48:29 -0500
- Subject: Symbol versioning in C++ (two ld bugs)
[cc'd to the other people who have been involved so far]
None of what follows is mentioned in the current ld manual. Consider that
as bug #0, if you will. (I volunteer to update ld/ld.texinfo if y'all
will help me work these out.)
Background
==========
For libstdc++-v3 we need to start versioning the symbols of the shared
library. I am exploring the option of requiring GNU ld and making use
of the "extern 'lang'" extension in the version scripts. Right now I'm
playing with a --version-script consisting of
FOO {
global:
extern "C++"
{
std::*
};
local:
* ;
};
which binds everything in namespace std to version FOO. The problem is
that there are all kinds of things in std which we must make local; the
script above exposes (and versions!) std::__random_implementation_detail,
which is bad.
So I tried to list something like
global:
extern "C++"
{
std::[A-Za-z][A-Za-z0-9_]*
};
and that's where the fun begins.
Bug #1
======
The parser routine which stores the symbol patterns for later comparison
is named "lang_new_vers_regex", implying that the symbol pattern is a
regular expression.
The routines which compare the pattern with a given symbol,
"lang_vers_match_lang_X" where X is c, cplsuplus, or java, all call
fnmatch().
fnmatch() matches shell filename patterns, i.e., globbing, not regexps.
Oops.
So: which kind of patterns are supposed to be accepted?
Bug #2
======
The ldlex.l lexer only specifies
[*?.$_a-zA-Z]([*?.$_a-zA-Z0-9]|::)*
for a version symbol pattern (see V_IDENTIFIER). No brackets, no ranges,
no braces -- that is, we can't even use the globbing patterns that fnmatch()
would allow!
The only "wildcard" used in the examples in the manual is a trailing
'*', and there's no documentation of what exactly it's supposed to mean,
although I think I can guess in the presence of fnmatch().
Should I be trying things like
global:
extern "C++"
{
std::A*
std::B*
...
std::Z*
std::a*
std::b*
...
std::z*
};
instead? That would seem exceptionally and needlessly pathetic. We ought
to be able to do better than that. :-)
For the record, std::* is not the only problem; there are other namespaces
and other patterns which also need to be exposed (the __cxa_* stuff for
example).
Phil
--
If ye love wealth greater than liberty, the tranquility of servitude greater
than the animating contest for freedom, go home and leave us in peace. We seek
not your counsel, nor your arms. Crouch down and lick the hand that feeds you;
and may posterity forget that ye were our countrymen. - Samuel Adams