deadbeef
deadbeef

Reputation: 629

Access a global static variable from a .so file without modifying library

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

Answers (2)

Ctx
Ctx

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

0___________
0___________

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

Related Questions