1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
|
;;
;; 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
;;
FASTCALL_FUNC macro FuncName,cbArgs
FuncNameReal EQU @&FuncName&@&cbArgs
FuncNameReal proc public
endm
FASTCALL_ENDFUNC macro
FuncNameReal endp
endm
ALTERNATE_ENTRY macro Name
decoratedName TEXTEQU @CatStr( _, Name ) )
decoratedName label proc
PUBLIC decoratedName
endm
LABELED_RETURN_ADDRESS macro Name
decoratedName TEXTEQU @CatStr( _, Name ) )
decoratedName label proc
PUBLIC decoratedName
endm
EXPORT_POINTER_TO_ADDRESS macro Name
local AddressToExport
AddressToExport label proc
.const
align 4
Name dd offset AddressToExport
public Name
.code
endm
__tls_array equ 2Ch ;; offsetof(TEB, ThreadLocalStoragePointer)
;;
;; __declspec(thread) version
;;
INLINE_GETTHREAD macro destReg, trashReg
ASSUME fs : NOTHING
EXTERN __tls_index : DWORD
EXTERN _tls_CurrentThread : DWORD
mov destReg, [__tls_index]
mov trashReg, fs:[__tls_array]
mov destReg, [trashReg + destReg * 4]
add destReg, SECTIONREL _tls_CurrentThread
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 dword ptr [threadReg + OFFSETOF__Thread__m_ppvHijackedReturnAddressLocation], 0
mov dword ptr [threadReg + OFFSETOF__Thread__m_pvHijackedReturnAddress], 0
@@:
endm
;;
;; 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.
;;
;; The macro assumes it is called from a helper that has already set up an EBP frame and that the values of
;; EBX, ESI and EDI remain unchanged from their values in managed code. It pushes the frame at the top of the
;; stack.
;;
;; EAX is trashed by this macro.
;;
PUSH_COOP_PINVOKE_FRAME macro transitionFrameReg
lea eax, [ebp + 8] ; get the ESP of the caller
push eax ; save ESP
push edi
push esi
push ebx
push PTFF_SAVE_ALL_PRESERVED + PTFF_SAVE_RSP
push eax ; Thread * (unused by stackwalker)
mov eax, [ebp + 0] ; Find previous EBP value
push eax ; save EBP
mov eax, [ebp + 4] ; Find the return address
push eax ; save m_RIP
lea transitionFrameReg, [esp + 0] ; transitionFrameReg == address of frame
endm
;;
;; Remove the frame from a previous call to PUSH_COOP_PINVOKE_FRAME from the top of the stack and restore EBX,
;; ESI and EDI to their previous values.
;;
;; TRASHES ECX
;;
POP_COOP_PINVOKE_FRAME macro
add esp, 4*4
pop ebx
pop esi
pop edi
pop ecx
endm
;;
;; CONSTANTS -- INTEGER
;;
TSF_Attached equ 01h
TSF_SuppressGcStress equ 08h
TSF_DoNotTriggerGc equ 10h
;; 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_ALL_PRESERVED equ 00000007h ;; 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 00000700h
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
;;
;; 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
;;
;; CONSTANTS -- SYMBOLS
;;
RhDebugBreak equ @RhDebugBreak@0
RhpGcAlloc equ @RhpGcAlloc@16
G_LOWEST_ADDRESS equ _g_lowest_address
G_HIGHEST_ADDRESS equ _g_highest_address
G_EPHEMERAL_LOW equ _g_ephemeral_low
G_EPHEMERAL_HIGH equ _g_ephemeral_high
G_CARD_TABLE equ _g_card_table
RhpWaitForSuspend2 equ @RhpWaitForSuspend2@0
RhpWaitForGC2 equ @RhpWaitForGC2@4
RhpReversePInvokeAttachOrTrapThread2 equ @RhpReversePInvokeAttachOrTrapThread2@4
RhpTrapThreads equ _RhpTrapThreads
RhpPublishObject equ @RhpPublishObject@8
ifdef FEATURE_GC_STRESS
THREAD__HIJACKFORGCSTRESS equ ?HijackForGcStress@Thread@@SGXPAUPAL_LIMITED_CONTEXT@@@Z
REDHAWKGCINTERFACE__STRESSGC equ ?StressGc@RedhawkGCInterface@@SGXXZ
endif ;; FEATURE_GC_STRESS
;;
;; IMPORTS
;;
EXTERN RhpGcAlloc : 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 THREAD__HIJACKFORGCSTRESS : PROC
EXTERN REDHAWKGCINTERFACE__STRESSGC : PROC
endif ;; FEATURE_GC_STRESS
EXTERN G_LOWEST_ADDRESS : DWORD
EXTERN G_HIGHEST_ADDRESS : DWORD
EXTERN G_EPHEMERAL_LOW : DWORD
EXTERN G_EPHEMERAL_HIGH : DWORD
EXTERN G_CARD_TABLE : DWORD
EXTERN RhpTrapThreads : DWORD
|