あなたが求めているのは、実行可能ですが、それほど簡単ではありません。
これを行う1つの方法は、命令のコード移動を補うことです。 RIP相対アドレッシング(012h、0dh、15h、1dh、25h、2dh、35h、または3dhのModRM
バイトを持つ)を使用するすべての命令を見つけ、その移動量(移動量)でdisp32
フィールドを調整する必要がありますしたがって、仮想アドレス空間では+/- 2GBに制限されます。これは、64ビットアドレス空間が4GBを超えると保証されない可能性があります)。
また、ほとんどの場合、たとえば、複数で、すべての元の命令を置き換え、それらの等価物とそれらの命令を置き換えることができます。
; These replace the original instruction and occupy exactly as many bytes as the original instruction:
JMP Equivalent1
NOP
NOP
Equivalent1End:
; This is the code equivalent to the original instruction:
Equivalent1:
Equivalent subinstruction 1
Equivalent subinstruction 2
...
JMP Equivalent1End
どちらの方法は、少なくともいくつかの基本的なx86の分解ルーチンが必要になります。
元のコードのパッチされたコピーを含むメモリが元のコードの+/- 2GB以内になるようにするには、WindowsでVirtualAlloc()
(またはそれに相当するもの)を使用する必要があります。特定のアドレスでの割り当ては失敗する可能性があります。
プリミティブ分解だけでなく、完全な命令のデコードと生成も必要です。
回避策は他にもあります。
RFLAGS
レジスタにTF
フラグを設定して、すべての命令の実行終了時にCPUがsingle-step
デバッグ割り込みを生成させるように命令境界を見つけることもできます。デバッグ例外ハンドラはそれらをキャッチし、次の命令のRIPの値を記録する必要があります。私はこれがWindowsのStructured Exception Handling (SEH)
(デバッグ割り込みでは試したことがない)を使用して実行できると信じています。これを行うには、すべてのコードをすべての命令で実行する必要があります。
Btwには、64ビットモードでの絶対アドレス指定があります。たとえば、0A0hから0A3hまでのオペコードを使用するMOVの/からのアキュムレータ命令を参照してください。
-mcmodel = largeが解決策になるはずです。私はgccのosxコンパイラがそれをサポートしていない理由を調査する必要があります – nux
多分それは古いです。小規模(標準)および中規模のコード・モデルが早期に追加され、大型モデルが後で追加されました。 – hirschhornsalz
私はあなたにとても感謝しています。これは非常によく見え、絶対に問題を解決する絶対に解決します。 – nux