Chromium Code Reviews| OLD | NEW |
|---|---|
| (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 | |
|
scottmg
2015/09/30 17:33:38
Context -> CONTEXT for consistency (and the next 2
| |
| 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. Also, zero out the unused VectorRegister and VectorControl fields, | |
| 479 ; and the debug control register fields. | |
|
scottmg
2015/09/30 17:33:38
Maybe something about "the rest of the structure"
| |
| 480 mov rbx, rcx | |
| 481 cld | |
| 482 lea rdi, [rcx.CONTEXT].c_FltSave | |
| 483 xor rax, rax | |
| 484 mov rcx, (sizeof(CONTEXT) - offsetof(CONTEXT, c_FltSave)) / \ | |
| 485 sizeof(qword) ; 122 | |
| 486 rep stosq | |
| 487 mov rcx, rbx | |
| 488 | |
| 489 ; Save the floating point (including SSE) state. The CONTEXT structure is | |
| 490 ; declared as 16-byte-aligned, which is correct for this operation. | |
| 491 fxsave [rcx.CONTEXT].c_FltSave | |
| 492 | |
| 493 ; TODO(mark): AVX/xsave support. | |
| 494 ; https://code.google.com/p/crashpad/issues/detail?id=58 | |
| 495 | |
| 496 ; The register parameter home address fields aren’t used, so zero them out. | |
| 497 mov [rcx.CONTEXT].c_P1Home, 0 | |
| 498 mov [rcx.CONTEXT].c_P2Home, 0 | |
| 499 mov [rcx.CONTEXT].c_P3Home, 0 | |
| 500 mov [rcx.CONTEXT].c_P4Home, 0 | |
| 501 mov [rcx.CONTEXT].c_P5Home, 0 | |
| 502 mov [rcx.CONTEXT].c_P6Home, 0 | |
| 503 | |
| 504 ; The debug registers can’t be read from user code, so zero them out in the | |
| 505 ; CONTEXT structure. context->ContextFlags doesn’t indicate that they are | |
| 506 ; present. | |
| 507 mov [rcx.CONTEXT].c_Dr0, 0 | |
| 508 mov [rcx.CONTEXT].c_Dr1, 0 | |
| 509 mov [rcx.CONTEXT].c_Dr2, 0 | |
| 510 mov [rcx.CONTEXT].c_Dr3, 0 | |
| 511 mov [rcx.CONTEXT].c_Dr6, 0 | |
| 512 mov [rcx.CONTEXT].c_Dr7, 0 | |
| 513 | |
| 514 ; Clean up by restoring clobbered registers, even those considered volatile by | |
| 515 ; the ABI, so that the captured context represents the state at this | |
| 516 ; function’s exit. | |
| 517 mov rax, [rcx.CONTEXT].c_Rax | |
| 518 mov rbx, [rcx.CONTEXT].c_Rbx | |
| 519 mov rdi, [rcx.CONTEXT].c_Rdi | |
| 520 popfq | |
| 521 | |
| 522 pop rbp | |
| 523 | |
| 524 ret | |
| 525 | |
| 526 CAPTURECONTEXT_SYMBOL endp | |
| 527 | |
| 528 endif | |
| 529 | |
| 530 _TEXT ends | |
| 531 end | |
| OLD | NEW |