ページ

2005年7月14日木曜日

x86 なメソッドを動的に生成する方法

Dynamically Writing and Executing Native Assembly in C# より


.NET Framework 2.0 では Marshal.GetDelegateForFunctionPointer() っていうのが追加されます。こいつは、「PInvoke する DLL を Load/Unload する方法」 で紹介したみたいに GetProcAddress() API で取得した関数ポインタなんかを .NET な delegate に変換するってのが普通の使い方だと思います。


んが、関数ポインタと言ったって特別なものではなく .NET 的には単なる IntPtr です。そこで、Marshal.AllocCoTaskMem() したメモリに適当なバイト列 (実は x86 コードになってる) を用意しておいて、その先頭アドレスを Marshal.GetDelegateForFunctionPointer() に渡せば delegate にできるってことになります。


っていうのを具体的にサンプルコードで示してるのが上記の blog です。インラインアセンブラならぬインラインマシン語ですね。すんげぇw

5 件のコメント:

  1. >Marshal.AllocCoTaskMem() したメモリに適当なバイト列 (実は x86 コードになってる) を用意しておい

    >て、その先頭アドレスを Marshal.GetDelegateForFunctionPointer() に渡せば delegate にできる

    >ってことになります。


    XPSP2 以降では、NX bit チェックにより無効かも。

    返信削除
  2. うーん、コードセグメント内なんだろうか>TaskMemAlloc で帰ってくる場所


    返信削除
  3. セグメントは、どっちかというとロードモジュール(=ファイル)のための概念だよん。


    NX bit と関係が深いのは、仮想記憶が管理する「ページ」の実行属性すね。


    ローダが


    ・コードセグメントの内容は実行属性の付いたページに読み込む

    ・初期化データ有りのデータセグメントは実行属性の無いページに読み込む

    ・初期化データの無いデータセグメントは実行属性の無いページを確保して0爆弾投下


    という作業を行ってからプログラムの実行が開始されるわけですが、NX bit サポート付きの x86 では、「実行属性の無いページに置かれたコード」を実行しようとすると、例外が発生します。

    (cpu レベルではソフトウェア割り込みかな?)


    ただし、これまでの、NX bit サポートの無い x86 では「実行属性が無いページにあるコード」も実行できちゃうのよね ;-p


    実行属性付きのメモリ確保は、VirtualXXX 系でしかできないんじゃないかな?

    返信削除
  4. えーと、著者さんはちゃんとわかってるようで、記事の一番下のところに

      このサンプルでは Marshal.AllocCoTaskMem() を使ってるけど、コードが

      PAGE_EXECUTE アクセスを持つページに確実にできるようにするために P/Invoke で

      VirtualAllocEx と VirtualProtectEx を使うようにすべき

    と書いてあります。


    # しかし、こういうネタは食いつきがいいなぁ(笑)

    返信削除