This is the mail archive of the
libc-alpha@sourceware.org
mailing list for the glibc project.
Re: Fixing namespace issues for variables
- From: Rich Felker <dalias at libc dot org>
- To: Joseph Myers <joseph at codesourcery dot com>
- Cc: libc-alpha at sourceware dot org
- Date: Sat, 24 Oct 2015 15:17:26 -0400
- Subject: Re: Fixing namespace issues for variables
- Authentication-results: sourceware.org; auth=none
- References: <alpine dot DEB dot 2 dot 10 dot 1510222324130 dot 23141 at digraph dot polyomino dot org dot uk> <20151024061325 dot GN8645 at brightrain dot aerifal dot cx> <alpine dot DEB dot 2 dot 10 dot 1510241056290 dot 27544 at digraph dot polyomino dot org dot uk>
On Sat, Oct 24, 2015 at 11:19:19AM +0000, Joseph Myers wrote:
> On Sat, 24 Oct 2015, Rich Felker wrote:
>
> > > So simply using aliases is not a solution in the case of data symbols.
> > > The solution I propose instead is as follows. math.h would (under
> > > appropriate feature test macros) do:
> >
> > I don't follow. How is this any different from environ, timezone,
> > daylight, etc.? They are all handled correctly by an alias; when
> > linking produces copy relocations, the linker does the right thing
> > automatically and preserves the aliasing.
>
> When I tried and failed to use aliases, it was for stdin / stdout /
> stderr, with the main name used internally being hidden. As noted in
> <https://sourceware.org/ml/libc-alpha/2015-10/msg00876.html> I've since
> located the linker magic that allows such aliases to work *if the internal
> name is exported* (so this provides yet another reason to need non-compat
> internal-namespace exports at public symbol versions, beyond uses in
> macros, inline functions, libc_nonshared, libgcc, libstdc++ etc.). As
> also noted there, since __signgam was not an exported symbol alongside
> signgam in glibc 2.0, use of aliases like that would break existing
> binaries, as existing binaries would preempt only signgam and so break the
> aliasing.
Yes. This is the traditional way things were always intended to work.
POSIX even has a note alluding to that somewhere (probably in part of
the rationale; I don't remember right off). Apparently that knowledge
was lost somewhere along the way.
> Furthermore, address comparison is not a solution as I hoped for
> distinguishing old and new binaries. When I said that programs defining
> their own tzname don't get it bound to the glibc symbol, I meant that the
> dynamic tzname symbol from the executable was unversioned. But an
> unversioned symbol from an executable will still preempt a versioned
> symbol from glibc (necessarily; recall that glibc 2.0 didn't have symbol
> versioning, so you can't distinguish an unversioned signgam definition
> from a binary linked with glibc 2.0 using the library's signgam from one
> from a new binary defining its own), and so &signgam == &__signgam would
> return false for the new binary as well as the old one.
I don't see how versioning is relevant here. If the main program
defines tzname, there is no copy relocation, tzname refers to the
object in the main program, and &tzname != &__tzname. If the main
program does not define tzname but references it, then one of two
things happens:
1. If libc.so has a public symbol __tzname for which tzname is an
alias, the main program has a copy relocation referencing __tzname and
pseudo-definitions for tzname and __tzname as the address of the copy
relocation, and libc sees &tzname == &__tzname.
2. If libc.so only exports tzname as the public symbol, the main
program has a copy relocation referencing tzname and a
pseudo-definition for tzname as the address of the copy relocation,
but __tzname is just the libc-internal definition, and &tzname !=
&__tzname.
> So you'd need at least four new public symbols (__signgam, plus new
> versions for lgamma, lgammaf, lgammal; gamma* could be kept pointing to
> old versions, which would have to set both __signgam and signgam in case
> the aliasing was broken) to do things with aliases. It might still be
Yes, this is the canonical fix and exactly what should be done.
> safer than __signgam_location, but we want to be sparing with public ABIs.
> (stdin / stdout / stderr would be much worse to do with versioning
> functions, but there macro definitions are unambiguously OK.)
Indeed.
> > > extern int *__signgam_location (void);
> > > #define signgam (*__signgam_location ())
> >
> > This is non-conforming. POSIX requries an extern object. Note that the
> > rule about being able to use the interface without including the
> > header applies to most of the interfaces in math.h.
>
> That rule is for *functions* (with certain types), not *variables*.
> POSIX seems silent on being able to use non-function interfaces like that
> (and as I said in my mail to the Austin Group list, the missing
> reservation as macros for all file scope identifiers seems a clear mistake
> in updating POSIX for C99).
Reservation as macros is not relevant. You're always allowed to
undef the macro and use the underlying object/function unless the
identifier is actually _specified_ to be a macro. It's non-conforming
to go around defining things as macros when they're required to exist
as objects or functions.
Rich