Создать основной файл с помощью GDB

Я использовал gdb generate-core-file для генерации файла ядра для процесса (mongod), но процесс mmap содержит много файлов данных, а Res этого процесса составляет до 36.1G.
после того, как файл ядра занял 34 ГБ, на диске больше нет свободного места, поэтому я получил:

предупреждение: запись раздела заметки (на устройстве не осталось места) Сохранено corefile core.12038

Я хочу знать, все ли данные mmap будут выгружены в основной файл? Что я могу сделать, если я хочу видеть только некоторые локальные переменные?

Предыстория: у нас возникла проблема с производством, а двоичный файл на производстве не содержит символьной информации. поэтому я хочу создать основной файл и провести анализ в автономном режиме.

2 ответа

Решение

Я хочу знать, все ли данные mmap будут выгружены в основной файл?

Обычно ядро ​​создает дамп только для записи mmaps, но не только для чтения. Однако это настраивается: см. Справочную страницу core(5) (часть "Управление тем, какие сопоставления записываются в дамп ядра").

Предыстория: у нас возникла проблема с производством, а двоичный файл на производстве не содержит символьной информации.

"Стандартный" подход заключается в удаленной отладке таких двоичных файлов с gdbserver и подключиться к нему с gdb у которого есть доступ к полному отладочному двоичному файлу.

Что я могу сделать, если я хочу видеть только некоторые локальные переменные? Предыстория: у нас возникла проблема с производством, а двоичный файл на производстве не содержит символьной информации.

Вы не упомянули ОС в своем вопросе, так что если вы на 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;
}

Поэтому я хочу получить значение локальной переменной "c" в функции 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"))
}

Поэтому я запустил "./a.out 21 23", а затем запустил сценарий 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
Другие вопросы по тегам