コアダンプでスタックトレースを再設定するには?

コアダンプでスタックトレースを再設定するには?

coredumpctlコアダンプを作成した後、ユーティリティはプログラムのスタックトレースを表示します。

たとえば、Firefoxコアダンプでは次のようになります。

Stack trace of thread 14469:
#0  0x00007f0ac652d3bd pthread_cond_wait@@GLIBC_2.3.2 (libpthread.so.0)
#1  0x0000560f2ab95488 _ZN7mozilla6detail21ConditionVariableImpl4waitERNS0_9MutexImplE (firefox)
#2  0x0000560f2ab95646 _ZN7mozilla6detail21ConditionVariableImpl8wait_forERNS0_9MutexImplERKNS_16BaseTimeDurationINS_27TimeDurati>
#3  0x00007f0aba9799f9 n/a (libxul.so)
#4  0x00007f0aba96eb9a n/a (libxul.so)
#5  0x00007f0ac652708c start_thread (libpthread.so.0)
#6  0x00007f0ac5abce7f __clone (libc.so.6)

これはCコードなので、コンパイルされることを考慮すると、シンボルはバイナリに直接含まれません。それでは、これはどのように可能ですか?
また、readelfは実際にこれをどのように実行しますか?

(私の考えはELFファイルに含まれているシンボルテーブルに関連しているようです。)

答え1

お分かりのように、これらのシンボルはELFファイルに含まれるシンボル情報から来ています。完全なシンボルテーブルが存在しない場合でも、ダイナミックリンクにはいくつかのシンボル情報が必要です。

実際のスタックトレース側では、関数呼び出し時にCPUから返された位置が格納される。 x86 などの CPU の場合、スタックにプッシュされます。 RISCマシンの場合、これは通常レジスタに保存されます。関数が他の関数(つまり、関数ではない場合)を呼び出そうとすると、leafこのレジスタはスタックにプッシュされます。スタックトラッキングコードは、スタックでこれらのアドレスを探し、その前の記号から最も近いアドレスを見つけてそれを報告します。一部のスタックトレースコードはシンボル名とその距離を印刷するため、精度の信頼性を高めることができます。たとえば、シンボルが戻りアドレスの前に40バイトしかない場合、そのシンボルが40,000バイトの前よりもコードにあるという確信が高くなります。後者の場合、戻りアドレスが他の関数を指していると思うかもしれませんが、その関数にはシンボルテーブルにエントリがありません。

多くの要因がこの結果を不正確にする可能性があります。コンパイラが関数aを関数bにインライン化すると、ユーザーは関数aに存在する可能性がありますが、スタックトレースはユーザーがbにあることを報告します。

コンパイラが関数 a が関数 c と同様の方法で終了する「テール呼び出しの最適化」を実行し、関数return b();c が関数 a を呼び出す場合、トレースに c->a->b が表示されると予想できますが、c - のみ表示になります。 >ㄴ。 cのソースコードを見て、bを直接呼び出さないことを見ると混乱する可能性があります。

関連情報