Как мне проанализировать файл дампа ядра программы с помощью GDB, если он имеет параметры командной строки?
Моя программа работает так:
exe -p param1 -i param2 -o param3
Он упал и сгенерировал файл дампа ядра core.pid
.
Я хочу проанализировать файл дампа
gdb ./exe -p param1 -i param2 -o param3 core.pid
Но GDB распознает параметры файла EXE как входные данные GDB.
Как мне проанализировать файл дампа ядра в этой ситуации?
Ответы
Ответ 1
Вы можете использовать ядро с gdb разными способами, но передача параметров, которые должны быть переданы в исполняемый файл gdb, не является способом использования файла ядра. Это также может быть причиной, по которой вы получили эту ошибку. Основной файл можно использовать следующими способами:
gdb <executable> <core-file>
или gdb <executable> -c <core-file>
или
gdb <executable>
...
(gdb) core <core-file>
При использовании файла ядра вам не нужно передавать аргументы. Сценарий сбоя отображается в gdb (проверяется с версией gdb версии 7.1 на Ubuntu).
Например:
$ ./crash -p param1 -o param2
Segmentation fault (core dumped)
$ gdb ./crash core
GNU gdb (GDB) 7.1-ubuntu
...
Core was generated by `./crash -p param1 -o param2'. <<<<< See this line shows crash scenario
Program terminated with signal 11, Segmentation fault.
#0 __strlen_ia32 () at ../sysdeps/i386/i686/multiarch/../../i586/strlen.S:99
99 ../sysdeps/i386/i686/multiarch/../../i586/strlen.S: No such file or directory.
in ../sysdeps/i386/i686/multiarch/../../i586/strlen.S
(gdb)
Если вы хотите передать параметры исполняемому файлу для отладки в gdb, используйте --args
.
Например:
$ gdb --args ./crash -p param1 -o param2
GNU gdb (GDB) 7.1-ubuntu
...
(gdb) r
Starting program: /home/@@@@/crash -p param1 -o param2
Program received signal SIGSEGV, Segmentation fault.
__strlen_ia32 () at ../sysdeps/i386/i686/multiarch/../../i586/strlen.S:99
99 ../sysdeps/i386/i686/multiarch/../../i586/strlen.S: No such file or directory.
in ../sysdeps/i386/i686/multiarch/../../i586/strlen.S
(gdb)
Персональные страницы будут полезны для просмотра других опций gdb.
Ответ 2
Простое использование GDB для отладки файлов coredump:
gdb <executable_path> <coredump_file_path>
Файл Coredump для "процесса" создается, как файл "core.pid".
После того, как вы войдете в gdb-prompt (при выполнении указанной выше команды), введите:
...
(gdb) where
Это даст вам информацию о стеке, где вы можете проанализировать причину сбоя/сбоя.
Другая команда для тех же целей:
...
(gdb) bt full
Это то же самое, что и выше. По соглашению он перечисляет всю информацию о стеке (что в конечном итоге приводит к месту сбоя).
Ответ 3
Просто пропустите параметры, gdb им не нужен:
gdb ./exe core.pid
Ответ 4
Из Учебное пособие по отладчику gms gdb:
prompt > myprogram
Segmentation fault (core dumped)
prompt > gdb myprogram
...
(gdb) core core.pid
...
Убедитесь, что ваш файл действительно является изображением core
- проверьте его, используя file
.
Ответ 5
Несколько другой подход позволит вам полностью пропустить GDB. Если все, что вам нужно - это обратная трассировка, специальная утилита "catchsegv" для Linux поймает SIGSEGV и отобразит обратную трассировку.
Ответ 6
Не имеет значения, если исполняемый файл имеет аргументы или нет, для запуска GDB в любом двоичном файле с сгенерированным файлом ядра. Синтаксис ниже.
Syntax:
gdb <binary name> <generated core file>
Eg:
gdb l3_entity 6290-corefile
позвольте мне привести пример ниже для большего понимания.
bash-4.1$**gdb l3_entity 6290-corefile**
**Core was generated** by `/dir1/dir2/dir3/l3_entity **Program terminated with signal SIGABRT, Aborted.**
#0
#1
#2
#3
#4
#5
#6
#7
#8
#9
#10
(gdb)
Из вышесказанного вы можете догадаться о ядре, будь то NULL-доступ или SIGABORT и т.д.
Эти числа от # 0 до # 10 являются кадрами стека GDB. Эти фреймы стека не относятся к вашему двоичному файлу. в приведенных выше 0 - 10 кадрах, если вы подозреваете что-либо неправильное, выберите этот кадр
(gdb) frame 8
Теперь, чтобы узнать подробности об этом:
(gdb) list +
Чтобы исследовать проблему, вы можете напечатать подозрительные значения переменных здесь в этот момент времени.
(gdb) print thread_name
Ответ 7
Пример минимального запуска objdump
+ gdb
TL; DR:
Теперь для полной настройки образовательного теста:
main.c
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int myfunc(int i) {
*(int*)(NULL) = i; /* line 7 */
return i - 1;
}
int main(int argc, char **argv) {
/* Setup some memory. */
char data_ptr[] = "string in data segment";
char *mmap_ptr;
char *text_ptr = "string in text segment";
(void)argv;
mmap_ptr = (char *)malloc(sizeof(data_ptr) + 1);
strcpy(mmap_ptr, data_ptr);
mmap_ptr[10] = 'm';
mmap_ptr[11] = 'm';
mmap_ptr[12] = 'a';
mmap_ptr[13] = 'p';
printf("text addr: %p\n", text_ptr);
printf("data addr: %p\n", data_ptr);
printf("mmap addr: %p\n", mmap_ptr);
/* Call a function to prepare a stack trace. */
return myfunc(argc);
}
Скомпилируйте и запустите для генерации ядра:
gcc -ggdb3 -std=c99 -Wall -Wextra -pedantic -o main.out main.c
ulimit -c unlimited
rm -f core
./main.out
Выход:
text addr: 0x4007d4
data addr: 0x7ffec6739220
mmap addr: 0x1612010
Segmentation fault (core dumped)
GDB указывает нам на точную линию, где произошел segfault, что большинство пользователей хотят при отладке:
gdb -q -nh main.out core
затем:
Reading symbols from main.out...done.
[New LWP 27479]
Core was generated by './main.out'.
Program terminated with signal SIGSEGV, Segmentation fault.
#0 0x0000000000400635 in myfunc (i=1) at main.c:7
7 *(int*)(NULL) = i;
(gdb) bt
#0 0x0000000000400635 in myfunc (i=1) at main.c:7
#1 0x000000000040072b in main (argc=1, argv=0x7ffec6739328) at main.c:28
который указывает нам прямо на глючную линию 7.
Анализ Binutils
Первый:
file core
говорит нам, что файл core
самом деле является файлом ELF:
core: ELF 64-bit LSB core file x86-64, version 1 (SYSV), SVR4-style, from './main.out'
именно поэтому мы можем проверить это непосредственно с помощью обычных инструментов binutils.
Беглый взгляд на стандарт ELF показывает, что на самом деле ему выделен тип ELF:
Elf32_Ehd.e_type == ET_CORE
Дополнительную информацию о формате можно найти по адресу:
man 5 core
Затем:
readelf -Wa core
дает некоторые подсказки о структуре файла. Кажется, что память содержится в обычных заголовках программы:
Program Headers:
Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align
NOTE 0x000468 0x0000000000000000 0x0000000000000000 0x000b9c 0x000000 0
LOAD 0x002000 0x0000000000400000 0x0000000000000000 0x001000 0x001000 R E 0x1000
LOAD 0x003000 0x0000000000600000 0x0000000000000000 0x001000 0x001000 R 0x1000
LOAD 0x004000 0x0000000000601000 0x0000000000000000 0x001000 0x001000 RW 0x1000
и в области заметок есть еще несколько метаданных. Примечательно, что компьютер должен быть там (подтверждение TODO):
Displaying notes found at file offset 0x00000468 with length 0x00000b9c:
Owner Data size Description
CORE 0x00000150 NT_PRSTATUS (prstatus structure)
CORE 0x00000088 NT_PRPSINFO (prpsinfo structure)
CORE 0x00000080 NT_SIGINFO (siginfo_t data)
CORE 0x00000130 NT_AUXV (auxiliary vector)
CORE 0x00000246 NT_FILE (mapped files)
Page size: 4096
Start End Page Offset
0x0000000000400000 0x0000000000401000 0x0000000000000000
/home/ciro/test/main.out
0x0000000000600000 0x0000000000601000 0x0000000000000000
/home/ciro/test/main.out
0x0000000000601000 0x0000000000602000 0x0000000000000001
/home/ciro/test/main.out
0x00007f8d939ee000 0x00007f8d93bae000 0x0000000000000000
/lib/x86_64-linux-gnu/libc-2.23.so
0x00007f8d93bae000 0x00007f8d93dae000 0x00000000000001c0
/lib/x86_64-linux-gnu/libc-2.23.so
0x00007f8d93dae000 0x00007f8d93db2000 0x00000000000001c0
/lib/x86_64-linux-gnu/libc-2.23.so
0x00007f8d93db2000 0x00007f8d93db4000 0x00000000000001c4
/lib/x86_64-linux-gnu/libc-2.23.so
0x00007f8d93db8000 0x00007f8d93dde000 0x0000000000000000
/lib/x86_64-linux-gnu/ld-2.23.so
0x00007f8d93fdd000 0x00007f8d93fde000 0x0000000000000025
/lib/x86_64-linux-gnu/ld-2.23.so
0x00007f8d93fde000 0x00007f8d93fdf000 0x0000000000000026
/lib/x86_64-linux-gnu/ld-2.23.so
CORE 0x00000200 NT_FPREGSET (floating point registers)
LINUX 0x00000340 NT_X86_XSTATE (x86 XSAVE extended state)
objdump
может легко сбросить всю память с помощью:
objdump -s core
который содержит:
Contents of section load1:
4007d0 01000200 73747269 6e672069 6e207465 ....string in te
4007e0 78742073 65676d65 6e740074 65787420 xt segment.text
Contents of section load15:
7ffec6739220 73747269 6e672069 6e206461 74612073 string in data s
7ffec6739230 65676d65 6e740000 00a8677b 9c6778cd egment....g{.gx.
Contents of section load4:
1612010 73747269 6e672069 6e206d6d 61702073 string in mmap s
1612020 65676d65 6e740000 11040000 00000000 egment..........
который точно соответствует значению stdout в нашем прогоне.
Протестировано в Ubuntu 16.04 amd64, GCC 6.4.0, binutils 2.26.1.
Ответ 8
Вы можете проанализировать файл дампа ядра с помощью команды "gdb".
gdb - The GNU Debugger
syntax:
# gdb executable-file core-file
ex: # gdb out.txt core.xxx
Спасибо.
Ответ 9
Просто введите команду
$ gdb <Binary> <codeDump>
или же
$ gdb <binary>
$ gdb) core <coreDump>
Не нужно приводить аргументы командной строки. Дамп кода сгенерирован из-за более раннего упражнения