首页 > 解决方案 > /proc/PID/maps 中的散点图

问题描述

我在 Linux 系统上检查 Python 进程的内存映射,发现了一些非常令人惊讶的东西。通常,当我检查 Python 进程的地图时,它们看起来像这样:

00400000-00401000 r-xp 00000000 fe:01 2904802                            python3.9
00600000-00601000 r--p 00000000 fe:01 2904802                            python3.9
00601000-00602000 rw-p 00001000 fe:01 2904802                            python3.9
00637000-00abe000 rw-p 00000000 00:00 0                                  [heap]
...
7f67d8565000-7f67d8593000 rw-p 00000000 00:00 0
7f67d8593000-7f67d88ea000 r-xp 00000000 fe:01 2904547                    libpython3.9.so.1.0
7f67d88ea000-7f67d8ae9000 ---p 00357000 fe:01 2904547                    libpython3.9.so.1.0
7f67d8ae9000-7f67d8aef000 r--p 00356000 fe:01 2904547                    libpython3.9.so.1.0
7f67d8aef000-7f67d8b29000 rw-p 0035c000 fe:01 2904547                    libpython3.9.so.1.0
7f67d8b29000-7f67d8b4b000 rw-p 00000000 00:00 0
...
7fff72a4f000-7fff72a70000 rw-p 00000000 00:00 0                          [stack]
7fff72a7c000-7fff72a80000 r--p 00000000 00:00 0                          [vvar]
7fff72a80000-7fff72a82000 r-xp 00000000 00:00 0                          [vdso]
ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0                  [vsyscall]

它具有以下结构:

但是我发现的地图是这样的:

00400000-00401000 r-xp 00000000 fd:00 67488961                           python3.9
00600000-00601000 r--p 00000000 fd:00 67488961                           python3.9
00601000-00602000 rw-p 00001000 fd:00 67488961                           python3.9
0067b000-00a58000 rw-p 00000000 00:00 0                                  [heap]
...
7f7b46014000-7f7b46484000 r--p 0050b000 fd:00 1059871                    libpython3.9.so.1.0
7f7b46484000-7f7b46485000 ---p 00000000 00:00 0
7f7b46485000-7f7b46cda000 rw-p 00000000 00:00 0
7f7b46cda000-7f7b46d16000 r--p 00a3d000 fd:00 1059871                    libpython3.9.so.1.0
7f7b46d16000-7f7b46d6f000 rw-p 00000000 00:00 0
7f7b46d6f000-7f7b46d92000 r--p 00001000 fd:00 67488961                   python3.9
7f7b46d92000-7f7b46d93000 ---p 00000000 00:00 0
7f7b46d93000-7f7b475d3000 rw-p 00000000 00:00 0
...
7f7b5a35d000-7f7b5a827000 r-xp 00000000 fd:00 1059871                    libpython3.9.so.1.0
7f7b5a827000-7f7b5aa27000 ---p 004ca000 fd:00 1059871                    libpython3.9.so.1.0
7f7b5aa27000-7f7b5aa2c000 r--p 004ca000 fd:00 1059871                    libpython3.9.so.1.0
7f7b5aa2c000-7f7b5aa67000 rw-p 004cf000 fd:00 1059871                    libpython3.9.so.1.0
7f7b5aa67000-7f7b5aa8b000 rw-p 00000000 00:00 0
...
7fff26f8e000-7fff27020000 rw-p 00000000 00:00 0                          [stack]
7fff27102000-7fff27106000 r--p 00000000 00:00 0                          [vvar]
7fff27106000-7fff27108000 r-xp 00000000 00:00 0                          [vdso]
ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0                  /vsyscall]

这有以下奇怪之处:

7f7b46cda000-7f7b46d16000 r--p 00a3d000 fd:00 1059871                    libpython3.9.so.1.0
7f7b46d16000-7f7b46d6f000 rw-p 00000000 00:00 0
7f7b46d6f000-7f7b46d92000 r--p 00001000 fd:00 67488961                   python3.9
7f7b46d92000-7f7b46d93000 ---p 00000000 00:00 0

你知道什么会导致这种影响,或者在什么情况下会发生这种情况?您知道在几个共享对象之后加载可执行文件的内存映射是如何可能的吗?

注意:这是使用 kernel Kernel 5.13.12-100.fc33.x86_64

标签: linuxmemorylinux-kernelelf

解决方案


你知道什么会导致这种影响,或者在什么情况下会发生这种情况?

可执行文件可以很简单地mmap(部分地)它自己。这可以用来检查它自己的符号表(打印崩溃堆栈跟踪所必需的),或者提取一些嵌入式资源。

可执行文件 (python3.9) 的映射首先出现,打开的共享库的映射出现在可执行文件中的映射之后。

这只是偶然的,并且仅适用于非 PIE 可执行文件。

传统x86_64上,非 PIE 可执行文件链接到在地址加载,并且共享库通常从主堆栈下方开始加载。0x400000

如果您链接一个非 PIE 可执行文件以在 eg 加载0x7ff000000000,那么它可能会出现在/proc/$pid/maps after共享库中。

更新:

这里的 python 二进制文件当然不是映射本身,所以这个解释不适用

  1. 你不可能知道——你几乎肯定没有阅读Python 3.9 中的所有代码以及你加载的每个模块。
  2. 无需猜测这些mmaped 区域来自何处,您只需查看.

要查看,请在 GDB 下运行您的程序,然后catch syscall mmap使用where. 这将允许您查看每个映射的来源。


推荐阅读