使用gdb生成核心文件

时间:2013-12-27 07:17:16

标签: gdb core-file

我使用gdb generate-core-file为进程(mongod)生成核心文件,但是进程mmap许多数据文件和此进程的Res高达36.1G。
在核心文件占用34G空间后,磁盘上没有更多可用空间,所以我得到了:

警告:写笔记部分(设备上没有剩余空间) 保存的corefile core.12038

我想知道是否所有的mmap数据都要转储到核心文件中?如果我只想查看一些局部变量,我该怎么办?

背景:  我们在生产上遇到了问题,生产中的二进制文件中没有符号信息。所以我想生成核心文件并做一些离线分析。

2 个答案:

答案 0 :(得分:1)

  

我想知道是否所有mmap数据都将转储到核心文件?

通常内核只转储可写的mmaps,但不转储为只读的mmaps。但是,这是可配置的:请参阅core(5)手册页(“控制哪些映射写入核心转储”部分)。

  

背景:我们在制作时遇到了问题,生产中的二进制文件中没有符号信息。

“标准”方法是使用gdbserver远程调试此类二进制文件,并使用{em> 可以访问完全调试二进制文件的gdb连接到它。

答案 1 :(得分:0)

  

如果我只想查看一些局部变量,我该怎么办?   背景:我们在制作上遇到了问题,生产中的二进制文件中没有符号信息。

你没有在你的问题中提到操作系统,所以如果你在Linux上 1)在生产服务器上安装带有调试信息的程序
2)如果你不能这样做分析你感兴趣的函数的汇编程序代码并从汇编程序获取局部变量的值

然后使用SystemTap跟踪您的程序。

让我用一个简单的例子说明这两种方法。 首先,分析C ++程序:

>cat main.cpp
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

int f(int arg)
{
    int a = arg+1;
    int b = arg+2;
    int c = a + b;
    printf ("printf in program: f, c: %d\n", c);
    return c;
}

int main(int argc, char *argv[])
{
   printf ("f: %p\n", &f);
   int sum = 0;
   while (true) {
     for (int i= atoi(argv[1]); i < atoi(argv[2]); ++i) {
       sum += f(i);
     }
     sleep(5);
   }

   printf("Sum: %d\n", sum);
   return 0;
}

所以我想获得本地变量的价值&#34; c&#34;在函数f()中。

1)如果符号信息可用

>cat measure_f.stp
probe process("a.out").statement("*@main.cpp:10")
{
  printf("SystemTap, time: %s, the local variable c :%d\n", ctime(gettimeofday_s()), $c)
}

>sudo stap measure_f.stp -c "./a.out 21 23"
f: 0x400634
printf in program: f, c: 45
printf in program: f, c: 47
SystemTap, time: Fri Dec 27 12:59:31 2013, the local variable c :45
SystemTap, time: Fri Dec 27 12:59:31 2013, the local variable c :47
printf in program: f, c: 45
printf in program: f, c: 47
SystemTap, time: Fri Dec 27 12:59:36 2013, the local variable c :45
SystemTap, time: Fri Dec 27 12:59:36 2013, the local variable c :47

1)如果符号信息不可用,则使用汇编程序

首先反汇编您的功能并找到您要监控的地址

(gdb) disassemble /m f
Dump of assembler code for function f(int):
6       {
   0x0000000000400634 <+0>:     push   %rbp
   0x0000000000400635 <+1>:     mov    %rsp,%rbp
   0x0000000000400638 <+4>:     sub    $0x20,%rsp
   0x000000000040063c <+8>:     mov    %edi,-0x14(%rbp)

7           int a = arg+1;
   0x000000000040063f <+11>:    mov    -0x14(%rbp),%eax
   0x0000000000400642 <+14>:    add    $0x1,%eax
   0x0000000000400645 <+17>:    mov    %eax,-0xc(%rbp)

8           int b = arg+2;
   0x0000000000400648 <+20>:    mov    -0x14(%rbp),%eax
   0x000000000040064b <+23>:    add    $0x2,%eax
   0x000000000040064e <+26>:    mov    %eax,-0x8(%rbp)

9           int c = a + b;
   0x0000000000400651 <+29>:    mov    -0x8(%rbp),%eax
   0x0000000000400654 <+32>:    mov    -0xc(%rbp),%edx
   0x0000000000400657 <+35>:    lea    (%rdx,%rax,1),%eax
   0x000000000040065a <+38>:    mov    %eax,-0x4(%rbp)

10          printf ("printf in program: f, c: %d\n", c);
   0x000000000040065d <+41>:    mov    -0x4(%rbp),%eax
   0x0000000000400660 <+44>:    mov    %eax,%esi
   0x0000000000400662 <+46>:    mov    $0x4007f8,%edi
   0x0000000000400667 <+51>:    mov    $0x0,%eax
   0x000000000040066c <+56>:    callq  0x4004f8 <printf@plt>

11          return c;
   0x0000000000400671 <+61>:    mov    -0x4(%rbp),%eax

12      }
   0x0000000000400674 <+64>:    leaveq
   0x0000000000400675 <+65>:    retq

正如您所看到的,为了获取局部变量c,必须在0x000000000040065a上获取寄存器%eax

> cat measure_f_2.stp
probe begin
{
  printf("Monitoring process %d\n", $1)
}

probe process($1).statement(0x000000000040065a).absolute
{ 
  printf("SystemTap (2), time: %s, the local variable c (rax):%d\n", ctime(gettimeofday_s()), register("rax"))
}

所以我开始了#34; ./ a.out 21 23&#34;然后运行我的SystemTap脚本

>sudo stap measure_f_2.stp 11564
Monitoring process 11564
SystemTap (2), time: Fri Dec 27 13:15:09 2013, the local variable c (rax):45
SystemTap (2), time: Fri Dec 27 13:15:09 2013, the local variable c (rax):47
SystemTap (2), time: Fri Dec 27 13:15:14 2013, the local variable c (rax):45
SystemTap (2), time: Fri Dec 27 13:15:14 2013, the local variable c (rax):47