summaryrefslogtreecommitdiff
path: root/src/vm/i386/RedirectedHandledJITCase.asm
blob: 80345623e79d966b4874d0fccb27b946c51be190 (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
; 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.

; ==++==
; 

; 
; ==--==
; ***********************************************************************
; File: RedirectedHandledJITCase.asm
;
; ***********************************************************************
;

; This contains thread-redirecting helper routines that are 100% x86 assembly

        .586
        .model  flat

        include asmconstants.inc

        option  casemap:none
        .code

EXTERN _GetCurrentSavedRedirectContext@0:PROC

;
; WARNING!!  These functions immediately ruin thread unwindability.  This is
; WARNING!!  OK as long as there is a mechanism for saving the thread context
; WARNING!!  prior to running these functions as well as a mechanism for 
; WARNING!!  restoring the context prior to any stackwalk.  This means that
; WARNING!!  we need to ensure that no GC can occur while the stack is 
; WARNING!!  unwalkable.  This further means that we cannot allow any exception
; WARNING!!  to occure when the stack is unwalkable
;


; If you edit this macro, make sure you update GetCONTEXTFromRedirectedStubStackFrame.
; This function is used by both the personality routine and the debugger to retrieve the original CONTEXT.
GenerateRedirectedHandledJITCaseStub MACRO reason

EXTERN ?RedirectedHandledJITCaseFor&reason&@Thread@@CGXXZ:proc

        ALIGN 4
_RedirectedHandledJITCaseFor&reason&_Stub@0 PROC PUBLIC

        push            eax                     ; where to stuff the fake return address
        push            ebp                     ; save interrupted ebp for stack walk
        mov             ebp, esp
        sub             esp, 4                  ; stack slot to save the CONTEXT *

        ;
        ; Save a copy of the redirect CONTEXT*.
        ; This is needed for the debugger to unwind the stack.
        ;
        call            _GetCurrentSavedRedirectContext@0

        mov             [ebp-4], eax
.errnz REDIRECTSTUB_EBP_OFFSET_CONTEXT + 4, REDIRECTSTUB_EBP_OFFSET_CONTEXT has changed - update asm stubs

        ;
        ; Fetch the interrupted eip and save it as our return address.
        ;
        mov             eax, [eax + CONTEXT_Eip]
        mov             [ebp+4], eax

        ;
        ; Call target, which will do whatever we needed to do in the context
        ; of the target thread, and will RtlRestoreContext when it is done.
        ;
        call            ?RedirectedHandledJITCaseFor&reason&@Thread@@CGXXZ
        
        int             3                       ; target shouldn't return.

; Put a label here to tell the debugger where the end of this function is.
PUBLIC _RedirectedHandledJITCaseFor&reason&_StubEnd@0
_RedirectedHandledJITCaseFor&reason&_StubEnd@0:

_RedirectedHandledJITCaseFor&reason&_Stub@0 ENDP

ENDM

; HijackFunctionStart and HijackFunctionEnd are used to tell BBT to keep the hijacking functions together.
; Debugger uses range to check whether IP falls into one of them (see code:Debugger::s_hijackFunction).

_HijackFunctionStart@0 proc public
ret
_HijackFunctionStart@0 endp

GenerateRedirectedHandledJITCaseStub <GCThreadControl>
GenerateRedirectedHandledJITCaseStub <DbgThreadControl>
GenerateRedirectedHandledJITCaseStub <UserSuspend>
GenerateRedirectedHandledJITCaseStub <YieldTask>

; Hijack for exceptions.
; This can be used to hijack at a 2nd-chance exception and execute the UEF

EXTERN _ExceptionHijackWorker@16:PROC

_ExceptionHijack@0 PROC PUBLIC

    ; This is where we land when we're hijacked from an IP by the debugger.
    ; The debugger has already pushed the args:
    ; - a CONTEXT 
    ; - a EXCEPTION_RECORD onto the stack
    ; - an DWORD to use to mulitplex the hijack
    ; - an arbitrary void* data parameter
    call _ExceptionHijackWorker@16
    
    ; Don't expect to return from here. Debugger will unhijack us. It has the full 
    ; context and can properly restore us.
    int 3

; Put a label here to tell the debugger where the end of this function is.
public _ExceptionHijackEnd@0
_ExceptionHijackEnd@0:

_ExceptionHijack@0 ENDP

; It is very important to have a dummy function here.
; Without it, the image has two labels without any instruction in between:
; One for the last label in this function, and one for the first function in the image following this asm file.
; Then the linker is free to remove from PDB the function symbol for the function
; immediately following this, and replace the reference with the last label in this file.
; When this happens, BBT loses info about function, moves pieces within the function to random place, and generates bad code.
_HijackFunctionLast@0 proc public
ret
_HijackFunctionLast@0 endp

; This is the first function outside the "keep together range". Used by BBT scripts.
_HijackFunctionEnd@0 proc public
ret
_HijackFunctionEnd@0 endp

END