-
Notifications
You must be signed in to change notification settings - Fork 4.6k
/
ThunkPoolThunks.S
133 lines (110 loc) · 3.77 KB
/
ThunkPoolThunks.S
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
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
#include <unixasmmacros.inc>
//;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; DATA SECTIONS ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
#define THUNK_CODESIZE 0x10 // 3 instructions, 4 bytes each (and we also have 4 bytes of padding)
#define THUNK_DATASIZE 0x10 // 2 qwords
#define POINTER_SIZE 0x08
#define THUNKS_MAP_SIZE 0x8000
#ifdef TARGET_APPLE
#define PAGE_SIZE 0x4000
#define PAGE_SIZE_LOG2 14
#else
#error Unsupported OS
#endif
// THUNK_POOL_NUM_THUNKS_PER_PAGE = min(PAGE_SIZE / THUNK_CODESIZE, (PAGE_SIZE - POINTER_SIZE) / THUNK_DATASIZE)
#define THUNK_POOL_NUM_THUNKS_PER_PAGE 0x3ff
//;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; Thunk Pages ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
.macro THUNKS_PAGE_BLOCK
IN_PAGE_INDEX = 0
.rept THUNK_POOL_NUM_THUNKS_PER_PAGE
// Set xip0 to the address of the current thunk's data block.
adr xip0, THUNKS_MAP_SIZE
// start : xip0 points to the current thunks first data cell in the data page
// set xip0 to beginning of data page : xip0 <- xip0 - (THUNK_DATASIZE * current thunk's index)
// fix offset to point to last QWROD in page : xip1 <- [xip0 + PAGE_SIZE - POINTER_SIZE]
// tailcall to the location pointed at by the last qword in the data page
ldr xip1, [xip0, #(PAGE_SIZE - POINTER_SIZE - (THUNK_DATASIZE * IN_PAGE_INDEX))]
br xip1
brk 0xf000 // Stubs need to be 16-byte aligned for CFG table. Filling padding with a
// deterministic brk instruction, instead of having it just filled with zeros.
IN_PAGE_INDEX = IN_PAGE_INDEX + 1
.endr
.endm
#ifdef TARGET_APPLE
// Create two segments in the Mach-O file:
// __THUNKS with executable permissions
// __THUNKS_DATA with read/write permissions
.section __THUNKS,__thunks,regular,pure_instructions
.p2align PAGE_SIZE_LOG2
PATCH_LABEL ThunkPool
.rept (THUNKS_MAP_SIZE / PAGE_SIZE)
.p2align PAGE_SIZE_LOG2
THUNKS_PAGE_BLOCK
.endr
.p2align PAGE_SIZE_LOG2
.section __THUNKS_DATA,__thunks,regular
.p2align PAGE_SIZE_LOG2
.space THUNKS_MAP_SIZE
.p2align PAGE_SIZE_LOG2
#else
#error Unsupported OS
#endif
//;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; General Helpers ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
//
// IntPtr RhpGetThunksBase()
//
LEAF_ENTRY RhpGetThunksBase
// Return the address of the first thunk pool to the caller (this is really the base address)
adrp x0, C_FUNC(ThunkPool)@PAGE
add x0, x0, C_FUNC(ThunkPool)@PAGEOFF
ret
LEAF_END RhpGetThunksBase
//
// int RhpGetNumThunksPerBlock()
//
LEAF_ENTRY RhpGetNumThunksPerBlock
mov x0, THUNK_POOL_NUM_THUNKS_PER_PAGE
ret
LEAF_END RhpGetNumThunksPerBlock
//
// int RhpGetThunkSize()
//
LEAF_ENTRY RhpGetThunkSize
mov x0, THUNK_CODESIZE
ret
LEAF_END RhpGetThunkSize
//
// int RhpGetNumThunkBlocksPerMapping()
//
LEAF_ENTRY RhpGetNumThunkBlocksPerMapping
mov x0, (THUNKS_MAP_SIZE / PAGE_SIZE)
ret
LEAF_END RhpGetNumThunkBlocksPerMapping
//
// int RhpGetThunkBlockSize
//
LEAF_ENTRY RhpGetThunkBlockSize
mov x0, PAGE_SIZE
ret
LEAF_END RhpGetThunkBlockSize
//
// IntPtr RhpGetThunkDataBlockAddress(IntPtr thunkStubAddress)
//
LEAF_ENTRY RhpGetThunkDataBlockAddress
mov x12, PAGE_SIZE - 1
bic x0, x0, x12
mov x12, THUNKS_MAP_SIZE
add x0, x0, x12
ret
LEAF_END RhpGetThunkDataBlockAddress
//
// IntPtr RhpGetThunkStubsBlockAddress(IntPtr thunkDataAddress)
//
LEAF_ENTRY RhpGetThunkStubsBlockAddress
mov x12, PAGE_SIZE - 1
bic x0, x0, x12
mov x12, THUNKS_MAP_SIZE
sub x0, x0, x12
ret
LEAF_END RhpGetThunkStubsBlockAddress