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.
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);