BACKGROUND: If an executable file has a external data reference, which is defined in a shared object, the compiler will use copy relocation and place a copy in its .bss section. Copy relocation is detailed in this site: http://www.shrubbery.net/solaris9ab/SUNWdev/LLM/p22.html#CHAPTER4-84604
However, my question is:
Is it possible to implement it through GOT, just like the external data reference in shared object? The executable can indirectly accesses this external code through its GOT entry, and this GOT entry can be stuffed with the real address of this symbol in run-time. I don't know why GCC doesn't implement it like this. What's the upside of copy relocation?
In languages like C and C++ addresses of objects with static storage duration qualify as address constants. It means that conceptually, at language level they are treated as if their values are "known" at compile time.
Of course, this is not the case in reality, when it comes to the matter in question. To counter that the compiler-linker-loader combination has to implement a dynamic mechanism that would provide full support the language-level concept of address constant. Intuitively a GOT-based mechanism, being based on full run-time indirection, would be much farther away from that concept than a load-time relocation-based mechanism.
For one thing, C language was designed as a language that requires no dynamic initialization of objects with static storage duration, i.e. conceptually there's no initializing startup code and no issues related to the order of initialization. But in a GOT-based implementation an initialization of a global variable with such address constant would require startup code to extract the actual value from GOT and place it into the variable. Meanwhile, a relocation-based approach produces a full illusion of such global variable beginning its life with the proper value without any startup code.
If you look at the features provided by the relocation mechanism, you will notice that they are in sync with the C specification of address constant. E.g. the final value might involve adding a fixed offset, which is intended to act as a loader-side implementation of C
[]
and->
operators, permissible in C address constant expressions.