Hi,

I've been looking into a bug that I've encountered running Mono on a 64-bit x86 system - specifically, where the "((code - start) < buf_len)" assert in mono_arch_get_static_rgctx_trampoline() fires. This seems to be a result of this code:

if ((((guint64)addr) >> 32) == 0)
        buf_len = 16;
else
        buf_len = 30;

...which assumes that if the destination address is <4Gb then a 32-bit jump will be used, which isn't true if the code being generated is more than ~2Gb away.

Looking further into this, I found that this pattern appears elsewhere in tramp-amd64.c as well - and may explain another problem I've been seeing where trampolines get "randomly" corrupted to point to nonsensical addresses.

Specifically, what I think is happening there is that mono_arch_create_specific_trampoline() is creating the trampoline, and that at the time of creation the target address is within a 32-bit jump from the source, so it generates a regular 32-bit CALL.

However, mono_arch_patch_callsite() appears to only check for the target address being >4Gb when patching, meaning that it can (as far as I can see) end up doing a 32-bit InterlockedExchange() that truncates the offset in the case where the target is too far away. This would then result in what I'm seeing, which is that the trampoline code is well-formed by the target of the CALL is non-executable memory with nothing in it.

Does this sound like a reasonable hypothesis? Or is there something that I'm missing about how trampolines operate that means that offsets of this nature shouldn't occur in the first place?

 Thanks for any ideas or advice!
--
 Ben Carter - b...@saillune.net
_______________________________________________
Mono-devel-list mailing list
Mono-devel-list@lists.ximian.com
http://lists.ximian.com/mailman/listinfo/mono-devel-list

Reply via email to