Create  Edit  Diff  FrontPage  Index  Search  Changes  Login

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の利用者がつけなくて良いという意味では望ま しいと思います)、また、よりスマートな解決方法があるかも知れない、など議 論の余地が大きいので、こちらへ投稿します。

Last modified:2003/10/19 18:01:37
Keyword(s):
References: