The Backyard - DlPatch Diff
- Added parts are displayed like this.
- Deleted parts are displayed
like this.
ruby-win32@moonwolf.comに投げたもの(に多少の語句追加―特に注記なし―と、修正―追記あり―したもの)
artonです。
ZnZさんのところで、http://www.tietew.jp/beckrb/msg00113.html
を見かけたので、VC6版(ASR)で、msgbox.rbがなぜ動くか調べてみました。
[[StdDeclCDecl]]ですが、とりあえず動くが、まずいでしょう、という結論です。
で、__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の利用者がつけなくて良いという意味では望ま
しいと思います)、また、よりスマートな解決方法があるかも知れない、など議
論の余地が大きいので、こちらへ投稿します。
artonです。
ZnZさんのところで、http://www.tietew.jp/beckrb/msg00113.html
を見かけたので、VC6版(ASR)で、msgbox.rbがなぜ動くか調べてみました。
[[StdDeclCDecl]]ですが、とりあえず動くが、まずいでしょう、という結論です。
で、__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の利用者がつけなくて良いという意味では望ま
しいと思います)、また、よりスマートな解決方法があるかも知れない、など議
論の余地が大きいので、こちらへ投稿します。