Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(177)

Side by Side Diff: util/win/capture_context.asm

Issue 1377963002: win: Add and use a custom CaptureContext() implementation (Closed) Base URL: https://chromium.googlesource.com/crashpad/crashpad@master
Patch Set: Created 5 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « util/win/capture_context.h ('k') | util/win/capture_context_test.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 ; Copyright 2015 The Crashpad Authors. All rights reserved.
2 ;
3 ; Licensed under the Apache License, Version 2.0 (the "License");
4 ; you may not use this file except in compliance with the License.
5 ; You may obtain a copy of the License at
6 ;
7 ; http://www.apache.org/licenses/LICENSE-2.0
8 ;
9 ; Unless required by applicable law or agreed to in writing, software
10 ; distributed under the License is distributed on an "AS IS" BASIS,
11 ; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 ; See the License for the specific language governing permissions and
13 ; limitations under the License.
14
15 ; Detect ml64 assembling for x86_64 by checking for rax.
16 ifdef rax
17 _M_X64 equ 1
18 else
19 _M_IX86 equ 1
20 endif
21
22 ifdef _M_IX86
23 .586
24 .XMM
25 .model flat
26 endif
27
28 ; namespace crashpad {
29 ; void CaptureContext(CONTEXT* context)
30 ; } // namespace crashpad
31 ifdef _M_IX86
32 CAPTURECONTEXT_SYMBOL equ ?CaptureContext@crashpad@@YAXPAU_CONTEXT@@@Z
33 elseifdef _M_X64
34 CAPTURECONTEXT_SYMBOL equ ?CaptureContext@crashpad@@YAXPEAU_CONTEXT@@@Z
35 endif
36
37 _TEXT segment
38 public CAPTURECONTEXT_SYMBOL
39
40 ifdef _M_IX86
41
42 CAPTURECONTEXT_SYMBOL proc
43
44 push ebp
45 mov ebp, esp
46
47 ; pushfd first, because some instructions affect eflags. eflags will be in
48 ; [ebp-4].
49 pushfd
50
51 ; Save the original value of ebx, and use ebx to hold the CONTEXT* argument.
52 ; The original value of ebx will be in [ebp-8].
53 push ebx
54 mov ebx, [ebp+8]
55
56 ; General-purpose registers whose values haven’t changed can be captured
57 ; directly.
58 mov dword ptr [ebx+156], edi ; context->Edi
scottmg 2015/09/29 21:58:40 Do you think it would be more readable to define
Mark Mentovai 2015/09/30 15:33:22 scottmg wrote:
59 mov dword ptr [ebx+160], esi ; context->Esi
60 mov dword ptr [ebx+168], edx ; context->Edx
61 mov dword ptr [ebx+172], ecx ; context->Ecx
62 mov dword ptr [ebx+176], eax ; context->Eax
63
64 ; Now that the original value of edx has been saved, it can be repurposed to
65 ; hold other registers’ values.
66
67 ; The original ebx was saved on the stack above.
68 mov edx, dword ptr [ebp-8]
69 mov dword ptr [ebx+164], edx ; context->Ebx
70
71 ; The original ebp was saved on the stack in this function’s prologue.
72 mov edx, dword ptr [ebp]
73 mov dword ptr [ebx+180], edx ; context->Ebp
74
75 ; eip can’t be accessed directly, but the return address saved on the stack
76 ; by the call instruction that reached this function can be used.
77 mov edx, dword ptr [ebp+4]
78 mov dword ptr [ebx+184], edx ; context->Eip
79
80 ; The original eflags was saved on the stack above.
81 mov edx, dword ptr [ebp-4]
82 mov dword ptr [ebx+192], edx ; context->EFlags
83
84 ; esp was saved in ebp in this function’s prologue, but the caller’s esp is 8
85 ; more than this value: 4 for the original ebp saved on the stack in this
86 ; function’s prologue, and 4 for the return address saved on the stack by the
87 ; call instruction that reached this function.
88 lea edx, [ebp+8]
89 mov dword ptr [ebx+196], edx ; context->Esp
90
91 ; The segment registers are 16 bits wide, but CONTEXT declares them as
92 ; unsigned 32-bit values, so zero the top half.
93 xor edx, edx
94 mov dx, gs
95 mov dword ptr [ebx+140], edx ; context->SegGs
96 mov dx, fs
97 mov dword ptr [ebx+144], edx ; context->SegFs
98 mov dx, es
99 mov dword ptr [ebx+148], edx ; context->SegEs
100 mov dx, ds
101 mov dword ptr [ebx+152], edx ; context->SegDs
102 mov dx, cs
103 mov dword ptr [ebx+188], edx ; context->SegCs
104 mov dx, ss
105 mov dword ptr [ebx+200], edx ; context->SegSs
106
107 ; Prepare for the string move that will populate the ExtendedRegisters area,
108 ; or the string store that will zero it.
109 cld
110
111 ; Use cpuid 1 to check whether fxsave is supported. If it is, perform it
112 ; before fnsave because fxsave is a less-destructive operation.
113 mov esi, ebx
114 mov eax, 1
115 cpuid
116 mov ebx, esi
117
118 test edx, 01000000 ; FXSR
119 jnz $FXSave
120
121 ; fxsave is not supported. Set ContextFlags to CONTEXT_i386 | CONTEXT_CONTROL
122 ; | CONTEXT_INTEGER | CONTEXT_SEGMENTS | CONTEXT_FLOATING_POINT, and zero the
123 ; ExtendedRegisters area.
124 mov dword ptr [ebx], 1000fh ; context->ContextFlags
125 lea edi, [ebx+204] ; context->ExtendedRegisters
126 xor eax, eax
127 mov ecx, 128
128 rep stosd
129 jmp $FXSaveDone
130
131 $FXSave:
132 ; fxsave is supported. Set ContextFlags to CONTEXT_i386 | CONTEXT_CONTROL |
133 ; CONTEXT_INTEGER | CONTEXT_SEGMENTS | CONTEXT_FLOATING_POINT |
134 ; CONTEXT_EXTENDED_REGISTERS.
135 mov dword ptr [ebx], 1002fh ; context->ContextFlags
136
137 ; fxsave requires a 16 byte-aligned destination memory area. Nothing
138 ; guarantees the alignment of a CONTEXT structure, so create a temporary
139 ; aligned fxsave destination on the stack.
140 and esp, 0fffffff0h
141 sub esp, 512
142
143 ; Zero out the temporary fxsave area before performing the fxsave. Some of the
144 ; fxsave area may not be written by fxsave, and some is definitely not written
145 ; by fxsave.
146 mov edi, esp
147 xor eax, eax
148 mov ecx, 128
149 rep stosd
150
151 fxsave [esp]
152
153 ; Copy the temporary fxsave area into the CONTEXT structure.
154 lea edi, [ebx+204] ; context->ExtendedRegisters
155 mov esi, esp
156 mov ecx, 128
157 rep movsd
158
159 ; Free the stack space used for the temporary fxsave area.
160 lea esp, [ebp-8]
161
162 ; TODO(mark): AVX/xsave support.
163 ; https://code.google.com/p/crashpad/issues/detail?id=58
164
165 $FXSaveDone:
166 ; fnsave reinitializes the FPU with an implicit finit operation, so use frstor
167 ; to restore the original state.
168 fnsave [ebx+28] ; context->FloatSave
169 frstor [ebx+28] ; context->FloatSave
170
171 mov dword ptr [ebx+136], 0 ; context->FloatSave.Spare0
scottmg 2015/09/29 21:58:40 Add " / .Cr0NpxState" to comment (for WOW64)
Mark Mentovai 2015/09/30 15:33:22 scottmg wrote:
172
173 ; The debug registers can’t be read from user code, so zero them out in the
174 ; CONTEXT structure. context->ContextFlags doesn’t indicate that they are
175 ; present.
176 mov dword ptr [ebx+4], 0 ; context->Dr0
177 mov dword ptr [ebx+8], 0 ; context->Dr1
178 mov dword ptr [ebx+12], 0 ; context->Dr2
179 mov dword ptr [ebx+16], 0 ; context->Dr3
180 mov dword ptr [ebx+20], 0 ; context->Dr6
181 mov dword ptr [ebx+24], 0 ; context->Dr7
182
183 ; Clean up by restoring clobbered registers, even those considered volatile
184 ; by the ABI, so that the captured context represents the state at this
185 ; function’s exit.
186 mov edi, dword ptr [ebx+156] ; context->Edi
187 mov esi, dword ptr [ebx+160] ; context->Esi
188 mov edx, dword ptr [ebx+168] ; context->Edx
189 mov ecx, dword ptr [ebx+172] ; context->Ecx
190 mov eax, dword ptr [ebx+176] ; context->Eax
191 pop ebx
192 popfd
193
194 pop ebp
195
196 ret
197
198 elseifdef _M_X64
199
200 CAPTURECONTEXT_SYMBOL proc frame
201
202 push rbp
203 .pushreg rbp
204 mov rbp, rsp
205 .setframe rbp, 0
206
207 ; Note that 16-byte stack alignment is not maintained because this function
208 ; does not call out to any other.
209
210 ; pushfq first, because some instructions affect rflags. rflags will be in
211 ; [rbp-8].
212 pushfq
213 .allocstack 8
214 .endprolog
215
216 ; Set ContextFlags to CONTEXT_AMD64 | CONTEXT_CONTROL | CONTEXT_INTEGER |
217 ; CONTEXT_SEGMENTS | CONTEXT_FLOATING_POINT.
218 mov dword ptr [rcx+48], 10000fh ; context->ContextFlags
219
220 ; General-purpose registers whose values haven’t changed can be captured
221 ; directly.
222 mov qword ptr [rcx+120], rax
223 mov qword ptr [rcx+136], rdx
224 mov qword ptr [rcx+144], rbx
225 mov qword ptr [rcx+168], rsi
226 mov qword ptr [rcx+176], rdi
227 mov qword ptr [rcx+184], r8
228 mov qword ptr [rcx+192], r9
229 mov qword ptr [rcx+200], r10
230 mov qword ptr [rcx+208], r11
231 mov qword ptr [rcx+216], r12
232 mov qword ptr [rcx+224], r13
233 mov qword ptr [rcx+232], r14
234 mov qword ptr [rcx+240], r15
235
236 ; Because of the calling convention, there’s no way to recover the value of
237 ; the caller’s rcx as it existed prior to calling this function. This
238 ; function captures a snapshot of the register state at its return, which
239 ; involves rcx containing a pointer to its first argument.
240 mov qword ptr [rcx+128], rcx
241
242 ; Now that the original value of rax has been saved, it can be repurposed to
243 ; hold other registers’ values.
244
245 ; Save mxcsr. This is duplicated in context->FloatSave.MxCsr, saved by fxsave
246 ; below.
247 stmxcsr dword ptr [rcx+52] ; context->MxCsr
248
249 ; Segment registers.
250 mov ax, cs
251 mov word ptr [rcx+56], ax ; context->SegCs
252 mov ax, ds
253 mov word ptr [rcx+58], ax ; context->SegDs
254 mov ax, es
255 mov word ptr [rcx+60], ax ; context->SegEs
256 mov ax, fs
257 mov word ptr [rcx+62], ax ; context->SegFs
258 mov ax, gs
259 mov word ptr [rcx+64], ax ; context->SegGs
260 mov ax, ss
261 mov word ptr [rcx+66], ax ; context->SegSs
262
263 ; The original rflags was saved on the stack above. Note that the CONTEXT
264 ; structure only stores eflags, the low 32 bits. The high 32 bits in rflags
265 ; are reserved.
266 mov rax, qword ptr [rbp-8]
267 mov dword ptr [rcx+68], eax ; context->EFlags
268
269 ; rsp was saved in rbp in this function’s prologue, but the caller’s rsp is
270 ; 16 more than this value: 8 for the original rbp saved on the stack in this
271 ; function’s prologue, and 8 for the return address saved on the stack by the
272 ; call instruction that reached this function.
273 lea rax, [rbp+16]
274 mov qword ptr [rcx+152], rax ; context->Rsp
275
276 ; The original rbp was saved on the stack in this function’s prologue.
277 mov rax, qword ptr [rbp]
278 mov qword ptr [rcx+160], rax ; context->Rbp
279
280 ; rip can’t be accessed directly, but the return address saved on the stack by
281 ; the call instruction that reached this function can be used.
282 mov rax, qword ptr [rbp+8]
283 mov qword ptr [rcx+248], rax ; context->Rip
284
285 ; Zero out the fxsave area before performing the fxsave. Some of the fxsave
286 ; area may not be written by fxsave, and some is definitely not written by
287 ; fxsave. Also, zero out the unused VectorRegister and VectorControl fields,
288 ; and the debug control register fields.
289 mov rbx, rcx
290 cld
291 lea rdi, [rcx+256] ; context->FltSave
292 xor rax, rax
293 mov rcx, 122
294 rep stosq
295 mov rcx, rbx
296
297 ; Save the floating point (including SSE) state. The CONTEXT structure is
298 ; declared as 16-byte-aligned, which is correct for this operation.
299 lea rax, [rcx+256] ; context->FltSave
300 fxsave [rax]
301
302 ; TODO(mark): AVX/xsave support.
303 ; https://code.google.com/p/crashpad/issues/detail?id=58
304
305 ; The register parameter home address fields aren’t used, so zero them out.
306 mov qword ptr [rcx], 0 ; context->P1Home
307 mov qword ptr [rcx+8], 0 ; context->P2Home
308 mov qword ptr [rcx+16], 0 ; context->P3Home
309 mov qword ptr [rcx+24], 0 ; context->P4Home
310 mov qword ptr [rcx+32], 0 ; context->P5Home
311 mov qword ptr [rcx+40], 0 ; context->P6Home
312
313 ; The debug registers can’t be read from user code, so zero them out in the
314 ; CONTEXT structure. context->ContextFlags doesn’t indicate that they are
315 ; present.
316 mov qword ptr [rcx+72], 0 ; context->Dr0
317 mov qword ptr [rcx+80], 0 ; context->Dr1
318 mov qword ptr [rcx+88], 0 ; context->Dr2
319 mov qword ptr [rcx+96], 0 ; context->Dr3
320 mov qword ptr [rcx+104], 0 ; context->Dr6
321 mov qword ptr [rcx+112], 0 ; context->Dr7
322
323 ; Clean up by restoring clobbered registers, even those considered volatile by
324 ; the ABI, so that the captured context represents the state at this
325 ; function’s exit.
326 mov rax, qword ptr [rcx+120] ; context->Rax
327 mov rbx, qword ptr [rcx+144] ; context->Rbx
328 mov rdi, qword ptr [rcx+176] ; context->Rdi
329 popfq
330
331 pop rbp
332
333 ret
334
335 endif
336
337 CAPTURECONTEXT_SYMBOL endp
338 _TEXT ends
339 end
OLDNEW
« no previous file with comments | « util/win/capture_context.h ('k') | util/win/capture_context_test.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698