0

Windows (32 ビットと 64 ビットの両方) で、プログラム (C++) を使用して、特定のメモリ位置が変更されたかどうかを判断できますか? データ ブレーク ポイントを設定できる Visual Studio で見られる概念を推定しようとしています。

ユースケース:I understand its a dirty hack, but the fastest to implement to be re-implemented later

プロセス境界を越えてデータを共有しています (32 ビット クライアントと 64 ビット サーバーの間で読み取られます)。クライアントは(私たちの制御を超えて)メモリを割り当て、アドレスをサーバーに渡します。サーバーはストレージを割り当ててクライアント メモリをシャドウし、さまざまなコード パスを介してそのシャドウされたメモリの場所を更新できます。これらの各場所を特定してトラップする代わりに (私はより簡単なパスを見つけようとしていました)、変更時にイベントを発生させ、最終的WriteProcessMemoryにクライアント プロセスにデータを書き戻します。

4

2 に答える 2

5

VirtualProtectWindows デバッグ インターフェイスの組み合わせを使用して解決策を見つけることはおそらく可能ですが、、このシナリオに特に適したソリューションかどうかはわかりません。問題の 1 つは、新しい書き込みごとに遅延が発生し、プログラムを「デバッガー」として監視している別のプロセスへの転送を見ていることです。そのプロセスは、そのページを「保護解除」し、他のサーバー (または、方向によってはクライアント) に対して「更新済み」としてマークし、更新を行うアプリケーションを「続行」する必要があります。これはかなり時間がかかります。そしてもちろん、書き込みプロセスが一連の更新をいつ完了したかを知る簡単な方法はありません。また、SEH の "__except" 呼び出しがあったときにどこで "続行" するかを正確に知る必要があります。

私がグラフィックスを扱ったとき、私たちと一部の競合他社のドライバーの両方がこれを行うことを知っていました。最初にメモリを書き込み保護し、次にWindows独自のページフォールトハンドラーにフックして、ページフォールトを検索し、それがその場合は、そのページを更新済みとしてマークし、書き込み可能にリセットします。これにより、ドライバーは更新されたリージョンのみをコピーできました。でもこの場合、すべての更新が行われた後に明確な「これが描きたい」があります。

于 2013-09-09T18:07:41.020 に答える
2

どうしてもやりたい場合は、デバッグ API を使用して独自のデータにブレークポイントを設定できます。これは、VS API と同じように、書き込み時にトリガーされます。

これの基本は、スレッドを開始して「デバッグ」を行うことです。そうなる:

  1. プライマリ スレッドを一時的に停止します。
  2. そのスレッドのレジスタを GetThreadContext で取得します
  3. DR0 ~ DR3 のいずれかにブレークするアドレスを設定します。
  4. DR 6 で問題のデータのサイズを設定します。
  5. DR 7 でブレークポイントのタイプ (この場合はデータ書き込み) を設定します。
  6. SetThreadContext を使用して、変更されたレジスタを使用するようにプライマリ スレッドに指示します。
  7. プライマリ スレッドの実行を再開します。

これは記憶に基づいているため、基本的なアイデアにかなり近いと思いますが、詳細を 1 つまたは 2 つ間違えているか、(可能性が高い) いくつかの手順を省略している可能性があります。

ほとんどの場合、問題のターゲットをオーバーロードするソース レベルで何かを行う方が簡単になるoperator=ため、データへの割り当て中にコードを実行できます。次に、そのオペレーターで、(たとえば)別のスレッドのコードが待機する(そして適切に反応する)イベントを設定できます。

もう 1 つの可能性 (特に、アドレス範囲全体へのアクセスを中断したい場合) は、 を使用VirtualProtectして、そのメモリ ブロックへのアクセスで例外を強制することです。デバッグ例外と同様に、これは同期的にトリガーされるため、非同期実行が必要な場合は、イベント (または何か) を設定し、それを待機する別のスレッドを用意して、イベントが設定されたときに実行されるようにする必要があります。

于 2013-09-09T17:41:25.310 に答える