4

这是文件/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

它表明该进程(自身)链接到/lib/ld-2.8.so和两个(许多)字节范围映射到内存中。

第一个 88kb 范围(22 个 4kb 页面)是sharedclean,也就是说它没有被写入。这可能是代码。

第二个 4kb 范围(单页)没有被共享并且它是的——进程已经写入它,因为它是从磁盘上的文件映射的内存。这大概就是数据了。

但那段记忆里到底是什么?

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

该技术需要考虑链接和地址空间随机化,例如来自execshield,以及单独的调试符号

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

4

3 回答 3

5

smaps 的格式为:

[底部]-[顶部] [烫发] [文件偏移]

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

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

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

GDB 文件格式(表面上)记录在http://sourceware.org/gdb/current/onlinedocs/gdbint_7.html#SEC60

于 2008-10-21T03:13:00.583 回答
3

查看ParaDyn项目(U. Wisc/U. Maryland)中的 SymtabAPI。它在许多平台上运行,并且支持的不仅仅是 ELF 文件(我相信它还支持 COFF 和其他一些文件)。这里有文档

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

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

于 2008-10-21T06:05:55.790 回答
0

您需要从 Linux 的内存处理程序中提取信息,以确定应用程序的虚拟内存映射与给定页面的关系。如果您还想跟踪已换出内存的页面中的信息,这将变得更加棘手。

您会在此处找到一些信息,这些信息可以帮助您入门。进程表包含一些分页信息,但您可能必须四处寻找几个不同的区域才能获得您正在寻找的所有深层信息。

-亚当

于 2008-10-20T20:40:03.950 回答