This is the mail archive of the libc-alpha@sourceware.org mailing list for the glibc project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Fixing namespace issues for variables


We have some bugs where library functions use a global variable outside 
the namespace of some standards containing those functions, interfering 
with programs' own use of variables by that name.  These are currently 
whitelisted in linknamespace.pl.  I'll use signgam (bug 15421) as the 
example in what follows (ISO C includes lgamma but not signgam), but the 
same applies equally to other cases of this issue.

Normally namespace issues could be fixed by making the problem symbol into 
a weak alias for an implementation-namespace symbol and using the 
implementation-namespace symbol internally.  However, this doesn't work 
for data symbols.

A non-PIC program using signgam - whether it defined its own copy with 
"int signgam;" or referenced libm's copy with "extern int signgam;" or via 
the declaration of signgam when <math.h> is included under some conditions 
- uses it with non-PIC code sequences appropriate to a copy of the 
variable located directly in that program.  When the program is linked, it 
then defines a dynamic symbol signgam (at the appropriate symbol version 
from glibc), and the dynamic linker makes this preempt the signgam symbol 
from libm, so that all references to signgam from within libm end up 
referring to the copy from the main program (there may also be a copy 
relocation to copy the initializer from libm to the copy in the main 
program).  If any reference from within libm uses a different name, that 
reference does not get preempted, meaning that the two symbols that were 
aliases when libm was linked are no longer aliases at runtime.

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:

extern int *__signgam_location (void);
#define signgam (*__signgam_location ())

__signgam_location would be a new dynamic symbol exported from libm.  The 
existing signgam export from libm would become a compat symbol.

In static libm, and shared libm for new ports, the variable signgam would 
simply be renamed to __signgam, and we'd have:

int *
__signgam_location (void)
{
  return &__signgam;
}

In shared libm for existing ports, it would instead return &signgam.  
This keeps binary compatibility for existing binaries and shared 
libraries, which will continue to bind to the signgam compat symbol from 
libm.  It is compatible with ISO C for newly linked programs, since (a) a 
strict ISO C program won't get the #define in <math.h>, (b) a signgam 
symbol from a new program won't bind to a compat symbol in libm and (c) 
internal references within libm will thus bind to the compat symbol and so 
be preempted by old programs but not new ones.  And there is no POSIX 
requirement to be able to declare variables (as opposed to certain 
functions) yourself without including the corresponding header, or to be 
able to use them after #undef, so I believe it is also compatible with 
POSIX.

Any comments on this approach?  Do people consider it, and the new 
__signgam_location symbol (and similar symbols in other cases), OK for 
fixing this problem?  I think it's preferable to adding new versions of 
the lgamma functions that don't set signgam and then selecting versions 
based on feature test macros (which is also dubious in conformance terms, 
since the lgamma functions *are* valid to declare yourself, in both ISO C 
and POSIX).

-- 
Joseph S. Myers
joseph@codesourcery.com


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]