GDB:列出崩溃进程的所有映射内存区域

Posted

技术标签:

【中文标题】GDB:列出崩溃进程的所有映射内存区域【英文标题】:GDB: Listing all mapped memory regions for a crashed process 【发布时间】:2011-08-07 03:58:12 【问题描述】:

我从 x86 Linux 机器上的死进程(内核 2.6.35-22,如果重要的话)得到一个全堆核心转储,我正试图在 GDB 中调试它。

有没有我可以使用的 GDB 命令,意思是“向我显示此进程分配的所有内存地址区域的列表?”换句话说,我能弄清楚我可以在这个转储中检查的所有可能的有效内存地址吗?

我问的原因是我需要在整个整个进程堆中搜索某个二进制字符串,并且为了使用find命令,我需要有一个开始和结束地址。简单地从 0x00 搜索到 0xff.. 是行不通的,因为 find 一遇到无法访问的地址就会停止:

(gdb) 查找 /w 0x10000000, 0xff000000, 0x12345678

警告:无法访问 0x105ef883 处的目标内存,正在暂停 搜索。

所以我需要获取内存中所有可读地址区域的列表,以便一次搜索一个。

(我需要这样做 that 的原因是我需要找到内存中所有指向 at 某个地址的结构。)

show memshow procinfo meminfo proc 似乎都没有满足我的需求。

【问题讨论】:

【参考方案1】:

在 GDB 7.2 中:

(gdb) help info proc
Show /proc process information about any running process.
Specify any process id, or use the program being debugged by default.
Specify any of the following keywords for detailed info:
  mappings -- list of mapped memory regions.
  stat     -- list a bunch of random process info.
  status   -- list a different bunch of random process info.
  all      -- list all available /proc info.

你想要info proc mappings,除非它在没有/proc 时不起作用(例如在事后调试期间)。

改用maintenance info sections

【讨论】:

这是我尝试的第一件事,但它似乎是空的(标题行下没有任何内容)。也许它只是不适用于核心转储? maintenance info sections 似乎更便携,应该是这里的主要答案。 如果您正在调试实时进程,您还可以从cat /proc/<pid>/maps获取/验证此信息 @phihag 那是converted to an answer。现在是多余的评论。 info proc mappings 为我工作。 PWNDGB 版本为vmmaps【参考方案2】:

如果你有程序和核心文件,你可以做以下步骤。

1) 在程序上运行 gdb 和核心文件

 $gdb ./test core

2) 输入信息文件,看看核心文件中有哪些不同的段。

    (gdb)info files

示例输出:

    (gdb)info files 

    Symbols from "/home/emntech/debugging/test".
    Local core dump file:
`/home/emntech/debugging/core', file type elf32-i386.
  0x0055f000 - 0x0055f000 is load1
  0x0057b000 - 0x0057c000 is load2
  0x0057c000 - 0x0057d000 is load3
  0x00746000 - 0x00747000 is load4
  0x00c86000 - 0x00c86000 is load5
  0x00de0000 - 0x00de0000 is load6
  0x00de1000 - 0x00de3000 is load7
  0x00de3000 - 0x00de4000 is load8
  0x00de4000 - 0x00de7000 is load9
  0x08048000 - 0x08048000 is load10
  0x08049000 - 0x0804a000 is load11
  0x0804a000 - 0x0804b000 is load12
  0xb77b9000 - 0xb77ba000 is load13
  0xb77cc000 - 0xb77ce000 is load14
  0xbf91d000 - 0xbf93f000 is load15

就我而言,我有 15 个片段。每个段都有地址的开始和地址的结束。选择要搜索数据的任何细分。例如,让我们选择 load11 并搜索模式。 Load11 的起始地址为 0x08049000,结束于 0x804a000。

3) 在片段中搜索模式。

(gdb) find /w 0x08049000 0x0804a000 0x8048034
 0x804903c
 0x8049040
 2 patterns found

如果您没有可执行文件,则需要使用打印核心文件所有段数据的程序。然后您可以在某个地址搜索特定数据。我没有找到任何这样的程序,您可以使用以下链接中的程序打印内核或可执行文件的所有段的数据。

 http://emntech.com/programs/printseg.c

【讨论】:

是否有办法让 gdb 搜索所有这些段而不手动指定每个段? 那个 printseg.c 已经不在那个网站上了。它在archive.org 上也没有【参考方案3】:
(gdb) maintenance info sections 
Exec file:
    `/path/to/app.out', file type elf32-littlearm.
    0x0000->0x0360 at 0x00008000: .intvecs ALLOC LOAD READONLY DATA HAS_CONTENTS

这是来自上面 phihag 的评论,值得单独回答。这可行,但 info proc 不适用于 gcc-arm-none-eabi Ubuntu 软件包中的 arm-none-eabi-gdb v7.4.1.20130913-cvs。

【讨论】:

【参考方案4】:

您还可以使用info files 列出进程二进制文件中加载的所有二进制文件的所有部分。

【讨论】:

【参考方案5】:

我刚刚看到了以下内容:

set mem inaccessible-by-default [on|off]

here

它可能允许您在不考虑内存是否可访问的情况下进行搜索。

【讨论】:

嗯,不幸的是,对我来说,在 GDB 10.1 上这不起作用。 @Gizmo 那是在 x86 上吗?该链接仍然描述了这一点,因为它应该可以工作。 是的,正在调试 x86 目标。【参考方案6】:

maintenance info sections 的问题在于该命令试图从二进制文件的节头中提取信息。如果二进制文件被触发(例如sstrip)或当加载程序可能在加载后更改内存权限时给出错误信息(例如RELRO 的情况),则它不起作用。

【讨论】:

info proc mappings 在调试核心转储时不可用。 啊,你是对的,info proc mappings不适用于这种情况。

以上是关于GDB:列出崩溃进程的所有映射内存区域的主要内容,如果未能解决你的问题,请参考以下文章

五十进程间通信——System V IPC 之共享内存

进程通信之内存共享篇

存储映射I/O

Linux进程通信 | 共享内存

共享内存原理

Android进程内存映射