From: Steve MacLean Date: Fri, 17 Feb 2017 18:25:37 +0000 (-0500) Subject: [ARM64/Unix] (dotnet/coreclr#9500) X-Git-Tag: submit/tizen/20210909.063632~11030^2~8037 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=1662aae5672c92986889b68f19c29e7bbe7edb3c;p=platform%2Fupstream%2Fdotnet%2Fruntime.git [ARM64/Unix] (dotnet/coreclr#9500) * [Arm64/Unix] Update arm64 *.S files to match *.asm * [Arm64/Unix] Fix CONTEXTToNativeContext() * [Arm64/Unix] ThrowExceptionFromContextInternal * [Arm64/Unix] Preserve x8 argument register * [ARM64/Unix] Add CFI directives Add native unwind info * [Arm64/Unix] Fix RtlRestoreContext * [Arm64/Unix] Restore FP from CurrentContextPointers * [Arm64/Unix] fix pointer math * [Arm64/Unix] Fix CallDescrWorkerInternal personality * [Arm64/Unix] More Fp fixups * [Arm64/Unix] CallEHFunclet machine state Restore non-volatile machine state in CallEHFunclet * [Arm64/Unix] CallDescrWorkerInternal Use empty stack slot to save argument * [Arm64/Unix] RtlVirtualUnwind update pointers * [Arm64] LazyMachState fixes * [Arm64/Unix] disable USE_REDIRECT_FOR_GCSTRESS When FEATURE_PAL is enableds USE_REDIRECT_FOR_GCSTRESS is not supported * [Arm64] ClearRegDisplayArgumentAndScratchRegisters() * [Arm64] Remove unnecesary copy in TransitionFrame * [Arm64/Unix] Fix comment per review * [Arm64/Unix] move constants per review * [Arm64/Unix] Use ldp per review Also fix indentation * [Arm64/Unix] Fix indentation per review * [Arm64/Unix] Remove m_Unwound per review comments * [Arm64/Unix] Use PREPARE_EXTERNAL_VAR to access globals * [Arm64/Unix] Fix more whitespace per earlier review comments Commit migrated from https://github.com/dotnet/coreclr/commit/9baa44aa334cf6f032e4abeae10dc1b960aaeb57 --- diff --git a/src/coreclr/src/debug/ee/arm64/dbghelpers.S b/src/coreclr/src/debug/ee/arm64/dbghelpers.S index 07ed04a..64932f3 100644 --- a/src/coreclr/src/debug/ee/arm64/dbghelpers.S +++ b/src/coreclr/src/debug/ee/arm64/dbghelpers.S @@ -1,25 +1,50 @@ -//Licensed to the .NET Foundation under one or more agreements. +// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#include "asmconstants.h" #include "unixasmmacros.inc" -NESTED_ENTRY FuncEvalHijack, _TEXT, FuncEvalHijackPersonalityRoutine +// +// hijacking stub used to perform a func-eval, see Debugger::FuncEvalSetup() for use. +// +// on entry: +// x0 : pointer to DebuggerEval object +// -// NOTE: FuncEvalHijackPersonalityRoutine is dependent on the stack layout so if -// you change the prolog you will also need to update the personality routine. +// @dbgtodo- once we port Funceval, use the ExceptionHijack stub instead of this func-eval stub. +NESTED_ENTRY FuncEvalHijack, _TEXT, UnhandledExceptionHandlerUnix -// push arg to the stack so our personality routine can find it -// push lr to get good stacktrace in debugger + // NOTE: FuncEvalHijackPersonalityRoutine is dependent on the stack layout so if + // you change the prolog you will also need to update the personality routine. -PROLOG_SAVE_REG_PAIR fp, lr, #-32 + // push arg to the stack so our personality routine can find it + // push lr to get good stacktrace in debugger + PROLOG_SAVE_REG_PAIR_INDEXED fp, lr, -32 + str x0, [sp, #16] + // FuncEvalHijackWorker returns the address we should jump to. + bl FuncEvalHijackWorker + + EPILOG_STACK_FREE 32 + EPILOG_BRANCH_REG x0 +NESTED_END FuncEvalHijack + +// This is the general purpose hijacking stub. The DacDbi Hijack primitive will +// set up the stack and then set the IP here, and so this just makes the call. +NESTED_ENTRY ExceptionHijack, _TEXT, UnhandledExceptionHandlerUnix + + // make the call + bl ExceptionHijackWorker + + // effective NOP to terminate unwind + mov x3, x3 + + // *** should never get here *** + EMIT_BREAKPOINT + +// exported label so the debugger knows where the end of this function is +PATCH_LABEL ExceptionHijackEnd + +NESTED_END ExceptionHijack, _TEXT - str x0, [sp, #16] - // FuncEvalHijackWorker returns the address we should jump to. - bl FuncEvalHijackWorker - - EPILOG_STACK_FREE 32 - EPILOG_BRANCH_REG x0 -NESTED_END FuncEvalHijack, _TEXT -//NESTED_ENTRY ExceptionHijack,,ExceptionHijackPersonalityRoutine \ No newline at end of file diff --git a/src/coreclr/src/debug/ee/wks/CMakeLists.txt b/src/coreclr/src/debug/ee/wks/CMakeLists.txt index 1088355..4c4c537 100644 --- a/src/coreclr/src/debug/ee/wks/CMakeLists.txt +++ b/src/coreclr/src/debug/ee/wks/CMakeLists.txt @@ -58,7 +58,7 @@ add_compile_options(-fPIC) if(CLR_CMAKE_PLATFORM_ARCH_AMD64 OR CLR_CMAKE_PLATFORM_ARCH_ARM OR CLR_CMAKE_PLATFORM_ARCH_ARM64 OR CLR_CMAKE_PLATFORM_ARCH_I386) add_library_clr(cordbee_wks ${CORDBEE_SOURCES_WKS} ../${ARCH_SOURCES_DIR}/dbghelpers.S) elseif(CLR_CMAKE_PLATFORM_ARCH_ARM64) - add_library_clr(cordbee_wks ${CORDBEE_SOURCES_WKS}) + add_library_clr(cordbee_wks ${CORDBEE_SOURCES_WKS} ../${ARCH_SOURCES_DIR}/dbghelpers.S) else() message(FATAL_ERROR "Only ARM and AMD64 is supported") endif() diff --git a/src/coreclr/src/pal/inc/unixasmmacrosarm64.inc b/src/coreclr/src/pal/inc/unixasmmacrosarm64.inc index 359f27f..ed73748 100644 --- a/src/coreclr/src/pal/inc/unixasmmacrosarm64.inc +++ b/src/coreclr/src/pal/inc/unixasmmacrosarm64.inc @@ -31,8 +31,8 @@ C_FUNC(\Name): .endm .macro LEAF_END_MARKED Name, Section - .global C_FUNC(\Name\()_End) C_FUNC(\Name\()_End): + .global C_FUNC(\Name\()_End) LEAF_END \Name, \Section .endm @@ -48,18 +48,23 @@ C_FUNC(\Name\()_End): .macro EPILOG_STACK_FREE Size add sp, sp, \Size + .cfi_adjust_cfa_offset -\Size .endm .macro EPILOG_STACK_RESTORE mov sp, fp + .cfi_restore sp .endm .macro PROLOG_SAVE_REG reg, ofs str \reg, [sp, \ofs] + .cfi_rel_offset \reg, \ofs .endm .macro PROLOG_SAVE_REG_PAIR reg1, reg2, ofs stp \reg1, \reg2, [sp, \ofs] + .cfi_rel_offset \reg1, \ofs + .cfi_rel_offset \reg2, \ofs + 8 .ifc \reg1, fp mov fp, sp .endif @@ -67,6 +72,9 @@ C_FUNC(\Name\()_End): .macro PROLOG_SAVE_REG_PAIR_INDEXED reg1, reg2, ofs stp \reg1, \reg2, [sp, \ofs]! + .cfi_adjust_cfa_offset -\ofs + .cfi_rel_offset \reg1, 0 + .cfi_rel_offset \reg2, 8 .ifc \reg1, fp mov fp, sp .endif @@ -74,14 +82,20 @@ C_FUNC(\Name\()_End): .macro EPILOG_RESTORE_REG reg, ofs ldr \reg, [sp, \ofs] + .cfi_restore \reg1 .endm .macro EPILOG_RESTORE_REG_PAIR reg1, reg2, ofs ldp \reg1, \reg2, [sp, \ofs] + .cfi_restore \reg1 + .cfi_restore \reg2 .endm .macro EPILOG_RESTORE_REG_PAIR_INDEXED reg1, reg2, ofs ldp \reg1, \reg2, [sp], \ofs + .cfi_restore \reg1 + .cfi_restore \reg2 + .cfi_adjust_cfa_offset -\ofs .endm .macro EPILOG_RETURN @@ -94,14 +108,14 @@ C_FUNC(\Name\()_End): //----------------------------------------------------------------------------- // Define the prolog for a TransitionFrame-based method. This macro should be called first in the method and -// comprises the entire prolog (i.e. don't modify SP after calling this).The locals must be 8 byte aligned +// comprises the entire prolog (i.e. don't modify SP after calling this).The locals must be 8 byte aligned // // Stack layout: // // (stack parameters) // ... // fp -// lr +// lr // CalleeSavedRegisters::x28 // CalleeSavedRegisters::x27 // CalleeSavedRegisters::x26 @@ -133,6 +147,7 @@ C_FUNC(\Name\()_End): .macro PROLOG_WITH_TRANSITION_BLOCK extraLocals = 0, SaveFPArgs = 1 __PWTB_FloatArgumentRegisters = \extraLocals + __PWTB_SaveFPArgs = \SaveFPArgs .if ((__PWTB_FloatArgumentRegisters % 16) != 0) __PWTB_FloatArgumentRegisters = __PWTB_FloatArgumentRegisters + 8 @@ -140,74 +155,114 @@ C_FUNC(\Name\()_End): __PWTB_TransitionBlock = __PWTB_FloatArgumentRegisters - .if \SaveFPArgs > 0 + .if (__PWTB_SaveFPArgs == 1) __PWTB_TransitionBlock = __PWTB_TransitionBlock + SIZEOF__FloatArgumentRegisters .endif __PWTB_StackAlloc = __PWTB_TransitionBlock - __PWTB_ArgumentRegisters = __PWTB_StackAlloc + 96 - - PROLOG_SAVE_REG_PAIR_INDEXED fp, lr, #-160 - // Spill callee saved registers - PROLOG_SAVE_REG_PAIR x19, x20, #16 - PROLOG_SAVE_REG_PAIR x21, x22, #32 - PROLOG_SAVE_REG_PAIR x23, x24, #48 - PROLOG_SAVE_REG_PAIR x25, x26, #64 - PROLOG_SAVE_REG_PAIR x27, x28, #80 - + __PWTB_ArgumentRegisters = __PWTB_StackAlloc + 96 + + PROLOG_SAVE_REG_PAIR_INDEXED fp, lr, -176 + // Spill callee saved registers + PROLOG_SAVE_REG_PAIR x19, x20, 16 + PROLOG_SAVE_REG_PAIR x21, x22, 32 + PROLOG_SAVE_REG_PAIR x23, x24, 48 + PROLOG_SAVE_REG_PAIR x25, x26, 64 + PROLOG_SAVE_REG_PAIR x27, x28, 80 + // Allocate space for the rest of the frame PROLOG_STACK_ALLOC __PWTB_StackAlloc - + // Spill argument registers. SAVE_ARGUMENT_REGISTERS sp, __PWTB_ArgumentRegisters - .if \SaveFPArgs > 0 + .if (__PWTB_SaveFPArgs == 1) SAVE_FLOAT_ARGUMENT_REGISTERS sp, \extraLocals .endif .endm //----------------------------------------------------------------------------- -// The Following sets of SAVE_*_REGISTERS expect the memory to be reserved and +// The Following sets of SAVE_*_REGISTERS expect the memory to be reserved and // base address to be passed in $reg // // Reserve 64 bytes of memory before calling SAVE_ARGUMENT_REGISTERS -.macro SAVE_ARGUMENT_REGISTERS reg, ofs +.macro SAVE_ARGUMENT_REGISTERS reg, ofs stp x0, x1, [\reg, #(\ofs)] + .cfi_rel_offset x0, \ofs + .cfi_rel_offset x1, \ofs + 8 stp x2, x3, [\reg, #(\ofs + 16)] + .cfi_rel_offset x2, \ofs + 16 + .cfi_rel_offset x3, \ofs + 24 stp x4, x5, [\reg, #(\ofs + 32)] + .cfi_rel_offset x4, \ofs + 32 + .cfi_rel_offset x5, \ofs + 40 stp x6, x7, [\reg, #(\ofs + 48)] + .cfi_rel_offset x6, \ofs + 48 + .cfi_rel_offset x7, \ofs + 56 + str x8, [\reg, #(\ofs + 64)] + .cfi_rel_offset x8, \ofs + 64 .endm // Reserve 64 bytes of memory before calling SAVE_FLOAT_ARGUMENT_REGISTERS -.macro SAVE_FLOAT_ARGUMENT_REGISTERS reg, ofs +.macro SAVE_FLOAT_ARGUMENT_REGISTERS reg, ofs stp d0, d1, [\reg, #(\ofs)] + .cfi_rel_offset d0, \ofs + 0 + .cfi_rel_offset d1, \ofs + 8 stp d2, d3, [\reg, #(\ofs + 16)] + .cfi_rel_offset d2, \ofs + 16 + .cfi_rel_offset d3, \ofs + 24 stp d4, d5, [\reg, #(\ofs + 32)] + .cfi_rel_offset d4, \ofs + 32 + .cfi_rel_offset d5, \ofs + 40 stp d6, d7, [\reg, #(\ofs + 48)] + .cfi_rel_offset d6, \ofs + 48 + .cfi_rel_offset d7, \ofs + 56 .endm -.macro RESTORE_ARGUMENT_REGISTERS reg, ofs +.macro RESTORE_ARGUMENT_REGISTERS reg, ofs ldp x0, x1, [\reg, #(\ofs)] + .cfi_restore x0 + .cfi_restore x1 ldp x2, x3, [\reg, #(\ofs + 16)] + .cfi_restore x2 + .cfi_restore x3 ldp x4, x5, [\reg, #(\ofs + 32)] + .cfi_restore x4 + .cfi_restore x5 ldp x6, x7, [\reg, #(\ofs + 48)] + .cfi_restore x6 + .cfi_restore x7 + ldr x8, [\reg, #(\ofs + 64)] + .cfi_restore x8 .endm -.macro RESTORE_FLOAT_ARGUMENT_REGISTERS reg, ofs +.macro RESTORE_FLOAT_ARGUMENT_REGISTERS reg, ofs ldp d0, d1, [\reg, #(\ofs)] + .cfi_restore d0 + .cfi_restore d1 ldp d2, d3, [\reg, #(\ofs + 16)] + .cfi_restore d2 + .cfi_restore d3 ldp d4, d5, [\reg, #(\ofs + 32)] + .cfi_restore d4 + .cfi_restore d5 ldp d6, d7, [\reg, #(\ofs + 48)] + .cfi_restore d6 + .cfi_restore d7 + +.endm +.macro EPILOG_BRANCH Target + b \Target .endm .macro EPILOG_BRANCH_REG reg @@ -216,40 +271,42 @@ C_FUNC(\Name\()_End): .endm -//----------------------------------------------------------------------------- -// Provides a matching epilog to PROLOG_WITH_TRANSITION_BLOCK and ends by preparing for tail-calling. -// Since this is a tail call argument registers are restored. -// -.macro EPILOG_WITH_TRANSITION_BLOCK_TAILCALL extraLocals = 0, SaveFPArgs =1 - __PWTB_FloatArgumentRegisters = \extraLocals +.macro EPILOG_WITH_TRANSITION_BLOCK_RETURN - .if ((__PWTB_FloatArgumentRegisters % 16) != 0) - __PWTB_FloatArgumentRegisters = __PWTB_FloatArgumentRegisters + 8 - .endif + EPILOG_STACK_FREE __PWTB_StackAlloc - __PWTB_TransitionBlock = __PWTB_FloatArgumentRegisters + EPILOG_RESTORE_REG_PAIR x19, x20, 16 + EPILOG_RESTORE_REG_PAIR x21, x22, 32 + EPILOG_RESTORE_REG_PAIR x23, x24, 48 + EPILOG_RESTORE_REG_PAIR x25, x26, 64 + EPILOG_RESTORE_REG_PAIR x27, x28, 80 + EPILOG_RESTORE_REG_PAIR_INDEXED fp, lr, 176 + ret - .if \SaveFPArgs > 0 - __PWTB_TransitionBlock = __PWTB_TransitionBlock + SIZEOF__FloatArgumentRegisters - .endif +.endm - __PWTB_StackAlloc = __PWTB_TransitionBlock - __PWTB_ArgumentRegisters = __PWTB_StackAlloc + 96 - .if \SaveFPArgs > 0 - RESTORE_FLOAT_ARGUMENT_REGISTERS sp, __PWTB_FloatArgumentRegisters +//----------------------------------------------------------------------------- +// Provides a matching epilog to PROLOG_WITH_TRANSITION_BLOCK and ends by preparing for tail-calling. +// Since this is a tail call argument registers are restored. +// +.macro EPILOG_WITH_TRANSITION_BLOCK_TAILCALL + + .if (__PWTB_SaveFPArgs == 1) + RESTORE_FLOAT_ARGUMENT_REGISTERS sp, __PWTB_FloatArgumentRegisters .endif RESTORE_ARGUMENT_REGISTERS sp, __PWTB_ArgumentRegisters + EPILOG_STACK_FREE __PWTB_StackAlloc - - EPILOG_RESTORE_REG_PAIR x19, x20, #16 - EPILOG_RESTORE_REG_PAIR x21, x22, #32 - EPILOG_RESTORE_REG_PAIR x23, x24, #48 - EPILOG_RESTORE_REG_PAIR x25, x26, #64 - EPILOG_RESTORE_REG_PAIR x27, x28, #80 - EPILOG_RESTORE_REG_PAIR_INDEXED fp, lr, #160 + + EPILOG_RESTORE_REG_PAIR x19, x20, 16 + EPILOG_RESTORE_REG_PAIR x21, x22, 32 + EPILOG_RESTORE_REG_PAIR x23, x24, 48 + EPILOG_RESTORE_REG_PAIR x25, x26, 64 + EPILOG_RESTORE_REG_PAIR x27, x28, 80 + EPILOG_RESTORE_REG_PAIR_INDEXED fp, lr, 176 .endm @@ -273,8 +330,8 @@ __RedirectionFuncName SETS "|?RedirectedHandledJITCaseFor":CC:"$reason":CC:"@Thr IMPORT $__RedirectionFuncName NESTED_ENTRY $__RedirectionStubFuncName - PROLOG_SAVE_REG_PAIR fp, lr, #-16 - sub sp, sp, #16 // stack slot for CONTEXT * and padding + PROLOG_SAVE_REG_PAIR fp, lr, -16 + sub sp, sp, #16 // stack slot for CONTEXT * and padding //REDIRECTSTUB_SP_OFFSET_CONTEXT is defined in asmconstants.h and is used in GetCONTEXTFromRedirectedStubStackFrame //If CONTEXT is not saved at 0 offset from SP it must be changed as well. diff --git a/src/coreclr/src/pal/src/arch/arm64/asmconstants.h b/src/coreclr/src/pal/src/arch/arm64/asmconstants.h new file mode 100644 index 0000000..b2bf744 --- /dev/null +++ b/src/coreclr/src/pal/src/arch/arm64/asmconstants.h @@ -0,0 +1,95 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#ifndef __PAL_ARM64_ASMCONSTANTS_H__ +#define __PAL_ARM64_ASMCONSTANTS_H__ + +#define CONTEXT_ARM64 0x00400000L + +#define CONTEXT_CONTROL_BIT (0) +#define CONTEXT_INTEGER_BIT (1) +#define CONTEXT_FLOATING_POINT_BIT (2) +#define CONTEXT_DEBUG_REGISTERS_BIT (3) + +#define CONTEXT_CONTROL (CONTEXT_ARM64 | (1L << CONTEXT_CONTROL_BIT)) +#define CONTEXT_INTEGER (CONTEXT_ARM64 | (1 << CONTEXT_INTEGER_BIT)) +#define CONTEXT_FLOATING_POINT (CONTEXT_ARM64 | (1 << CONTEXT_FLOATING_POINT_BIT)) +#define CONTEXT_DEBUG_REGISTERS (CONTEXT_ARM64 | (1 << CONTEXT_DEBUG_REGISTERS_BIT)) + +#define CONTEXT_FULL (CONTEXT_CONTROL | CONTEXT_INTEGER | CONTEXT_FLOATING_POINT) + + +#define CONTEXT_ContextFlags 0 +#define CONTEXT_Cpsr CONTEXT_ContextFlags+4 +#define CONTEXT_X0 CONTEXT_Cpsr+4 +#define CONTEXT_X1 CONTEXT_X0+8 +#define CONTEXT_X2 CONTEXT_X1+8 +#define CONTEXT_X3 CONTEXT_X2+8 +#define CONTEXT_X4 CONTEXT_X3+8 +#define CONTEXT_X5 CONTEXT_X4+8 +#define CONTEXT_X6 CONTEXT_X5+8 +#define CONTEXT_X7 CONTEXT_X6+8 +#define CONTEXT_X8 CONTEXT_X7+8 +#define CONTEXT_X9 CONTEXT_X8+8 +#define CONTEXT_X10 CONTEXT_X9+8 +#define CONTEXT_X11 CONTEXT_X10+8 +#define CONTEXT_X12 CONTEXT_X11+8 +#define CONTEXT_X13 CONTEXT_X12+8 +#define CONTEXT_X14 CONTEXT_X13+8 +#define CONTEXT_X15 CONTEXT_X14+8 +#define CONTEXT_X16 CONTEXT_X15+8 +#define CONTEXT_X17 CONTEXT_X16+8 +#define CONTEXT_X18 CONTEXT_X17+8 +#define CONTEXT_X19 CONTEXT_X18+8 +#define CONTEXT_X20 CONTEXT_X19+8 +#define CONTEXT_X21 CONTEXT_X20+8 +#define CONTEXT_X22 CONTEXT_X21+8 +#define CONTEXT_X23 CONTEXT_X22+8 +#define CONTEXT_X24 CONTEXT_X23+8 +#define CONTEXT_X25 CONTEXT_X24+8 +#define CONTEXT_X26 CONTEXT_X25+8 +#define CONTEXT_X27 CONTEXT_X26+8 +#define CONTEXT_X28 CONTEXT_X27+8 +#define CONTEXT_Fp CONTEXT_X28+8 +#define CONTEXT_Lr CONTEXT_Fp+8 +#define CONTEXT_Sp CONTEXT_Lr+8 +#define CONTEXT_Pc CONTEXT_Sp+8 +#define CONTEXT_NEON_OFFSET CONTEXT_Pc+8 +#define CONTEXT_V0 0 +#define CONTEXT_V1 CONTEXT_V0+16 +#define CONTEXT_V2 CONTEXT_V1+16 +#define CONTEXT_V3 CONTEXT_V2+16 +#define CONTEXT_V4 CONTEXT_V3+16 +#define CONTEXT_V5 CONTEXT_V4+16 +#define CONTEXT_V6 CONTEXT_V5+16 +#define CONTEXT_V7 CONTEXT_V6+16 +#define CONTEXT_V8 CONTEXT_V7+16 +#define CONTEXT_V9 CONTEXT_V8+16 +#define CONTEXT_V10 CONTEXT_V9+16 +#define CONTEXT_V11 CONTEXT_V10+16 +#define CONTEXT_V12 CONTEXT_V11+16 +#define CONTEXT_V13 CONTEXT_V12+16 +#define CONTEXT_V14 CONTEXT_V13+16 +#define CONTEXT_V15 CONTEXT_V14+16 +#define CONTEXT_V16 CONTEXT_V15+16 +#define CONTEXT_V17 CONTEXT_V16+16 +#define CONTEXT_V18 CONTEXT_V17+16 +#define CONTEXT_V19 CONTEXT_V18+16 +#define CONTEXT_V20 CONTEXT_V19+16 +#define CONTEXT_V21 CONTEXT_V20+16 +#define CONTEXT_V22 CONTEXT_V21+16 +#define CONTEXT_V23 CONTEXT_V22+16 +#define CONTEXT_V24 CONTEXT_V23+16 +#define CONTEXT_V25 CONTEXT_V24+16 +#define CONTEXT_V26 CONTEXT_V25+16 +#define CONTEXT_V27 CONTEXT_V26+16 +#define CONTEXT_V28 CONTEXT_V27+16 +#define CONTEXT_V29 CONTEXT_V28+16 +#define CONTEXT_V30 CONTEXT_V29+16 +#define CONTEXT_V31 CONTEXT_V30+16 +#define CONTEXT_FLOAT_CONTROL_OFFSET CONTEXT_V31 +#define CONTEXT_Fpcr 0 +#define CONTEXT_Fpsr CONTEXT_Fpcr+4 + +#endif diff --git a/src/coreclr/src/pal/src/arch/arm64/context2.S b/src/coreclr/src/pal/src/arch/arm64/context2.S index a64e62c..e62a9ac 100644 --- a/src/coreclr/src/pal/src/arch/arm64/context2.S +++ b/src/coreclr/src/pal/src/arch/arm64/context2.S @@ -8,87 +8,7 @@ // #include "unixasmmacros.inc" - -#define CONTEXT_ARM64 0x00400000L - -#define CONTEXT_CONTROL (CONTEXT_ARM64 | 0x1L) -#define CONTEXT_INTEGER (CONTEXT_ARM64 | 0x2L) -#define CONTEXT_FLOATING_POINT (CONTEXT_ARM64 | 0x4L) -#define CONTEXT_DEBUG_REGISTERS (CONTEXT_ARM64 | 0x8L) - -#define CONTEXT_FULL (CONTEXT_CONTROL | CONTEXT_INTEGER | CONTEXT_FLOATING_POINT) - -#define CONTEXT_ContextFlags 0 -#define CONTEXT_Cpsr CONTEXT_ContextFlags+4 -#define CONTEXT_X0 CONTEXT_Cpsr+4 -#define CONTEXT_X1 CONTEXT_X0+8 -#define CONTEXT_X2 CONTEXT_X1+8 -#define CONTEXT_X3 CONTEXT_X2+8 -#define CONTEXT_X4 CONTEXT_X3+8 -#define CONTEXT_X5 CONTEXT_X4+8 -#define CONTEXT_X6 CONTEXT_X5+8 -#define CONTEXT_X7 CONTEXT_X6+8 -#define CONTEXT_X8 CONTEXT_X7+8 -#define CONTEXT_X9 CONTEXT_X8+8 -#define CONTEXT_X10 CONTEXT_X9+8 -#define CONTEXT_X11 CONTEXT_X10+8 -#define CONTEXT_X12 CONTEXT_X11+8 -#define CONTEXT_X13 CONTEXT_X12+8 -#define CONTEXT_X14 CONTEXT_X13+8 -#define CONTEXT_X15 CONTEXT_X14+8 -#define CONTEXT_X16 CONTEXT_X15+8 -#define CONTEXT_X17 CONTEXT_X16+8 -#define CONTEXT_X18 CONTEXT_X17+8 -#define CONTEXT_X19 CONTEXT_X18+8 -#define CONTEXT_X20 CONTEXT_X19+8 -#define CONTEXT_X21 CONTEXT_X20+8 -#define CONTEXT_X22 CONTEXT_X21+8 -#define CONTEXT_X23 CONTEXT_X22+8 -#define CONTEXT_X24 CONTEXT_X23+8 -#define CONTEXT_X25 CONTEXT_X24+8 -#define CONTEXT_X26 CONTEXT_X25+8 -#define CONTEXT_X27 CONTEXT_X26+8 -#define CONTEXT_X28 CONTEXT_X27+8 -#define CONTEXT_Fp CONTEXT_X28+8 -#define CONTEXT_Lr CONTEXT_Fp+8 -#define CONTEXT_Sp CONTEXT_Lr+8 -#define CONTEXT_Pc CONTEXT_Sp+8 -#define CONTEXT_NEON_OFFSET CONTEXT_Pc+8 -#define CONTEXT_V0 0 -#define CONTEXT_V1 CONTEXT_V0+16 -#define CONTEXT_V2 CONTEXT_V1+16 -#define CONTEXT_V3 CONTEXT_V2+16 -#define CONTEXT_V4 CONTEXT_V3+16 -#define CONTEXT_V5 CONTEXT_V4+16 -#define CONTEXT_V6 CONTEXT_V5+16 -#define CONTEXT_V7 CONTEXT_V6+16 -#define CONTEXT_V8 CONTEXT_V7+16 -#define CONTEXT_V9 CONTEXT_V8+16 -#define CONTEXT_V10 CONTEXT_V9+16 -#define CONTEXT_V11 CONTEXT_V10+16 -#define CONTEXT_V12 CONTEXT_V11+16 -#define CONTEXT_V13 CONTEXT_V12+16 -#define CONTEXT_V14 CONTEXT_V13+16 -#define CONTEXT_V15 CONTEXT_V14+16 -#define CONTEXT_V16 CONTEXT_V15+16 -#define CONTEXT_V17 CONTEXT_V16+16 -#define CONTEXT_V18 CONTEXT_V17+16 -#define CONTEXT_V19 CONTEXT_V18+16 -#define CONTEXT_V20 CONTEXT_V19+16 -#define CONTEXT_V21 CONTEXT_V20+16 -#define CONTEXT_V22 CONTEXT_V21+16 -#define CONTEXT_V23 CONTEXT_V22+16 -#define CONTEXT_V24 CONTEXT_V23+16 -#define CONTEXT_V25 CONTEXT_V24+16 -#define CONTEXT_V26 CONTEXT_V25+16 -#define CONTEXT_V27 CONTEXT_V26+16 -#define CONTEXT_V28 CONTEXT_V27+16 -#define CONTEXT_V29 CONTEXT_V28+16 -#define CONTEXT_V30 CONTEXT_V29+16 -#define CONTEXT_V31 CONTEXT_V30+16 -#define CONTEXT_FLOAT_CONTROL_OFFSET CONTEXT_V31 -#define CONTEXT_Fpcr 0 -#define CONTEXT_Fpsr CONTEXT_Fpcr+4 +#include "asmconstants.h" // Incoming: // x0: Context* @@ -115,10 +35,8 @@ LEAF_ENTRY CONTEXT_CaptureContext, _TEXT ldr x2, [sp, 24] str w2, [x0, CONTEXT_Cpsr] stp fp, lr, [x0, CONTEXT_Fp] - add sp, sp, #32 - mov x2, sp + add x2, sp, #32 stp x2, lr, [x0, CONTEXT_Sp] - sub sp, sp, #32 LOCAL_LABEL(Done_CONTEXT_CONTROL): // we dont clobber x1 in the CONTEXT_CONTROL case @@ -224,14 +142,8 @@ LEAF_ENTRY RtlRestoreContext, _TEXT // since we potentially clobber x0 below, we'll bank it in x16 mov x16, x0 - ldr w2, [x16, CONTEXT_ContextFlags] - // clangs assembler doesn't seem to support the mov Wx, imm32 yet - movz w3, #0x40, lsl #16 - movk w3, #0x4 - mov w4, w3 - and w3, w2, w3 - cmp w3, w4 - b.ne LOCAL_LABEL(No_Restore_CONTEXT_FLOATING_POINT) + ldr w17, [x16, CONTEXT_ContextFlags] + tbz w17, #CONTEXT_FLOATING_POINT_BIT, LOCAL_LABEL(No_Restore_CONTEXT_FLOATING_POINT) add x16, x16, CONTEXT_NEON_OFFSET ldp q0, q1, [x16, CONTEXT_V0] @@ -256,12 +168,7 @@ LEAF_ENTRY RtlRestoreContext, _TEXT sub x16, x16, CONTEXT_NEON_OFFSET LOCAL_LABEL(No_Restore_CONTEXT_FLOATING_POINT): - movz w2, #0x40, lsl #16 - movk w2, #0x2 - mov w3, w2 - and w2, w1, w2 - cmp w2, w3 - b.ne LOCAL_LABEL(No_Restore_CONTEXT_INTEGER) + tbz w17, #CONTEXT_INTEGER_BIT, LOCAL_LABEL(No_Restore_CONTEXT_INTEGER) ldp x0, x1, [x16, CONTEXT_X0] ldp x2, x3, [x16, CONTEXT_X2] @@ -279,12 +186,7 @@ LOCAL_LABEL(No_Restore_CONTEXT_FLOATING_POINT): ldr x28, [x16, CONTEXT_X28] LOCAL_LABEL(No_Restore_CONTEXT_INTEGER): - movz w2, #0x40, lsl #16 - movk w2, #0x2 - mov w3, w2 - and w2, w1, w2 - cmp w2, w3 - b.ne LOCAL_LABEL(No_Restore_CONTEXT_CONTROL) + tbz w17, #CONTEXT_CONTROL_BIT, LOCAL_LABEL(No_Restore_CONTEXT_CONTROL) ldr w17, [x16, CONTEXT_Cpsr] msr nzcv, x17 @@ -293,8 +195,8 @@ LOCAL_LABEL(No_Restore_CONTEXT_INTEGER): mov sp, x17 ldr x17, [x16, CONTEXT_Pc] br x17 - + LOCAL_LABEL(No_Restore_CONTEXT_CONTROL): - ret + ret LEAF_END RtlRestoreContext, _TEXT diff --git a/src/coreclr/src/pal/src/arch/arm64/exceptionhelper.S b/src/coreclr/src/pal/src/arch/arm64/exceptionhelper.S index 4fdcfc5..480846e 100644 --- a/src/coreclr/src/pal/src/arch/arm64/exceptionhelper.S +++ b/src/coreclr/src/pal/src/arch/arm64/exceptionhelper.S @@ -3,7 +3,30 @@ // See the LICENSE file in the project root for more information. #include "unixasmmacros.inc" +#include "asmconstants.h" +////////////////////////////////////////////////////////////////////////// +// +// This function creates a stack frame right below the target frame, restores all callee +// saved registers, SP, and LR from the passed in context. +// Then it uses the ThrowExceptionHelper to throw the passed in exception from that context. +// EXTERN_C void ThrowExceptionFromContextInternal(CONTEXT* context, PAL_SEHException* ex); LEAF_ENTRY ThrowExceptionFromContextInternal, _TEXT - EMIT_BREAKPOINT + // Save the FP & LR to the stack so that the unwind can work at the instruction after + // loading the FP from the context, but before loading the SP from the context. + stp fp, lr, [sp, -16]! + + ldp x19,x20, [x0, #(CONTEXT_X19)] + ldp x21,x22, [x0, #(CONTEXT_X21)] + ldp x23,x24, [x0, #(CONTEXT_X23)] + ldp x24,x25, [x0, #(CONTEXT_X24)] + ldp x26,x27, [x0, #(CONTEXT_X26)] + ldp x28,fp, [x0, #(CONTEXT_X28)] + ldr lr, [x0, #(CONTEXT_Pc)] + ldr x2, [x0, #(CONTEXT_Sp)] + mov sp, x2 + + // The PAL_SEHException pointer + mov x0, x1 + b EXTERNAL_C_FUNC(ThrowExceptionHelper) LEAF_END ThrowExceptionFromContextInternal, _TEXT diff --git a/src/coreclr/src/pal/src/exception/seh-unwind.cpp b/src/coreclr/src/pal/src/exception/seh-unwind.cpp index aeb6fa4..1f20ee0 100644 --- a/src/coreclr/src/pal/src/exception/seh-unwind.cpp +++ b/src/coreclr/src/pal/src/exception/seh-unwind.cpp @@ -244,6 +244,7 @@ static void GetContextPointers(unw_cursor_t *cursor, unw_context_t *unwContext, GetContextPointer(cursor, unwContext, UNW_AARCH64_X26, &contextPointers->X26); GetContextPointer(cursor, unwContext, UNW_AARCH64_X27, &contextPointers->X27); GetContextPointer(cursor, unwContext, UNW_AARCH64_X28, &contextPointers->X28); + GetContextPointer(cursor, unwContext, UNW_AARCH64_X29, &contextPointers->Fp); #else #error unsupported architecture #endif diff --git a/src/coreclr/src/pal/src/include/pal/context.h b/src/coreclr/src/pal/src/include/pal/context.h index 6857c13..08fa05d 100644 --- a/src/coreclr/src/pal/src/include/pal/context.h +++ b/src/coreclr/src/pal/src/include/pal/context.h @@ -248,8 +248,7 @@ inline void *FPREG_Xstate_Ymmh(const ucontext_t *uc) #define MCREG_Sp(mc) ((mc).sp) #define MCREG_Pc(mc) ((mc).pc) -#define MCREG_PState(mc) ((mc).pstate) -#define MCREG_Cpsr(mc) ((mc).cpsr) +#define MCREG_Cpsr(mc) ((mc).pstate) #else // For FreeBSD, as found in x86/ucontext.h #define MCREG_Rbp(mc) ((mc).mc_rbp) diff --git a/src/coreclr/src/pal/src/thread/context.cpp b/src/coreclr/src/pal/src/thread/context.cpp index bee6ddd..98867c9 100644 --- a/src/coreclr/src/pal/src/thread/context.cpp +++ b/src/coreclr/src/pal/src/thread/context.cpp @@ -127,6 +127,8 @@ typedef int __ptrace_request; ASSIGN_REG(R12) #elif defined(_ARM64_) #define ASSIGN_CONTROL_REGS \ + ASSIGN_REG(Cpsr) \ + ASSIGN_REG(Fp) \ ASSIGN_REG(Sp) \ ASSIGN_REG(Lr) \ ASSIGN_REG(Pc) diff --git a/src/coreclr/src/unwinder/arm64/unwinder_arm64.cpp b/src/coreclr/src/unwinder/arm64/unwinder_arm64.cpp index e13c7b9..36f7de1 100644 --- a/src/coreclr/src/unwinder/arm64/unwinder_arm64.cpp +++ b/src/coreclr/src/unwinder/arm64/unwinder_arm64.cpp @@ -109,16 +109,37 @@ typedef struct _ARM64_VFP_STATE typedef struct _ARM64_UNWIND_PARAMS { - ULONG_PTR ControlPc; - PULONG_PTR LowLimit; - PULONG_PTR HighLimit; PKNONVOLATILE_CONTEXT_POINTERS ContextPointers; } ARM64_UNWIND_PARAMS, *PARM64_UNWIND_PARAMS; #define UNWIND_PARAMS_SET_TRAP_FRAME(Params, Address, Size) -#define UPDATE_CONTEXT_POINTERS(Params, RegisterNumber, Address) -#define UPDATE_FP_CONTEXT_POINTERS(Params, RegisterNumber, Address) +#define UPDATE_CONTEXT_POINTERS(Params, RegisterNumber, Address) \ +do { \ + if (ARGUMENT_PRESENT(Params)) { \ + PKNONVOLATILE_CONTEXT_POINTERS ContextPointers = (Params)->ContextPointers; \ + if (ARGUMENT_PRESENT(ContextPointers)) { \ + if (RegisterNumber >= 19 && RegisterNumber <= 30) { \ + (&ContextPointers->X19)[RegisterNumber - 19] = (PDWORD64)Address; \ + } \ + } \ + } \ +} while (0) + + +#define UPDATE_FP_CONTEXT_POINTERS(Params, RegisterNumber, Address) \ +do { \ + if (ARGUMENT_PRESENT(Params)) { \ + PKNONVOLATILE_CONTEXT_POINTERS ContextPointers = (Params)->ContextPointers; \ + if (ARGUMENT_PRESENT(ContextPointers) && \ + (RegisterNumber >= 8) && \ + (RegisterNumber <= 15)) { \ + \ + (&ContextPointers->D8)[RegisterNumber - 8] = (PDWORD64)Address; \ + } \ + } \ +} while (0) + #define VALIDATE_STACK_ADDRESS_EX(Params, Context, Address, DataSize, Alignment, OutStatus) #define VALIDATE_STACK_ADDRESS(Params, Context, DataSize, Alignment, OutStatus) @@ -215,7 +236,7 @@ Return Value: for (RegIndex = 0; RegIndex < 18; RegIndex++) { UPDATE_CONTEXT_POINTERS(UnwindParams, RegIndex, SourceAddress); #ifdef __clang__ - *(&ContextRecord->X0 + (RegIndex * sizeof(void*))) = MEMORY_READ_QWORD(UnwindParams, SourceAddress); + *(&ContextRecord->X0 + RegIndex) = MEMORY_READ_QWORD(UnwindParams, SourceAddress); #else ContextRecord->X[RegIndex] = MEMORY_READ_QWORD(UnwindParams, SourceAddress); #endif @@ -295,7 +316,7 @@ Return Value: for (RegIndex = 0; RegIndex < 29; RegIndex++) { UPDATE_CONTEXT_POINTERS(UnwindParams, RegIndex, SourceAddress); #ifdef __clang__ - *(&ContextRecord->X0 + (RegIndex * sizeof(void*))) = MEMORY_READ_QWORD(UnwindParams, SourceAddress); + *(&ContextRecord->X0 + RegIndex) = MEMORY_READ_QWORD(UnwindParams, SourceAddress); #else ContextRecord->X[RegIndex] = MEMORY_READ_QWORD(UnwindParams, SourceAddress); #endif @@ -479,9 +500,9 @@ Return Value: // for (RegIndex = 0; RegIndex < RegisterCount; RegIndex++) { - UPDATE_CONTEXT_POINTERS(UnwindParams, RegIndex, CurAddress); + UPDATE_CONTEXT_POINTERS(UnwindParams, FirstRegister + RegIndex, CurAddress); #ifdef __clang__ - *(&ContextRecord->X0 + (RegIndex * sizeof(void*))) = MEMORY_READ_QWORD(UnwindParams, CurAddress); + *(&ContextRecord->X0 + FirstRegister + RegIndex) = MEMORY_READ_QWORD(UnwindParams, CurAddress); #else ContextRecord->X[FirstRegister + RegIndex] = MEMORY_READ_QWORD(UnwindParams, CurAddress); #endif @@ -555,7 +576,7 @@ Return Value: // for (RegIndex = 0; RegIndex < RegisterCount; RegIndex++) { - UPDATE_FP_CONTEXT_POINTERS(UnwindParams, RegIndex, CurAddress); + UPDATE_FP_CONTEXT_POINTERS(UnwindParams, FirstRegister + RegIndex, CurAddress); ContextRecord->V[FirstRegister + RegIndex].Low = MEMORY_READ_QWORD(UnwindParams, CurAddress); CurAddress += 8; } @@ -1591,7 +1612,6 @@ BOOL DacUnwindStackFrame(T_CONTEXT *pContext, T_KNONVOLATILE_CONTEXT_POINTERS* p } #if defined(FEATURE_PAL) -//TODO: Fix the context pointers PEXCEPTION_ROUTINE RtlVirtualUnwind( IN ULONG HandlerType, @@ -1615,6 +1635,9 @@ RtlVirtualUnwind( rfe.BeginAddress = FunctionEntry->BeginAddress; rfe.UnwindData = FunctionEntry->UnwindData; + ARM64_UNWIND_PARAMS unwindParams; + unwindParams.ContextPointers = ContextPointers; + if ((rfe.UnwindData & 3) != 0) { hr = RtlpUnwindFunctionCompact(ControlPc - ImageBase, @@ -1623,7 +1646,7 @@ RtlVirtualUnwind( EstablisherFrame, &handlerRoutine, HandlerData, - NULL); + &unwindParams); } else @@ -1635,7 +1658,7 @@ RtlVirtualUnwind( EstablisherFrame, &handlerRoutine, HandlerData, - NULL); + &unwindParams); } _ASSERTE(SUCCEEDED(hr)); diff --git a/src/coreclr/src/vm/arm64/asmhelpers.S b/src/coreclr/src/vm/arm64/asmhelpers.S index d92e91c..dd28c3e 100644 --- a/src/coreclr/src/vm/arm64/asmhelpers.S +++ b/src/coreclr/src/vm/arm64/asmhelpers.S @@ -107,6 +107,7 @@ LEAF_ENTRY HelperMethodFrameRestoreState, _TEXT RestoreRegMS 26, X26 RestoreRegMS 27, X27 RestoreRegMS 28, X28 + RestoreRegMS 29, X29 LOCAL_LABEL(Done): // Its imperative that the return value of HelperMethodFrameRestoreState is zero // as it is used in the state machine to loop until it becomes zero. @@ -120,18 +121,18 @@ LEAF_END HelperMethodFrameRestoreState, _TEXT // The call in ndirect import precode points to this function. NESTED_ENTRY NDirectImportThunk, _TEXT, NoHandler - PROLOG_SAVE_REG_PAIR_INDEXED fp, lr, #-144 + PROLOG_SAVE_REG_PAIR_INDEXED fp, lr, -160 SAVE_ARGUMENT_REGISTERS sp, 16 - SAVE_FLOAT_ARGUMENT_REGISTERS sp, 80 + SAVE_FLOAT_ARGUMENT_REGISTERS sp, 88 mov x0, x12 bl NDirectImportWorker mov x12, x0 // pop the stack and restore original register state - RESTORE_FLOAT_ARGUMENT_REGISTERS sp, 80 + RESTORE_FLOAT_ARGUMENT_REGISTERS sp, 88 RESTORE_ARGUMENT_REGISTERS sp, 16 - EPILOG_RESTORE_REG_PAIR_INDEXED fp, lr, #144 + EPILOG_RESTORE_REG_PAIR_INDEXED fp, lr, 160 // If we got back from NDirectImportWorker, the MD has been successfully // linked. Proceed to execute the original DLL call. @@ -140,8 +141,14 @@ NESTED_ENTRY NDirectImportThunk, _TEXT, NoHandler NESTED_END NDirectImportThunk, _TEXT // ------------------------------------------------------------------ -// ARM64TODO: Implement PrecodeFixupThunk when PreCode is Enabled +// The call in fixup precode initally points to this function. +// The pupose of this function is to load the MethodDesc and forward the call to prestub. NESTED_ENTRY PrecodeFixupThunk, _TEXT, NoHandler + // x12 = FixupPrecode * + // On Exit + // x12 = MethodDesc* + // x13, x14 Trashed + // Inline computation done by FixupPrecode::GetMethodDesc() ldrb w13, [x12, #Offset_PrecodeChunkIndex] //m_PrecodeChunkIndex ldrb w14, [x12, #Offset_MethodDescChunkIndex] // m_MethodDescChunkIndex @@ -181,34 +188,6 @@ C_FUNC(ThePreStubPatchLabel): LEAF_END ThePreStubPatch, _TEXT -// ------------------------------------------------------------------ -// void ResolveWorkerAsmStub(args in regs x0-x7 & stack, x11:IndirectionCellAndFlags, x12:DispatchToken) -// -// The stub dispatch thunk which transfers control to VSD_ResolveWorker. -NESTED_ENTRY ResolveWorkerAsmStub, _TEXT, NoHandler - - PROLOG_WITH_TRANSITION_BLOCK - - add x0, sp, #__PWTB_TransitionBlock // pTransitionBlock - and x1, x11, #-4 // Indirection cell - mov x2, x12 // DispatchToken - and x3, x11, #3 // flag - bl C_FUNC(VSD_ResolveWorker) - mov x9, x0 - - EPILOG_WITH_TRANSITION_BLOCK_TAILCALL - - EPILOG_BRANCH_REG x9 - -NESTED_END ResolveWorkerAsmStub, _TEXT - -NESTED_ENTRY ResolveWorkerChainLookupAsmStub, _TEXT, NoHandler - - // ARMSTUB TODO: implement chained lookup - b C_FUNC(ResolveWorkerAsmStub) - -NESTED_END ResolveWorkerChainLookupAsmStub, _TEXT - //----------------------------------------------------------------------------- // The following Macros help in WRITE_BARRIER Implemetations // WRITE_BARRIER_ENTRY @@ -288,6 +267,49 @@ WRITE_BARRIER_ENTRY JIT_WriteBarrier dmb ST str x15, [x14] +#ifdef WRITE_BARRIER_CHECK + // Update GC Shadow Heap + + // need temporary registers. Save them before using. + stp x12, x13, [sp, #-16]! + + // Compute address of shadow heap location: + // pShadow = g_GCShadow + (x14 - g_lowest_address) + PREPARE_EXTERNAL_VAR g_lowest_address, x12 + ldr x12, [x12] + sub x12, x14, x12 + PREPARE_EXTERNAL_VAR g_GCShadow, x13 + ldr x13, [x13] + add x12, x13, x12 + + // if (pShadow >= g_GCShadowEnd) goto end + PREPARE_EXTERNAL_VAR g_GCShadowEnd, x13 + ldr x13, [x13] + cmp x12, x13 + bhs LOCAL_LABEL(shadowupdateend) + + // *pShadow = x15 + str x15, [x12] + + // Ensure that the write to the shadow heap occurs before the read from the GC heap so that race + // conditions are caught by INVALIDGCVALUE. + dmb sy + + // if ([x14] == x15) goto end + ldr x13, [x14] + cmp x13, x15 + beq LOCAL_LABEL(shadowupdateend) + + // *pShadow = INVALIDGCVALUE (0xcccccccd) + mov x13, #0 + movk x13, #0xcccd + movk x13, #0xcccc, LSL #16 + str x13, [x12] + +LOCAL_LABEL(shadowupdateend): + ldp x12, x13, [sp],#16 +#endif + // Branch to Exit if the reference is not in the Gen0 heap // PREPARE_EXTERNAL_VAR g_ephemeral_low, x12 @@ -347,9 +369,9 @@ LEAF_END JIT_PatchedCodeLast, _TEXT NESTED_ENTRY VirtualMethodFixupStub, _TEXT, NoHandler // Save arguments and return address - PROLOG_SAVE_REG_PAIR_INDEXED fp, lr, #-144 + PROLOG_SAVE_REG_PAIR_INDEXED fp, lr, -160 SAVE_ARGUMENT_REGISTERS sp, 16 - SAVE_FLOAT_ARGUMENT_REGISTERS sp, 80 + SAVE_FLOAT_ARGUMENT_REGISTERS sp, 88 // Refer to ZapImportVirtualThunk::Save // for details on this. @@ -366,8 +388,8 @@ NESTED_ENTRY VirtualMethodFixupStub, _TEXT, NoHandler // pop the stack and restore original register state RESTORE_ARGUMENT_REGISTERS sp, 16 - RESTORE_FLOAT_ARGUMENT_REGISTERS sp, 80 - EPILOG_RESTORE_REG_PAIR_INDEXED fp, lr, #144 + RESTORE_FLOAT_ARGUMENT_REGISTERS sp, 88 + EPILOG_RESTORE_REG_PAIR_INDEXED fp, lr, 160 PATCH_LABEL VirtualMethodFixupPatchLabel @@ -425,15 +447,161 @@ LOCAL_LABEL(LNullThis): LEAF_END SinglecastDelegateInvokeStub, _TEXT +#ifdef FEATURE_COMINTEROP + +#define ComCallPreStub_FrameSize (SIZEOF__GSCookie + SIZEOF__ComMethodFrame) +#define ComCallPreStub_FirstStackAdjust (SIZEOF__ArgumentRegisters + 2 * 8) // reg args , fp & lr already pushed +#define ComCallPreStub_StackAlloc0 (ComCallPreStub_FrameSize - ComCallPreStub_FirstStackAdjust) +#define ComCallPreStub_StackAlloc1 (ComCallPreStub_StackAlloc0 + SIZEOF__FloatArgumentRegisters + 8)// 8 for ErrorReturn +#define ComCallPreStub_StackAlloc (ComCallPreStub_StackAlloc1 + (ComCallPreStub_StackAlloc1 & 8)) + +#define ComCallPreStub_FrameOffset (ComCallPreStub_StackAlloc - (SIZEOF__ComMethodFrame - ComCallPreStub_FirstStackAdjust)) +#define ComCallPreStub_ErrorReturnOffset0 SIZEOF__FloatArgumentRegisters + +#define ComCallPreStub_FirstStackAdjust (ComCallPreStub_ErrorReturnOffset0 + (ComCallPreStub_ErrorReturnOffset0 & 8)) + +// ------------------------------------------------------------------ +// COM to CLR stub called the first time a particular method is invoked.// +// +// On entry: +// x12 : ComCallMethodDesc* provided by prepad thunk +// plus user arguments in registers and on the stack +// +// On exit: +// tail calls to real method +// +NESTED_ENTRY ComCallPreStub, _TEXT, NoHandler + + // Save arguments and return address + PROLOG_SAVE_REG_PAIR fp, lr, -ComCallPreStub_FirstStackAdjust! + PROLOG_STACK_ALLOC ComCallPreStub_StackAlloc + + SAVE_ARGUMENT_REGISTERS sp, (16+ComCallPreStub_StackAlloc) + + SAVE_FLOAT_ARGUMENT_REGISTERS sp, 0 + + str x12, [sp, #(ComCallPreStub_FrameOffset + UnmanagedToManagedFrame__m_pvDatum)] + add x0, sp, #(ComCallPreStub_FrameOffset) + add x1, sp, #(ComCallPreStub_ErrorReturnOffset) + bl ComPreStubWorker + + cbz x0, ComCallPreStub_ErrorExit + + mov x12, x0 + + // pop the stack and restore original register state + RESTORE_FLOAT_ARGUMENT_REGISTERS sp, 0 + RESTORE_ARGUMENT_REGISTERS sp, (16+ComCallPreStub_StackAlloc) + + EPILOG_STACK_FREE ComCallPreStub_StackAlloc + EPILOG_RESTORE_REG_PAIR fp, lr, ComCallPreStub_FirstStackAdjust! + + // and tailcall to the actual method + EPILOG_BRANCH_REG x12 + +ComCallPreStub_ErrorExit + ldr x0, [sp, #(ComCallPreStub_ErrorReturnOffset)] // ErrorReturn + + // pop the stack + EPILOG_STACK_FREE ComCallPreStub_StackAlloc + EPILOG_RESTORE_REG_PAIR fp, lr, ComCallPreStub_FirstStackAdjust! + + EPILOG_RETURN + +NESTED_END ComCallPreStub, _TEXT + +// ------------------------------------------------------------------ +// COM to CLR stub which sets up a ComMethodFrame and calls COMToCLRWorker. +// +// On entry: +// x12 : ComCallMethodDesc* provided by prepad thunk +// plus user arguments in registers and on the stack +// +// On exit: +// Result in x0/d0 as per the real method being called +// + NESTED_ENTRY GenericComCallStub, _TEXT, NoHandler + + // Save arguments and return address + PROLOG_SAVE_REG_PAIR fp, lr, -GenericComCallStub_FirstStackAdjust! + PROLOG_STACK_ALLOC GenericComCallStub_StackAlloc + + SAVE_ARGUMENT_REGISTERS sp, (16+GenericComCallStub_StackAlloc) + SAVE_FLOAT_ARGUMENT_REGISTERS sp, 0 + + str x12, [sp, #(GenericComCallStub_FrameOffset + UnmanagedToManagedFrame__m_pvDatum)] + add x1, sp, #GenericComCallStub_FrameOffset + bl COMToCLRWorker + + // pop the stack + EPILOG_STACK_FREE GenericComCallStub_StackAlloc + EPILOG_RESTORE_REG_PAIR fp, lr, GenericComCallStub_FirstStackAdjust! + + EPILOG_RETURN + + NESTED_END GenericComCallStub, _TEXT + +// ------------------------------------------------------------------ +// COM to CLR stub called from COMToCLRWorker that actually dispatches to the real managed method. +// +// On entry: +// x0 : dwStackSlots, count of argument stack slots to copy +// x1 : pFrame, ComMethodFrame pushed by GenericComCallStub above +// x2 : pTarget, address of code to call +// x3 : pSecretArg, hidden argument passed to target above in x12 +// x4 : pDangerousThis, managed 'this' reference +// +// On exit: +// Result in x0/d0 as per the real method being called +// + NESTED_ENTRY COMToCLRDispatchHelper, _TEXT,CallDescrWorkerUnwindFrameChainHandler + + PROLOG_SAVE_REG_PAIR fp, lr, -16! + + cbz x0, COMToCLRDispatchHelper_RegSetup + + add x9, x1, #SIZEOF__ComMethodFrame + add x9, x9, x0, LSL #3 +COMToCLRDispatchHelper_StackLoop + ldr x8, [x9, #-8]! + str x8, [sp, #-8]! + sub x0, x0, #1 + cbnz x0, COMToCLRDispatchHelper_StackLoop + +COMToCLRDispatchHelper_RegSetup + + RESTORE_FLOAT_ARGUMENT_REGISTERS x1, -1 * GenericComCallStub_FrameOffset + + mov lr, x2 + mov x12, x3 + + mov x0, x4 + + ldp x2, x3, [x1, #(SIZEOF__ComMethodFrame - SIZEOF__ArgumentRegisters + 16)] + ldp x4, x5, [x1, #(SIZEOF__ComMethodFrame - SIZEOF__ArgumentRegisters + 32)] + ldp x6, x7, [x1, #(SIZEOF__ComMethodFrame - SIZEOF__ArgumentRegisters + 48)] + ldr x8, [x1, #(SIZEOF__ComMethodFrame - SIZEOF__ArgumentRegisters + 64)] + + ldr x1, [x1, #(SIZEOF__ComMethodFrame - SIZEOF__ArgumentRegisters + 8)] + + blr lr + + EPILOG_STACK_RESTORE + EPILOG_RESTORE_REG_PAIR fp, lr, 16! + EPILOG_RETURN + + NESTED_END COMToCLRDispatchHelper, _TEXT + +#endif // FEATURE_COMINTEROP // // x12 = UMEntryThunk* // NESTED_ENTRY TheUMEntryPrestub, _TEXT, UnhandledExceptionHandlerUnix // Save arguments and return address - PROLOG_SAVE_REG_PAIR_INDEXED fp, lr, #-144 + PROLOG_SAVE_REG_PAIR_INDEXED fp, lr, -160 SAVE_ARGUMENT_REGISTERS sp, 16 - SAVE_FLOAT_ARGUMENT_REGISTERS sp, 80 + SAVE_FLOAT_ARGUMENT_REGISTERS sp, 88 mov x0, x12 bl C_FUNC(TheUMEntryPrestubWorker) @@ -443,8 +611,8 @@ NESTED_ENTRY TheUMEntryPrestub, _TEXT, UnhandledExceptionHandlerUnix // pop the stack and restore original register state RESTORE_ARGUMENT_REGISTERS sp, 16 - RESTORE_FLOAT_ARGUMENT_REGISTERS sp, 80 - EPILOG_RESTORE_REG_PAIR_INDEXED fp, lr, #144 + RESTORE_FLOAT_ARGUMENT_REGISTERS sp, 88 + EPILOG_RESTORE_REG_PAIR_INDEXED fp, lr, 160 // and tailcall to the actual method EPILOG_BRANCH_REG x12 @@ -457,14 +625,14 @@ NESTED_END TheUMEntryPrestub, _TEXT NESTED_ENTRY UMThunkStub, _TEXT, UnhandledExceptionHandlerUnix // Save arguments and return address - PROLOG_SAVE_REG_PAIR_INDEXED fp, lr, #-96 // 64 for regArgs, 8 for x19 & 8 for x12 + PROLOG_SAVE_REG_PAIR_INDEXED fp, lr, -112 // 72 for regArgs, 8 for x19 & 8 for x12 // save callee saved reg x19. x19 is used in the method to store thread* - PROLOG_SAVE_REG x19, #88 + PROLOG_SAVE_REG x19, 96 SAVE_ARGUMENT_REGISTERS sp, 16 -#define UMThunkStub_HiddenArg 80 // offset of saved UMEntryThunk * -#define UMThunkStub_StackArgs 96 // offset of original stack args (total size of UMThunkStub frame) +#define UMThunkStub_HiddenArg 88 // offset of saved UMEntryThunk * +#define UMThunkStub_StackArgs 112 // offset of original stack args (total size of UMThunkStub frame) // save UMEntryThunk* str x12, [sp, #UMThunkStub_HiddenArg] @@ -542,8 +710,8 @@ LOCAL_LABEL(UMThunkStub_PostCall): str w4, [x19, #Thread__m_fPreemptiveGCDisabled] EPILOG_STACK_RESTORE - EPILOG_RESTORE_REG x19, #88 - EPILOG_RESTORE_REG_PAIR_INDEXED fp, lr, #96 + EPILOG_RESTORE_REG x19, 96 + EPILOG_RESTORE_REG_PAIR_INDEXED fp, lr, 112 EPILOG_RETURN @@ -581,7 +749,7 @@ LOCAL_LABEL(UMThunkStub_WrongAppDomain): bl C_FUNC(UM2MDoADCallBack) // restore integral return value - ldr x0, [fp, #16] + ldp x0, x1, [fp, #16] // restore FP or HFA return value RESTORE_FLOAT_ARGUMENT_REGISTERS sp, 0 @@ -601,8 +769,8 @@ NESTED_END UMThunkStub, _TEXT NESTED_ENTRY UM2MThunk_WrapperHelper, _TEXT, NoHandler - PROLOG_SAVE_REG_PAIR_INDEXED fp, lr, #-32 - PROLOG_SAVE_REG x19, #16 + PROLOG_SAVE_REG_PAIR_INDEXED fp, lr, -32 + PROLOG_SAVE_REG x19, 16 // save pThunkArgs in non-volatile reg. It is required after return from call to ILStub @@ -659,13 +827,14 @@ LOCAL_LABEL(UM2MThunk_WrapperHelper_RegArgumentsSetup): blr x16 // save integral return value - str x0, [x19] + stp x0, x1, [x19] + // save FP/HFA return values SAVE_FLOAT_ARGUMENT_REGISTERS x19, -1 * (SIZEOF__FloatArgumentRegisters + 16) EPILOG_STACK_RESTORE - EPILOG_RESTORE_REG x19, #16 - EPILOG_RESTORE_REG_PAIR_INDEXED fp, lr, #32 + EPILOG_RESTORE_REG x19, 16 + EPILOG_RESTORE_REG_PAIR_INDEXED fp, lr, 32 EPILOG_RETURN NESTED_END UM2MThunk_WrapperHelper, _TEXT @@ -675,13 +844,13 @@ NESTED_END UM2MThunk_WrapperHelper, _TEXT // ------------------------------------------------------------------ // Hijack function for functions which return a scalar type or a struct (value type) NESTED_ENTRY OnHijackTripThread, _TEXT, NoHandler - PROLOG_SAVE_REG_PAIR fp, lr, #-144 - // Spill callee saved registers - PROLOG_SAVE_REG_PAIR x19, x20, #16 - PROLOG_SAVE_REG_PAIR x21, x22, #32 - PROLOG_SAVE_REG_PAIR x23, x24, #48 - PROLOG_SAVE_REG_PAIR x25, x26, #64 - PROLOG_SAVE_REG_PAIR x27, x28, #80 + PROLOG_SAVE_REG_PAIR_INDEXED fp, lr, -144 + // Spill callee saved registers + PROLOG_SAVE_REG_PAIR x19, x20, 16 + PROLOG_SAVE_REG_PAIR x21, x22, 32 + PROLOG_SAVE_REG_PAIR x23, x24, 48 + PROLOG_SAVE_REG_PAIR x25, x26, 64 + PROLOG_SAVE_REG_PAIR x27, x28, 80 // save any integral return value(s) stp x0, x1, [sp, #96] @@ -692,7 +861,7 @@ NESTED_ENTRY OnHijackTripThread, _TEXT, NoHandler mov x0, sp bl OnHijackWorker - + // restore any integral return value(s) ldp x0, x1, [sp, #96] @@ -700,12 +869,12 @@ NESTED_ENTRY OnHijackTripThread, _TEXT, NoHandler ldp d0, d1, [sp, #112] ldp d2, d3, [sp, #128] - EPILOG_RESTORE_REG_PAIR x19, x20, #16 - EPILOG_RESTORE_REG_PAIR x21, x22, #32 - EPILOG_RESTORE_REG_PAIR x23, x24, #48 - EPILOG_RESTORE_REG_PAIR x25, x26, #64 - EPILOG_RESTORE_REG_PAIR x27, x28, #80 - EPILOG_RESTORE_REG_PAIR fp, lr, #144 + EPILOG_RESTORE_REG_PAIR x19, x20, 16 + EPILOG_RESTORE_REG_PAIR x21, x22, 32 + EPILOG_RESTORE_REG_PAIR x23, x24, 48 + EPILOG_RESTORE_REG_PAIR x25, x26, 64 + EPILOG_RESTORE_REG_PAIR x27, x28, 80 + EPILOG_RESTORE_REG_PAIR_INDEXED fp, lr, 144 EPILOG_RETURN NESTED_END OnHijackTripThread, _TEXT @@ -732,16 +901,6 @@ GenerateRedirectedHandledJITCaseStub GCStress // This helper enables us to call into a funclet after restoring Fp register NESTED_ENTRY CallEHFunclet, _TEXT, NoHandler - - // Using below prolog instead of PROLOG_SAVE_REG_PAIR fp,lr, #-16 - // is intentional. Above statement would also emit instruction to save - // sp in fp. If sp is saved in fp in prolog then it is not expected that fp can change in the body - // of method. However, this method needs to be able to change fp before calling funclet. - // This is required to access locals in funclet. - PROLOG_SAVE_REG_PAIR_INDEXED x19,x20, #-16 - PROLOG_SAVE_REG fp, #0 - PROLOG_SAVE_REG lr, #8 - // On entry: // // X0 = throwable @@ -749,16 +908,36 @@ NESTED_ENTRY CallEHFunclet, _TEXT, NoHandler // X2 = address of X19 register in CONTEXT record// used to restore the non-volatile registers of CrawlFrame // X3 = address of the location where the SP of funclet's caller (i.e. this helper) should be saved. // - // Save the SP of this function - str fp, [x3] + PROLOG_SAVE_REG_PAIR_INDEXED fp, lr, -96 + // Spill callee saved registers + PROLOG_SAVE_REG_PAIR x19, x20, 16 + PROLOG_SAVE_REG_PAIR x21, x22, 32 + PROLOG_SAVE_REG_PAIR x23, x24, 48 + PROLOG_SAVE_REG_PAIR x25, x26, 64 + PROLOG_SAVE_REG_PAIR x27, x28, 80 + + // Save the SP of this function + mov x4, sp + str x4, [x3] + + ldp x19, x20, [x2, #0] + ldp x21, x22, [x2, #16] + ldp x23, x24, [x2, #32] + ldp x25, x26, [x2, #48] + ldp x27, x28, [x2, #64] ldr fp, [x2, #80] // offset of fp in CONTEXT relative to X19 // Invoke the funclet blr x1 nop - EPILOG_RESTORE_REG_PAIR_INDEXED fp, lr, #16 + EPILOG_RESTORE_REG_PAIR x19, x20, 16 + EPILOG_RESTORE_REG_PAIR x21, x22, 32 + EPILOG_RESTORE_REG_PAIR x23, x24, 48 + EPILOG_RESTORE_REG_PAIR x25, x26, 64 + EPILOG_RESTORE_REG_PAIR x27, x28, 80 + EPILOG_RESTORE_REG_PAIR_INDEXED fp, lr, 96 EPILOG_RETURN NESTED_END CallEHFunclet, _TEXT @@ -767,7 +946,7 @@ NESTED_END CallEHFunclet, _TEXT // frame pointer for accessing the locals in the parent method. NESTED_ENTRY CallEHFilterFunclet, _TEXT, NoHandler - PROLOG_SAVE_REG_PAIR_INDEXED fp, lr, #-16 + PROLOG_SAVE_REG_PAIR_INDEXED fp, lr, -16 // On entry: // @@ -781,7 +960,7 @@ NESTED_ENTRY CallEHFilterFunclet, _TEXT, NoHandler // Invoke the filter funclet blr x2 - EPILOG_RESTORE_REG_PAIR_INDEXED fp, lr, #16 + EPILOG_RESTORE_REG_PAIR_INDEXED fp, lr, 16 EPILOG_RETURN NESTED_END CallEHFilterFunclet, _TEXT @@ -800,7 +979,7 @@ NESTED_END CallEHFilterFunclet, _TEXT // IN: lr: original IP before redirect // - PROLOG_SAVE_REG_PAIR_INDEXED fp, lr, #-16 + PROLOG_SAVE_REG_PAIR_INDEXED fp, lr, -16 PROLOG_STACK_ALLOC FaultingExceptionFrame_StackAlloc // At this point, the stack maybe misaligned if the thread abort was asynchronously @@ -838,7 +1017,7 @@ NESTED_END CallEHFilterFunclet, _TEXT // NESTED_ENTRY NakedThrowHelper2, _TEXT ,FixContextHandler - PROLOG_SAVE_REG_PAIR_INDEXED fp,lr, #-16 + PROLOG_SAVE_REG_PAIR_INDEXED fp,lr, -16 // On entry: // @@ -850,32 +1029,147 @@ NESTED_ENTRY NakedThrowHelper2, _TEXT ,FixContextHandler NESTED_END NakedThrowHelper2, _TEXT + GenerateRedirectedStubWithFrame NakedThrowHelper, NakedThrowHelper2 +// ------------------------------------------------------------------ +// ResolveWorkerChainLookupAsmStub +// +// This method will perform a quick chained lookup of the entry if the +// initial cache lookup fails. +// +// On Entry: +// x9 contains the pointer to the current ResolveCacheElem +// x11 contains the address of the indirection (and the flags in the low two bits) +// x12 contains our contract the DispatchToken +// Must be preserved: +// x0 contains the instance object ref that we are making an interface call on +// x9 Must point to a ResolveCacheElem [For Sanity] +// [x1-x7] contains any additional register arguments for the interface method +// +// Loaded from x0 +// x13 contains our type the MethodTable (from object ref in x0) +// +// On Exit: +// x0, [x1-x7] arguments for the interface implementation target +// +// On Exit (to ResolveWorkerAsmStub): +// x11 contains the address of the indirection and the flags in the low two bits. +// x12 contains our contract (DispatchToken) +// x16,x17 will be trashed +// + +#define BACKPATCH_FLAG 1 +#define PROMOTE_CHAIN_FLAG 2 + +NESTED_ENTRY ResolveWorkerChainLookupAsmStub, _TEXT, NoHandler + + tst x11, #BACKPATCH_FLAG // First we check if x11 has the BACKPATCH_FLAG set + bne LOCAL_LABEL(Fail) // If the BACKPATCH_FLAGS is set we will go directly to the ResolveWorkerAsmStub + + ldr x13, [x0] // retrieve the MethodTable from the object ref in x0 +LOCAL_LABEL(MainLoop): + ldr x9, [x9, #ResolveCacheElem__pNext] // x9 <= the next entry in the chain + cmp x9, #0 + beq LOCAL_LABEL(Fail) + + ldp x16, x17, [x9] + cmp x16, x13 // compare our MT with the one in the ResolveCacheElem + bne LOCAL_LABEL(MainLoop) + + cmp x17, x12 // compare our DispatchToken with one in the ResolveCacheElem + bne LOCAL_LABEL(MainLoop) + +LOCAL_LABEL(Success): + PREPARE_EXTERNAL_VAR g_dispatch_cache_chain_success_counter, x13 + ldr x16, [x13] + subs x16, x16, #1 + str x16, [x13] + blt LOCAL_LABEL(Promote) + + ldr x16, [x9, #ResolveCacheElem__target] // get the ImplTarget + br x16 // branch to interface implemenation target + +LOCAL_LABEL(Promote): + // Move this entry to head postion of the chain + mov x16, #256 + str x16, [x13] // be quick to reset the counter so we don't get a bunch of contending threads + orr x11, x11, #PROMOTE_CHAIN_FLAG // set PROMOTE_CHAIN_FLAG + +LOCAL_LABEL(Fail): + b ResolveWorkerAsmStub // call the ResolveWorkerAsmStub method to transition into the VM + +NESTED_END ResolveWorkerChainLookupAsmStub, _TEXT + +// ------------------------------------------------------------------ +// void ResolveWorkerAsmStub(args in regs x0-x7 & stack and possibly retbuf arg in x8, x11:IndirectionCellAndFlags, x12:DispatchToken) +// +// The stub dispatch thunk which transfers control to VSD_ResolveWorker. +NESTED_ENTRY ResolveWorkerAsmStub, _TEXT, NoHandler + + PROLOG_WITH_TRANSITION_BLOCK + + add x0, sp, #__PWTB_TransitionBlock // pTransitionBlock + and x1, x11, #-4 // Indirection cell + mov x2, x12 // DispatchToken + and x3, x11, #3 // flag + bl VSD_ResolveWorker + mov x9, x0 + + EPILOG_WITH_TRANSITION_BLOCK_TAILCALL + + EPILOG_BRANCH_REG x9 + +NESTED_END ResolveWorkerAsmStub, _TEXT + #ifdef FEATURE_READYTORUN NESTED_ENTRY DelayLoad_MethodCall_FakeProlog, _TEXT, NoHandler DelayLoad_MethodCall: .global DelayLoad_MethodCall + PROLOG_WITH_TRANSITION_BLOCK + + add x0, sp, #__PWTB_TransitionBlock // pTransitionBlock + mov x1, x11 // Indirection cell + mov x2, x9 // sectionIndex + mov x3, x10 // Module* + bl ExternalMethodFixupWorker + mov x12, x0 + + EPILOG_WITH_TRANSITION_BLOCK_TAILCALL + // Share patch label + b ExternalMethodFixupPatchLabel - EMIT_BREAKPOINT NESTED_END DelayLoad_MethodCall_FakeProlog, _TEXT .macro DynamicHelper frameFlags, suffix - NESTED_ENTRY DelayLoad_Helper\suffix\()_FakeProlog, _TEXT, NoHandler +NESTED_ENTRY DelayLoad_Helper\suffix\()_FakeProlog, _TEXT, NoHandler DelayLoad_Helper\suffix: - .global DelayLoad_Helper\suffix + .global DelayLoad_Helper\suffix - EMIT_BREAKPOINT + PROLOG_WITH_TRANSITION_BLOCK + + add x0, sp, #__PWTB_TransitionBlock // pTransitionBlock + mov x1, x11 // Indirection cell + mov x2, x9 // sectionIndex + mov x3, x10 // Module* + mov x4, \frameFlags + bl DynamicHelperWorker + cbnz x0, LOCAL_LABEL(FakeProlog\suffix\()_0) + ldr x0, [sp, #__PWTB_ArgumentRegisters] + EPILOG_WITH_TRANSITION_BLOCK_RETURN +LOCAL_LABEL(FakeProlog\suffix\()_0): + mov x12, x0 + EPILOG_WITH_TRANSITION_BLOCK_TAILCALL + EPILOG_BRANCH_REG x12 - NESTED_END DelayLoad_Helper\suffix\()_FakeProlog, _TEXT +NESTED_END DelayLoad_Helper\suffix\()_FakeProlog, _TEXT .endm DynamicHelper DynamicHelperFrameFlags_Default DynamicHelper DynamicHelperFrameFlags_ObjectArg, _Obj DynamicHelper DynamicHelperFrameFlags_ObjectArg | DynamicHelperFrameFlags_ObjectArg2, _ObjObj - #endif #ifdef FEATURE_PREJIT @@ -891,7 +1185,7 @@ NESTED_ENTRY StubDispatchFixupStub, _TEXT, NoHandler and x1, x11, #-4 // Indirection cell mov x2, #0 // sectionIndex mov x3, #0 // pModule - bl StubDispatchFixupWorker + bl C_FUNC(StubDispatchFixupWorker) mov x9, x0 EPILOG_WITH_TRANSITION_BLOCK_TAILCALL @@ -900,3 +1194,36 @@ NESTED_ENTRY StubDispatchFixupStub, _TEXT, NoHandler NESTED_END StubDispatchFixupStub, _TEXT #endif + +#ifdef FEATURE_COMINTEROP + +// Function used by COM interop to get floating point return value (since it's not in the same +// register(s) as non-floating point values). +// +// On entry// +// x0 : size of the FP result (4 or 8 bytes) +// x1 : pointer to 64-bit buffer to receive result +// +// On exit: +// buffer pointed to by x1 on entry contains the float or double argument as appropriate +// + LEAF_ENTRY getFPReturn + str d0, [x1] + LEAF_END + +// ------------------------------------------------------------------ +// Function used by COM interop to set floating point return value (since it's not in the same +// register(s) as non-floating point values). +// +// On entry: +// x0 : size of the FP result (4 or 8 bytes) +// x1 : 32-bit or 64-bit FP result +// +// On exit: +// s0 : float result if x0 == 4 +// d0 : double result if x0 == 8 +// + LEAF_ENTRY setFPReturn + fmov d0, x1 + LEAF_END +#endif diff --git a/src/coreclr/src/vm/arm64/asmhelpers.asm b/src/coreclr/src/vm/arm64/asmhelpers.asm index 2fc6a6a0..d760765 100644 --- a/src/coreclr/src/vm/arm64/asmhelpers.asm +++ b/src/coreclr/src/vm/arm64/asmhelpers.asm @@ -1311,4 +1311,4 @@ Fail #endif ; Must be at very end of file - END \ No newline at end of file + END diff --git a/src/coreclr/src/vm/arm64/calldescrworkerarm64.S b/src/coreclr/src/vm/arm64/calldescrworkerarm64.S index 803b949..2210d70 100644 --- a/src/coreclr/src/vm/arm64/calldescrworkerarm64.S +++ b/src/coreclr/src/vm/arm64/calldescrworkerarm64.S @@ -11,9 +11,10 @@ //----------------------------------------------------------------------------- //void CallDescrWorkerInternal(CallDescrData * pCallDescrData); -NESTED_ENTRY CallDescrWorkerInternal, _TEXT, UnhandledExceptionHandlerUnix - PROLOG_SAVE_REG_PAIR_INDEXED fp, lr, #-32 - PROLOG_SAVE_REG x19, #16 //the stack slot at sp+24 is empty for 16 byte alligment +NESTED_ENTRY CallDescrWorkerInternal, _TEXT, NoHandler + PROLOG_SAVE_REG_PAIR_INDEXED fp, lr, -32 + PROLOG_SAVE_REG x19, 16 + PROLOG_SAVE_REG x0, 24 mov x19, x0 // save pCallDescrData in x19 @@ -44,29 +45,31 @@ LOCAL_LABEL(stackloop): bne LOCAL_LABEL(stackloop) LOCAL_LABEL(donestack): - // If FP arguments are supplied in registers (x8 != NULL) then initialize all of them from the pointer + // If FP arguments are supplied in registers (x9 != NULL) then initialize all of them from the pointer // given in x8. - ldr x8, [x19,#CallDescrData__pFloatArgumentRegisters] - cbz x8, LOCAL_LABEL(NoFloatingPoint) - ldp d0, d1, [x8] - ldp d2, d3, [x8, #16] - ldp d4, d5, [x8, #32] - ldp d6, d7, [x8, #48] + ldr x9, [x19,#CallDescrData__pFloatArgumentRegisters] + cbz x9, LOCAL_LABEL(NoFloatingPoint) + ldp d0, d1, [x9] + ldp d2, d3, [x9, #16] + ldp d4, d5, [x9, #32] + ldp d6, d7, [x9, #48] LOCAL_LABEL(NoFloatingPoint): // Copy [pArgumentRegisters, ..., pArgumentRegisters + 56] // into x0, ..., x7 - ldr x8, [x19,#CallDescrData__pArgumentRegisters] - ldp x0, x1, [x8] - ldp x2, x3, [x8, #16] - ldp x4, x5, [x8, #32] - ldp x6, x7, [x8, #48] + ldr x9, [x19,#CallDescrData__pArgumentRegisters] + ldp x0, x1, [x9] + ldp x2, x3, [x9, #16] + ldp x4, x5, [x9, #32] + ldp x6, x7, [x9, #48] + ldr x8, [x9, #64] - // ARM64TODO: => see if anything special needs to be done for remoting // call pTarget - ldr x8, [x19,#CallDescrData__pTarget] - blr x8 + ldr x9, [x19,#CallDescrData__pTarget] + blr x9 + + ldr x19, [fp, 24] // Fixup corrupted X19 caller preserved register ldr w3, [x19,#CallDescrData__fpReturnSize] @@ -110,7 +113,7 @@ LOCAL_LABEL(NoDoubleHFAReturn): LOCAL_LABEL(IntReturn): // Save return value into retbuf for int - str x0, [x19, #(CallDescrData__returnValue + 0)] + stp x0, x1, [x19, #(CallDescrData__returnValue + 0)] LOCAL_LABEL(ReturnDone): @@ -122,7 +125,7 @@ LOCAL_LABEL(ReturnDone): #endif EPILOG_STACK_RESTORE - EPILOG_RESTORE_REG x19, #16 //the stack slot at sp+24 is empty for 16 byte alligment - EPILOG_RESTORE_REG_PAIR_INDEXED fp, lr, #32 + EPILOG_RESTORE_REG x19, 16 //the stack slot at sp+24 is empty for 16 byte alligment + EPILOG_RESTORE_REG_PAIR_INDEXED fp, lr, 32 EPILOG_RETURN NESTED_END CallDescrWorkerInternal, _TEXT diff --git a/src/coreclr/src/vm/arm64/cgencpu.h b/src/coreclr/src/vm/arm64/cgencpu.h index be3e34d..a176028 100644 --- a/src/coreclr/src/vm/arm64/cgencpu.h +++ b/src/coreclr/src/vm/arm64/cgencpu.h @@ -14,7 +14,9 @@ #define INSTRFMT_K64 #include +#ifndef FEATURE_PAL #define USE_REDIRECT_FOR_GCSTRESS +#endif // FEATURE_PAL EXTERN_C void getFPReturn(int fpSize, INT64 *pRetVal); EXTERN_C void setFPReturn(int fpSize, INT64 retVal); diff --git a/src/coreclr/src/vm/arm64/gmscpu.h b/src/coreclr/src/vm/arm64/gmscpu.h index e95ef63..7785daf 100644 --- a/src/coreclr/src/vm/arm64/gmscpu.h +++ b/src/coreclr/src/vm/arm64/gmscpu.h @@ -56,25 +56,34 @@ inline void LazyMachState::setLazyStateFromUnwind(MachState* copy) _sp = copy->_sp; _pc = copy->_pc; - // Now copy the preserved register pointers. Note that some of the pointers could be - // pointing to copy->captureX19_X29[]. If that is case then while copying to destination - // ensure that they point to corresponding element in captureX19_X29[] of destination. - ULONG64* srcLowerBound = ©->captureX19_X29[0]; - ULONG64* srcUpperBound = (ULONG64*)((BYTE*)copy + offsetof(MachState, ptrX19_X29)); + // Capture* has already been set, so there is no need to touch it + // loop over the nonvolatile context pointers and make + // sure to properly copy interior pointers into the + // new struct - for (int i = 0; iptrX19_X29; + PULONG64* pDst = (PULONG64 *)&this->ptrX19_X29; + + const PULONG64 LowerBoundDst = (PULONG64) this; + const PULONG64 LowerBoundSrc = (PULONG64) copy; + + const PULONG64 UpperBoundSrc = (PULONG64) ((BYTE*)LowerBoundSrc + sizeof(*copy)); + + for (int i = 0; i < NUM_NONVOLATILE_CONTEXT_POINTERS; i++) { - if (copy->ptrX19_X29[i] >= srcLowerBound && copy->ptrX19_X29[i] < srcUpperBound) - { - ptrX19_X29[i] = (PTR_ULONG64)((BYTE*)copy->ptrX19_X29[i] - (BYTE*)srcLowerBound + (BYTE*)captureX19_X29); - } - else + PULONG64 valueSrc = *pSrc++; + + if ((LowerBoundSrc <= valueSrc) && (valueSrc < UpperBoundSrc)) { - ptrX19_X29[i] = copy->ptrX19_X29[i]; + // make any pointer interior to 'src' interior to 'dst' + valueSrc = (PULONG64)((BYTE*)valueSrc - (BYTE*)LowerBoundSrc + (BYTE*)LowerBoundDst); } + + *pDst++ = valueSrc; } + // this has to be last because we depend on write ordering to // synchronize the race implicit in updating this struct VolatileStore(&_isValid, TRUE); diff --git a/src/coreclr/src/vm/arm64/pinvokestubs.S b/src/coreclr/src/vm/arm64/pinvokestubs.S index f6c33ba..c87e800 100644 --- a/src/coreclr/src/vm/arm64/pinvokestubs.S +++ b/src/coreclr/src/vm/arm64/pinvokestubs.S @@ -21,44 +21,28 @@ // $VASigCookieReg : register which contains the VASigCookie // $SaveFPArgs : "Yes" or "No" . For varidic functions FP Args are not present in FP regs // So need not save FP Args registers for vararg Pinvoke -.macro PINVOKE_STUB FuncPrefix,VASigCookieReg,HiddenArg,SaveFPArgs +.macro PINVOKE_STUB __PInvokeStubFuncName,__PInvokeGenStubFuncName,__PInvokeStubWorkerName,VASigCookieReg,HiddenArg,SaveFPArgs -#if NOTYET - GBLS __PInvokeStubFuncName - GBLS __PInvokeGenStubFuncName - GBLS __PInvokeStubWorkerName - IF "\FuncPrefix" == "GenericPInvokeCalli" -__PInvokeStubFuncName SETS "\FuncPrefix":CC:"Helper" - ELSE -__PInvokeStubFuncName SETS "\FuncPrefix":CC:"Stub" - ENDIF -__PInvokeGenStubFuncName SETS "\FuncPrefix":CC:"GenILStub" -__PInvokeStubWorkerName SETS "\FuncPrefix":CC:"StubWorker" - - IF "\VASigCookieReg" == "x1" -__PInvokeStubFuncName SETS "\__PInvokeStubFuncName":CC:"_RetBuffArg" -__PInvokeGenStubFuncName SETS "\__PInvokeGenStubFuncName":CC:"_RetBuffArg" - ENDIF - - NESTED_ENTRY \__PInvokeStubFuncName + NESTED_ENTRY \__PInvokeStubFuncName, _TEXT, NoHandler // get the stub ldr x9, [\VASigCookieReg, #VASigCookie__pNDirectILStub] // if null goto stub generation - cbz x9, %0 + cbz x9, LOCAL_LABEL(\__PInvokeStubFuncName\()_0) EPILOG_BRANCH_REG x9 -0 +LOCAL_LABEL(\__PInvokeStubFuncName\()_0): + EPILOG_BRANCH \__PInvokeGenStubFuncName - NESTED_END + NESTED_END \__PInvokeStubFuncName, _TEXT - NESTED_ENTRY \__PInvokeGenStubFuncName + NESTED_ENTRY \__PInvokeGenStubFuncName, _TEXT, NoHandler PROLOG_WITH_TRANSITION_BLOCK 0, \SaveFPArgs @@ -66,9 +50,9 @@ __PInvokeGenStubFuncName SETS "\__PInvokeGenStubFuncName":CC:"_RetBuffArg" mov x2, \HiddenArg // x1 = VaSigCookie - IF "\VASigCookieReg" != "x1" + .ifnc \VASigCookieReg, x1 mov x1, \VASigCookieReg - ENDIF + .endif // x0 = pTransitionBlock add x0, sp, #__PWTB_TransitionBlock @@ -86,10 +70,7 @@ __PInvokeGenStubFuncName SETS "\__PInvokeGenStubFuncName":CC:"_RetBuffArg" EPILOG_BRANCH \__PInvokeStubFuncName - NESTED_END -#else - EMIT_BREAKPOINT -#endif + NESTED_END \__PInvokeGenStubFuncName, _TEXT .endm // ------------------------------------------------------------------ @@ -100,7 +81,7 @@ __PInvokeGenStubFuncName SETS "\__PInvokeGenStubFuncName":CC:"_RetBuffArg" // x0 = VASigCookie* // x12 = MethodDesc * // -PINVOKE_STUB VarargPInvoke, x0, x12, 1 +PINVOKE_STUB VarargPInvokeStub, VarargPInvokeGenILStub, VarargPInvokeStubWorker, x0, x12, 0 // ------------------------------------------------------------------ @@ -111,7 +92,7 @@ PINVOKE_STUB VarargPInvoke, x0, x12, 1 // x15 = VASigCookie* // x14 = Unmanaged target // -PINVOKE_STUB GenericPInvokeCalli, x15, x14, 1 +PINVOKE_STUB GenericPInvokeCalliHelper, GenericPInvokeCalliGenILStub, GenericPInvokeCalliStubWorker, x15, x14, 1 // ------------------------------------------------------------------ // VarargPInvokeStub_RetBuffArg & VarargPInvokeGenILStub_RetBuffArg @@ -121,4 +102,4 @@ PINVOKE_STUB GenericPInvokeCalli, x15, x14, 1 // x1 = VASigCookie* // x12 = MethodDesc* // -PINVOKE_STUB VarargPInvoke, x1, x12, 0 +PINVOKE_STUB VarargPInvokeStub_RetBuffArg, VarargPInvokeGenILStub_RetBuffArg, VarargPInvokeStubWorker, x1, x12, 0 diff --git a/src/coreclr/src/vm/arm64/stubs.cpp b/src/coreclr/src/vm/arm64/stubs.cpp index e526d9e..f56f6ab 100644 --- a/src/coreclr/src/vm/arm64/stubs.cpp +++ b/src/coreclr/src/vm/arm64/stubs.cpp @@ -268,6 +268,12 @@ static BYTE gLoadFromLabelIF[sizeof(LoadFromLabelInstructionFormat)]; #endif +void ClearRegDisplayArgumentAndScratchRegisters(REGDISPLAY * pRD) +{ + for (int i=0; i < 18; i++) + pRD->volatileCurrContextPointers.X[i] = NULL; +} + #ifndef CROSSGEN_COMPILE void LazyMachState::unwindLazyState(LazyMachState* baseState, MachState* unwoundstate, @@ -371,6 +377,20 @@ void LazyMachState::unwindLazyState(LazyMachState* baseState, } } while (true); +#ifdef FEATURE_PAL + unwoundstate->captureX19_X29[0] = context.X19; + unwoundstate->captureX19_X29[1] = context.X20; + unwoundstate->captureX19_X29[2] = context.X21; + unwoundstate->captureX19_X29[3] = context.X22; + unwoundstate->captureX19_X29[4] = context.X23; + unwoundstate->captureX19_X29[5] = context.X24; + unwoundstate->captureX19_X29[6] = context.X25; + unwoundstate->captureX19_X29[7] = context.X26; + unwoundstate->captureX19_X29[8] = context.X27; + unwoundstate->captureX19_X29[9] = context.X28; + unwoundstate->captureX19_X29[10] = context.Fp; +#endif + #ifdef DACCESS_COMPILE // For DAC builds, we update the registers directly since we dont have context pointers unwoundstate->captureX19_X29[0] = context.X19; @@ -450,6 +470,20 @@ void HelperMethodFrame::UpdateRegDisplay(const PREGDISPLAY pRD) pRD->pCurrentContext->X28 = (DWORD64)(pUnwoundState->captureX19_X29[9]); pRD->pCurrentContext->Fp = (DWORD64)(pUnwoundState->captureX19_X29[10]); pRD->pCurrentContext->Lr = NULL; // Unwind again to get Caller's PC + + pRD->pCurrentContextPointers->X19 = pUnwoundState->ptrX19_X29[0]; + pRD->pCurrentContextPointers->X20 = pUnwoundState->ptrX19_X29[1]; + pRD->pCurrentContextPointers->X21 = pUnwoundState->ptrX19_X29[2]; + pRD->pCurrentContextPointers->X22 = pUnwoundState->ptrX19_X29[3]; + pRD->pCurrentContextPointers->X23 = pUnwoundState->ptrX19_X29[4]; + pRD->pCurrentContextPointers->X24 = pUnwoundState->ptrX19_X29[5]; + pRD->pCurrentContextPointers->X25 = pUnwoundState->ptrX19_X29[6]; + pRD->pCurrentContextPointers->X26 = pUnwoundState->ptrX19_X29[7]; + pRD->pCurrentContextPointers->X27 = pUnwoundState->ptrX19_X29[8]; + pRD->pCurrentContextPointers->X28 = pUnwoundState->ptrX19_X29[9]; + pRD->pCurrentContextPointers->Fp = pUnwoundState->ptrX19_X29[10]; + pRD->pCurrentContextPointers->Lr = NULL; + return; } #endif // DACCESS_COMPILE @@ -462,6 +496,20 @@ void HelperMethodFrame::UpdateRegDisplay(const PREGDISPLAY pRD) pRD->pCurrentContext->Pc = pRD->ControlPC; pRD->pCurrentContext->Sp = pRD->SP; +#ifdef FEATURE_PAL + pRD->pCurrentContext->X19 = m_MachState.ptrX19_X29[0] ? *m_MachState.ptrX19_X29[0] : m_MachState.captureX19_X29[0]; + pRD->pCurrentContext->X20 = m_MachState.ptrX19_X29[1] ? *m_MachState.ptrX19_X29[1] : m_MachState.captureX19_X29[1]; + pRD->pCurrentContext->X21 = m_MachState.ptrX19_X29[2] ? *m_MachState.ptrX19_X29[2] : m_MachState.captureX19_X29[2]; + pRD->pCurrentContext->X22 = m_MachState.ptrX19_X29[3] ? *m_MachState.ptrX19_X29[3] : m_MachState.captureX19_X29[3]; + pRD->pCurrentContext->X23 = m_MachState.ptrX19_X29[4] ? *m_MachState.ptrX19_X29[4] : m_MachState.captureX19_X29[4]; + pRD->pCurrentContext->X24 = m_MachState.ptrX19_X29[5] ? *m_MachState.ptrX19_X29[5] : m_MachState.captureX19_X29[5]; + pRD->pCurrentContext->X25 = m_MachState.ptrX19_X29[6] ? *m_MachState.ptrX19_X29[6] : m_MachState.captureX19_X29[6]; + pRD->pCurrentContext->X26 = m_MachState.ptrX19_X29[7] ? *m_MachState.ptrX19_X29[7] : m_MachState.captureX19_X29[7]; + pRD->pCurrentContext->X27 = m_MachState.ptrX19_X29[8] ? *m_MachState.ptrX19_X29[8] : m_MachState.captureX19_X29[8]; + pRD->pCurrentContext->X28 = m_MachState.ptrX19_X29[9] ? *m_MachState.ptrX19_X29[9] : m_MachState.captureX19_X29[9]; + pRD->pCurrentContext->Fp = m_MachState.ptrX19_X29[10] ? *m_MachState.ptrX19_X29[10] : m_MachState.captureX19_X29[10]; + pRD->pCurrentContext->Lr = NULL; // Unwind again to get Caller's PC +#else // FEATURE_PAL pRD->pCurrentContext->X19 = *m_MachState.ptrX19_X29[0]; pRD->pCurrentContext->X20 = *m_MachState.ptrX19_X29[1]; pRD->pCurrentContext->X21 = *m_MachState.ptrX19_X29[2]; @@ -474,6 +522,7 @@ void HelperMethodFrame::UpdateRegDisplay(const PREGDISPLAY pRD) pRD->pCurrentContext->X28 = *m_MachState.ptrX19_X29[9]; pRD->pCurrentContext->Fp = *m_MachState.ptrX19_X29[10]; pRD->pCurrentContext->Lr = NULL; // Unwind again to get Caller's PC +#endif #if !defined(DACCESS_COMPILE) pRD->pCurrentContextPointers->X19 = m_MachState.ptrX19_X29[0]; @@ -489,6 +538,8 @@ void HelperMethodFrame::UpdateRegDisplay(const PREGDISPLAY pRD) pRD->pCurrentContextPointers->Fp = m_MachState.ptrX19_X29[10]; pRD->pCurrentContextPointers->Lr = NULL; // Unwind again to get Caller's PC #endif + + ClearRegDisplayArgumentAndScratchRegisters(pRD); } #endif // CROSSGEN_COMPILE @@ -759,23 +810,15 @@ void UpdateRegDisplayFromCalleeSavedRegisters(REGDISPLAY * pRD, CalleeSavedRegis void TransitionFrame::UpdateRegDisplay(const PREGDISPLAY pRD) { - pRD->IsCallerContextValid = FALSE; pRD->IsCallerSPValid = FALSE; // Don't add usage of this field. This is only temporary. - // copy the argumetn registers - ArgumentRegisters *pArgRegs = GetArgumentRegisters(); - for (int i = 0; i < ARGUMENTREGISTERS_SIZE; i++) -#ifdef __clang__ - *(&pRD->pCurrentContext->X0 + (sizeof(void*)*i)) = pArgRegs->x[i]; -#else - pRD->pCurrentContext->X[i] = pArgRegs->x[i]; -#endif - // copy the callee saved regs CalleeSavedRegisters *pCalleeSaved = GetCalleeSavedRegisters(); UpdateRegDisplayFromCalleeSavedRegisters(pRD, pCalleeSaved); + ClearRegDisplayArgumentAndScratchRegisters(pRD); + // copy the control registers pRD->pCurrentContext->Fp = pCalleeSaved->x29; pRD->pCurrentContext->Lr = pCalleeSaved->x30; @@ -788,6 +831,7 @@ void TransitionFrame::UpdateRegDisplay(const PREGDISPLAY pRD) LOG((LF_GCROOTS, LL_INFO100000, "STACKWALK TransitionFrame::UpdateRegDisplay(pc:%p, sp:%p)\n", pRD->ControlPC, pRD->SP)); } + #endif #ifndef CROSSGEN_COMPILE @@ -832,6 +876,8 @@ void FaultingExceptionFrame::UpdateRegDisplay(const PREGDISPLAY pRD) pRD->pCurrentContextPointers->Fp = (PDWORD64)&m_ctx.Fp; pRD->pCurrentContextPointers->Lr = (PDWORD64)&m_ctx.Lr; + ClearRegDisplayArgumentAndScratchRegisters(pRD); + pRD->IsCallerContextValid = FALSE; pRD->IsCallerSPValid = FALSE; // Don't add usage of this field. This is only temporary. @@ -859,20 +905,34 @@ void InlinedCallFrame::UpdateRegDisplay(const PREGDISPLAY pRD) return; } - // reset pContext; it's only valid for active (top-most) frame - pRD->pContext = NULL; + pRD->IsCallerContextValid = FALSE; + pRD->IsCallerSPValid = FALSE; + + pRD->pCurrentContext->Pc = *(DWORD64 *)&m_pCallerReturnAddress; + pRD->pCurrentContext->Sp = *(DWORD64 *)&m_pCallSiteSP; + pRD->pCurrentContext->Fp = *(DWORD64 *)&m_pCalleeSavedFP; + + pRD->pCurrentContextPointers->X19 = NULL; + pRD->pCurrentContextPointers->X20 = NULL; + pRD->pCurrentContextPointers->X21 = NULL; + pRD->pCurrentContextPointers->X22 = NULL; + pRD->pCurrentContextPointers->X23 = NULL; + pRD->pCurrentContextPointers->X24 = NULL; + pRD->pCurrentContextPointers->X25 = NULL; + pRD->pCurrentContextPointers->X26 = NULL; + pRD->pCurrentContextPointers->X27 = NULL; + pRD->pCurrentContextPointers->X28 = NULL; pRD->ControlPC = m_pCallerReturnAddress; pRD->SP = (DWORD) dac_cast(m_pCallSiteSP); - pRD->IsCallerContextValid = FALSE; - pRD->IsCallerSPValid = FALSE; + // reset pContext; it's only valid for active (top-most) frame + pRD->pContext = NULL; + + ClearRegDisplayArgumentAndScratchRegisters(pRD); - pRD->pCurrentContext->Pc = m_pCallerReturnAddress; - pRD->pCurrentContext->Sp = pRD->SP; // Update the frame pointer in the current context. - pRD->pCurrentContext->Fp = m_pCalleeSavedFP; pRD->pCurrentContextPointers->Fp = &m_pCalleeSavedFP; LOG((LF_GCROOTS, LL_INFO100000, "STACKWALK InlinedCallFrame::UpdateRegDisplay(pc:%p, sp:%p)\n", pRD->ControlPC, pRD->SP)); diff --git a/src/coreclr/src/vm/exceptionhandling.cpp b/src/coreclr/src/vm/exceptionhandling.cpp index 05500d4..20929bc 100644 --- a/src/coreclr/src/vm/exceptionhandling.cpp +++ b/src/coreclr/src/vm/exceptionhandling.cpp @@ -448,14 +448,7 @@ void ExceptionTracker::UpdateNonvolatileRegisters(CONTEXT *pContextRecord, REGDI UPDATEREG(X26); UPDATEREG(X27); UPDATEREG(X28); - // Obtain value of Fp from CurrentContext instead of from CurrentContextPointers - // It should not matter. CurrentContextPointers does not have value of FP as this will - // require changes in MachState to also store pointer of FP which it does not do currently. - pContextRecord->Fp = pRegDisplay->pCurrentContext->Fp; - if (pAbortContext) - { - pAbortContext->Fp = pContextRecord->Fp; - } + UPDATEREG(Fp); #else PORTABILITY_ASSERT("ExceptionTracker::UpdateNonvolatileRegisters");