2007-11-12 Rodrigo Kumpera <rkumpera@novell.com>
authorRodrigo Kumpera <kumpera@gmail.com>
Mon, 12 Nov 2007 19:31:15 +0000 (19:31 -0000)
committerRodrigo Kumpera <kumpera@gmail.com>
Mon, 12 Nov 2007 19:31:15 +0000 (19:31 -0000)
* 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.

svn path=/trunk/mono/; revision=89485

mono/mini/ChangeLog
mono/mini/mini-arm.c
mono/mini/tramp-arm.c

index f74030b076235366630a82f0b301caf94d0c1616..69aaac19fe42dff149fa82f5fc680a5e74157d55 100644 (file)
@@ -1,3 +1,11 @@
+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
index 3a194e370f1cbb643951cae50a75b0e2a12487aa..79cbbfce9a84546566cdb468612933e5d8b3e318 100644 (file)
@@ -1909,7 +1909,37 @@ arm_patch (guchar *code, const guchar *target)
         *      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];
index 4a85cb921c0d2cc75f36be9b72fc4ba603e6029b..7fcb71e32b688dbfeccf7f7b98336a00a6acf071 100644 (file)
@@ -92,6 +92,13 @@ mono_arch_patch_callsite (guint8 *code_ptr, guint8 *addr)
                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 ();
 }