This is the mail archive of the gcc@gcc.gnu.org mailing list for the GCC project.


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

Re: [I don't think it's off-topic at all] Linking speed for C++


On Tue, May 29, 2001 at 10:57:39PM +0200, Michael Matz wrote:
> This is due to lib1's version of init() setting another TheA
> than the one read from in main().  I don't know why exactly
> this is happening.

Welcome to Dynamic Linking 304, in which we discuss the peculiarities
of data symbols as seen on common 32-bit architectures.

Exhibit A:

> And the testing insn in main() which abort is this:
>  8048595:       83 3d 0c 97 04 08 00    cmpl   $0x0,0x804970c

Applications are typically built non-pic.  Every address is absolute,
which means that we must know the address of every object at link time
and not runtime.  Yet if symbol in question comes from a shared
library, how can this be?

For functions, the answer is simple: the known fixed address is the
address of a PLT thunk which branches to the actual address in the
shared library.  But what about data?  The instruction above is not
prepared for indirection.

Exhibit B:

> The program itself has for TheA the following relocation:
> 0804970c R_386_COPY        _1A.TheA

For every data object referenced by the main application, the linker
allocates space in the application's .bss section (sometimes referred
to as the .dynbss).  The above relocation copies the in-file contents
of the actual data in the shared library (recall that this ocurrs
before any constructors are run) to the application's .dynbss.

Under normal conditions, the symbol resolution rules search the main
application first, and so _everyone_ uses the copy in the .dynbss,
and everyone is happy.

But look what happens when we change the rules, as with -Bsymbolic:
the shared library searches itself first (optimized at link time in
this instance -- you'd get the same net result from ld.so if you
somehow manually added DT_SYMBOLIC to _DYNAMIC in the normal lib1),
the symbol gets resolved locally, and the application's copy is not
used.  Which then causes the application to fail.

Conclusion: symbol resolution rule changes cannot be made in the
presense of shared (in the multiple users sense) data.

There is something else to watch here.  Note that the linker had
to *reserve* space in the application.  This implies that the size
of the data is known at link time.  Which implies that that size
is constant.  Which implies that the size of the data is part of
the ABI, even if the structure is opaque at the language level.

An example of this last point appears in traditional stdio:

  struct FILE;
  extern FILE _iob[3];
  #define stdin  (&_iob[0])
  #define stdout (&_iob[1])
  #define stderr (&_iob[2])

Note that the entire _iob array will be copied into the main
application if the program references any of the standard files.
Which means that you cannot change the size of struct FILE even
though the application code thinks of it as opaque.

Conclusion: extreme caution should be employed with shared data.

> Is ld.so wrong, or ld, or as, or gcc?

None of the above, I'm afraid.

Of course, there is another way to avoid these problems that 
hasn't been mentioned yet -- build the application PIC as well.


r~


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