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

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: Address review feeback (2) 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 offsetof macro structure, field
29 exitm <structure.&field>
30 endm
31
32 ; The CONTEXT structure definitions that follow are based on those in <winnt.h>.
33 ; Field names are prefixed (as in c_Rax) to avoid colliding with the predefined
34 ; register names (such as Rax).
35
36 ifdef _M_IX86
37
38 CONTEXT_i386 equ 10000h
39 CONTEXT_CONTROL equ CONTEXT_i386 or 1h
40 CONTEXT_INTEGER equ CONTEXT_i386 or 2h
41 CONTEXT_SEGMENTS equ CONTEXT_i386 or 4h
42 CONTEXT_FLOATING_POINT equ CONTEXT_i386 or 8h
43 CONTEXT_DEBUG_REGISTERS equ CONTEXT_i386 or 10h
44 CONTEXT_EXTENDED_REGISTERS equ CONTEXT_i386 or 20h
45 CONTEXT_XSTATE equ CONTEXT_i386 or 40h
46
47 MAXIMUM_SUPPORTED_EXTENSION equ 512
48
49 CONTEXT struct
50 c_ContextFlags dword ?
51
52 c_Dr0 dword ?
53 c_Dr1 dword ?
54 c_Dr2 dword ?
55 c_Dr3 dword ?
56 c_Dr6 dword ?
57 c_Dr7 dword ?
58
59 struct c_FloatSave
60 f_ControlWord dword ?
61 f_StatusWord dword ?
62 f_TagWord dword ?
63 f_ErrorOffset dword ?
64 f_ErrorSelector dword ?
65 f_DataOffset dword ?
66 f_DataSelector dword ?
67 f_RegisterArea byte 80 dup(?)
68
69 union
70 f_Spare0 dword ? ; As in FLOATING_SAVE_AREA.
71 f_Cr0NpxState dword ? ; As in WOW64_FLOATING_SAVE_AREA.
72 ends
73 ends
74
75 c_SegGs dword ?
76 c_SegFs dword ?
77 c_SegEs dword ?
78 c_SegDs dword ?
79
80 c_Edi dword ?
81 c_Esi dword ?
82 c_Ebx dword ?
83 c_Edx dword ?
84 c_Ecx dword ?
85 c_Eax dword ?
86
87 c_Ebp dword ?
88
89 c_Eip dword ?
90 c_SegCs dword ?
91
92 c_EFlags dword ?
93
94 c_Esp dword ?
95 c_SegSs dword ?
96
97 c_ExtendedRegisters byte MAXIMUM_SUPPORTED_EXTENSION dup(?)
98 CONTEXT ends
99
100 elseifdef _M_X64
101
102 M128A struct 16
103 m_Low qword ?
104 m_High qword ?
105 M128A ends
106
107 CONTEXT_AMD64 equ 100000h
108 CONTEXT_CONTROL equ CONTEXT_AMD64 or 1h
109 CONTEXT_INTEGER equ CONTEXT_AMD64 or 2h
110 CONTEXT_SEGMENTS equ CONTEXT_AMD64 or 4h
111 CONTEXT_FLOATING_POINT equ CONTEXT_AMD64 or 8h
112 CONTEXT_DEBUG_REGISTERS equ CONTEXT_AMD64 or 10h
113 CONTEXT_XSTATE equ CONTEXT_AMD64 or 40h
114
115 CONTEXT struct 16
116 c_P1Home qword ?
117 c_P2Home qword ?
118 c_P3Home qword ?
119 c_P4Home qword ?
120 c_P5Home qword ?
121 c_P6Home qword ?
122
123 c_ContextFlags dword ?
124 c_MxCsr dword ?
125
126 c_SegCs word ?
127 c_SegDs word ?
128 c_SegEs word ?
129 c_SegFs word ?
130 c_SegGs word ?
131 c_SegSs word ?
132
133 c_EFlags dword ?
134
135 c_Dr0 qword ?
136 c_Dr1 qword ?
137 c_Dr2 qword ?
138 c_Dr3 qword ?
139 c_Dr6 qword ?
140 c_Dr7 qword ?
141
142 c_Rax qword ?
143 c_Rcx qword ?
144 c_Rdx qword ?
145 c_Rbx qword ?
146 c_Rsp qword ?
147 c_Rbp qword ?
148 c_Rsi qword ?
149 c_Rdi qword ?
150 c_R8 qword ?
151 c_R9 qword ?
152 c_R10 qword ?
153 c_R11 qword ?
154 c_R12 qword ?
155 c_R13 qword ?
156 c_R14 qword ?
157 c_R15 qword ?
158
159 c_Rip qword ?
160
161 union
162 struct c_FltSave
163 f_ControlWord word ?
164 f_StatusWord word ?
165 f_TagWord byte ?
166 f_Reserved1 byte ?
167 f_ErrorOpcode word ?
168 f_ErrorOffset dword ?
169 f_ErrorSelector word ?
170 f_Reserved2 word ?
171 f_DataOffset dword ?
172 f_DataSelector word ?
173 f_Reserved3 word ?
174 f_MxCsr dword ?
175 f_MxCsr_Mask dword ?
176 f_FloatRegisters M128A 8 dup(<?>)
177 f_XmmRegisters M128A 16 dup(<?>)
178 f_Reserved4 byte 96 dup(?)
179 ends
180 struct
181 fx_Header M128A 2 dup(<?>)
182 fx_Legacy M128A 8 dup(<?>)
183 fx_Xmm0 M128A <?>
184 fx_Xmm1 M128A <?>
185 fx_Xmm2 M128A <?>
186 fx_Xmm3 M128A <?>
187 fx_Xmm4 M128A <?>
188 fx_Xmm5 M128A <?>
189 fx_Xmm6 M128A <?>
190 fx_Xmm7 M128A <?>
191 fx_Xmm8 M128A <?>
192 fx_Xmm9 M128A <?>
193 fx_Xmm10 M128A <?>
194 fx_Xmm11 M128A <?>
195 fx_Xmm12 M128A <?>
196 fx_Xmm13 M128A <?>
197 fx_Xmm14 M128A <?>
198 fx_Xmm15 M128A <?>
199 ends
200 ends
201
202 c_VectorRegister M128A 26 dup(<?>)
203 c_VectorControl qword ?
204
205 c_DebugControl qword ?
206 c_LastBranchToRip qword ?
207 c_LastBranchFromRip qword ?
208 c_LastExceptionToRip qword ?
209 c_LastExceptionFromRip qword ?
210 CONTEXT ends
211
212 endif
213
214 ; namespace crashpad {
215 ; void CaptureContext(CONTEXT* context)
216 ; } // namespace crashpad
217 ifdef _M_IX86
218 CAPTURECONTEXT_SYMBOL equ ?CaptureContext@crashpad@@YAXPAU_CONTEXT@@@Z
219 elseifdef _M_X64
220 CAPTURECONTEXT_SYMBOL equ ?CaptureContext@crashpad@@YAXPEAU_CONTEXT@@@Z
221 endif
222
223 _TEXT segment
224 public CAPTURECONTEXT_SYMBOL
225
226 ifdef _M_IX86
227
228 CAPTURECONTEXT_SYMBOL proc
229
230 push ebp
231 mov ebp, esp
232
233 ; pushfd first, because some instructions affect eflags. eflags will be in
234 ; [ebp-4].
235 pushfd
236
237 ; Save the original value of ebx, and use ebx to hold the CONTEXT* argument.
238 ; The original value of ebx will be in [ebp-8].
239 push ebx
240 mov ebx, [ebp+8]
241
242 ; General-purpose registers whose values haven’t changed can be captured
243 ; directly.
244 mov [ebx.CONTEXT].c_Edi, edi
245 mov [ebx.CONTEXT].c_Esi, esi
246 mov [ebx.CONTEXT].c_Edx, edx
247 mov [ebx.CONTEXT].c_Ecx, ecx
248 mov [ebx.CONTEXT].c_Eax, eax
249
250 ; Now that the original value of edx has been saved, it can be repurposed to
251 ; hold other registers’ values.
252
253 ; The original ebx was saved on the stack above.
254 mov edx, dword ptr [ebp-8]
255 mov [ebx.CONTEXT].c_Ebx, edx
256
257 ; The original ebp was saved on the stack in this function’s prologue.
258 mov edx, dword ptr [ebp]
259 mov [ebx.CONTEXT].c_Ebp, edx
260
261 ; eip can’t be accessed directly, but the return address saved on the stack
262 ; by the call instruction that reached this function can be used.
263 mov edx, dword ptr [ebp+4]
264 mov [ebx.CONTEXT].c_Eip, edx
265
266 ; The original eflags was saved on the stack above.
267 mov edx, dword ptr [ebp-4]
268 mov [ebx.CONTEXT].c_EFlags, edx
269
270 ; esp was saved in ebp in this function’s prologue, but the caller’s esp is 8
271 ; more than this value: 4 for the original ebp saved on the stack in this
272 ; function’s prologue, and 4 for the return address saved on the stack by the
273 ; call instruction that reached this function.
274 lea edx, [ebp+8]
275 mov [ebx.CONTEXT].c_Esp, edx
276
277 ; The segment registers are 16 bits wide, but CONTEXT declares them as
278 ; unsigned 32-bit values, so zero the top half.
279 xor edx, edx
280 mov dx, gs
281 mov [ebx.CONTEXT].c_SegGs, edx
282 mov dx, fs
283 mov [ebx.CONTEXT].c_SegFs, edx
284 mov dx, es
285 mov [ebx.CONTEXT].c_SegEs, edx
286 mov dx, ds
287 mov [ebx.CONTEXT].c_SegDs, edx
288 mov dx, cs
289 mov [ebx.CONTEXT].c_SegCs, edx
290 mov dx, ss
291 mov [ebx.CONTEXT].c_SegSs, edx
292
293 ; Prepare for the string move that will populate the ExtendedRegisters area,
294 ; or the string store that will zero it.
295 cld
296
297 ; Use cpuid 1 to check whether fxsave is supported. If it is, perform it
298 ; before fnsave because fxsave is a less-destructive operation.
299 mov esi, ebx
300 mov eax, 1
301 cpuid
302 mov ebx, esi
303
304 test edx, 01000000 ; FXSR
305 jnz $FXSave
306
307 ; fxsave is not supported. Set ContextFlags to not include
308 ; CONTEXT_EXTENDED_REGISTERS, and zero the ExtendedRegisters area.
309 mov [ebx.CONTEXT].c_ContextFlags, CONTEXT_i386 or \
310 CONTEXT_CONTROL or \
311 CONTEXT_INTEGER or \
312 CONTEXT_SEGMENTS or \
313 CONTEXT_FLOATING_POINT
314 lea edi, [ebx.CONTEXT].c_ExtendedRegisters
315 xor eax, eax
316 mov ecx, MAXIMUM_SUPPORTED_EXTENSION / sizeof(dword) ; 128
317 rep stosd
318 jmp $FXSaveDone
319
320 $FXSave:
321 ; fxsave is supported. Set ContextFlags to include CONTEXT_EXTENDED_REGISTERS.
322 mov [ebx.CONTEXT].c_ContextFlags, CONTEXT_i386 or \
323 CONTEXT_CONTROL or \
324 CONTEXT_INTEGER or \
325 CONTEXT_SEGMENTS or \
326 CONTEXT_FLOATING_POINT or \
327 CONTEXT_EXTENDED_REGISTERS
328
329 ; fxsave requires a 16 byte-aligned destination memory area. Nothing
330 ; guarantees the alignment of a CONTEXT structure, so create a temporary
331 ; aligned fxsave destination on the stack.
332 and esp, 0fffffff0h
333 sub esp, MAXIMUM_SUPPORTED_EXTENSION
334
335 ; Zero out the temporary fxsave area before performing the fxsave. Some of the
336 ; fxsave area may not be written by fxsave, and some is definitely not written
337 ; by fxsave.
338 mov edi, esp
339 xor eax, eax
340 mov ecx, MAXIMUM_SUPPORTED_EXTENSION / sizeof(dword) ; 128
341 rep stosd
342
343 fxsave [esp]
344
345 ; Copy the temporary fxsave area into the CONTEXT structure.
346 lea edi, [ebx.CONTEXT].c_ExtendedRegisters
347 mov esi, esp
348 mov ecx, MAXIMUM_SUPPORTED_EXTENSION / sizeof(dword) ; 128
349 rep movsd
350
351 ; Free the stack space used for the temporary fxsave area.
352 lea esp, [ebp-8]
353
354 ; TODO(mark): AVX/xsave support.
355 ; https://code.google.com/p/crashpad/issues/detail?id=58
356
357 $FXSaveDone:
358 ; fnsave reinitializes the FPU with an implicit finit operation, so use frstor
359 ; to restore the original state.
360 fnsave [ebx.CONTEXT].c_FloatSave
361 frstor [ebx.CONTEXT].c_FloatSave
362
363 ; cr0 is inaccessible from user code, and this field would not be used anyway.
364 mov [ebx.CONTEXT].c_FloatSave.f_Cr0NpxState, 0
365
366 ; The debug registers can’t be read from user code, so zero them out in the
367 ; CONTEXT structure. context->ContextFlags doesn’t indicate that they are
368 ; present.
369 mov [ebx.CONTEXT].c_Dr0, 0
370 mov [ebx.CONTEXT].c_Dr1, 0
371 mov [ebx.CONTEXT].c_Dr2, 0
372 mov [ebx.CONTEXT].c_Dr3, 0
373 mov [ebx.CONTEXT].c_Dr6, 0
374 mov [ebx.CONTEXT].c_Dr7, 0
375
376 ; Clean up by restoring clobbered registers, even those considered volatile
377 ; by the ABI, so that the captured context represents the state at this
378 ; function’s exit.
379 mov edi, [ebx.CONTEXT].c_Edi
380 mov esi, [ebx.CONTEXT].c_Esi
381 mov edx, [ebx.CONTEXT].c_Edx
382 mov ecx, [ebx.CONTEXT].c_Ecx
383 mov eax, [ebx.CONTEXT].c_Eax
384 pop ebx
385 popfd
386
387 pop ebp
388
389 ret
390
391 CAPTURECONTEXT_SYMBOL endp
392
393 elseifdef _M_X64
394
395 CAPTURECONTEXT_SYMBOL proc frame
396
397 push rbp
398 .pushreg rbp
399 mov rbp, rsp
400 .setframe rbp, 0
401
402 ; Note that 16-byte stack alignment is not maintained because this function
403 ; does not call out to any other.
404
405 ; pushfq first, because some instructions affect rflags. rflags will be in
406 ; [rbp-8].
407 pushfq
408 .allocstack 8
409 .endprolog
410
411 mov [rcx.CONTEXT].c_ContextFlags, CONTEXT_AMD64 or \
412 CONTEXT_CONTROL or \
413 CONTEXT_INTEGER or \
414 CONTEXT_SEGMENTS or \
415 CONTEXT_FLOATING_POINT
416
417 ; General-purpose registers whose values haven’t changed can be captured
418 ; directly.
419 mov [rcx.CONTEXT].c_Rax, rax
420 mov [rcx.CONTEXT].c_Rdx, rdx
421 mov [rcx.CONTEXT].c_Rbx, rbx
422 mov [rcx.CONTEXT].c_Rsi, rsi
423 mov [rcx.CONTEXT].c_Rdi, rdi
424 mov [rcx.CONTEXT].c_R8, r8
425 mov [rcx.CONTEXT].c_R9, r9
426 mov [rcx.CONTEXT].c_R10, r10
427 mov [rcx.CONTEXT].c_R11, r11
428 mov [rcx.CONTEXT].c_R12, r12
429 mov [rcx.CONTEXT].c_R13, r13
430 mov [rcx.CONTEXT].c_R14, r14
431 mov [rcx.CONTEXT].c_R15, r15
432
433 ; Because of the calling convention, there’s no way to recover the value of
434 ; the caller’s rcx as it existed prior to calling this function. This
435 ; function captures a snapshot of the register state at its return, which
436 ; involves rcx containing a pointer to its first argument.
437 mov [rcx.CONTEXT].c_Rcx, rcx
438
439 ; Now that the original value of rax has been saved, it can be repurposed to
440 ; hold other registers’ values.
441
442 ; Save mxcsr. This is duplicated in context->FltSave.MxCsr, saved by fxsave
443 ; below.
444 stmxcsr [rcx.CONTEXT].c_MxCsr
445
446 ; Segment registers.
447 mov [rcx.CONTEXT].c_SegCs, cs
448 mov [rcx.CONTEXT].c_SegDs, ds
449 mov [rcx.CONTEXT].c_SegEs, es
450 mov [rcx.CONTEXT].c_SegFs, fs
451 mov [rcx.CONTEXT].c_SegGs, gs
452 mov [rcx.CONTEXT].c_SegSs, ss
453
454 ; The original rflags was saved on the stack above. Note that the CONTEXT
455 ; structure only stores eflags, the low 32 bits. The high 32 bits in rflags
456 ; are reserved.
457 mov rax, qword ptr [rbp-8]
458 mov [rcx.CONTEXT].c_EFlags, eax
459
460 ; rsp was saved in rbp in this function’s prologue, but the caller’s rsp is
461 ; 16 more than this value: 8 for the original rbp saved on the stack in this
462 ; function’s prologue, and 8 for the return address saved on the stack by the
463 ; call instruction that reached this function.
464 lea rax, [rbp+16]
465 mov [rcx.CONTEXT].c_Rsp, rax
466
467 ; The original rbp was saved on the stack in this function’s prologue.
468 mov rax, qword ptr [rbp]
469 mov [rcx.CONTEXT].c_Rbp, rax
470
471 ; rip can’t be accessed directly, but the return address saved on the stack by
472 ; the call instruction that reached this function can be used.
473 mov rax, qword ptr [rbp+8]
474 mov [rcx.CONTEXT].c_Rip, rax
475
476 ; Zero out the fxsave area before performing the fxsave. Some of the fxsave
477 ; area may not be written by fxsave, and some is definitely not written by
478 ; fxsave. This also zeroes out the rest of the CONTEXT structure to its end,
479 ; including the unused VectorRegister and VectorControl fields, and the debug
480 ; control register fields.
481 mov rbx, rcx
482 cld
483 lea rdi, [rcx.CONTEXT].c_FltSave
484 xor rax, rax
485 mov rcx, (sizeof(CONTEXT) - offsetof(CONTEXT, c_FltSave)) / \
486 sizeof(qword) ; 122
487 rep stosq
488 mov rcx, rbx
489
490 ; Save the floating point (including SSE) state. The CONTEXT structure is
491 ; declared as 16-byte-aligned, which is correct for this operation.
492 fxsave [rcx.CONTEXT].c_FltSave
493
494 ; TODO(mark): AVX/xsave support.
495 ; https://code.google.com/p/crashpad/issues/detail?id=58
496
497 ; The register parameter home address fields aren’t used, so zero them out.
498 mov [rcx.CONTEXT].c_P1Home, 0
499 mov [rcx.CONTEXT].c_P2Home, 0
500 mov [rcx.CONTEXT].c_P3Home, 0
501 mov [rcx.CONTEXT].c_P4Home, 0
502 mov [rcx.CONTEXT].c_P5Home, 0
503 mov [rcx.CONTEXT].c_P6Home, 0
504
505 ; The debug registers can’t be read from user code, so zero them out in the
506 ; CONTEXT structure. context->ContextFlags doesn’t indicate that they are
507 ; present.
508 mov [rcx.CONTEXT].c_Dr0, 0
509 mov [rcx.CONTEXT].c_Dr1, 0
510 mov [rcx.CONTEXT].c_Dr2, 0
511 mov [rcx.CONTEXT].c_Dr3, 0
512 mov [rcx.CONTEXT].c_Dr6, 0
513 mov [rcx.CONTEXT].c_Dr7, 0
514
515 ; Clean up by restoring clobbered registers, even those considered volatile by
516 ; the ABI, so that the captured context represents the state at this
517 ; function’s exit.
518 mov rax, [rcx.CONTEXT].c_Rax
519 mov rbx, [rcx.CONTEXT].c_Rbx
520 mov rdi, [rcx.CONTEXT].c_Rdi
521 popfq
522
523 pop rbp
524
525 ret
526
527 CAPTURECONTEXT_SYMBOL endp
528
529 endif
530
531 _TEXT ends
532 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