void mono_arch_patch_callsite (guint8 *method_start, guint8 *code, guint8 *addr) { guint8 *callsite_begin; guint64 *callsite = (guint64*)(gpointer)(code - 16); guint64 *next_bundle; guint64 ins, instructions [3]; guint64 buf [16]; Ia64CodegenState gen; gpointer func = ((gpointer*)(gpointer)addr)[0]; while ((ia64_bundle_template (callsite) != IA64_TEMPLATE_MLX) && (ia64_bundle_template (callsite) != IA64_TEMPLATE_MLXS)) callsite -= 2; callsite_begin = (guint8*)callsite; next_bundle = callsite + 2; ins = ia64_bundle_ins1 (next_bundle); if (ia64_ins_opcode (ins) == 5) { /* ld8_inc_imm -> indirect call through a function pointer */ g_assert (ia64_ins_r1 (ins) == GP_SCRATCH_REG2); g_assert (ia64_ins_r3 (ins) == GP_SCRATCH_REG); return; } /* Patch the code generated by emit_call */ instructions [0] = ia64_bundle_ins1 (callsite); instructions [1] = ia64_bundle_ins2 (callsite); instructions [2] = ia64_bundle_ins3 (callsite); ia64_codegen_init (gen, (guint8*)buf); ia64_movl (gen, GP_SCRATCH_REG, func); instructions [1] = gen.instructions [0]; instructions [2] = gen.instructions [1]; ia64_codegen_init (gen, (guint8*)buf); ia64_emit_bundle_template (&gen, ia64_bundle_template (callsite), instructions [0], instructions [1], instructions [2]); ia64_codegen_close (gen); /* This might not be safe, but not all itanium processors support st16 */ callsite [0] = buf [0]; callsite [1] = buf [1]; mono_arch_flush_icache (callsite_begin, code - callsite_begin); }
{ guint8 *buf = code.buf; int template; guint64 dw1, dw2; guint64 ins1, ins2, ins3; ia64_break_i (code, 0x1234); ia64_codegen_close (code); dw1 = ((guint64*)buf) [0]; dw2 = ((guint64*)buf) [1]; template = ia64_bundle_template (buf); ins1 = ia64_bundle_ins1 (buf); ins2 = ia64_bundle_ins2 (buf); ins3 = ia64_bundle_ins3 (buf); code.buf = buf; ia64_emit_bundle_template (&code, template, ins1, ins2, ins3); g_assert (dw1 == ((guint64*)buf) [0]); g_assert (dw2 == ((guint64*)buf) [1]); } #endif mono_disassemble_code (buf, 40960, "code"); return 0; }