SPRAB89A September 2011 – March 2014
In Linux, external symbols generally have STV_DEFAULT visibility, and are therefore subject to preemption unless declared otherwise. This would normally result in GOT-based addressing for almost all references to variables, including those defined in the same module. In other words, Linux modules are required to treat all references to extern variables as if they were imported, even if they are not. To avoid the resultant performance penalty, executables employ a special convention that allows them to evade it.
An executable may choose to treat any reference to a variable as if as it was its own—that is, defined in the executable—allowing the compiler to generate efficient DP-relative addressing. At static link time, any variable that turns out to be imported is given a duplicate definition in the executable. At dynamic load time, the duplicate definition preempts the original definition in the library, and any initializer is copied from the preempted definition to the new definition.
The size of the duplicate definition is specified by the st_size field from the source definition. The minimum alignment of the duplicate definition is given as follows:
(Intuitively, this defines the duplicate object to be at least as well aligned as the original object, up to its maximum possible required alignment.)
Any initial value stored in the original symbol when the process image was created must be propagated to the duplicate. The R_C6000_COPY relocation serves this purpose. The linker marks the duplicate definition in the executable with R_C6000_COPY. At load time, the dynamic loader finds the referenced symbol in the library and copies the data at that location to the duplicate definition in the executable.
In this way the executable is not penalized for dynamic linking. Instead, the penalty is borne by the library, which must assume that all its extern variables are imported—which, because of preemption, it would have to do anyway.