Анализировать обратный след сбоя, произошедшего из-за неисправной библиотеки

В моем приложении я установил обработчик сигнала, чтобы перехватить ошибки сегмента и распечатать бактры.
Мое приложение загружает некоторые библиотеки плагинов, когда начинается процесс.

Если мое приложение завершается сбоем из-за ошибки из-за ошибки в основном исполняемом двоичном файле, я могу проанализировать обратную трассировку с помощью:

addr2line -Cif -e ./myapplication 0x4...

Он точно отображает функцию и исходный_файл: line_no

Однако как проанализировать, происходит ли сбой из-за ошибки в плагине, как показано ниже?

/opt/myapplication(_Z7sigsegvv+0x15)[0x504245]
/lib64/libpthread.so.0[0x3f1c40f500]
/opt/myapplication/modules/myplugin.so(_ZN11ICAPSection7processEP12CONNECTION_TP7Filebufi+0x6af)[0x7f5588fe4bbf]
/opt/myapplication/modules/myplugin.so(_Z11myplugin_reqmodP12CONNECTION_TP7Filebuf+0x68)[0x7f5588fe51e8]
/opt/myapplication(_ZN10Processors7ExecuteEiP12CONNECTION_TP7Filebuf+0x5b)[0x4e584b]
/opt/myapplication(_Z15process_requestP12CONNECTION_TP7Filebuf+0x462)[0x4efa92]
/opt/myapplication(_Z14handle_requestP12CONNECTION_T+0x1c6d)[0x4d4ded]
/opt/myapplication(_Z13process_entryP12CONNECTION_T+0x240)[0x4d79c0]
/lib64/libpthread.so.0[0x3f1c407851]
/lib64/libc.so.6(clone+0x6d)[0x3f1bce890d]

Библиотеки моих приложений и плагинов были скомпилированы с помощью gcc и не имеют ограничений.
Мое приложение, когда выполняется, загружает plugin.so с dlopen
К сожалению, сбой происходит на сайте, где я не могу запустить приложение под GDB.

Яростно гуглил вокруг, чтобы найти ответ, но все сайты, обсуждающие backtrace и addr2line, исключают сценарии, в которых может потребоваться анализ неисправных плагинов.
Я надеюсь, что какой-нибудь добросердечный хак знает решение этой дилеммы и может поделиться некоторыми идеями. Это было бы так неоценимо для коллег-программистов.

Тонны спасибо заранее.

6

Решение

Вот несколько советов, которые могут помочь вам отладить это:

Адрес в вашей трассировке является адресом в адресном пространстве процесса в момент его сбоя. Это означает, что если вы хотите перевести его в «физический» адрес относительно начала .text раздел вашей библиотеки, вы должны вычесть начальный адрес соответствующего раздела pmap с адреса в вашем следе.

К сожалению, это означает, что вам нужен pmap процесса, прежде чем он потерпел крах. По общему признанию, я понятия не имею, является ли загрузка адресов для библиотек в одной системе постоянной, если вы закроете и повторно запустите ее (возможно, есть функции безопасности, которые рандомизируют это), но, как вы заметили, она, безусловно, не переносима между системами.

На вашей позиции я бы попробовал:

  • разбивая имена символов с c++filt -n или вручную. У меня сейчас нет оболочки, поэтому вот моя попытка вручную: _ZN11ICAPSection7processEP12CONNECTION_TP7Filebufi является ICAPSection::process(CONNECTION_T *, Filebuf *, int), Это уже может быть полезно. Если не:
  • использование objdump или же nm (Я почти уверен, что они могут это сделать), чтобы найти адрес, соответствующий искаженному имени, а затем добавить смещение (+0x6af согласно вашей стековой трассировке) к этому, затем ищите результирующий адрес с addr2line,
5

Другие решения

Ответ us2012 был довольно хитрым, чтобы решить проблему. Я просто пытаюсь повторить это здесь, просто чтобы помочь любому другому новичку, борющемуся с той же самой проблемой, или если кто-то хочет предложить улучшения.

В обратном следе ясно видно, что в коде для myplugin.so существует недостаток. И обратный след указывает, что он существует в:

/opt/myapplication/modules/myplugin.so(_ZN11ICAPSection7processEP12CONNECTION_TP7Filebufi+0x6af)[0x7f5588fe4bbf]

Проблема определения местоположения линии, соответствующей этой ошибке, не может быть определена так просто:

addr2line -Cif -e /opt/myapplication/modules/myplugin.so 0x7f5588fe4bbf

Правильной процедурой здесь будет использование nm или objdump для определения адреса, указывающего на искаженное имя. (Разбивка, как это делается нами2012, на самом деле не является необходимой в данный момент). Итак, используя:

nm -Dlan /opt/myapplication/modules/myplugin.so | grep "_ZN11ICAPSection7processEP12CONNECTION_TP7Filebufi"

Я получил:

0000000000008510 T _ZN11ICAPSection7processEP12CONNECTION_TP7Filebufi   /usr/local/src/unstable/myapplication/sources/modules/myplugin/myplugin.cpp:518

Интересно отметить, что myplugin.cpp: 518 фактически указывает на строку, где открытие «{» функции ICAPSection :: process (CONNECTION_T *, Filebuf *, int)

Затем мы добавляем 0x6af к адресу (показан выводом nm выше) 0000000000008510 с помощью команды оболочки linux

 printf '0x%x\n' $(( 0x0000000000008510 + 0x6af ))

И это приводит к 0x8bbf

И это фактический source_file: line_no ошибочного кода, и он может быть точно определен с помощью addr2line как:

addr2line -Cif -e /opt/myapplication/modules/myplugin.so 0x8bbf

Который отображает:

std::char_traits<char>::length(char const*)
/usr/include/c++/4.4/bits/char_traits.h:263
std::string::assign(char const*)
/usr/include/c++/4.4/bits/basic_string.h:970
std::string::operator=(char const*)
/usr/include/c++/4.4/bits/basic_string.h:514
??
/usr/local/src/unstable/myapplication/sources/modules/myplugin/myplugin.cpp:622

Я не слишком уверен, почему имя функции не отображалось здесь, но myplugin.cpp: 622 было совершенно точно, где вина.

4