Home > OS >  Will an executable access shared-libraries' global variable via GOT?
Will an executable access shared-libraries' global variable via GOT?

Time:12-26

I was learning dynamic linking recently and gave it a try:

dynamic.c

int global_variable = 10;

int XOR(int a) {
        return global_variable;
}

test.c

#include <stdio.h>
extern int global_variable;
extern int XOR(int);

int main() {
        global_variable = 3;
        printf("%d\n", XOR(0x10));
}

The compiling commands are:

clang -shared -fPIC -o dynamic.so dynamic.c
clang -o test test.c dynamic.so

I was expecting that in executable test the main function will access global_variable via GOT. However, on the contrary, the global_variable is placed in test's data section and XOR in dynamic.so access the global_variable indirectly.

Could anyone tell me why the compiler didn't ask the test to access global_variable via GOT, but asked the shared object file to do so?

CodePudding user response:

Part of the point of a shared library is that one copy gets loaded into memory, and multiple processes can access that one copy. But every program has its own copy of each of the library's variables. If they were accessed relative to the library's GOT then those would instead be shared among the processes using the library, just like the functions are.

There are other possibilities, but it is clean and consistent for each executable to provide for itself all the variables it needs. That requires the library functions to access all of its variables with static storage duration (not just external ones) indirectly, relative to the program. This is ordinary dynamic linking, just going the opposite direction from what you usually think of.

CodePudding user response:

I tried reproducing your problem with exactly the same code and compilation commands as the ones you provided, but it seems like both main and XOR use the GOT to access the global_variable. I will answer by providing example output of commands that i used to inspect the data flow. If your outputs differ from mine, it means there is some other difference between our environments (i mean a big difference, if only addresses/values are different then its ok). Best way to find that difference is for you to provide commands you originally used as well as their output.

First step is to check what address is accessed whenever a write or read to global_variable happens. For that we can use objdump -D -j .text test command to disassemble the code and look at the main function:

0000000000001150 <main>:
    1150:       55                      push   %rbp
    1151:       48 89 e5                mov    %rsp,%rbp
    1154:       48 8b 05 8d 2e 00 00    mov    0x2e8d(%rip),%rax        # 3fe8 <global_variable>
    115b:       c7 00 03 00 00 00       movl   $0x3,(%rax)
    1161:       bf 10 00 00 00          mov    $0x10,           
  • Related