summaryrefslogtreecommitdiff
path: root/src/vm/arm/ehhelpers.asm
blob: ac26c7eaf4a4209b1dedf2406bacf97ecc6a55da (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
; 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 "ksarm.h"

#include "asmconstants.h"

#include "asmmacros.h"

    IMPORT FixContextHandler
    IMPORT LinkFrameAndThrow
    IMPORT HijackHandler
    IMPORT ThrowControlForThread

;
; 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 occur when the stack is unwalkable
;

        TEXTAREA

        ; GSCookie, scratch area
        GBLA OFFSET_OF_FRAME

        ; GSCookie + alignment padding
OFFSET_OF_FRAME SETA 4 + SIZEOF__GSCookie

        MACRO
        GenerateRedirectedStubWithFrame $STUB, $TARGET

        ; 
        ; This is the primary function to which execution will be redirected to.
        ;
        NESTED_ENTRY $STUB

        ;
        ; IN: lr: original IP before redirect
        ;

        PROLOG_PUSH         {r4,r7,lr}
        PROLOG_STACK_ALLOC  OFFSET_OF_FRAME + SIZEOF__FaultingExceptionFrame

        ; At this point, the stack maybe misaligned if the thread abort was asynchronously
        ; triggered in the prolog or epilog of the managed method. For such a case, we must
        ; align the stack before calling into the VM.
        ;
        ; Runtime check for 8-byte alignment. 
        PROLOG_STACK_SAVE r7
        and r0, r7, #4
        sub sp, sp, r0

        ; Save pointer to FEF for GetFrameFromRedirectedStubStackFrame
        add r4, sp, #OFFSET_OF_FRAME

        ; Prepare to initialize to NULL
        mov r1,#0
        str r1, [r4]                                                        ; Initialize vtbl (it is not strictly necessary)
        str r1, [r4, #FaultingExceptionFrame__m_fFilterExecuted]            ; Initialize BOOL for personality routine

        mov r0, r4                      ; move the ptr to FEF in R0
        
        ; stack must be 8 byte aligned
        CHECK_STACK_ALIGNMENT       
        
        bl            $TARGET

        ; Target should not return.
        EMIT_BREAKPOINT

        NESTED_END $STUB

        MEND

; ------------------------------------------------------------------
;
; Helpers for async (NullRef, AccessViolation) exceptions
;

        NESTED_ENTRY NakedThrowHelper2,,FixContextHandler
        PROLOG_PUSH         {r0, lr}

        ; On entry:
        ;
        ; R0 = Address of FaultingExceptionFrame
        bl LinkFrameAndThrow

        ; Target should not return.
        EMIT_BREAKPOINT

        NESTED_END NakedThrowHelper2


        GenerateRedirectedStubWithFrame NakedThrowHelper, NakedThrowHelper2

; ------------------------------------------------------------------
;
; Helpers for ThreadAbort exceptions
;

        NESTED_ENTRY RedirectForThreadAbort2,,HijackHandler
        PROLOG_PUSH         {r0, lr}

        ; stack must be 8 byte aligned
        CHECK_STACK_ALIGNMENT       

        ; On entry:
        ;
        ; R0 = Address of FaultingExceptionFrame.
        ;
        ; Invoke the helper to setup the FaultingExceptionFrame and raise the exception
        bl              ThrowControlForThread

        ; ThrowControlForThread doesn't return.
        EMIT_BREAKPOINT

        NESTED_END RedirectForThreadAbort2

        GenerateRedirectedStubWithFrame RedirectForThreadAbort, RedirectForThreadAbort2

; ------------------------------------------------------------------

        ; This helper enables us to call into a funclet after applying the non-volatiles
        NESTED_ENTRY CallEHFunclet

        PROLOG_PUSH         {r4-r11, lr}
        PROLOG_STACK_ALLOC  4

        ; On entry:
        ;
        ; R0 = throwable        
        ; R1 = PC to invoke
        ; R2 = address of R4 register in CONTEXT record; used to restore the non-volatile registers of CrawlFrame
        ; R3 = 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 sp, [r3]
        ; apply the non-volatiles corresponding to the CrawlFrame
        ldm r2, {r4-r11}
        ; Invoke the funclet
        blx r1

        EPILOG_STACK_FREE   4
        EPILOG_POP          {r4-r11, pc}

        NESTED_END CallEHFunclet

        ; This helper enables us to call into a filter funclet by passing it the CallerSP to lookup the 
        ; frame pointer for accessing the locals in the parent method.
        NESTED_ENTRY CallEHFilterFunclet

        PROLOG_PUSH         {lr}
        PROLOG_STACK_ALLOC  4

        ; On entry:
        ;
        ; R0 = throwable        
        ; R1 = SP of the caller of the method/funclet containing the filter
        ; R2 = PC to invoke
        ; R3 = 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 sp, [r3]
        ; Invoke the filter funclet
        blx r2

        EPILOG_STACK_FREE   4
        EPILOG_POP          {pc}

        NESTED_END CallEHFilterFunclet
        END