ここ数週間、私はアンマネージ.NETデバッグAPIをいじっています。
MSDNはインターフェイス自体を文書化していますが、実際にそれらを意味のある方法で使用する方法を見つけるために、さまざまなブログ(主にMike Stall )とCLRマネージデバッガーサンプルおよびILSpyソースのマネージラッパーに頼りました。最終的に、実行中のプロセスにテストプログラムをアタッチし、ブレークポイントを設定してヒットすることができました。
次にやりたいのは、そのようなブレークポイントに到達することです。関連するオブジェクトインスタンスのフィールドを読み取ります。これは、デバッグターゲットメソッドがNGENまたはJITされていない場合に、NGENされたアセンブリの読み込みを無効にし(環境設定「COMPLUS_ZAPDISABLE = 1」)、JIT最適化を無効にする(別名「.iniファイルトリック」 )ことで正常に機能します。 )。
ただし、理想的なターゲットである小売用に最適化された(NGEN / JITされた)コードで同じことを試してみると、機能しません。たとえば、エントリブレークポイントをヒットしても、メソッド引数の数を取得できますが、最初の引数自体を取得できません(デバッグAPIは例外をスローします)。
さて、これの理由は、デバッグAPIがプラットフォームに依存しないことになっているためだと思います。この場合、アセンブリはもう存在しません。しかし、このプラットフォームのIntelへの依存関係を受け入れるとどうなりますか?CLRがfastcall呼び出し規約を使用していることを知っている限り、この場合、ECXレジスタには最初のメソッド引数(メンバー関数の暗黙の「this」参照)が含まれます。
私はこれをテストしましたが、実際にブレークポイントに到達すると、ECXにはNGENされたアセンブリにOBJECTREF(オブジェクトインスタンスのアドレス)が含まれます。
インスタンスフィールドを読み取る最後のステップは、このポインタを基準にしたフィールドオフセットを取得することです。これは、ネイティブコード生成中にCLRがインスタンスフィールドのパッキングをどのように行うかを知ることができないため、私が立ち往生している場所です。。
これはCLRのバージョン/実装に依存する可能性があることを認識していますが、SOS拡張機能を備えたWinDbgがこのレイアウトを見つけることができるため、明らかに方法があります。デバッグAPIを使用しない場合、どういうわけかSOS.dllを活用できますか?