30

コール トレースには、次のようなエントリが含まれます。

 [<deadbeef>] FunctionName+0xAB/0xCD [module_name]
 [<f00fface>] ? AnotherFunctionName+0x12/0x40 [module_name]
 [<deaffeed>] ClearFunctionName+0x88/0x88 [module_name]

「?」の意味は何ですか? AnotherFunctionName の前にマークしますか?

4

1 に答える 1

37

'?' このスタック エントリに関する情報はおそらく信頼できないことを意味します。

スタック出力メカニズム ( dump_trace() 関数の実装を参照) は、検出したアドレスがコール スタック内の有効な戻りアドレスであることを証明できませんでした。

'?' それ自体はprintk_stack_address()によって出力されます。

スタック エントリは有効である場合とそうでない場合があります。単にスキップする場合もあります。関連するモジュールの逆アセンブルを調査して、どの関数がClearFunctionName+0x88(または、x86 ではその位置の直前で) 呼び出されているかを確認すると役立つ場合があります。

信頼性について

x86 では、dump_stack() が呼び出されたときに実際にスタックを調べる関数は、で定義されているprint_context_stack()arch/x86/kernel/dumpstack.cです。そのコードを見てみましょう。以下で説明します。

DWARF2 スタック アンワインド機能は、Linux システムでは利用できないと思います (OpenSUSE または SLES でない場合、ほとんどの場合、利用できません)。この場合、print_context_stack()以下を行うようです。

スタック位置のアドレスであることが保証されているアドレス (コード内の「stack」変数) から開始します。実際には のローカル変数のアドレスですdump_stack()

この関数は、そのアドレスを繰り返しインクリメントし ( while (valid_stack_ptr ...) { ... stack++})、それが指しているものがカーネル コード内のアドレスでもある可能性があるかどうかをチェックします ( if (__kernel_text_address(addr)) ...)。このようにして、これらの関数が呼び出されたときにスタックにプッシュされた関数の戻りアドレスを見つけようとします。

もちろん、戻りアドレスのように見えるすべての unsigned long 値が実際には戻りアドレスであるとは限りません。そのため、関数はそれをチェックしようとします。カーネルのコードでフレーム ポインターが使用されている場合 (CONFIG_FRAME_POINTER が設定されている場合は、%ebp/%rbp レジスターが使用されます)、それらを使用して関数のスタック フレームをトラバースできます。関数の戻りアドレスは、フレーム ポインタのすぐ上 (つまり%ebp/%rbp + sizeof(unsigned long)) にあります。print_context_stack はまさにそれをチェックします。

値「stack」が指すスタック フレームがリターン アドレスである場合、その値は信頼できるスタック エントリと見なされます。ops->addressで呼び出され、reliable == 1最終的に呼び出さprintk_stack_address()れ、値が信頼できる呼び出しスタック エントリとして出力されます。それ以外の場合、アドレスは信頼できないと見なされます。とにかく出力されますが、「?」が付いています 先頭に追加。

[注意] フレーム ポインタ情報が利用できない場合 (たとえば、Debian 6 のデフォルトのように)、すべてのコール スタック エントリは、この理由で信頼できないものとしてマークされます。

DWARF2 巻き戻しをサポートしている (および CONFIG_STACK_UNWIND が設定されている) システムは、まったく別の話です。

于 2012-10-29T07:18:33.353 に答える