;; ;; 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 AsmOffsets.inc ; generated by the build from AsmOffsets.cpp ;; ;; MACROS ;; ; ; Define macros to build unwind data for prologues. ; push_nonvol_reg macro Reg .errnz ___STACK_ADJUSTMENT_FORBIDDEN, push Reg .pushreg Reg endm push_vol_reg macro Reg .errnz ___STACK_ADJUSTMENT_FORBIDDEN, push_vol_reg cannot be used after save_reg_postrsp push Reg .allocstack 8 endm push_imm macro imm .errnz ___STACK_ADJUSTMENT_FORBIDDEN, push_vol_reg cannot be used after save_reg_postrsp push imm .allocstack 8 endm push_eflags macro .errnz ___STACK_ADJUSTMENT_FORBIDDEN, push_eflags cannot be used after save_reg_postrsp pushfq .allocstack 8 endm alloc_stack macro Size .errnz ___STACK_ADJUSTMENT_FORBIDDEN, alloc_stack cannot be used after save_reg_postrsp sub rsp, Size .allocstack Size endm save_reg_frame macro Reg, FrameReg, Offset .erre ___FRAME_REG_SET, save_reg_frame cannot be used before set_frame mov Offset[FrameReg], Reg .savereg Reg, Offset endm save_reg_postrsp macro Reg, Offset .errnz ___FRAME_REG_SET, save_reg_postrsp cannot be used after set_frame mov Offset[rsp], Reg .savereg Reg, Offset ___STACK_ADJUSTMENT_FORBIDDEN = 1 endm save_xmm128_frame macro Reg, FrameReg, Offset .erre ___FRAME_REG_SET, save_xmm128_frame cannot be used before set_frame movdqa Offset[FrameReg], Reg .savexmm128 Reg, Offset endm save_xmm128_postrsp macro Reg, Offset .errnz ___FRAME_REG_SET, save_reg_postrsp cannot be used after set_frame movdqa Offset[rsp], Reg .savexmm128 Reg, Offset ___STACK_ADJUSTMENT_FORBIDDEN = 1 endm set_frame macro Reg, Offset .errnz ___FRAME_REG_SET, set_frame cannot be used more than once if Offset lea Reg, Offset[rsp] else mov reg, rsp endif .setframe Reg, Offset ___FRAME_REG_SET = 1 endm END_PROLOGUE macro .endprolog endm ; ; Define function entry/end macros. ; LEAF_ENTRY macro Name, Section Section segment para 'CODE' align 16 public Name Name proc endm LEAF_END macro Name, section Name endp Section ends endm LEAF_END_MARKED macro Name, section public Name&_End Name&_End label qword ; this nop is important to keep the label in ; the right place in the face of BBT nop Name endp Section ends endm NESTED_ENTRY macro Name, Section, Handler Section segment para 'CODE' align 16 public Name ifb Name proc frame else Name proc frame:Handler endif ___FRAME_REG_SET = 0 ___STACK_ADJUSTMENT_FORBIDDEN = 0 endm NESTED_END macro Name, section Name endp Section ends endm NESTED_END_MARKED macro Name, section public Name&_End Name&_End label qword Name endp Section ends endm ALTERNATE_ENTRY macro Name Name label proc PUBLIC Name endm LABELED_RETURN_ADDRESS macro Name Name label proc PUBLIC Name endm EXPORT_POINTER_TO_ADDRESS macro Name local AddressToExport AddressToExport label proc .const align 8 Name dq offset AddressToExport public Name .code endm _tls_array equ 58h ;; offsetof(TEB, ThreadLocalStoragePointer) ;; ;; __declspec(thread) version ;; INLINE_GETTHREAD macro destReg, trashReg EXTERN _tls_index : DWORD EXTERN tls_CurrentThread:DWORD ;; ;; construct 'eax' from 'rax' so that the register size and data size match ;; ;; BEWARE: currently only r10 is allowed as destReg from the r8-r15 set. ;; ifidni , destRegDWORD EQU r10d else destRegDWORD TEXTEQU @CatStr( e, @SubStr( destReg, 2, 2 ) ) endif mov destRegDWORD, [_tls_index] mov trashReg, gs:[_tls_array] mov trashReg, [trashReg + destReg * 8] mov destRegDWORD, SECTIONREL tls_CurrentThread add destReg, trashReg endm INLINE_THREAD_UNHIJACK macro threadReg, trashReg1, trashReg2 ;; ;; Thread::Unhijack() ;; mov trashReg1, [threadReg + OFFSETOF__Thread__m_pvHijackedReturnAddress] cmp trashReg1, 0 je @F mov trashReg2, [threadReg + OFFSETOF__Thread__m_ppvHijackedReturnAddressLocation] mov [trashReg2], trashReg1 mov qword ptr [threadReg + OFFSETOF__Thread__m_ppvHijackedReturnAddressLocation], 0 mov qword ptr [threadReg + OFFSETOF__Thread__m_pvHijackedReturnAddress], 0 @@: endm DEFAULT_FRAME_SAVE_FLAGS equ PTFF_SAVE_ALL_PRESERVED + PTFF_SAVE_RSP ;; ;; Macro used from unmanaged helpers called from managed code where the helper does not transition immediately ;; into pre-emptive mode but may cause a GC and thus requires the stack is crawlable. This is typically the ;; case for helpers that meddle in GC state (e.g. allocation helpers) where the code must remain in ;; cooperative mode since it handles object references and internal GC state directly but a garbage collection ;; may be inevitable. In these cases we need to be able to transition to pre-meptive mode deep within the ;; unmanaged code but still be able to initialize the stack iterator at the first stack frame which may hold ;; interesting GC references. In all our helper cases this corresponds to the most recent managed frame (e.g. ;; the helper's caller). ;; ;; This macro builds a frame describing the current state of managed code. ;; ;; INVARIANTS ;; - The macro assumes it is called from a prolog, prior to a frame pointer being setup. ;; - All preserved registers remain unchanged from their values in managed code. ;; PUSH_COOP_PINVOKE_FRAME macro trashReg lea trashReg, [rsp + 8h] push_vol_reg trashReg ; save caller's RSP push_nonvol_reg r15 ; save preserved registers push_nonvol_reg r14 ; .. push_nonvol_reg r13 ; .. push_nonvol_reg r12 ; .. push_nonvol_reg rdi ; .. push_nonvol_reg rsi ; .. push_nonvol_reg rbx ; .. push_imm DEFAULT_FRAME_SAVE_FLAGS ; save the register bitmask push_vol_reg trashReg ; Thread * (unused by stackwalker) push_nonvol_reg rbp ; save caller's RBP mov trashReg, [rsp + 11*8] ; Find the return address push_vol_reg trashReg ; save m_RIP lea trashReg, [rsp + 0] ; trashReg == address of frame ;; allocate scratch space and any required alignment alloc_stack 28h endm ;; ;; Pop the frame and restore register state preserved by PUSH_COOP_PINVOKE_FRAME ;; POP_COOP_PINVOKE_FRAME macro add rsp, 30h pop rbp ; restore RBP pop r10 ; discard thread pop r10 ; discard bitmask pop rbx pop rsi pop rdi pop r12 pop r13 pop r14 pop r15 pop r10 ; discard caller RSP endm ; - TAILCALL_RAX: ("jmp rax") should be used for tailcalls, this emits an instruction ; sequence which is recognized by the unwinder as a valid epilogue terminator TAILJMP_RAX TEXTEQU ;; ;; CONSTANTS -- INTEGER ;; TSF_Attached equ 01h TSF_SuppressGcStress equ 08h TSF_DoNotTriggerGc equ 10h ;; ;; Rename fields of nested structs ;; OFFSETOF__Thread__m_alloc_context__alloc_ptr equ OFFSETOF__Thread__m_rgbAllocContextBuffer + OFFSETOF__gc_alloc_context__alloc_ptr OFFSETOF__Thread__m_alloc_context__alloc_limit equ OFFSETOF__Thread__m_rgbAllocContextBuffer + OFFSETOF__gc_alloc_context__alloc_limit ;; GC type flags GC_ALLOC_FINALIZE equ 1 ;; Note: these must match the defs in PInvokeTransitionFrameFlags PTFF_SAVE_RBX equ 00000001h PTFF_SAVE_RSI equ 00000002h PTFF_SAVE_RDI equ 00000004h PTFF_SAVE_R12 equ 00000010h PTFF_SAVE_R13 equ 00000020h PTFF_SAVE_R14 equ 00000040h PTFF_SAVE_R15 equ 00000080h PTFF_SAVE_ALL_PRESERVED equ 000000F7h ;; NOTE: RBP is not included in this set! PTFF_SAVE_RSP equ 00008000h PTFF_SAVE_RAX equ 00000100h ;; RAX is saved if it contains a GC ref and we're in hijack handler PTFF_SAVE_ALL_SCRATCH equ 00007F00h PTFF_RAX_IS_GCREF equ 00010000h ;; iff PTFF_SAVE_RAX: set -> eax is Object, clear -> eax is scalar PTFF_RAX_IS_BYREF equ 00020000h ;; iff PTFF_SAVE_RAX: set -> eax is ByRef, clear -> eax is Object or scalar PTFF_THREAD_ABORT equ 00040000h ;; indicates that ThreadAbortException should be thrown when returning from the transition ;; These must match the TrapThreadsFlags enum TrapThreadsFlags_None equ 0 TrapThreadsFlags_AbortInProgress equ 1 TrapThreadsFlags_TrapThreads equ 2 ;; This must match HwExceptionCode.STATUS_REDHAWK_THREAD_ABORT STATUS_REDHAWK_THREAD_ABORT equ 43h ;; ;; CONSTANTS -- SYMBOLS ;; ifdef FEATURE_GC_STRESS REDHAWKGCINTERFACE__STRESSGC equ ?StressGc@RedhawkGCInterface@@SAXXZ THREAD__HIJACKFORGCSTRESS equ ?HijackForGcStress@Thread@@SAXPEAUPAL_LIMITED_CONTEXT@@@Z endif ;; FEATURE_GC_STRESS ;; ;; IMPORTS ;; EXTERN RhpGcAlloc : PROC EXTERN RhpValidateExInfoPop : PROC EXTERN RhDebugBreak : PROC EXTERN RhpWaitForSuspend2 : PROC EXTERN RhpWaitForGC2 : PROC EXTERN RhpReversePInvokeAttachOrTrapThread2 : PROC EXTERN RhExceptionHandling_FailedAllocation : PROC EXTERN RhpPublishObject : PROC EXTERN RhpCalculateStackTraceWorker : PROC EXTERN RhThrowHwEx : PROC EXTERN RhThrowEx : PROC EXTERN RhRethrow : PROC ifdef FEATURE_GC_STRESS EXTERN REDHAWKGCINTERFACE__STRESSGC : PROC EXTERN THREAD__HIJACKFORGCSTRESS : PROC endif ;; FEATURE_GC_STRESS EXTERN g_lowest_address : QWORD EXTERN g_highest_address : QWORD EXTERN g_ephemeral_low : QWORD EXTERN g_ephemeral_high : QWORD EXTERN g_card_table : QWORD EXTERN RhpTrapThreads : DWORD