2016-04-22 9 views
7

バグを解決しながら、私は2つのWin64 DLLのインポートジャンプテーブルの違いに気づいた。 kernel32.dllの64ビットバージョンは、そのインポートジャンプテーブルにplain FF25jmp命令を使用します。一方、advapi32.dllの64ビットバージョンは48FF25を使用し、jmpオペコードの前に接頭辞REX.w=1を示します。しかし、両方ともRIP +オフセットアドレスを指定する32ビットオペランドを持つようです。AMD64の前にREX.w接頭辞の意味jmp(FF25)

この特定のオペコードにREX.wというプレフィックスの意味はありますか?

私は機械コードで頻繁に作業しているわけではありませんので、実際の間違いをお許しください。

+0

インテルのドキュメントに記載されています。 –

+2

それはIntelのマニュアルには載っていないし、私が持っている逆アセンブラもそれを理解できない。私は 'rex.w'はちょうど無視されると思います。 – Jester

答えて

9

REX.W接頭辞は無視されます。 64ビットモードでは、FF /4オペコードには常に64ビットオペランド(JMP r/m64)があるため、オペランドサイズの変更プレフィックス(REX.W、66)は無効です。

このREX.Wプレフィックスが存在する理由は、Microsoftのx64呼び出し規約の巻き戻しに関する規則に準拠するためです。ジャンプインポートスタブは実質的に1命令関数であり、Windows上の例外は非同期であるため、いつでもこの関数を実行している間に例外が生成される可能性があります。 Microsoftはrestrictions on instructions used at the start and end of functionsの番号を付けます。特に、関数は特定の命令だけを含むエピローグで終わらなければなりません。最後の命令は、それがREX.W接頭辞を使用する必要があり、間接ジャンプがある場合は、MSDNのKevin Frei's blogよる:

もう一つのノート:最終JMPはIP相対JMPではなく、間接的な JMP場合、 OSがその関数の外にジャンプすることをOSに指示するためには、REXプレフィックスが先行しなければなりません。そうでなければ、OSは同じ関数内の別の場所へジャンプしたとみなします。

前述このルールは、Microsoftの公式ドキュメントは、最終的なJMP命令を必要とするものと完全に一致していないためREX.Wを使用して間の矛盾を約来ていることがあります。

JMP文のサブセットのみをエピローグで許容される。 ModRM modLM modフィールド値00の場合、これらの値は で、ModRMメモリ参照のjmpsクラスのみです。ModRM modフィールド値01または 10のエピローグでjmpsを使用することは禁止されています。これはのModR/Mエンコーディングを使用していない相対JMP命令を排除するために、JMPの最も一般的な種類が持つ機能を終了するので、私はそれを信じるに傾いていることを

注意の公式文書ですここで間違っている。

Microsoftのアンワインダーが特別にインポートジャンプスタブを処理している、またはREX.W接頭辞なしのジャンプスタブがバグであり、例外が発生したときにプログラムが終了する可能性が非常に低い実行中に発生します。

+3

それはまさにその理由です。 CoreClrには、https:// githubにOS Unwinderのコピーがあります。com/dotnet/coreclr/blob/master/src/unwinder/amd64/unwinder_amd64.cppここでスタックアンワインダーの動作を確認できます。 Kevinが彼のブログで指摘したのとまったく同じようにREX接頭辞を実際にチェックします。 –

+3

これは、SDKドキュメントの['RtlVirtualUnwind'関数](https://msdn.microsoft.com/en-us/library/windows/desktop/ms680617.aspx)、特に「備考」の下に半分の記載があります。ここでは、スタックアンワインディングコードによって認識されるx64のエピローグマーカーの網羅的なリストを示しています。 –

関連する問題