-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathplot.S
242 lines (219 loc) · 6.12 KB
/
plot.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
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
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
#include "plot.h"
// Stack at entry:
// offset contents
// ===============
// 0 GOOT address
// 8 trampoline index
// 16 return address (must be preserved)
//
// Stack during execution:
// offset contents
// ===============
// 0 saved %rdx
// 8 saved %rcx
// 16 saved %rax
// 24 GOOT address
// 32 trampoline index
// 40 return address (must be preserved)
.type procedure_linkage_override, @function
.globl procedure_linkage_override
procedure_linkage_override:
.cfi_startproc
.cfi_adjust_cfa_offset 16
push %rax
.cfi_adjust_cfa_offset 8
push %rcx
.cfi_adjust_cfa_offset 8
push %rdx
.cfi_adjust_cfa_offset 8
mov 24(%rsp), %rcx // GOOT address
mov 32(%rsp), %rdx // trampoline index
mov %rcx, %rax
mov 24(%rcx, %rdx, 8), %rcx // handle/shadow address
add 8(%rax), %rdx // index += adjustment
mov 0(%rax), %rax // identifier
cmp 0(%rcx), %rax // override_table == identifier
jne .Lpreceding_page
sub 8(%rcx), %edx // index -= first_entry
movsx %edx, %rdx
add 16(%rcx), %rdx // index += last_adjustment
.Lpreceding_page:
add $24, %rcx // gots address
mov %rcx, 24(%rsp)
mov %rdx, 32(%rsp)
call namespace_thread // namespace address
mov (%rax), %rdx // namespace
mov (%rcx, %rdx, 8), %rcx // got address: gots[namespace]
mov 32(%rsp), %rdx // GOT index
mov (%rcx, %rdx, 8), %rcx // symbol address
test %rcx, %rcx
jnz .Lfound_symbol
mov 24(%rsp), %rcx // gots address
mov (%rcx), %rcx // got address: gots[BASE]
mov (%rcx, %rdx, 8), %rcx // symbol address
mov (%rax), %rdx // namespace
movq $0, (%rax) // clear namespace
call namespace_caller // caller address
mov %rdx, (%rax) // save namespace
lea hook_retpoline(%rip), %rdx
mov %rdx, 24(%rsp) // stack alignment fixup "return" address
lea hook_trampoline(%rip), %rdx
mov %rdx, 32(%rsp) // callback hook trampoline "return" address
mov (%rsp), %rdx // saved %rdx
mov %rdx, -16(%rsp) // save %rdx
mov 8(%rsp), %rdx // saved %rcx
mov %rdx, -8(%rsp) // save %rcx
mov 16(%rsp), %rdx // saved %rax
mov %rdx, (%rsp) // save %rax
sub $16, %rsp
mov shared_pretrampoline@gotpcrel(%rip), %rax
mov (%rax), %al
test %al, %al
jz .Lfound_symbol
int3 // induce SIGTRAP
.Lfound_symbol:
mov %rcx, 32(%rsp) // return address
pop %rdx
.cfi_adjust_cfa_offset -8
pop %rcx
.cfi_adjust_cfa_offset -8
pop %rax
.cfi_adjust_cfa_offset -8
add $8, %rsp // symbol address address
.cfi_adjust_cfa_offset -8
ret // symbol address
.cfi_endproc
.size procedure_linkage_override, .-procedure_linkage_override
// Stack at entry:
// offset contents
// ===============
// 0 return address (hook_trampoline() function)
// 8 preserved return address
// -- (alignment reference point)
.type hook_retpoline, @function
hook_retpoline:
.cfi_startproc
// Fix stack alignment
ret
.cfi_endproc
.size hook_retpoline, .-hook_retpoline
// Stack at entry:
// offset contents
// ===============
// 0 preserved return address
//
// Stack during execution:
// offset contents
// ===============
// 0 (alignment gap)
// 8 saved %rdx
// 16 saved %rax
// 24 preserved return address
.type hook_trampoline, @function
hook_trampoline:
.cfi_startproc
push %rax
.cfi_adjust_cfa_offset 8
push %rdx
.cfi_adjust_cfa_offset 8
sub $8, %rsp // alignment
.cfi_adjust_cfa_offset 8
call namespace_caller // caller address
mov (%rax), %rcx // namespace
call namespace_thread // namespace address
mov %rcx, (%rax) // restore namespace
mov %rcx, %rdi // namespace
call namespace_trampolining // trampolining address
mov (%rax), %cl // trampolining
test %cl, %cl
jnz .Lskip_hook
mov shared_trampoline@gotpcrel(%rip), %rcx
mov (%rcx), %rcx
test %rcx, %rcx
jz .Lskip_hook
movb $1, (%rax) // lock ourselves out of here
mov %rax, (%rsp) // save trampolining address
call *%rcx
mov (%rsp), %rax // trampolining address
movb $0, (%rax) // "unlock," as John Bercow would say
.Lskip_hook:
add $8, %rsp
.cfi_adjust_cfa_offset -8
pop %rdx
.cfi_adjust_cfa_offset -8
pop %rax
.cfi_adjust_cfa_offset -8
ret
.cfi_endproc
.size hook_trampoline, .-hook_trampoline
.type plot_is_trampoline, @function
plot_is_trampoline:
.globl plot_is_trampoline
.cfi_startproc
mov hook_retpoline@gotpcrel(%rip), %rax
cmp %rdi, %rax
je .Lshortcircuit
mov hook_trampoline@gotpcrel(%rip), %rax
cmp %rdi, %rax
.Lshortcircuit:
sete %al
movzb %al, %eax
ret
.cfi_endproc
.size plot_is_trampoline, .-plot_is_trampoline
// Ideally, the assembly macro alone would suffice to generate all table entries; unfortunately, GAS
// uses a hardcoded recursion depth limit, so we have to unroll the loop to support larger tables.
#define ENTRY(id, count) \
entry (id), ((count) / 5); \
entry ((id) + (count) / 5), ((count) / 5); \
entry ((id) + (count) / 5 * 2), ((count) / 5); \
entry ((id) + (count) / 5 * 3), ((count) / 5); \
entry ((id) + (count) / 5 * 4), ((count) / 5); \
.if count % 5; \
entry ((id) + (count) / 5 * 5), ((count) % 5); \
.endif; \
.macro entry id=0, count=1
push $\id
jmp plot_template_code
.iflt \id - 11
nop
nop
nop
.endif
.iflt \id - 0x80
nop
nop
nop
.endif
.if \count - 1
entry (\id + 1), (\count - 1)
.endif
.endm
.section .rodata
.align 8
.globl plot_template
plot_template:
.quad 0x0
.quad 0x0
plot_template_code:
push -0x16(%rip)
push -0x14(%rip)
ret
nop
nop
nop
plot_template_entries:
entry 0
plot_template_entry_end:
ENTRY(1, (PLOT_ENTRIES_PER_PAGE - 1))
plot_template_end:
.align 8
.globl plot_size
plot_size:
.quad plot_template_end - plot_template
.globl plot_entries_offset
plot_entries_offset:
.quad plot_template_entries - plot_template_code
.globl plot_entry_size
plot_entry_size:
.quad plot_template_entry_end - plot_template_entries