Я следовал инструкциям несколько похожих ТАК вопрос, но линия, которую я получаю, не имеет смысла.
У меня есть процесс Apache, выполняющий php, скомпилированный с пользовательским расширением php. Иногда я получаю ошибку сегментации и дамп ядра.
Это работает на современном сервере RHEL 6.5.
Я установил debuginfo rpm для нашего расширения php. Открытие ядра и получение bt дает мне
(gdb) bt
#0 0x00007f7d7b99dd2f in ?? () from /etc/httpd/modules/libphp5.so
#1 0x00007f7d74783c81 in zif_x12_parse_file () from /usr/lib64/php/modules/x12_parser.so
#2 0x00007f7d7ba093b8 in ?? () from /etc/httpd/modules/libphp5.so
#3 0x00007f7d7b9e0500 in execute () from /etc/httpd/modules/libphp5.so
#4 0x00007f7d7b9ba70d in zend_execute_scripts () from /etc/httpd/modules/libphp5.so
#5 0x00007f7d7b968798 in php_execute_script () from /etc/httpd/modules/libphp5.so
#6 0x00007f7d7ba43d75 in ?? () from /etc/httpd/modules/libphp5.so
#7 0x00007f7d864b4bb0 in ap_run_handler ()
#8 0x00007f7d864b846e in ap_invoke_handler ()
#9 0x00007f7d864c3b30 in ap_process_request ()
#10 0x00007f7d864c09a8 in ?? ()
#11 0x00007f7d864bc6b8 in ap_run_process_connection ()
#12 0x00007f7d864c8977 in ?? ()
#13 0x00007f7d864c8c8a in ?? ()
#14 0x00007f7d864c8fbb in ap_mpm_run ()
#15 0x00007f7d864a0900 in main ()
Я предполагаю, что проблема на самом деле в нашем коде, а не в php на вершине стека. Таким образом, я получаю местоположение так загружен
(gdb) info shared x12
From To Syms Read Shared Object Library
0x00007f7d7477ec20 0x00007f7d74784038 Yes /usr/lib64/php/modules/x12_parser.so
Вычитание места начала загрузки из ячейки памяти стека
0x00007f7d74783c81 − 0x00007f7d7477ec20 = 5061
И пробивая это в addr2line
$ addr2line -e /usr/lib/debug/usr/lib64/php/modules/x12_parser.so.debug 0x5061
/usr/src/debug/php-x12_parser-5.3.3/php-x12_parser/x12_parser.c:321
Но строка 321 отсутствует в файле zif_x12_parse_file. И, даже если бы это было так, это не линия, которая, я думаю, могла бы потерпеть крах.
Так что же я сделал не так при расчете линии аварии?
Примечание: те строки, которые имеют взяты из файлов, которые были скомпилированы без
вся информация о GDB
Оказалось, я делал этот путь трудно. Мне просто нужно было установить RPM Debuginfo до сбоя. Теперь я получаю приятные следы.
#0 0x00007fc97334fd2f in ?? () from /etc/httpd/modules/libphp5.so
#1 0x00007fc96c135b3b in zif_x12_parse_file (ht=<value optimized out>,return_value=0x7fc98ec278f8, return_value_ptr=<value optimized out>, this_ptr=<value optimized out>, return_value_used=<value optimized out>) at /usr/src/debug/php-x12_parser-5.3.3/php-x12_parser/x12_parser.c:609
#2 0x00007fc9733bb3b8 in ?? () from /etc/httpd/modules/libphp5.so
#3 0x00007fc973392500 in execute () from /etc/httpd/modules/libphp5.so
Вместо того, чтобы использовать базовый адрес из gdb
«s info sharedlibrary
команда, используйте базовый адрес из карты памяти процесса, /proc/#####/maps
,
gdb
будет отслеживать самый низкий доступный адрес для исполняемого адресного пространства совместно используемой библиотеки, обычно принимая p_vaddr
запись в .text
раздел файла ELF и перемещение его по базе отображаемой области.
Вот пример:
#include <stdlib.h>
main()
{
char arg[40];
sprintf(arg, "grep libc /proc/%d/maps", getpid());
system(arg);
abort();
}
$ gdb ab (GDB) запустить 7ffff7a14000-7ffff7bcf000 r-xp 00000000 08:01 397695 /lib/x86_64-linux-gnu/libc-2.19.so 7ffff7bcf000-7ffff7dcf000 --- p 001bb000 08:01 397695 /lib/x86_64-linux-gnu/libc-2.19.so 7ffff7dcf000-7ffff7dd3000 r - p 001bb000 08:01 397695 /lib/x86_64-linux-gnu/libc-2.19.so 7ffff7dd3000-7ffff7dd5000 rw-p 001bf000 08:01 397695 /lib/x86_64-linux-gnu/libc-2.19.so Программа получила сигнал SIGABRT, Прервано. 0x00007ffff7a4abb9 в __GI_raise (sig = sig @ entry = 6) в ../nptl/sysdeps/unix/sysv/linux/raise.c:56 (gdb) информация Из в Симс Читать библиотеку общих объектов 0x00007ffff7ddaae0 0x00007ffff7df54e0 Да /lib64/ld-linux-x86-64.so.2 0x00007ffff7a334a0 0x00007ffff7b790c3 Да /lib/x86_64-linux-gnu/libc.so.6 $ eu-readelf -S /lib/x86_64-linux-gnu/libc-2.19.so | egrep 'Имя | текст' [Nr] Имя Тип Addr Off Размер ES Флаги Lk Inf Al [12] .Текст ПРОБИТЫ 000000000001f4a0 0001f4a0 00145c23 0 AX 0 0 16 $ printf "% x \ n" $ (( 0x7ffff7a14000 + 0x1f4a0 )) 7ffff7a334a0
Дать addr2line
разница между желаемым адресом инструкции и базой отображаемой области:
$ printf "% x \ n" $ ((0x00007ffff7a4abb9 - 0x7FFFF7A14000)) 36bb9 $ addr2line -e /lib/x86_64-linux-gnu/libc-2.19.so 36bb9 /build/buildd/eglibc-2.19/signal/../nptl/sysdeps/unix/sysv/linux/raise.c:56
Имейте в виду, что указатель инструкции, скорее всего, указывает на инструкцию после той, которая вызвала ошибку, поэтому в некоторых случаях (но не в этом примере) номер строки источника может быть отключен на 1.