我有一个小的静态库(.a
)。在静态库中是一个指向大型静态分配的1D数组的指针。
当我将代码链接到此库时,指针的地址在各个位置进行硬编码,通过反汇编很容易找到。问题是,我希望我的代码能够访问这个数组(库是错误的,我想知道原因)。
当然,通过反汇编,将该地址硬编码到我的代码中然后重新编译来获取指针是微不足道的。这不会是一个问题,除了库可以与其他模块以不同的方式配置,并且数组的指针根据链接的模块而改变。
获取指针有什么选择?因为数组的起始状态是可预测的,所以我可以遍历内存,使用信号处理程序捕获段错误,直到找到看起来合理的内容。还有更好的方法吗?
答案 0 :(得分:4)
由于您的库是.a
存档,我假设您使用的是某种UNIX。
全局数组应具有与之关联的符号名称。根据符号的描述,您的工作会更容易或更难。
如果有一个描述此数组的全局符号,那么您可以直接引用它,例如
extern char some_array[];
for (int i = 0; i < 100; i++) printf("%2d: 0x%2x\n", i, some_array[i]);
如果符号是本地符号,则可以先使用objcopy --globalize-symbol=some_array
对其进行全球化,然后按上述步骤操作。
那么如何确定描述该数组的符号是什么?运行objdump -dr foo.o
,其中foo.o
包含您知道引用该数组的说明。将在引用指令旁边显示的重定位将告诉您名称。
最后,运行nm foo.o | grep some_array
。如果你看到00000XX D some_array
,那么你就完成了 - 数组是全局可见的(B
相同)。如果您看到000XX d some_array
,则需要先对其进行全球化(同样适用于b
)。
更新
-dr to objectdump无法正常工作
是的,因为符号结果是本地的,重定位可能是.bss + 0xNNN
。
00000000006b5ec0 b grid
00000000006c8620 b grid
00000000006da4a0 b grid
00000000006ec320 b grid
00000000006fe1a0 b grid
您必须在最终链接的可执行文件上运行nm
,而不是在归档中的单个foo.o
对象上运行grid
。在你的二进制文件中有五个名为// foo.c
static char grid[1000];
的单独的静态数组,只有第一个是你显然关心的那个。
声明“extern int grid [];”并使用它给出一个未定义的引用
这是本地符号的预期:库中的代码类似于:
grid
如果没有首先全局化该符号,则无法从foo.o
外部引用此{{1}}。
出于安全原因,我不允许在我们的服务器上运行库的更改二进制文件
我希望您理解该论点是 total BS :如果您可以将自己的代码链接到该二进制文件中,那么您可以在服务器上执行任何(受制于用户ID限制);你已经信任了。如果他不信任你,修改第三方库应该是服务器管理员的至少担心。