コールトレースには、次のようなエントリが含まれています。
[<deadbeef>] FunctionName+0xAB/0xCD [module_name]
[<f00fface>] ? AnotherFunctionName+0x12/0x40 [module_name]
[<deaffeed>] ClearFunctionName+0x88/0x88 [module_name]
「?」の意味は何ですか? AnotherFunctionNameの前にマークしますか?
「?」このスタックエントリに関する情報はおそらく信頼できないことを意味します。
スタック出力メカニズム( dump_trace()関数 の実装を参照)は、検出したアドレスが呼び出しスタック内の有効な戻りアドレスであることを証明できませんでした。
「?」それ自体は printk_stack_address() によって出力されます。
スタックエントリは有効かどうかはわかりません。時々それを単にスキップするかもしれません。関連するモジュールの逆アセンブリを調査して、どの関数が_ClearFunctionName+0x88
_(または、x86ではその位置の直前)で呼び出されているかを確認すると役立つ場合があります。
信頼性について
X86では、dump_stack()が呼び出されると、実際にスタックを検査する関数は print_context_stack() _Arch/x86/kernel/dumpstack.c
_で定義されます。そのコードを見てください、私はそれを以下で説明しようとします。
LinuxシステムではDWARF2スタックアンワインド機能が利用できないと思います(OpenSUSEまたはSLESでない場合は、ほとんどの場合利用できません)。この場合、print_context_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が設定されている)システムはまったく別の話です。