从.so文件访问全局静态变量而不修改库

dea*_*eef 3 c compiler-construction

我有一个在库(.so文件)中定义的全局静态变量,我想从我的应用程序访问它.应用程序.so在运行时加载库.

有没有办法在不修改库代码的情况下访问静态变量?我知道这并不简单,因为我看到一旦编译完成,变量符号本身将从符号表中消失.我仍然认为可能有一些hacky方式(通过爬行符号表等)来访问此变量.有帮助吗?

lib.c -> static struct Abc abc --> compiled to a.so
app.c ->loads a.so and need to access abc variable?
Run Code Online (Sandbox Code Playgroud)

更新:a.so是使用编译的gcc -O2 option.

P__*_*J__ 6

这是不可能的,因为static全局变量的想法是使它对除当前编译单元之外的任何东西都不可见

如果库开发人员使对象静态,可能是因为某个原因而完成的,并且他不希望在库代码之外访问该对象

  • 这个错误的答案得出结论,因为C的语义排除了C语义内部的解决方案,因此无法解决问题.然而,这个问题要求采用"hacky方式",这意味着C语义之外的解决方案是可以接受的,而且这个答案没有考虑到这一点. (3认同)

Ctx*_*Ctx 5

一般来说,不能访问静态全局变量是正确的。在某些情况下,它甚至可能会被优化掉,因此根本不存在固定的内存位置。

但是如果它没有被优化掉,那么当然总是有“hackish”的方式来访问它。然而,爬取符号表不是一种选择,因为符号通常不会在那里列出。您必须更深入地研究汇编代码。此示例适用于带有 gcc 和 x86_64 cpu 的 linux。它假定源可用,以识别汇编代码中的变量访问。

想象一下以下共享对象源文件:

static int bar = 31337;

int foo (void) {
    bar = getpid();
}
Run Code Online (Sandbox Code Playgroud)

bar是你的静态变量。您现在可以通过检查反汇编的源代码来找出bar函数的偏移量foo——尽管整个库重新定位,但它始终保持不变:

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  
Run Code Online (Sandbox Code Playgroud)

在这里,您会看到该函数foo具有地址6a0(稍后会重定位)并且bar在 address 处访问静态全局变量200978,这使得总偏移量为200978-6a0 = 2002D8。所以如果你打开共享库

void *h = dlopen("shared.so", RTLD_LAZY);
Run Code Online (Sandbox Code Playgroud)

并查找符号 foo

void *foo = dlsym(h, "foo");
Run Code Online (Sandbox Code Playgroud)

您可以bar通过添加计算出的偏移量来计算的地址:

int *a = foo + 0x2002D8;
printf("%d\n", *a);
Run Code Online (Sandbox Code Playgroud)

根据要求,一种骇人听闻的方式;)