如何转储进程的内存页面?

时间:2015-02-17 23:39:32

标签: memory memory-management gdb dump

我想在完成执行后转储进程的内存页面。我正在尝试使用gdb,首先我在exit和_exit设置断点,然后我在gdb中运行进程,一旦进程中断,我使用info proc mappings来获取进程的内存映射。它看起来如下:

Mapped address spaces:

          Start Addr           End Addr       Size     Offset objfile
            0x400000           0x415000    0x15000        0x0 /path/workspace/freqmine
            0x614000           0x615000     0x1000    0x14000 /path/workspace/freqmine
            0x615000           0x616000     0x1000    0x15000 /path/workspace/freqmine
            0x616000          0x129b000   0xc85000        0x0 [heap]
      0x7ffff71f4000     0x7ffff720a000    0x16000        0x0 /lib/x86_64-linux-gnu/libgcc_s.so.1
      0x7ffff720a000     0x7ffff7409000   0x1ff000    0x16000 /lib/x86_64-linux-gnu/libgcc_s.so.1
      0x7ffff7409000     0x7ffff740a000     0x1000    0x15000 /lib/x86_64-linux-gnu/libgcc_s.so.1
      0x7ffff740a000     0x7ffff750f000   0x105000        0x0 /lib/x86_64-linux-gnu/libm-2.19.so
      0x7ffff750f000     0x7ffff770e000   0x1ff000   0x105000 /lib/x86_64-linux-gnu/libm-2.19.so
      0x7ffff770e000     0x7ffff770f000     0x1000   0x104000 /lib/x86_64-linux-gnu/libm-2.19.so
      0x7ffff770f000     0x7ffff7710000     0x1000   0x105000 /lib/x86_64-linux-gnu/libm-2.19.so
      0x7ffff7710000     0x7ffff78cb000   0x1bb000        0x0 /lib/x86_64-linux-gnu/libc-2.19.so
      0x7ffff78cb000     0x7ffff7acb000   0x200000   0x1bb000 /lib/x86_64-linux-gnu/libc-2.19.so
      0x7ffff7acb000     0x7ffff7acf000     0x4000   0x1bb000 /lib/x86_64-linux-gnu/libc-2.19.so
      0x7ffff7acf000     0x7ffff7ad1000     0x2000   0x1bf000 /lib/x86_64-linux-gnu/libc-2.19.so
      0x7ffff7ad1000     0x7ffff7ad6000     0x5000        0x0 
      0x7ffff7ad6000     0x7ffff7bbc000    0xe6000        0x0 /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.19
      0x7ffff7bbc000     0x7ffff7dbb000   0x1ff000    0xe6000 /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.19
      0x7ffff7dbb000     0x7ffff7dc3000     0x8000    0xe5000 /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.19
      0x7ffff7dc3000     0x7ffff7dc5000     0x2000    0xed000 /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.19
      0x7ffff7dc5000     0x7ffff7dda000    0x15000        0x0 
      0x7ffff7dda000     0x7ffff7dfd000    0x23000        0x0 /lib/x86_64-linux-gnu/ld-2.19.so
      0x7ffff7fce000     0x7ffff7fd3000     0x5000        0x0 
      0x7ffff7ff7000     0x7ffff7ffa000     0x3000        0x0 
      0x7ffff7ffa000     0x7ffff7ffc000     0x2000        0x0 [vdso]
      0x7ffff7ffc000     0x7ffff7ffd000     0x1000    0x22000 /lib/x86_64-linux-gnu/ld-2.19.so
      0x7ffff7ffd000     0x7ffff7ffe000     0x1000    0x23000 /lib/x86_64-linux-gnu/ld-2.19.so
      0x7ffff7ffe000     0x7ffff7fff000     0x1000        0x0 
      0x7ffffffdd000     0x7ffffffff000    0x22000        0x0 [stack]
  0xffffffffff600000 0xffffffffff601000     0x1000        0x0 [vsyscall]

现在我有两个问题,第一个:我的机器上的getconf PAGESIZE返回4096,它等于0x1000,但其中一些内存空间大小不同。怎么可能?这些空间是内存页还是逻辑空间?如果这些不是内存页面,我如何查看内存页面的地址,甚至直接将内存页面转储到文件?

我的第二个问题如下:这些地址应该是程序查看的虚拟地址(不是物理地址),为什么程序空间不能从0开始?如果我尝试从地址0开始转储内存,我会收到以下错误:Cannot access memory at address 0x0。还有为什么这些内存空间之间存在一些无法访问的区域(例如堆之后的区域)?进程的虚拟空间不应该是连续的吗?

1 个答案:

答案 0 :(得分:2)

  但是,其中一些内存空间有不同的大小。怎么可能?

简单:它们跨越多个页面(请注意,它们的所有大小都是倍数 0x1000)。

  

这些空间是内存页还是逻辑空间?

它们是一个或多个页面的跨度,具有相同的底层映射(相同的文件)和相同的保护。我不确定你究竟称之为“逻辑空间”,但你可以称之为“逻辑空间”。

  

这些地址应该是程序查看的虚拟地址(不是物理地址),

正确。

  

那么为什么程序空间不能从0开始?

因为很久以前VAX机器用于在地址0处映射某些东西,并且这使得查找NULL指针解除引用很难(它们没有崩溃)。这被认为是坏主意,因此后来的UNIX变体映射零页面,并且任何取消引用NULL指针的尝试都会导致{{1} },帮助您调试程序。