Memory 检查pmap报告的虚拟内存块

Memory 检查pmap报告的虚拟内存块,memory,gdb,massif,Memory,Gdb,Massif,我发现我的程序有漏洞。它没有被“valgrind memcheck”抓住(我通过总结报告确认了这一点,它没有接近我所能看到的最高使用率)。在使用“valgrind massif——pages as heap”时,我可以更接近我的内存使用情况。 然而,它并没有报告对执行mmap并分配大部分内存的部分的完整回溯,我也不能检查内存分配,因为我只能在程序终止后收集massif输出。 我尝试的另一件事是检查占用大量RSS空间的内存块。但是,我不知道如何查看pmap报告的内存块的内容。把那个地址放在gdb力

我发现我的程序有漏洞。它没有被“valgrind memcheck”抓住(我通过总结报告确认了这一点,它没有接近我所能看到的最高使用率)。在使用“valgrind massif——pages as heap”时,我可以更接近我的内存使用情况。 然而,它并没有报告对执行mmap并分配大部分内存的部分的完整回溯,我也不能检查内存分配,因为我只能在程序终止后收集massif输出。 我尝试的另一件事是检查占用大量RSS空间的内存块。但是,我不知道如何查看pmap报告的内存块的内容。把那个地址放在gdb力帮助上。我听说gdb使用了一些地址随机化。有人能帮助我如何获得与pmap输出报告的内存位置相对应的符号吗

把那个地址放在gdb力帮助上

我不知道你所说的“把那个地址放在gdb上”是什么意思,但正确地这样做会有所帮助

我听说gdb使用了一些地址随机化

你听错了:GDB本身不做任何随机化,它(默认情况下)禁用操作系统执行的随机化,以便使调试更容易和更具可复制性

有人能帮助我如何获得与pmap输出报告的内存位置相对应的符号吗

您感到困惑:堆分配的内存定义上没有任何符号

好的,让我们来看一个使用GDB检查在
pmap
中可见的内存的例子。让我们从编译这个程序开始,它构建了一个100万长的链表,其中包含一些字符串:

#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>

typedef struct Node { struct Node *next; char payload[64]; } Node;

int main()
{
  int j;   
  Node *head = NULL;

  for (j = 0; j < 1000000; j++) {
    Node *n = malloc(sizeof(*n));
    n->next = head;
    sprintf(n->payload, "string %d", j);
    head = n;
  }
  return 0;
}

gcc -Wall -g -std=c99 t.c && gdb -q ./a.out

(gdb) b 17
Breakpoint 1 at 0x4005e3: file t.c, line 17.
(gdb) r
Starting program: /tmp/a.out

Breakpoint 1, main () at t.c:17
17    return 0;
很明显,78MiB的
anon
空间(从
0x602000
开始)必须是大多数数据所在的位置。(您还可以通过在循环中单步执行几次来验证这一点。)

我们如何看待这些数据?像这样:

(gdb) x/30gx 0x602000
0x602000:   0x0000000000000000  0x0000000000000051
0x602010:   0x0000000000000000  0x3020676e69727473
0x602020:   0x0000000000000000  0x0000000000000000
0x602030:   0x0000000000000000  0x0000000000000000
0x602040:   0x0000000000000000  0x0000000000000000
0x602050:   0x0000000000000000  0x0000000000000051
0x602060:   0x0000000000602010  0x3120676e69727473
0x602070:   0x0000000000000000  0x0000000000000000
0x602080:   0x0000000000000000  0x0000000000000000
0x602090:   0x0000000000000000  0x0000000000000000
0x6020a0:   0x0000000000000000  0x0000000000000051
0x6020b0:   0x0000000000602060  0x3220676e69727473
0x6020c0:   0x0000000000000000  0x0000000000000000
0x6020d0:   0x0000000000000000  0x0000000000000000
0x6020e0:   0x0000000000000000  0x0000000000000000
您可以立即注意到,在
0x602018
、在
0x602068
0x6020b8
中都有
ASCII
字符串

您可以这样检查这些字符串:

(gdb) x/s 0x602018
0x602018:   "string 0"
(gdb) x/s 0x602068
0x602068:   "string 1"
(gdb) x/s 0x6020b8
0x6020b8:   "string 2"
您还可以注意到,在
0x602060
处有一个指向
0x602010
的指针,在
0x6020b0
处有一个指向
0x602060
的指针

这让您猜测在
0x602060
处有一个节点,在
0x6020b0
处有另一个节点。你可以证实这个猜测:

(gdb) p *(Node*)0x602060
$1 = {next = 0x602010, payload = "string 1", '\000' <repeats 55 times>}
(gdb) p *(Node*)0x6020b0
$2 = {next = 0x602060, payload = "string 2", '\000' <repeats 55 times>}
(gdb)p*(节点*)0x602060
$1={next=0x602010,payload=“string 1”,'\000'}
(gdb)p*(节点*)0x6020b0
$2={next=0x602060,payload=“string 2”,'\000'}
这就是全部

(gdb) p *(Node*)0x602060
$1 = {next = 0x602010, payload = "string 1", '\000' <repeats 55 times>}
(gdb) p *(Node*)0x6020b0
$2 = {next = 0x602060, payload = "string 2", '\000' <repeats 55 times>}