+2007-11-12 Rodrigo Kumpera <rkumpera@novell.com>
+
+ * tramp-arm.c (mono_arch_patch_callsite): Support patching
+ BX call sequence.
+
+ * mini-arm.c (arm_patch): Implement patching of BX call
+ sequence. Fixes one of the bugs in #322722.
+
2007-11-03 David S. Miller <davem@huronp11.davemloft.net>
* mini-sparc.c (mono_arch_flush_icache): Make more efficient
* address constant // execution never reaches here
*/
if ((ins & 0x0ffffff0) == 0x12fff10) {
- /* branch and exchange: the address is constructed in a reg */
+ /* Branch and exchange: the address is constructed in a reg
+ * We can patch BX when the code sequence is the following:
+ * ldr ip, [pc, #0] ; 0x8
+ * b 0xc
+ * .word code_ptr
+ * mov lr, pc
+ * bx ips
+ * */
+ guint32 ccode [4];
+ guint8 *emit = (guint8*)ccode;
+ ARM_LDR_IMM (emit, ARMREG_IP, ARMREG_PC, 0);
+ ARM_B (emit, 0);
+ ARM_MOV_REG_REG (emit, ARMREG_LR, ARMREG_PC);
+ ARM_BX (emit, ARMREG_IP);
+
+ /*patching from magic trampoline*/
+ if (ins == ccode [3]) {
+ g_assert (code32 [-4] == ccode [0]);
+ g_assert (code32 [-3] == ccode [1]);
+ g_assert (code32 [-1] == ccode [2]);
+ code32 [-2] = (guint32)target;
+ return;
+ }
+ /*patching from JIT*/
+ if (ins == ccode [0]) {
+ g_assert (code32 [1] == ccode [1]);
+ g_assert (code32 [3] == ccode [2]);
+ g_assert (code32 [4] == ccode [3]);
+ code32 [2] = (guint32)target;
+ return;
+ }
g_assert_not_reached ();
} else {
guint32 ccode [4];
return;
}
+ if ((((*code) >> 20) & 0xFF) == 0x12) {
+ /*g_print ("patching bx\n");*/
+ arm_patch ((char*)code, addr);
+ mono_arch_flush_icache ((char*)(code - 2), 4);
+ return;
+ }
+
g_assert_not_reached ();
}