miura1729/mruby — pull request #5 by herumi (2014-03-22 07:52:09+00:00)
Title: use eax instead of edi to call ci->entry

Linux(Linux 3.11.0-15-generic #25-Ubuntu SMP, gcc 4.8.1)でビルドすると
bin/mruby benchmark/prime.rb
などがsegmentation faultしていました。
logを追いかけるとmrb->cをediに割り当てるようになってから落ちるようです。
cygwinでは動いていたので違いを見るとcall ci->entryでcygwinではeaxを使っている
のにLinux上ではediを使っていてせっかくediに割り当てた値を壊してしまっているせいのようです。

-----------------------------------------------------------------------------
Linuxで落ちるときのvm.oの逆アセンブルコード
-----------------------------------------------------------------------------
objdump -CSlw -M intel build/host/src/vm.o|less

if (cbase == NULL && ci->used > 0) {
prev_pc = *ppc;
e7b: 8b 2e mov ebp,DWORD PTR [esi]
/home/shigeo/Program/mruby/src/vm.c:910

//printf("%x %x \n", ci->entry, *ppc);

asm volatile("mov %0, %%ecx\n\t"
e7d: 89 c1 mov ecx,eax
e7f: 8b 9c 24 80 03 00 00 mov ebx,DWORD PTR [esp+0x380]
e86: 89 d6 mov esi,edx
e88: 8b 7a 08 mov edi,DWORD PTR [edx+0x8]
/home/shigeo/Program/mruby/src/vm.c:925
"%ebx",
"%esi",
"%edi",
"memory");

asm volatile("call *%0\n\t"
e8b: 8b 7c 24 50 mov edi,DWORD PTR [esp+0x50] ***
e8f: ff 57 10 call DWORD PTR [edi+0x10] ***
-----------------------------------------------------------------------------

-----------------------------------------------------------------------------
cygwinで動いてるときのコード
-----------------------------------------------------------------------------
asm volatile("call *%0\n\t"
e93: 8b 44 24 58 mov eax,DWORD PTR [esp+0x58]
e97: ff 50 10 call DWORD PTR [eax+0x10]
-----------------------------------------------------------------------------

***でediを経由しているため壊れていました。
試行錯誤したら、

asm volatile("call *%0\n\t"
:
: "g"(ci->entry)
: "%edx");

の"%edx"を取り除くとcygwinと同様のコード生成をして動くようになりました。
一応この修正をしてもcygwin上でも一応動いてるようです。
# インラインアセンブラはよくわからないのでこの修正でよいのか分かりませんが。