Reputation: 467
When you link an application let's call it main_program
with a shared library message_library
on a Linux device, there's a scenario to consider. This shared library contains a global variable message
that both the library and the program need to use. Now, during the linking process, relocations happen. These relocations are important because they ensure everything works correctly. It's crucial to understand how the order of these relocations is managed to make sure everything behaves as expected.
Here's a simplified breakdown of the process:
main_program.cpp
#include <iostream>
extern const char* message;
void print_message();
int main() {
std::cout << message << '\n';
print_message();
}
message_lib.cpp
#include <iostream>
const char* message = "Meow!";
void print_message() {
std::cout << message << '\n';
}
Compilation and linking:
$ g++ main_app.cpp -c -pie -o main_app.o
$ g++ message_lib.cpp -fPIC -shared -o libmessage.so
$ g++ main_app.o libmessage.so -o main_app
Relevant relocations as reported by readelf:
main_app
:
Offset Info Type Sym. Value Sym. Name + Addend
000000004150 000c00000005 R_X86_64_COPY 0000000000004150 message + 0
For libmessage.so
:
Offset Info Type Sym. Value Sym. Name + Addend
000000004040 000000000008 R_X86_64_RELATIVE 2000
000000003fd8 000b00000006 R_X86_64_GLOB_DAT 0000000000004040 message + 0
My question is: How is the order for applying relocations specified in ELF shared libraries? Is there a predefined mechanism within the ELF format or the ABI that dictates this order? Alternatively, does the dynamic linker autonomously resolve relocation dependencies to ensure correct behavior?
Furthermore, is there an implicit assumption that the static linker arranges relocations in such a way that those within the executable can be processed after those within shared libraries?
Upvotes: 0
Views: 14