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.
这是不可能的,因为static全局变量的想法是使它对除当前编译单元之外的任何东西都不可见
如果库开发人员使对象静态,可能是因为某个原因而完成的,并且他不希望在库代码之外访问该对象
一般来说,不能访问静态全局变量是正确的。在某些情况下,它甚至可能会被优化掉,因此根本不存在固定的内存位置。
但是如果它没有被优化掉,那么当然总是有“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)
根据要求,一种骇人听闻的方式;)