我从 x86 Linux 机器(内核 2.6.35-22,如果重要的话)上的死进程中获得了全堆核心转储,我正在尝试在 GDB 中进行调试。
是否有一个我可以使用的 GDB 命令,意思是“显示该进程分配的所有内存地址区域的列表?”换句话说,我可以找出可以在此转储中检查的所有可能的有效内存地址吗?
我问的原因是我需要在整个进程堆中搜索某个二进制字符串,并且为了使用
find
命令,我需要有一个开始和结束地址。简单地从 0x00 到 0xff 进行搜索是行不通的,因为 find
一旦遇到无法访问的地址就会停止:
(gdb) 查找 /w 0x10000000, 0xff000000, 0x12345678
警告:无法访问 0x105ef883 处的目标内存,正在停止 搜索。
所以我需要获取内存中所有可读地址区域的列表,以便我可以一次搜索一个。
(我需要做that的原因是我需要找到内存中指向at某个地址的所有结构。)
show mem
、show proc
、info mem
、info proc
似乎都不能满足我的需要。
在 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
。
如果您有程序和核心文件,则可以执行以下步骤。
1)在程序上运行 gdb 以及核心文件
$gdb ./test core
2) 输入 info 文件并查看核心文件中有哪些不同的段。
(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) 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。
您还可以使用
info files
列出进程二进制文件中加载的所有二进制文件的所有部分。
maintenance info sections
的问题是该命令尝试从二进制文件的节头中提取信息。如果二进制文件被触发(例如通过sstrip
),或者当加载程序可能在加载后更改内存权限时给出错误信息(例如RELRO
的情况),则它不起作用。
请注意,如果您想确定进程的共享内存段、
mmap()
区域等映射到其地址空间的位置,这些都不会帮助您。
此信息似乎未包含在核心中。
maintenance info target-sections
和 maintenance info target
都没有显示出来。
(所以它可能根本不存在,或者充其量是在 gdb 不使用的核心部分中。也许可以从内部 libc 簿记状态中找出一些信息,但不是以通用方式)。