'?'このスタックエントリに関する情報がおそらく信頼できないことを意味します。
スタック出力メカニズム(実装はdump_trace() functionを参照)は、見つかったアドレスがコールスタックの有効なリターンアドレスであることを証明できませんでした。
'?'それ自体はprintk_stack_address()によって出力されます。
スタックエントリが有効かどうか。時にはそれをスキップすることもあります。 関連モジュールの分解を調べて、ClearFunctionName+0x88
(またはその位置の直前のx86では)で呼び出される関数を調べると便利です。 dump_stack()が呼び出された信頼性x86で
に関する
、実際print_context_stack()はarch/x86/kernel/dumpstack.c
で定義されているスタックを検査する機能。そのコードを見て、私はそれを以下で説明しようとします。
あなたのLinuxシステムでDWARF2のスタックアンワインド機能が利用できないと仮定します(ほとんどの場合、OpenSUSEまたはSLESでない場合はそうではありません)。この場合、print_context_stack()
は次のようになります。
スタック位置のアドレスであることが保証されているアドレス(コード内の 'stack'変数)から開始します。実際にはローカル変数のアドレスはdump_stack()
です。
この関数は、そのアドレス(while (valid_stack_ptr ...) { ... stack++}
)を繰り返しインクリメントし、そのポインタが指すものがカーネルコード(if (__kernel_text_address(addr)) ...
)のアドレスである可能性があるかどうかを確認します。このようにして、これらの関数が呼び出されたときにスタックにプッシュされた関数の戻りアドレスを見つけようとします。
もちろん、リターンアドレスのように見えるすべての符号なしロング値が実際にリターンアドレスであるとは限りません。関数はそれをチェックしようとします。カーネルのコードでフレームポインタが使用されている場合(%ebp /%rbpレジスタはCONFIG_FRAME_POINTERが設定されている場合に使用されます)、それらを使用して関数のスタックフレームをトラバースすることができます。関数の戻りアドレスは、フレームポインタのすぐ上にあります(つまり、%ebp/%rbp + sizeof(unsigned long)
にあります)。 print_context_stackはそれを正確にチェックします。
値 'stack'が指すスタックフレームがリターンアドレスの場合、この値は信頼できるスタックエントリとみなされます。 ops->address
がreliable == 1
で呼び出されると、最終的にはprintk_stack_address()
が呼び出され、その値は信頼できる呼び出しスタックエントリとして出力されます。さもなければ、アドレスは信頼できないと考えられるでしょう。それはとにかく出力されますが、 '?'プリペンド。
[NB]フレームポインタ情報が利用できない場合(デフォルトではDebian 6のように)、すべてのコールスタックエントリはこの理由で信頼性がないとマークされます。
DWARF2巻き戻しサポート(およびCONFIG_STACK_UNWINDが設定されている)を備えたシステムは、まったく別の話です。
偉大な答え - それは完了するために1つが欠けています(そして、私はアーチコードのインダイレクションのレベルに少し戸惑っています) - エントリを信頼できないものにしてしまいますか? – qdot
私は自分の答えを編集しました。うまくいけば、私の説明はあまり混乱しない。 – Eugene
Getting there :)あなたの答えは実際に私の疑念を確認してくれます。ちょっとした背景情報を与えるために、ドライバのようなバイナリBLOB +ラッパーを更新しようとしています。私が混乱して何らかの説明をした理由は、ブロブストア内のいくつかの関数はローカル変数内のポインタを指しており、システム全体がちょっと捨てられているようです。あなたの「まったく別の話」を完成させてください。特に、メインカーネルがDWARF2の場合はどのように動作しますか?モジュールの一部はそうではありません。 – qdot