ruby 1.8.0 dl.so パッチ
ruby-win32@moonwolf.comに投げたもの(に多少の語句追加―特に注記なし―と、修正―追記あり―したもの)
artonです。
ZnZさんのところで、http://www.tietew.jp/beckrb/msg00113.html を見かけたので、VC6版(ASR)で、msgbox.rbがなぜ動くか調べてみました。 __stdcallと__cdeclですが、とりあえず動くが、まずいでしょう、という結論です。 で、__cdecl、__stdcall両方を呼べれば良いのですから、呼び出し前の引数をス タックへ積む直前と、呼出し後のコンパイラが生成したスタック調整直後でesp を保存/復帰させれば良いだろうということで、以下のパッチを作ってみました。
diff -c sym.c.original sym.c *** sym.c.original Sat Mar 29 11:56:18 2003 --- sym.c Sun Oct 19 16:56:43 2003 *************** *** 329,334 **** --- 329,337 ---- int i; long ftype; void *func; + #if defined(_MSC_VER) + void *spsave; + #endif rb_secure_update(self); Data_Get_Struct(self, struct sym_data, sym); *************** *** 607,612 **** --- 610,618 ---- DLSTACK_END(sym->type); { + #if defined(_MSC_VER) + __asm mov spsave, esp + #endif switch( sym->type[0] ){ case '0': { *************** *** 675,680 **** --- 681,689 ---- rb_raise(rb_eDLTypeError, "unknown type `%c'", sym->type[0]); } } + #if defined(_MSC_VER) + __asm mov esp, spsave + #endif } #else /* defined(DLSTACK) */ switch(ftype){ ------------------------
VC++6SP5であれば、これは
; 613 : #if defined(_MSC_VER) ; 614 : __asm mov spsave, esp 010e4 89 65 d0 mov DWORD PTR _spsave$[ebp], esp ; 615 : #endif ; 616 : switch( sym->type[0] ){ −−−−−−−−−−−−
(ここにはペーストミスしたコードが貼り付けてあった。以下が正しい)
$L56554: ; 684 : #if defined(_MSC_VER) ; 685 : __asm mov esp, spsave 015fc 8b 65 d0 mov esp, DWORD PTR _spsave$[ebp] ; 688 : #else /* defined(DLSTACK) */ ; 689 : switch(ftype){
で、おそらくうまく動きます(msgbox.rbを使った、__stdcallの呼び出しについ ては正常に動作し、パッチの前後のespが正しい値になります(MessageBoxは4引 数=16バイトのずれが解消)
ただ、mingw、cygwin、bccについてはこちらに環境がないこともあって、どのよ うなコードになるかわかりません。 また、上記のような強制的な方法でespを調整することが本当に望ましいか (__stdcallと__cdeclの区別をdlの利用者がつけなくて良いという意味では望ま しいと思います)、また、よりスマートな解決方法があるかも知れない、など議 論の余地が大きいので、こちらへ投稿します。
Keyword(s):
References: