-
Notifications
You must be signed in to change notification settings - Fork 4.7k
/
ThunkPoolThunks.S
119 lines (97 loc) · 2.91 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
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
.intel_syntax noprefix
#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
#define PAGE_SIZE 0x1000
#define PAGE_SIZE_LOG2 12
// THUNK_POOL_NUM_THUNKS_PER_PAGE = min(PAGE_SIZE / THUNK_CODESIZE, (PAGE_SIZE - POINTER_SIZE) / THUNK_DATASIZE)
#define THUNK_POOL_NUM_THUNKS_PER_PAGE 0xff
//;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; Thunk Pages ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
.macro THUNKS_PAGE_BLOCK
IN_PAGE_INDEX = 0
.rept THUNK_POOL_NUM_THUNKS_PER_PAGE
.p2align 4
// Set r10 to the address of the current thunk's data block.
lea r10, [rip + THUNKS_MAP_SIZE - 7]
// jump to the location pointed at by the last qword in the data page
jmp qword ptr[r10 + PAGE_SIZE - POINTER_SIZE - (THUNK_DATASIZE * IN_PAGE_INDEX)]
IN_PAGE_INDEX = IN_PAGE_INDEX + 1
.endr
.endm
#ifdef TARGET_APPLE
// Thunk pool
.text
.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
#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)
lea rax, [rip + C_FUNC(ThunkPool)]
ret
LEAF_END RhpGetThunksBase
//
// int RhpGetNumThunksPerBlock()
//
LEAF_ENTRY RhpGetNumThunksPerBlock
mov rax, THUNK_POOL_NUM_THUNKS_PER_PAGE
ret
LEAF_END RhpGetNumThunksPerBlock
//
// int RhpGetThunkSize()
//
LEAF_ENTRY RhpGetThunkSize
mov rax, THUNK_CODESIZE
ret
LEAF_END RhpGetThunkSize
//
// int RhpGetNumThunkBlocksPerMapping()
//
LEAF_ENTRY RhpGetNumThunkBlocksPerMapping
mov rax, (THUNKS_MAP_SIZE / PAGE_SIZE)
ret
LEAF_END RhpGetNumThunkBlocksPerMapping
//
// int RhpGetThunkBlockSize
//
LEAF_ENTRY RhpGetThunkBlockSize
mov rax, PAGE_SIZE
ret
LEAF_END RhpGetThunkBlockSize
//
// IntPtr RhpGetThunkDataBlockAddress(IntPtr thunkStubAddress)
//
LEAF_ENTRY RhpGetThunkDataBlockAddress
mov rax, rdi
mov rdi, PAGE_SIZE - 1
not rdi
and rax, rdi
add rax, THUNKS_MAP_SIZE
ret
LEAF_END RhpGetThunkDataBlockAddress
//
// IntPtr RhpGetThunkStubsBlockAddress(IntPtr thunkDataAddress)
//
LEAF_ENTRY RhpGetThunkStubsBlockAddress
mov rax, rdi
mov rdi, PAGE_SIZE - 1
not rdi
and rax, rdi
sub rax, THUNKS_MAP_SIZE
ret
LEAF_END RhpGetThunkStubsBlockAddress