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
|
// 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 "unixasmmacros.inc"
#include "asmconstants.h"
.syntax unified
.thumb
//
// 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
//
// GSCookie + alignment padding
OFFSET_OF_FRAME=(4 + SIZEOF__GSCookie)
.macro GenerateRedirectedStubWithFrame STUB, TARGET
//
// This is the primary function to which execution will be redirected to.
//
NESTED_ENTRY \STUB, _TEXT, NoHandler
//
// IN: lr: original IP before redirect
//
PROLOG_PUSH "{r4,r7,lr}"
alloc_stack 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
// We lose stack unwindability here by configuring fp(r7) incorrectely
// here.
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 C_FUNC(\TARGET)
// Target should not return.
EMIT_BREAKPOINT
NESTED_END \STUB, _TEXT
.endm
// ------------------------------------------------------------------
// This helper enables us to call into a funclet after applying the non-volatiles
NESTED_ENTRY CallEHFunclet, _TEXT, NoHandler
PROLOG_PUSH "{r4-r11, lr}"
PROLOG_STACK_SAVE_OFFSET r7, #12
alloc_stack 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-r6}
add r2, r2, #4
ldm r2!, {r8-r11}
// Invoke the funclet
blx r1
free_stack 4
EPILOG_POP "{r4-r11, pc}"
NESTED_END CallEHFunclet, _TEXT
// 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, _TEXT, NoHandler
PROLOG_PUSH "{r7, lr}"
PROLOG_STACK_SAVE r7
// 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_POP "{r7, pc}"
NESTED_END CallEHFilterFunclet, _TEXT
|