【问题标题】:Finding address of variable in shared library在共享库中查找变量的地址
【发布时间】:2014-01-20 14:15:22
【问题描述】:

我想在 .so 文件中查找变量的地址。 if的名字我不知道,只知道它是一个整数,我知道它的值。我还知道,一旦动态链接器加载并链接了库,内存中的地址就是0x6416A0,相对于库地址。这个偏移量大于动态库本身的大小。我只有库的二进制编译版本。

为了在.so 文件中找到变量的地址,我使用objdump 查看了它:

$ objdump -x /path/to/lib.so
Program Header:
LOAD off    0x0000000000000000 vaddr 0x0000000000000000 paddr 0x0000000000000000 align 2**21
     filesz 0x0000000000505fa9 memsz 0x0000000000505fa9 flags r-x
LOAD off    0x0000000000506000 vaddr 0x0000000000706000 paddr 0x0000000000706000 align 2**21
     filesz 0x00000000000db8f0 memsz 0x00000000001764c0 flags rw-
DYNAMIC off    0x00000000005210b0 vaddr 0x00000000007210b0 paddr 0x00000000007210b0 align 2**3
     filesz 0x00000000000003e0 memsz 0x00000000000003e0 flags rw-
EH_FRAME off    0x0000000000476898 vaddr 0x0000000000476898 paddr 0x0000000000476898 align 2**2
     filesz 0x0000000000014674 memsz 0x0000000000014674 flags r--
STACK off    0x0000000000000000 vaddr 0x0000000000000000 paddr 0x0000000000000000 align 2**3
     filesz 0x0000000000000000 memsz 0x0000000000000000 flags rw-
[...]

上面我只显示了Program Header,但我要查找的地址不在可用部分的任何地址范围内。如您所见,使用的地址与0x7210b0 一样大,但我的地址不在我看到的任何范围内。

由于链接器使用mmap 来加载.so 文件的内容,我假设知道内存中的偏移量相当于知道文件中的偏移量。显然这是错误的。谁能帮我理解它是如何工作的?有没有简单的方法将内存地址映射到文件地址上?

【问题讨论】:

  • 如果您甚至不知道该变量的名称,那么您将很难找到它。这有点像说“有这个东西,我想找到它。它是红色的,但我不知道它叫什么。你能帮我找到它吗?”。说真的,您不能通过调整再次构建和链接库吗?你为什么要在图书馆里找到它呢?
  • @Phil_12d3 当然我不能构建和链接它——一些库是二进制的。问题不在于找到 something red:我确实知道链接后变量在内存中的地址。我不知道链接器实际上是如何加载库的,以及地址映射到文件的哪个物理部分。
  • @angainor 对不起,但你没有说你不能——这只是一个想法。我有很多库,也有它们的代码。 nm 也不太可能有帮助,因为它只会显示地址、部分和名称。尽管可能是什么,但您也许可以做出有根据的猜测。
  • cat /proc/<pid>/maps 的输出?
  • @ninjalj Bingo - 这确实帮助我得到了我想要的东西。动态库被多次映射,其中一个内存范围确实包含我正在寻找的地址。谢谢!

标签: linux linker gdb shared-libraries


【解决方案1】:

如果您在带有GNU libc 的Linux 系统上,并且该变量是某个dynamically linked 库的动态符号表中的已知名称,即ELF 共享对象,并且您可以更改代码的主程序(或一些由它动态链接的共享对象,也许在玩LD_PRELOAD 技巧)你可以使用dladdr(3) 函数(给定一个指针,dladdr 给你一个带有符号和共享对象名称的Dl_info 结构接近给定的指针)。

由于动态链接的共享对象库通常在不可预测的地址上使用mmap(2)-ed(例如因为ASLR),您需要在运行时执行此操作。 (另请参阅进程内部的/proc/self/maps;阅读proc(5) 等...)

阅读Drepper's paper: How to write Shared Libraries;注意VDSO...

请注意,给定的*.so 文件有几个mmap-ed 段,并且它的一些(文件)数据不是 mmap-ed!使用pmap(1) 找出答案。

【讨论】:

  • 谢谢。不幸的是,我不知道变量的名称。但是,您的回答和@ninjalj 的评论确实让我解决了这个问题。在/proc/self/maps 中,我看到该库被多次映射,在.so 文件中具有不同的偏移量。那里列出的虚拟地址范围之一确实包含我正在寻找的变量地址,因此我能够在 .so 文件中找到相应的地址。杰出的!谢谢。
  • 你不需要知道变量的名字。 dladdr 会找到它。您绝对应该阅读 Drepper 的(长篇)论文!
  • 没错,我现在明白了。但在我的情况下,变量似乎没有被导出(本地?)。我将再次使用dladdr,但由于我现在知道文件地址,我看到它没有列在objdump -T 显示的任何导出符号旁边。所以我猜dladdr 也找不到它。我说的对吗?
猜你喜欢
  • 2014-12-16
  • 2013-10-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-01-14
  • 2017-07-10
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多