Welcome to mirror list, hosted at ThFree Co, Russian Federation.

PInvoke.asm « i386 « Runtime « Native « src - github.com/mono/corert.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: 85fcec5f2546e876e6a13f08938becf09bf2054c (plain)
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
;; 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.

        .586
        .model  flat
        option  casemap:none
        .code


include AsmMacros.inc

extern RhpReversePInvokeBadTransition : proc

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;; RhpWaitForSuspend -- rare path for RhpPInvoke and RhpReversePInvokeReturn
;;
;;
;; INPUT: none
;;
;; TRASHES: none
;; 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
_RhpWaitForSuspend proc public
        push        ebp
        mov         ebp, esp
        push        eax
        push        ecx
        push        edx

        call        RhpWaitForSuspend2
        
        pop         edx
        pop         ecx
        pop         eax
        pop         ebp
        ret
_RhpWaitForSuspend endp


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;; RhpWaitForGCNoAbort
;;
;;
;; INPUT: ECX: transition frame
;;
;; OUTPUT: 
;; 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
_RhpWaitForGCNoAbort proc public
        push        ebp
        mov         ebp, esp
        push        eax
        push        edx
        push        ebx
        push        esi

        mov         esi, [ecx + OFFSETOF__PInvokeTransitionFrame__m_pThread]

        test        dword ptr [esi + OFFSETOF__Thread__m_ThreadStateFlags], TSF_DoNotTriggerGc
        jnz         Done

        ; passing transition frame pointer in ecx
        call        RhpWaitForGC2

Done:
        pop         esi
        pop         ebx
        pop         edx
        pop         eax
        pop         ebp
        ret
_RhpWaitForGCNoAbort endp

RhpThrowHwEx equ @RhpThrowHwEx@0
EXTERN RhpThrowHwEx : PROC

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;; RhpWaitForGC
;;
;;
;; INPUT: ECX: transition frame
;;
;; OUTPUT: 
;; 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
_RhpWaitForGC proc public
        push        ebp
        mov         ebp, esp
        push        ebx

        mov         ebx, ecx
        test        [RhpTrapThreads], TrapThreadsFlags_TrapThreads
        jz          NoWait

        call        _RhpWaitForGCNoAbort
NoWait:
        test        [RhpTrapThreads], TrapThreadsFlags_AbortInProgress
        jz          Done
        test        dword ptr [ebx + OFFSETOF__PInvokeTransitionFrame__m_Flags], PTFF_THREAD_ABORT
        jz          Done

        mov         ecx, STATUS_REDHAWK_THREAD_ABORT
        pop         ebx
        pop         ebp
        pop         edx                 ; return address as exception RIP
        jmp         RhpThrowHwEx        ; Throw the ThreadAbortException as a special kind of hardware exception
Done:
        pop         ebx
        pop         ebp
        ret
_RhpWaitForGC endp

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;; RhpReversePInvoke
;;
;; IN:  EAX: address of reverse pinvoke frame
;;                  0: save slot for previous M->U transition frame
;;                  4: save slot for thread pointer to avoid re-calc in epilog sequence
;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
FASTCALL_FUNC RhpReversePInvoke, 0
        push        ecx         ; save arg regs -- we could omit this if we knew the calling convention wasn't fastcall.
        push        edx         ; ...

        ;; edx = GetThread(), TRASHES ecx
        INLINE_GETTHREAD edx, ecx
        mov         [eax + 4], edx          ; save thread pointer for RhpReversePInvokeReturn
        
        ; edx = thread
        ; eax = prev save slot
        ; ecx = scratch

        test        dword ptr [edx + OFFSETOF__Thread__m_ThreadStateFlags], TSF_Attached
        jz          AttachThread

ThreadAttached:
        ;;
        ;; Check for the correct mode.  This is accessible via various odd things that we cannot completely 
        ;; prevent such as :
        ;;     1) Registering a reverse pinvoke entrypoint as a vectored exception handler
        ;;     2) Performing a managed delegate invoke on a reverse pinvoke delegate.
        ;;
        cmp         dword ptr [edx + OFFSETOF__Thread__m_pTransitionFrame], 0
        je          CheckBadTransition

        ; Save previous TransitionFrame prior to making the mode transition so that it is always valid 
        ; whenever we might attempt to hijack this thread.
        mov         ecx, [edx + OFFSETOF__Thread__m_pTransitionFrame]
        mov         [eax], ecx

ReverseRetry:
        mov         dword ptr [edx + OFFSETOF__Thread__m_pTransitionFrame], 0
        test        [RhpTrapThreads], TrapThreadsFlags_TrapThreads
        jnz         ReverseTrapReturningThread

AllDone:
        pop         edx         ; restore arg reg
        pop         ecx         ; restore arg reg
        ret
        
CheckBadTransition:
        ;; Allow 'bad transitions' in when the TSF_DoNotTriggerGc mode is set.  This allows us to have 
        ;; [NativeCallable] methods that are called via the "restricted GC callouts" as well as from native,
        ;; which is necessary because the methods are CCW vtable methods on interfaces passed to native.
        test        dword ptr [edx + OFFSETOF__Thread__m_ThreadStateFlags], TSF_DoNotTriggerGc
        jz          BadTransition

        ;; zero-out our 'previous transition frame' save slot
        mov         dword ptr [eax], 0

        ;; nothing more to do
        jmp         AllDone

ReverseTrapReturningThread:
        ;; put the previous frame back (sets us back to preemptive mode)
        mov         ecx, [eax]
        mov         [edx + OFFSETOF__Thread__m_pTransitionFrame], ecx

AttachThread:
        mov         ecx, eax                    ; arg <- address of reverse pinvoke frame
        call        RhpReversePInvokeAttachOrTrapThread2
        jmp         AllDone

BadTransition:
        pop         edx
        pop         ecx
        mov         ecx, dword ptr [esp]        ; arg <- return address
        jmp         RhpReversePInvokeBadTransition
FASTCALL_ENDFUNC

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;; RhpReversePInvokeReturn
;;
;; IN:  ECX: address of reverse pinvoke frame
;;                  0: save slot for previous M->U transition frame
;;                  4: save slot for thread pointer to avoid re-calc in epilog sequence
;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
FASTCALL_FUNC RhpReversePInvokeReturn, 0
        push        edx         ; save return value

        mov         edx, [ecx + 4]  ; get Thread pointer
        mov         ecx, [ecx + 0]  ; get previous M->U transition frame

        mov         [edx + OFFSETOF__Thread__m_pTransitionFrame], ecx
        test        [RhpTrapThreads], TrapThreadsFlags_TrapThreads
        pop         edx         ; restore return value
        jnz         _RhpWaitForSuspend
        ret

FASTCALL_ENDFUNC


        end