return TRUE;
}
- if (((guint64)(*lmf)->previous_lmf) & 1) {
+ if (((guint64)(*lmf)->previous_lmf) & 4) {
+ MonoLMFTramp *ext = (MonoLMFTramp*)(*lmf);
+
+ rip = (guint64)MONO_CONTEXT_GET_IP (ext->ctx);
+ } else if (((guint64)(*lmf)->previous_lmf) & 1) {
/* This LMF has the rip field set */
rip = (*lmf)->rip;
} else if ((*lmf)->rsp == 0) {
if (!ji)
return FALSE;
- /* Adjust IP */
- rip --;
-
frame->ji = ji;
frame->type = FRAME_TYPE_MANAGED_TO_NATIVE;
- new_ctx->gregs [AMD64_RIP] = rip;
- new_ctx->gregs [AMD64_RBP] = (*lmf)->rbp;
- new_ctx->gregs [AMD64_RSP] = (*lmf)->rsp;
-
if (((guint64)(*lmf)->previous_lmf) & 4) {
MonoLMFTramp *ext = (MonoLMFTramp*)(*lmf);
/* Trampoline frame */
- for (i = 0; i < AMD64_NREG; ++i) {
- if (AMD64_IS_CALLEE_SAVED_REG (i) && i != AMD64_RBP)
- new_ctx->gregs [i] = ext->ctx->gregs [i];
- }
+ for (i = 0; i < AMD64_NREG; ++i)
+ new_ctx->gregs [i] = ext->ctx->gregs [i];
+ /* Adjust IP */
+ new_ctx->gregs [AMD64_RIP] --;
} else {
/*
* The registers saved in the LMF will be restored using the normal unwind info,
* when the wrapper frame is processed.
*/
+ /* Adjust IP */
+ rip --;
+ new_ctx->gregs [AMD64_RIP] = rip;
+ new_ctx->gregs [AMD64_RSP] = (*lmf)->rsp;
+ new_ctx->gregs [AMD64_RBP] = (*lmf)->rbp;
for (i = 0; i < AMD64_NREG; ++i) {
if (AMD64_IS_CALLEE_SAVED_REG (i) && i != AMD64_RBP)
new_ctx->gregs [i] = 0;
/* Initial LMF */
return;
- if ((guint64)lmf->previous_lmf & 1)
+ if ((guint64)lmf->previous_lmf & 5)
/* Already hijacked or trampoline LMF entry */
return;
/* RAX is already saved */
amd64_mov_reg_membase (code, AMD64_RAX, AMD64_RBP, rbp_offset, sizeof(mgreg_t));
amd64_mov_membase_reg (code, AMD64_RBP, saved_regs_offset + (i * sizeof(mgreg_t)), AMD64_RAX, sizeof(mgreg_t));
+ } else if (i == AMD64_RIP) {
+ if (has_caller)
+ amd64_mov_reg_membase (code, AMD64_R11, AMD64_RBP, 8, sizeof(gpointer));
+ else
+ amd64_mov_reg_imm (code, AMD64_R11, 0);
+ amd64_mov_membase_reg (code, AMD64_RBP, saved_regs_offset + (i * sizeof(mgreg_t)), AMD64_R11, sizeof(mgreg_t));
+ } else if (i == AMD64_RSP) {
+ amd64_mov_reg_reg (code, AMD64_R11, AMD64_RSP, sizeof(mgreg_t));
+ amd64_alu_reg_imm (code, X86_ADD, AMD64_R11, framesize + 16);
+ amd64_mov_membase_reg (code, AMD64_RBP, saved_regs_offset + (i * sizeof(mgreg_t)), AMD64_R11, sizeof(mgreg_t));
} else if (i != AMD64_R11) {
amd64_mov_membase_reg (code, AMD64_RBP, saved_regs_offset + (i * sizeof(mgreg_t)), i, sizeof(mgreg_t));
} else {
else
amd64_mov_reg_imm (code, AMD64_R11, 0);
amd64_mov_membase_reg (code, AMD64_RBP, lmf_offset + MONO_STRUCT_OFFSET (MonoLMF, rip), AMD64_R11, sizeof(mgreg_t));
- /* Save fp */
- amd64_mov_reg_membase (code, AMD64_R11, AMD64_RSP, framesize, sizeof(mgreg_t));
- amd64_mov_membase_reg (code, AMD64_RBP, lmf_offset + MONO_STRUCT_OFFSET (MonoLMF, rbp), AMD64_R11, sizeof(mgreg_t));
/* Save sp */
amd64_mov_reg_reg (code, AMD64_R11, AMD64_RSP, sizeof(mgreg_t));
amd64_alu_reg_imm (code, X86_ADD, AMD64_R11, framesize + 16);
amd64_mov_membase_reg (code, AMD64_RBP, lmf_offset + MONO_STRUCT_OFFSET (MonoLMF, rsp), AMD64_R11, sizeof(mgreg_t));
- /* Save pointer to registers */
+ /* Save pointer to context */
amd64_lea_membase (code, AMD64_R11, AMD64_RBP, ctx_offset);
amd64_mov_membase_reg (code, AMD64_RBP, lmf_offset + MONO_STRUCT_OFFSET (MonoLMFTramp, ctx), AMD64_R11, sizeof(mgreg_t));