6

私のアプリケーションでは、セグメンテーション違反をキャッチし、bactrace を出力するようにシグナル ハンドラーをセットアップしました。私のアプリケーションは、プロセスの開始時にいくつかのプラグイン ライブラリを読み込みます。

メインの実行可能バイナリのエラーが原因で、アプリケーションがセグメンテーション違反でクラッシュした場合、次の方法でバックトレースを分析できます。

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

関数と source_file: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 でコンパイルされており、ストリップされていません。アプリケーションを実行すると、dlopen で plugin.so がロードされます 残念ながら、gdb でアプリケーションを実行できないサイトでクラッシュが発生しています。

必死に答えを探し回っていますが、backtrace と addr2line について議論しているすべてのサイトは、障害のあるプラグインの分析が必要になるシナリオを除外しています。心優しいハックがこのジレンマの解決策を知っており、いくつかの洞察を共有できることを願っています. 仲間のプログラマーにとっては非常に貴重です。

事前にたくさんの感謝を。

4

2 に答える 2

6

これをデバッグするのに役立つヒントを次に示します。

バックトレースのアドレスは、プロセスがクラッシュしたときのアドレス空間のアドレスです。つまり.text、ライブラリのセクションの開始に関連する「物理」アドレスに変換したい場合は、バックトレースのアドレスから関連するセクションの開始アドレスを差し引く必要がありpmapます。

pmap残念ながら、これは、クラッシュする前にプロセスが必要であることを意味します。単一のシステムを閉じて再実行した場合にライブラリのロードアドレスが一定であるかどうかは確かにわかりませんが(これをランダム化するセキュリティ機能があると想像できます)、お気づきのように、システム間で移植可能ではありません.

あなたの立場では、私は試してみます:

  • c++filt -nまたは手動でシンボル名をデマングルします。私は現在シェルを持っていないので、ここに私の手動の試みがあります: _ZN11ICAPSection7processEP12CONNECTION_TP7Filebufiis ICAPSection::process(CONNECTION_T *, Filebuf *, int). これはすでに役に立っているかもしれません。そうでない場合:
  • objdumpまたはnm(彼らがそれを行うことができると確信しています) を使用して、マングルされた名前に対応するアドレスを見つけ、(+0x6afスタックトレースに従って) オフセットをこれに追加し、結果のアドレスを で検索しますaddr2line
于 2013-09-19T13:23:21.657 に答える
5

us2012 の回答は、問題を解決するために必要なかなりのトリックでした。同じ問題に苦しんでいる他の初心者を助けるために、または誰かが改善を提供したい場合に、ここでもう一度言い直そうとしています.

バックトレースを見ると、myplugin.so のコードに欠陥があることがはっきりとわかります。また、バックトレースは、次の場所に存在することを示しています。

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

この障害に対応する行を特定する問題は、次のように単純には判断できません。

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

ここでの正しい手順は、nm または objdump を使用して、マングルされた名前を指すアドレスを判別することです。(us2012 によって行われたデマングルは、この時点では実際には必要ありません)。だから使用:

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) の開始 "{" がある行を指していることです。

次に、Linux シェル コマンドを使用して、0000000000008510 のアドレスに 0x6af を追加します (上記の nm 出力で明らかになります)。

 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は非常に正確に障害の場所でした。

于 2013-09-19T15:28:40.917 に答える