[runtime]Generate the proper exit code for block guard trampolines.
authorRodrigo Kumpera <kumpera@gmail.com>
Wed, 14 Aug 2013 22:13:37 +0000 (18:13 -0400)
committerRodrigo Kumpera <kumpera@gmail.com>
Wed, 14 Aug 2013 23:05:33 +0000 (19:05 -0400)
Finally blocks use a non-standard calling convention which means we need to take it
into account in the return address hijacking trampoline.

A finally block is called with ESP % 16 == 4. Once inside the finally block, ESP returns
to be % 16 == 0 due to the call instruction pushing the return address.

The problem comes when we want to hijack the return address. Our trampolines expect a
normal calling convention with ESP properly aligned, so we use a small thunk of code that
does that before jumping into the trampoline itself. This is required as we'll enter native.

The problem lies on the exit path as the trampoline jump to an arbitrary place instead back
to the above thunk. This leaves the stack with the thunk adjustment in, which will cause
the resulting code to misalign the stack even further.

The solution, though a big ugly, is to change the exit path of the trampoline fix the stack
to be "properly" misaligned.

mono/mini/tramp-x86.c

index f9964799473d2abce509645308b5e44084270ad7..193d3ec9eb063befa3a6b27da81973e705b3e68e 100644 (file)
@@ -525,7 +525,14 @@ mono_arch_create_generic_trampoline (MonoTrampolineType tramp_type, MonoTrampInf
                g_assert (pushed_args == -1);
        }
 
-       x86_ret (code);
+       /*block guard trampolines are called with the stack aligned but must exit with the stack unaligned. */
+       if (tramp_type == MONO_TRAMPOLINE_HANDLER_BLOCK_GUARD) {
+               x86_pop_reg (code, X86_EAX);
+               x86_alu_reg_imm (code, X86_ADD, X86_ESP, 0x8);
+               x86_jump_reg (code, X86_EAX);
+       } else {
+               x86_ret (code);
+       }
 
        nacl_global_codeman_validate (&buf, 256, &code);
        g_assert ((code - buf) <= 256);