mirror of https://github.com/dotnet/runtime
Merge 0ecb1b402c
into 02596ba8d9
This commit is contained in:
commit
93b2766158
|
@ -111,6 +111,9 @@ typedef enum
|
|||
|
||||
#define AMD64_CALLEE_SAVED_REGS ((1<<AMD64_RDI) | (1<<AMD64_RSI) | (1<<AMD64_RBX) | (1<<AMD64_R12) | (1<<AMD64_R13) | (1<<AMD64_R14) | (1<<AMD64_R15) | (1<<AMD64_RBP))
|
||||
#define AMD64_IS_CALLEE_SAVED_REG(reg) (AMD64_CALLEE_SAVED_REGS & (1 << (reg)))
|
||||
|
||||
#define AMD64_CALLEE_SAVED_XREGS ((1<<AMD64_XMM6) | (1<<AMD64_XMM7) | (1<<AMD64_XMM8) | (1<<AMD64_XMM9) | (1<<AMD64_XMM10) | (1<<AMD64_XMM11) | (1<<AMD64_XMM12) | (1<<AMD64_XMM13) | (1<<AMD64_XMM14) | (1<<AMD64_XMM15))
|
||||
#define AMD64_IS_CALLEE_SAVED_XREG(reg) (AMD64_CALLEE_SAVED_XREGS & (1 << (reg)))
|
||||
#else
|
||||
#define AMD64_CALLEE_REGS ((1<<AMD64_RAX) | (1<<AMD64_RCX) | (1<<AMD64_RDX) | (1<<AMD64_RSI) | (1<<AMD64_RDI) | (1<<AMD64_R8) | (1<<AMD64_R9) | (1<<AMD64_R10))
|
||||
#define AMD64_IS_CALLEE_REG(reg) (AMD64_CALLEE_REGS & (1 << (reg)))
|
||||
|
|
|
@ -258,13 +258,27 @@ mono_arch_get_restore_context (MonoTrampInfo **info, gboolean aot)
|
|||
|
||||
amd64_mov_reg_reg (code, AMD64_R11, AMD64_ARG_REG1, 8);
|
||||
|
||||
/* Restore all registers except %rip and %r11 */
|
||||
/* Restore all general registers except %rip and %r11 */
|
||||
gregs_offset = MONO_STRUCT_OFFSET (MonoContext, gregs);
|
||||
for (i = 0; i < AMD64_NREG; ++i) {
|
||||
if (i != AMD64_RIP && i != AMD64_RSP && i != AMD64_R8 && i != AMD64_R9 && i != AMD64_R10 && i != AMD64_R11)
|
||||
amd64_mov_reg_membase (code, i, AMD64_R11, gregs_offset + (i * 8), 8);
|
||||
}
|
||||
|
||||
#ifdef AMD64_CALLEE_SAVED_XREGS
|
||||
/* Restore all callee saved XMM registers */
|
||||
int fregs_offset = MONO_STRUCT_OFFSET (MonoContext, fregs);
|
||||
for (i = 0; i < AMD64_XMM_NREG; ++i) {
|
||||
if (AMD64_IS_CALLEE_SAVED_XREG (i)) {
|
||||
#if defined(MONO_HAVE_SIMD_REG)
|
||||
amd64_movdqu_reg_membase (code, i, AMD64_R11, fregs_offset + (i * sizeof (MonoContextSimdReg)));
|
||||
#else
|
||||
amd64_movsd_reg_membase (code, i, AMD64_R11, fregs_offset + (i * sizeof (double)));
|
||||
#endif
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* The context resides on the stack, in the stack frame of the
|
||||
* caller of this function. The stack pointer that we need to
|
||||
|
@ -467,7 +481,11 @@ get_throw_trampoline (MonoTrampInfo **info, gboolean rethrow, gboolean corlib, g
|
|||
MonoJumpInfo *ji = NULL;
|
||||
GSList *unwind_ops = NULL;
|
||||
int i, stack_size, arg_offsets [16], ctx_offset, regs_offset;
|
||||
#ifdef AMD64_CALLEE_SAVED_XREGS
|
||||
const int kMaxCodeSize = 300;
|
||||
#else
|
||||
const int kMaxCodeSize = 256;
|
||||
#endif
|
||||
|
||||
#ifdef TARGET_WIN32
|
||||
const int dummy_stack_space = 6 * sizeof (target_mgreg_t); /* Windows expects stack space allocated for all 6 dummy args. */
|
||||
|
@ -517,6 +535,20 @@ get_throw_trampoline (MonoTrampInfo **info, gboolean rethrow, gboolean corlib, g
|
|||
/* Save IP */
|
||||
amd64_mov_reg_membase (code, AMD64_RAX, AMD64_RSP, stack_size, sizeof (target_mgreg_t));
|
||||
amd64_mov_membase_reg (code, AMD64_RSP, regs_offset + (AMD64_RIP * sizeof (target_mgreg_t)), AMD64_RAX, sizeof (target_mgreg_t));
|
||||
|
||||
#ifdef AMD64_CALLEE_SAVED_XREGS
|
||||
int fregs_offset = ctx_offset + MONO_STRUCT_OFFSET (MonoContext, fregs);
|
||||
for (i = 0; i < AMD64_XMM_NREG; ++i) {
|
||||
if (AMD64_IS_CALLEE_SAVED_XREG (i)) {
|
||||
#if defined(MONO_HAVE_SIMD_REG)
|
||||
amd64_movdqu_membase_reg (code, AMD64_RSP, fregs_offset + (i * sizeof (MonoContextSimdReg)), i);
|
||||
#else
|
||||
amd64_movsd_membase_reg (code, AMD64_RSP, fregs_offset + (i * sizeof (double)), i);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Set arg1 == ctx */
|
||||
amd64_lea_membase (code, AMD64_RAX, AMD64_RSP, ctx_offset);
|
||||
amd64_mov_membase_reg (code, AMD64_RSP, arg_offsets [0], AMD64_RAX, sizeof (target_mgreg_t));
|
||||
|
@ -617,6 +649,75 @@ mono_arch_get_throw_corlib_exception (MonoTrampInfo **info, gboolean aot)
|
|||
}
|
||||
#endif /* !DISABLE_JIT */
|
||||
|
||||
#if defined(AMD64_CALLEE_SAVED_XREGS) && defined(TARGET_WIN32)
|
||||
|
||||
static gboolean
|
||||
unwind_llvm_frame_win64 (
|
||||
gpointer ip,
|
||||
mono_unwind_reg_t *regs,
|
||||
int nregs,
|
||||
gboolean readonly_regs,
|
||||
host_mgreg_t **save_locations,
|
||||
int save_locations_len)
|
||||
{
|
||||
gboolean result = FALSE;
|
||||
DWORD64 address = (DWORD64)ip;
|
||||
DWORD64 image_base = 0;
|
||||
UNWIND_HISTORY_TABLE entry = { 0 };
|
||||
|
||||
if (RtlLookupFunctionEntry(address, &image_base, &entry)) {
|
||||
for (DWORD i = 0; i < entry.Count; i++) {
|
||||
DWORD64 start = entry.Entry[i].ImageBase + entry.Entry[i].FunctionEntry->BeginAddress;
|
||||
DWORD64 end = entry.Entry[i].ImageBase + entry.Entry[i].FunctionEntry->EndAddress;
|
||||
DWORD64 start_offset = address - start;
|
||||
UNWIND_INFO* unwind_info_address = (UNWIND_INFO*)(entry.Entry[i].ImageBase + entry.Entry[i].FunctionEntry->UnwindInfoAddress);
|
||||
guint8 *fixed_stack_loc = NULL;
|
||||
|
||||
if (!unwind_info_address->FrameRegister) {
|
||||
g_assert (nregs > AMD64_RSP);
|
||||
fixed_stack_loc = (guint8 *)(regs [AMD64_RSP]);
|
||||
} else {
|
||||
g_assert (nregs > unwind_info_address->FrameRegister);
|
||||
fixed_stack_loc = (guint8 *)((guint8 *)(regs [unwind_info_address->FrameRegister]) - (unwind_info_address->FrameOffset * 16));
|
||||
}
|
||||
|
||||
g_assert (fixed_stack_loc);
|
||||
|
||||
if (start <= address && end >= address) {
|
||||
for (guchar j = 0; j < unwind_info_address->CountOfCodes; j++) {
|
||||
if (start_offset > unwind_info_address->UnwindCode[j].CodeOffset) {
|
||||
if (unwind_info_address->UnwindCode[j].UnwindOp == UWOP_SAVE_XMM128 || unwind_info_address->UnwindCode[j].UnwindOp == UWOP_SAVE_XMM128_FAR) {
|
||||
int reg = AMD64_NREG + unwind_info_address->UnwindCode[j].OpInfo;
|
||||
guint8 *offset = fixed_stack_loc;
|
||||
if (unwind_info_address->UnwindCode[j].UnwindOp == UWOP_SAVE_XMM128) {
|
||||
g_assert (j + 1 < unwind_info_address->CountOfCodes);
|
||||
offset = offset + unwind_info_address->UnwindCode[j+1].FrameOffset * 16;
|
||||
j += 1;
|
||||
}
|
||||
if (unwind_info_address->UnwindCode[j].UnwindOp == UWOP_SAVE_XMM128_FAR) {
|
||||
g_assert (j + 2 < unwind_info_address->CountOfCodes);
|
||||
offset = offset + (((guint)(unwind_info_address->UnwindCode[j+1].FrameOffset << 16)) | ((guint)unwind_info_address->UnwindCode[j+2].FrameOffset));
|
||||
j += 2;
|
||||
}
|
||||
|
||||
if (!readonly_regs && regs && (reg < nregs))
|
||||
regs [reg] = GUINT64_TO_HMREG (*(guint64*)(offset));
|
||||
|
||||
if (save_locations && (reg < save_locations_len) && !save_locations [reg])
|
||||
save_locations [reg] = (host_mgreg_t *)offset;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
result = TRUE;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* mono_arch_unwind_frame:
|
||||
*
|
||||
|
@ -641,7 +742,14 @@ mono_arch_unwind_frame (MonoJitTlsData *jit_tls,
|
|||
*new_ctx = *ctx;
|
||||
|
||||
if (ji != NULL) {
|
||||
host_mgreg_t regs [MONO_MAX_IREGS + 1];
|
||||
#ifdef AMD64_CALLEE_SAVED_XREGS
|
||||
host_mgreg_t *restored_regs [AMD64_NREG + AMD64_XMM_NREG];
|
||||
#else
|
||||
host_mgreg_t *restored_regs [AMD64_NREG];
|
||||
#endif
|
||||
|
||||
const int restored_regs_len = G_N_ELEMENTS (restored_regs);
|
||||
|
||||
guint8 *cfa;
|
||||
guint32 unwind_info_len;
|
||||
guint8 *unwind_info;
|
||||
|
@ -665,19 +773,34 @@ mono_arch_unwind_frame (MonoJitTlsData *jit_tls,
|
|||
if (ji->has_arch_eh_info)
|
||||
epilog = (guint8*)ji->code_start + ji->code_size - mono_jinfo_get_epilog_size (ji);
|
||||
|
||||
for (i = 0; i < AMD64_NREG; ++i)
|
||||
regs [i] = new_ctx->gregs [i];
|
||||
|
||||
gboolean success = mono_unwind_frame (unwind_info, unwind_info_len, (guint8 *)ji->code_start,
|
||||
(guint8*)ji->code_start + ji->code_size,
|
||||
(guint8 *)ip, epilog ? &epilog : NULL, regs, MONO_MAX_IREGS + 1,
|
||||
save_locations, MONO_MAX_IREGS, &cfa);
|
||||
(guint8 *)ip, epilog ? &epilog : NULL,
|
||||
new_ctx->gregs, AMD64_NREG, TRUE,
|
||||
restored_regs, restored_regs_len, &cfa);
|
||||
|
||||
#if defined(AMD64_CALLEE_SAVED_XREGS) && defined(TARGET_WIN32)
|
||||
if (ji->from_llvm)
|
||||
success &= unwind_llvm_frame_win64 ((guint8 *)ip, new_ctx->gregs, AMD64_NREG, TRUE, restored_regs, restored_regs_len);
|
||||
#endif
|
||||
|
||||
if (!success)
|
||||
return FALSE;
|
||||
|
||||
for (i = 0; i < AMD64_NREG; ++i)
|
||||
new_ctx->gregs [i] = regs [i];
|
||||
for (i = 0; i < AMD64_NREG; ++i) {
|
||||
if (i < restored_regs_len && restored_regs [i])
|
||||
new_ctx->gregs [i] = *(restored_regs [i]);
|
||||
}
|
||||
|
||||
#ifdef AMD64_CALLEE_SAVED_XREGS
|
||||
for (i = 0; i < AMD64_XMM_NREG; ++i) {
|
||||
if (AMD64_NREG + i < restored_regs_len && restored_regs [AMD64_NREG + i])
|
||||
memcpy (&(new_ctx->fregs [i]), restored_regs [AMD64_NREG + i], sizeof (new_ctx->fregs [0]));
|
||||
}
|
||||
#endif
|
||||
|
||||
if (save_locations)
|
||||
memcpy (save_locations, restored_regs, MONO_MAX_IREGS * sizeof (restored_regs [0]));
|
||||
|
||||
/* The CFA becomes the new SP value */
|
||||
new_ctx->gregs [AMD64_RSP] = (host_mgreg_t)(gsize)cfa;
|
||||
|
|
|
@ -499,7 +499,7 @@ mono_arch_unwind_frame (MonoJitTlsData *jit_tls,
|
|||
|
||||
gboolean success = mono_unwind_frame (unwind_info, unwind_info_len, (guint8*)ji->code_start,
|
||||
(guint8*)ji->code_start + ji->code_size,
|
||||
(guint8*)ip, NULL, regs, MONO_MAX_IREGS + 8,
|
||||
(guint8*)ip, NULL, regs, MONO_MAX_IREGS + 8, FALSE,
|
||||
save_locations, MONO_MAX_IREGS, &cfa);
|
||||
|
||||
if (!success)
|
||||
|
|
|
@ -461,7 +461,7 @@ mono_arch_unwind_frame (MonoJitTlsData *jit_tls,
|
|||
gpointer ip = MINI_FTNPTR_TO_ADDR (MONO_CONTEXT_GET_IP (ctx));
|
||||
gboolean success = mono_unwind_frame (unwind_info, unwind_info_len, (guint8*)ji->code_start,
|
||||
(guint8*)ji->code_start + ji->code_size,
|
||||
(guint8*)ip, NULL, regs, MONO_MAX_IREGS + 8,
|
||||
(guint8*)ip, NULL, regs, MONO_MAX_IREGS + 8, FALSE,
|
||||
save_locations, MONO_MAX_IREGS, (guint8**)&cfa);
|
||||
|
||||
if (!success)
|
||||
|
|
|
@ -583,7 +583,7 @@ mono_arch_unwind_frame (MonoJitTlsData *jit_tls,
|
|||
|
||||
gboolean success = mono_unwind_frame (unwind_info, unwind_info_len, (guint8*)ji->code_start,
|
||||
(guint8*)ji->code_start + ji->code_size,
|
||||
(guint8*)ip, NULL, regs, ppc_lr + 1,
|
||||
(guint8*)ip, NULL, regs, ppc_lr + 1, FALSE,
|
||||
save_locations, MONO_MAX_IREGS, &cfa);
|
||||
|
||||
if (!success)
|
||||
|
|
|
@ -430,7 +430,7 @@ mono_arch_unwind_frame (MonoJitTlsData *jit_tls, MonoJitInfo *ji,
|
|||
|
||||
gboolean success = mono_unwind_frame (unwind_info, unwind_info_len, (guint8 *)ji->code_start,
|
||||
(guint8 *)ji->code_start + ji->code_size, (guint8 *)ip, NULL, regs,
|
||||
MONO_MAX_IREGS + 12 + 1, save_locations, MONO_MAX_IREGS, (guint8 **)&cfa);
|
||||
MONO_MAX_IREGS + 12 + 1, FALSE, save_locations, MONO_MAX_IREGS, (guint8 **)&cfa);
|
||||
|
||||
if (!success)
|
||||
return FALSE;
|
||||
|
|
|
@ -534,7 +534,7 @@ mono_arch_unwind_frame (MonoJitTlsData *jit_tls,
|
|||
memcpy (®s[16], &ctx->uc_mcontext.fpregs.fprs, 16 * sizeof(host_mgreg_t));
|
||||
gboolean success = mono_unwind_frame (unwind_info, unwind_info_len, ji->code_start,
|
||||
(guint8 *) ji->code_start + ji->code_size,
|
||||
ip, epilog ? &epilog : NULL, regs, 32, save_locations,
|
||||
ip, epilog ? &epilog : NULL, regs, 32, FALSE, save_locations,
|
||||
MONO_MAX_IREGS, &cfa);
|
||||
|
||||
if (!success)
|
||||
|
|
|
@ -839,7 +839,7 @@ mono_arch_unwind_frame (MonoJitTlsData *jit_tls,
|
|||
|
||||
gboolean success = mono_unwind_frame ((guint8*)unwind_info, unwind_info_len, (guint8*)ji->code_start,
|
||||
(guint8*)ji->code_start + ji->code_size,
|
||||
(guint8*)ip, NULL, regs, MONO_MAX_IREGS + 1,
|
||||
(guint8*)ip, NULL, regs, MONO_MAX_IREGS + 1, FALSE,
|
||||
save_locations, MONO_MAX_IREGS, &cfa);
|
||||
|
||||
if (!success)
|
||||
|
|
|
@ -1991,6 +1991,23 @@ mono_arch_allocate_vars (MonoCompile *cfg)
|
|||
if (AMD64_IS_CALLEE_SAVED_REG (i) && (cfg->arch.saved_iregs & (1 << i))) {
|
||||
offset += sizeof (target_mgreg_t);
|
||||
}
|
||||
|
||||
#if defined(AMD64_CALLEE_SAVED_XREGS)
|
||||
if (cfg->method->save_lmf) {
|
||||
#if defined(MONO_HAVE_SIMD_REG)
|
||||
int xreg_size = sizeof (MonoContextSimdReg);
|
||||
#else
|
||||
int xreg_size = sizeof (double);
|
||||
#endif
|
||||
offset = ALIGN_TO (offset, xreg_size);
|
||||
for (guint i = 0; i < AMD64_XMM_NREG; ++i) {
|
||||
if (AMD64_IS_CALLEE_SAVED_XREG (i)) {
|
||||
offset += xreg_size;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!cfg->arch.omit_fp)
|
||||
cfg->arch.reg_save_area_offset = -offset;
|
||||
|
||||
|
@ -8422,6 +8439,38 @@ MONO_RESTORE_WARNING
|
|||
}
|
||||
}
|
||||
|
||||
#if defined(AMD64_CALLEE_SAVED_XREGS)
|
||||
if (method->save_lmf) {
|
||||
#if defined(MONO_HAVE_SIMD_REG)
|
||||
int xreg_size = sizeof (MonoContextSimdReg);
|
||||
#else
|
||||
int xreg_size = sizeof (double);
|
||||
#endif
|
||||
save_area_offset = ALIGN_TO (save_area_offset, xreg_size);
|
||||
|
||||
for (guint16 i = 0; i < AMD64_XMM_NREG; ++i) {
|
||||
if (AMD64_IS_CALLEE_SAVED_XREG (i)) {
|
||||
#if defined(MONO_HAVE_SIMD_REG)
|
||||
amd64_movdqu_membase_reg (code, cfg->frame_reg, save_area_offset, i);
|
||||
#else
|
||||
amd64_movsd_membase_reg (code, cfg->frame_reg, save_area_offset, i);
|
||||
#endif
|
||||
if (cfg->arch.omit_fp) {
|
||||
mono_emit_unwind_op_offset (cfg, code, AMD64_NREG + i, - (cfa_offset - save_area_offset));
|
||||
/* These are handled automatically by the stack marking code */
|
||||
mini_gc_set_slot_type_from_cfa (cfg, - (cfa_offset - save_area_offset), SLOT_NOREF);
|
||||
} else {
|
||||
mono_emit_unwind_op_offset (cfg, code, AMD64_NREG + i, - (-save_area_offset + (2 * 8)));
|
||||
// FIXME: GC
|
||||
}
|
||||
|
||||
save_area_offset += xreg_size;
|
||||
async_exc_point (code);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* store runtime generic context */
|
||||
if (cfg->rgctx_var) {
|
||||
g_assert (cfg->rgctx_var->opcode == OP_REGOFFSET &&
|
||||
|
|
|
@ -545,15 +545,7 @@ mono_amd64_get_exception_trampolines (gboolean aot);
|
|||
int
|
||||
mono_amd64_get_tls_gs_offset (void);
|
||||
|
||||
#if defined(TARGET_WIN32) && !defined(DISABLE_JIT)
|
||||
|
||||
#define MONO_ARCH_HAVE_UNWIND_TABLE 1
|
||||
#define MONO_ARCH_HAVE_CODE_CHUNK_TRACKING 1
|
||||
|
||||
#ifdef ENABLE_CHECKED_BUILD
|
||||
#define ENABLE_CHECKED_BUILD_UNWINDINFO
|
||||
#endif
|
||||
|
||||
#if defined(TARGET_WIN32)
|
||||
#define MONO_MAX_UNWIND_CODES 22
|
||||
|
||||
typedef enum _UNWIND_OP_CODES {
|
||||
|
@ -563,7 +555,7 @@ typedef enum _UNWIND_OP_CODES {
|
|||
UWOP_SET_FPREG, /* no info, FP = RSP + UNWIND_INFO.FPRegOffset*16 */
|
||||
UWOP_SAVE_NONVOL, /* info == register number, offset in next slot */
|
||||
UWOP_SAVE_NONVOL_FAR, /* info == register number, offset in next 2 slots */
|
||||
UWOP_SAVE_XMM128, /* info == XMM reg number, offset in next slot */
|
||||
UWOP_SAVE_XMM128 = 8, /* info == XMM reg number, offset in next slot */
|
||||
UWOP_SAVE_XMM128_FAR, /* info == XMM reg number, offset in next 2 slots */
|
||||
UWOP_PUSH_MACHFRAME /* info == 0: no error-code, 1: error-code */
|
||||
} UNWIND_CODE_OPS;
|
||||
|
@ -593,6 +585,15 @@ typedef struct _UNWIND_INFO {
|
|||
* OPTIONAL ULONG ExceptionData[]; */
|
||||
} UNWIND_INFO, *PUNWIND_INFO;
|
||||
|
||||
#if !defined(DISABLE_JIT)
|
||||
|
||||
#define MONO_ARCH_HAVE_UNWIND_TABLE 1
|
||||
#define MONO_ARCH_HAVE_CODE_CHUNK_TRACKING 1
|
||||
|
||||
#ifdef ENABLE_CHECKED_BUILD
|
||||
#define ENABLE_CHECKED_BUILD_UNWINDINFO
|
||||
#endif
|
||||
|
||||
static inline guint
|
||||
mono_arch_unwindinfo_get_size (guchar code_count)
|
||||
{
|
||||
|
@ -634,7 +635,8 @@ mono_arch_code_chunk_new (void *chunk, int size);
|
|||
void
|
||||
mono_arch_code_chunk_destroy (void *chunk);
|
||||
|
||||
#endif /* defined(TARGET_WIN32) && !defined(DISABLE_JIT) */
|
||||
#endif /* !defined(DISABLE_JIT) */
|
||||
#endif /* defined(TARGET_WIN32) */
|
||||
|
||||
#ifdef MONO_ARCH_HAVE_UNWIND_TABLE
|
||||
// Allocate additional size for max 3 unwind ops (push + fp or sp small|large) + unwind info struct trailing code buffer.
|
||||
|
|
|
@ -180,7 +180,7 @@ mono_unwind_ops_encode (GSList *unwind_ops, guint32 *out_len);
|
|||
gboolean
|
||||
mono_unwind_frame (guint8 *unwind_info, guint32 unwind_info_len,
|
||||
guint8 *start_ip, guint8 *end_ip, guint8 *ip, guint8 **mark_locations,
|
||||
mono_unwind_reg_t *regs, int nregs,
|
||||
mono_unwind_reg_t *regs, int nregs, gboolean readonly_regs,
|
||||
host_mgreg_t **save_locations, int save_locations_len,
|
||||
guint8 **out_cfa);
|
||||
|
||||
|
|
|
@ -46,8 +46,18 @@ static int unwind_info_size;
|
|||
#define unwind_unlock() mono_os_mutex_unlock (&unwind_mutex)
|
||||
|
||||
#ifdef TARGET_AMD64
|
||||
static int map_hw_reg_to_dwarf_reg [] = { 0, 2, 1, 3, 7, 6, 4, 5, 8, 9, 10, 11, 12, 13, 14, 15, 16 };
|
||||
static int map_hw_reg_to_dwarf_reg [] = {
|
||||
0, 2, 1, 3, 7, 6, 4, 5, 8, 9, 10, 11, 12, 13, 14, 15, 16
|
||||
#ifdef AMD64_CALLEE_SAVED_XREGS
|
||||
, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32
|
||||
#endif
|
||||
};
|
||||
|
||||
#ifdef AMD64_CALLEE_SAVED_XREGS
|
||||
#define NUM_DWARF_REGS (AMD64_NREG + AMD64_XMM_NREG)
|
||||
#else
|
||||
#define NUM_DWARF_REGS AMD64_NREG
|
||||
#endif
|
||||
#define DWARF_DATA_ALIGN (-8)
|
||||
#define DWARF_PC_REG (mono_hw_reg_to_dwarf_reg (AMD64_RIP))
|
||||
#elif defined(TARGET_ARM)
|
||||
|
@ -545,7 +555,7 @@ typedef struct {
|
|||
gboolean
|
||||
mono_unwind_frame (guint8 *unwind_info, guint32 unwind_info_len,
|
||||
guint8 *start_ip, guint8 *end_ip, guint8 *ip, guint8 **mark_locations,
|
||||
mono_unwind_reg_t *regs, int nregs,
|
||||
mono_unwind_reg_t *regs, int nregs, gboolean readonly_regs,
|
||||
host_mgreg_t **save_locations, int save_locations_len,
|
||||
guint8 **out_cfa)
|
||||
{
|
||||
|
@ -587,6 +597,7 @@ mono_unwind_frame (guint8 *unwind_info, guint32 unwind_info_len,
|
|||
reg_saved [hwreg] = TRUE;
|
||||
locations [hwreg].loc_type = LOC_OFFSET;
|
||||
locations [hwreg].offset = decode_uleb128 (p, &p) * DWARF_DATA_ALIGN;
|
||||
|
||||
break;
|
||||
case 0: {
|
||||
int ext_op = *p;
|
||||
|
@ -694,14 +705,18 @@ mono_unwind_frame (guint8 *unwind_info, guint32 unwind_info_len,
|
|||
for (hwreg = 0; hwreg < NUM_HW_REGS; ++hwreg) {
|
||||
if (reg_saved [hwreg] && locations [hwreg].loc_type == LOC_OFFSET) {
|
||||
int dwarfreg = mono_hw_reg_to_dwarf_reg (hwreg);
|
||||
if (hwreg >= nregs) {
|
||||
if (!readonly_regs && hwreg >= nregs) {
|
||||
mono_runtime_printf_err ("Unwind failure. Assertion at %s %d\n.", __FILE__, __LINE__);
|
||||
return FALSE;
|
||||
}
|
||||
if (IS_DOUBLE_REG (dwarfreg))
|
||||
regs [hwreg] = GUINT64_TO_HMREG (*(guint64*)(cfa_val + locations [hwreg].offset));
|
||||
else
|
||||
regs [hwreg] = *(host_mgreg_t*)(cfa_val + locations [hwreg].offset);
|
||||
|
||||
if (!readonly_regs) {
|
||||
if (IS_DOUBLE_REG (dwarfreg))
|
||||
regs [hwreg] = GUINT64_TO_HMREG (*(guint64*)(cfa_val + locations [hwreg].offset));
|
||||
else
|
||||
regs [hwreg] = *(host_mgreg_t*)(cfa_val + locations [hwreg].offset);
|
||||
}
|
||||
|
||||
if (save_locations && hwreg < save_locations_len)
|
||||
save_locations [hwreg] = (host_mgreg_t*)(cfa_val + locations [hwreg].offset);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue