Reputation: 629
I have a global static variable defined in a library (.so
file) which I want to access from my application. Application loads the .so
library at run time.
Is there a way to access the static variable without modifying the library code? I know it is not straightforward as I see that variable symbol itself will be gone from symbol table once compilation is done. I still think that there could be some hacky way (by crawling symbol table etc) to access this variable. Any help?
lib.c -> static struct Abc abc --> compiled to a.so
app.c ->loads a.so and need to access abc variable?
update: a.so is compiled using gcc -O2 option
.
Upvotes: 4
Views: 981
Reputation: 18410
In general, it is correct that a static global variable cannot be accessed. It even might be optimized away under some circumstances, so that there doesn't exist a fixed memory location at all.
But if it is not optimized away, then of course there are always "hackish" ways to access it anyway. Crawling the symbol table is however not an option, since the symbol usually is not listed there. You have to dig deeper into the assembly code. This example is for linux with gcc and x86_64 cpu. It assumes, that the source is available, to identify the variable access in the assembly code.
Imagine the following shared object source file:
static int bar = 31337;
int foo (void) {
bar = getpid();
}
bar
is your static variable. You can now find out the offset of bar
from the function foo
- which is always constant despite relocation of the whole library - by examining the disassembled source:
objdump -x shared.so
00000000000006a0 <foo>:
6a0: 48 83 ec 08 sub $0x8,%rsp
6a4: 31 c0 xor %eax,%eax
6a6: e8 c5 fe ff ff callq 570 <getpid@plt>
6ab: 89 05 c7 02 20 00 mov %eax,0x2002c7(%rip) # 200978 <_fini+0x2002c0>
6b1: 48 83 c4 08 add $0x8,%rsp
6b5: c3 retq
Here, you see that the function foo
has address 6a0
(subject to relocation later) and the static global variable bar
is accessed at address 200978
, which makes a total offset of 200978-6a0 = 2002D8
. So if you open the shared library
void *h = dlopen("shared.so", RTLD_LAZY);
and lookup the symbol foo
void *foo = dlsym(h, "foo");
you can calculate the address of bar
by adding the calculated offset:
int *a = foo + 0x2002D8;
printf("%d\n", *a);
A hackish way, as requested ;)
Upvotes: 6
Reputation: 67476
It is not possible as the idea of the static
global variable is to make it invisible to anything except the current compilation unit
If the library developer made the object static probably it was done for a reason and he did not want this object to accessed outside the library code
Upvotes: 5