Анализ core-dump многопоточного приложения с помощью GDB

Недавно по работе мне пришлось анализировать core-dump, сброшенный процессом httpd. Поиск нужных команд для gdb занял некоторое время. Для того, чтобы сэкономить время другим, напишу о своем опыте. Итак, мы открыли с помощью GDB core-dump:
gdb  /path/to/binary --core /path/to/core_file
Httpd – многопоточное приложение. Если сделать backtrace для основного потока, скорее всего ничего страшного не увидишь — он будет вертеться где-то в __kernel_vsyscal и не будет делать ничего достойного генерации core-dump-а Поэтому нам нужно сделать backtrace всех потоков с помощью команды:
thread apply all bt
Для того, чтобы вывести это все в отдельный файл, можно воспользоваться командами:
set pagination off
 
set logging file ./threads.txt
 
set logging on
 
thread apply all bt
 
set logging off
Если корок много или просто есть необходимость использовать shell, пригодится команда:
gdb /path/to/binary /path/to/core_file --batch --quiet -ex "thread apply all bt full" /
-ex "quit" > output_file
В файле, куда Вы перенаправили вывод трейсов, найти нужный поток можно по строке «sig_». В моем случае причина сброса корки оказалось в том, что через прокси была запрошена страница весом 42 Мегабайта: http://compamal.happy.nu/blog/sakai.php?itemid=540 Сейчас она весит уже 55 Мегабайт — спам-боты трудятся 🙂 В общем-то это не рекорд, в других корках были ссылки на страницы и побольше. Рекорд — 450 Мегабайт, но это страница уже недоступна. В общем, не открывайте на своем прокси анонимный доступ. Переходим к разбору нужного потока:
thread 177
выбираем фрейм:
frame 5
Выводим локальные переменные:
info locals
или аргументы функции:
info args
В моем случае нужный аргумент (буфер длиной 42 Мегабайта) был объявлен как void* buffer Для того, чтобы вывести его в файл, можно воспользоваться командами:
set pagination off
set logging file ./buffer.txt
set print elements 0
set logging on
p (char*) buffer
set logging off
You can leave a response, or trackback from your own site.

Leave a Reply