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 ;)