将运行Linux进程中的内存地址范围转换为目标文件中的符号?

时间:2008-10-20 20:32:13

标签: linux memory debugging symbols elf

以下是 / proc / self / smaps 文件的片段:

00af8000-00b14000 r-xp 00000000 fd:00 16417      /lib/ld-2.8.so
Size:                112 kB
Rss:                  88 kB
Pss:                   1 kB
Shared_Clean:         88 kB
Shared_Dirty:          0 kB
Private_Clean:         0 kB
Private_Dirty:         0 kB
Referenced:           88 kB
Swap:                  0 kB
00b14000-00b15000 r--p 0001c000 fd:00 16417      /lib/ld-2.8.so
Size:                  4 kB
Rss:                   4 kB
Pss:                   4 kB
Shared_Clean:          0 kB
Shared_Dirty:          0 kB
Private_Clean:         0 kB
Private_Dirty:         4 kB
Referenced:            4 kB
Swap:                  0 kB

它显示此进程(self)链接到 /ll/ld-2.8.so 以及映射到内存中的两个(中)字节范围。< / p>

88kb(22个4kb页面)的第一个范围是共享 clean ,即它尚未被写入。这可能是代码。

第二个4kb范围(单个页面)未共享且 - 进程已写入,因为它是从磁盘上的文件映射的内存。这可能是数据。

但那个记忆中有什么?

如何将内存范围 00b14000-00b15000 转换为有用的信息,例如声明大型静态结构的文件的行号?

该技术需要考虑prelinkingaddress space randomization,例如execshieldseparate debugging symbols

(动机是识别流行的库,这些库也会创建脏内存并修复它们,例如通过声明结构const)。

3 个答案:

答案 0 :(得分:5)

smaps的格式是:

[BOTTOM] - [TOP] [PERM] [FILE OFFSET]

b80e9000-b80ea000 rw-p 0001b000 08:05 605294 /lib/ld-2.8.90.so

因此文件偏移量0x0001b000处的文件'/lib/ld-2.8.90.so'的实际内容映射到该程序内存中的0xb80e9000。

要提取映射地址的行号或C代码,您需要将其与可执行文件或库文件的ELF部分匹配,然后提取GDB符号(如果所述可执行文件或库仍然具有它们)。

GDB文件格式记录在({3}}

上(表面上)

答案 1 :(得分:3)

从ParaDyn项目(U. Wisc / U.Malland)看SymtabAPI。它运行在许多平台上,并且不仅支持ELF文件(我相信它还支持COFF和其他一些)。有documentation here

具体来说,您可以查看AddressLookup类;我认为它完全符合您的要求。还有一些工具(getLoadAddresses())用于查找在任何给定时间加载的.so,我相信你也可以提取加载模块的代码部分的范围,这样你就可以知道内存的某些部分是什么

警告:我认为它会正确处理地址空间随机化,但我并不完全确定。

答案 2 :(得分:0)

您需要从Linux的内存处理程序中提取信息,以确定应用程序的虚拟内存映射与给定页面的关系。如果你还想跟踪已经换掉内存的页面中的信息,那就太麻烦了。

你会发现some information here可以帮助你入门。流程表包含一些寻呼信息,但您可能需要浏览几个不同的区域以获取您正在寻找的所有深层信息。

- 亚当