сбой расширения php - преобразование адреса памяти в номер строки

0

Я следовал инструкциям несколько аналогичного вопроса SO, но строка, которую я получаю, не имеет смысла.

У меня есть apache-процесс, выполняющий php, скомпилированный с помощью специального расширения c 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
rhel

3 ответа

0
Лучший ответ

Оказалось, что я стараюсь сделать это. Мне просто нужно было установить debuginfo rpm перед сбоем. Теперь я получаю хорошие следы назад.

#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
0

Вместо использования базового адреса из команды gdb 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) run
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
Program received signal SIGABRT, Aborted.
0x00007ffff7a4abb9 in __GI_raise (sig=sig@entry=6) at
                      ../nptl/sysdeps/unix/sysv/linux/raise.c:56
(gdb) info sharedlibrary
From                To                  Syms Read  Shared Object Library
0x00007ffff7ddaae0  0x00007ffff7df54e0  Yes        /lib64/ld-linux-x86-64.so.2
0x00007ffff7a334a0  0x00007ffff7b790c3  Yes        /lib/x86_64-linux-gnu/libc.so.6

$ eu-readelf  -S  /lib/x86_64-linux-gnu/libc-2.19.so | egrep 'Name|text'
[Nr] Name      Type         Addr             Off      Size     ES Flags Lk Inf Al
[12] .text     PROGBITS     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.

0
  • перекомпилируйте библиотеку с помощью -gdb3.
  • затем повторно запустить программу (возможно через gdb)
  • посмотрите на трассировку стека.

Примечание: те строки, которые имеют? из файлов, которые были скомпилированы без всякой информации gdb

  • 0
    Он уже был скомпилирован с -g, который является общей версией -gdb. -gdb3 увеличивает уровень доступной информации отладки, но не решает проблему, с которой я столкнулся.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню