5fd59c65 |
1 | ;******************************************************************************\r |
2 | ;*\r |
3 | ;* Copyright (c) 2006, Intel Corporation \r |
4 | ;* All rights reserved. This program and the accompanying materials \r |
5 | ;* are licensed and made available under the terms and conditions of the BSD License \r |
6 | ;* which accompanies this distribution. The full text of the license may be found at \r |
7 | ;* http://opensource.org/licenses/bsd-license.php \r |
8 | ;* \r |
9 | ;* THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, \r |
10 | ;* WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. \r |
11 | ;*\r |
12 | ;******************************************************************************\r |
13 | \r |
14 | EXCPT64_DIVIDE_ERROR EQU 0\r |
15 | EXCPT64_DEBUG EQU 1\r |
16 | EXCPT64_NMI EQU 2\r |
17 | EXCPT64_BREAKPOINT EQU 3\r |
18 | EXCPT64_OVERFLOW EQU 4\r |
19 | EXCPT64_BOUND EQU 5\r |
20 | EXCPT64_INVALID_OPCODE EQU 6\r |
21 | EXCPT64_DOUBLE_FAULT EQU 8\r |
22 | EXCPT64_INVALID_TSS EQU 10\r |
23 | EXCPT64_SEG_NOT_PRESENT EQU 11\r |
24 | EXCPT64_STACK_FAULT EQU 12\r |
25 | EXCPT64_GP_FAULT EQU 13\r |
26 | EXCPT64_PAGE_FAULT EQU 14\r |
27 | EXCPT64_FP_ERROR EQU 16\r |
28 | EXCPT64_ALIGNMENT_CHECK EQU 17\r |
29 | EXCPT64_MACHINE_CHECK EQU 18\r |
30 | EXCPT64_SIMD EQU 19\r |
31 | \r |
32 | FXSTOR_FLAG EQU 01000000h ; bit cpuid 24 of feature flags\r |
33 | \r |
34 | ;; The FXSTOR and FXRSTOR commands are used for saving and restoring the x87,\r |
35 | ;; MMX, SSE, SSE2, etc registers. The initialization of the debugsupport driver\r |
36 | ;; MUST check the CPUID feature flags to see that these instructions are available\r |
37 | ;; and fail to init if they are not.\r |
38 | \r |
39 | ;; fxstor [rdi]\r |
40 | FXSTOR_RDI MACRO\r |
41 | db 0fh, 0aeh, 00000111y ; mod = 00, reg/op = 000, r/m = 111 = [rdi]\r |
42 | ENDM\r |
43 | \r |
44 | ;; fxrstor [rsi]\r |
45 | FXRSTOR_RSI MACRO\r |
46 | db 0fh, 0aeh, 00001110y ; mod = 00, reg/op = 001, r/m = 110 = [rsi]\r |
47 | ENDM\r |
48 | \r |
49 | data SEGMENT\r |
50 | \r |
51 | public OrigVector, InterruptEntryStub, StubSize, CommonIdtEntry, FxStorSupport\r |
52 | \r |
53 | StubSize dd InterruptEntryStubEnd - InterruptEntryStub\r |
54 | AppRsp dq 1111111111111111h ; ?\r |
55 | DebugRsp dq 2222222222222222h ; ?\r |
56 | ExtraPush dq 3333333333333333h ; ?\r |
57 | ExceptData dq 4444444444444444h ; ?\r |
58 | Rflags dq 5555555555555555h ; ?\r |
59 | OrigVector dq 6666666666666666h ; ?\r |
60 | \r |
61 | ;; The declarations below define the memory region that will be used for the debug stack.\r |
62 | ;; The context record will be built by pushing register values onto this stack.\r |
63 | ;; It is imparitive that alignment be carefully managed, since the FXSTOR and\r |
64 | ;; FXRSTOR instructions will GP fault if their memory operand is not 16 byte aligned.\r |
65 | ;;\r |
66 | ;; The stub will switch stacks from the application stack to the debuger stack\r |
67 | ;; and pushes the exception number.\r |
68 | ;;\r |
69 | ;; Then we building the context record on the stack. Since the stack grows down,\r |
70 | ;; we push the fields of the context record from the back to the front. There\r |
71 | ;; are 336 bytes of stack used prior allocating the 512 bytes of stack to be\r |
72 | ;; used as the memory buffer for the fxstor instruction. Therefore address of\r |
73 | ;; the buffer used for the FXSTOR instruction is &Eax - 336 - 512, which\r |
74 | ;; must be 16 byte aligned.\r |
75 | ;;\r |
76 | ;; We carefully locate the stack to make this happen.\r |
77 | ;;\r |
78 | ;; For reference, the context structure looks like this:\r |
79 | ;; struct {\r |
80 | ;; UINT64 ExceptionData;\r |
81 | ;; FX_SAVE_STATE_X64 FxSaveState; // 512 bytes, must be 16 byte aligned\r |
82 | ;; UINT64 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7;\r |
83 | ;; UINT64 Cr0, Cr1, Cr2, Cr3, Cr4, Cr8;\r |
84 | ;; UINT64 RFlags;\r |
85 | ;; UINT64 Ldtr, Tr;\r |
86 | ;; UINT64 Gdtr[2], Idtr[2];\r |
87 | ;; UINT64 Rip;\r |
88 | ;; UINT64 Gs, Fs, Es, Ds, Cs, Ss;\r |
89 | ;; UINT64 Rdi, Rsi, Rbp, Rsp, Rbx, Rdx, Rcx, Rax;\r |
90 | ;; UINT64 R8, R9, R10, R11, R12, R13, R14, R15;\r |
91 | ;; } SYSTEM_CONTEXT_X64; // 64 bit system context record\r |
92 | \r |
93 | align 16\r |
94 | DebugStackEnd db "DbgStkEnd >>>>>>" ;; 16 byte long string - must be 16 bytes to preserve alignment\r |
95 | dd 1ffch dup (000000000h) ;; 32K should be enough stack\r |
96 | ;; This allocation is coocked to insure \r |
97 | ;; that the the buffer for the FXSTORE instruction\r |
98 | ;; will be 16 byte aligned also.\r |
99 | ;;\r |
100 | ExceptionNumber dq ? ;; first entry will be the vector number pushed by the stub\r |
101 | \r |
102 | DebugStackBegin db "<<<< DbgStkBegin" ;; initial debug ESP == DebugStackBegin, set in stub\r |
103 | \r |
104 | data ENDS\r |
105 | \r |
106 | text SEGMENT\r |
107 | \r |
108 | externdef InterruptDistrubutionHub:near\r |
109 | \r |
110 | ;------------------------------------------------------------------------------\r |
111 | ; VOID\r |
112 | ; EfiWbinvd (\r |
113 | ; VOID\r |
114 | ; )\r |
115 | ;\r |
116 | ; Abstract: Writeback and invalidate cache\r |
117 | ;\r |
118 | EfiWbinvd PROC PUBLIC\r |
119 | wbinvd\r |
120 | ret\r |
121 | EfiWbinvd ENDP\r |
122 | \r |
123 | ;------------------------------------------------------------------------------\r |
124 | ; BOOLEAN\r |
125 | ; FxStorSupport (\r |
126 | ; void\r |
127 | ; )\r |
128 | ;\r |
129 | ; Abstract: Returns TRUE if FxStor instructions are supported\r |
130 | ;\r |
131 | FxStorSupport PROC PUBLIC\r |
132 | \r |
133 | ;\r |
134 | ; cpuid corrupts rbx which must be preserved per the C calling convention\r |
135 | ;\r |
136 | push rbx\r |
137 | mov rax, 1\r |
138 | cpuid\r |
139 | mov eax, edx\r |
140 | and rax, FXSTOR_FLAG\r |
141 | shr rax, 24\r |
142 | pop rbx\r |
143 | ret\r |
144 | FxStorSupport ENDP\r |
145 | \r |
146 | \r |
147 | ;------------------------------------------------------------------------------\r |
148 | ; DESCRIPTOR *\r |
149 | ; GetIdtr (\r |
150 | ; void\r |
151 | ; )\r |
152 | ;\r |
153 | ; Abstract: Returns physical address of IDTR\r |
154 | ;\r |
155 | GetIdtr PROC PUBLIC\r |
156 | push rbp\r |
157 | mov rbp, rsp\r |
158 | \r |
159 | sub rsp, 8h\r |
160 | sidt QWORD PTR [rbp - 6]\r |
161 | mov rax, QWORD PTR [rbp - 4]\r |
162 | \r |
163 | mov rsp, rbp\r |
164 | pop rbp\r |
165 | ret\r |
166 | GetIdtr ENDP\r |
167 | \r |
168 | \r |
169 | ;------------------------------------------------------------------------------\r |
170 | ; BOOLEAN\r |
171 | ; WriteInterruptFlag (\r |
172 | ; BOOLEAN NewState // rcx\r |
173 | ; )\r |
174 | ;\r |
175 | ; Abstract: Programs interrupt flag to the requested state and returns previous\r |
176 | ; state.\r |
177 | ;\r |
178 | WriteInterruptFlag PROC PUBLIC\r |
179 | \r |
180 | pushfq\r |
181 | pop rax\r |
182 | and rax, 200h\r |
183 | shr rax, 9\r |
184 | cmp rcx, 0\r |
185 | jnz EnableIF\r |
186 | cli\r |
187 | ret\r |
188 | EnableIF:\r |
189 | sti\r |
190 | ret\r |
191 | \r |
192 | WriteInterruptFlag ENDP\r |
193 | \r |
194 | \r |
195 | \r |
196 | ;------------------------------------------------------------------------------\r |
197 | ; void\r |
198 | ; Vect2Desc (\r |
199 | ; DESCRIPTOR * DestDesc, // rcx\r |
200 | ; void (*Vector) (void) // rdx\r |
201 | ; )\r |
202 | ;\r |
203 | ; Abstract: Encodes an IDT descriptor with the given physical address\r |
204 | ;\r |
205 | Vect2Desc PROC PUBLIC\r |
206 | \r |
207 | mov rax, rdx\r |
208 | mov word ptr [rcx], ax ; write bits 15..0 of offset\r |
209 | mov dx, cs\r |
210 | mov word ptr [rcx+2], dx ; SYS_CODE_SEL from GDT\r |
211 | mov word ptr [rcx+4], 0e00h OR 8000h ; type = 386 interrupt gate, present\r |
212 | shr rax, 16\r |
213 | mov word ptr [rcx+6], ax ; write bits 31..16 of offset\r |
214 | shr rax, 16\r |
215 | mov dword ptr [rcx+8], eax ; write bits 63..32 of offset\r |
216 | \r |
217 | ret\r |
218 | \r |
219 | Vect2Desc ENDP\r |
220 | \r |
221 | \r |
222 | \r |
223 | ;------------------------------------------------------------------------------\r |
224 | ; InterruptEntryStub\r |
225 | ;\r |
226 | ; Abstract: This code is not a function, but is a small piece of code that is\r |
227 | ; copied and fixed up once for each IDT entry that is hooked.\r |
228 | ;\r |
229 | InterruptEntryStub::\r |
230 | push 0 ; push vector number - will be modified before installed\r |
231 | db 0e9h ; jump rel32\r |
232 | dd 0 ; fixed up to relative address of CommonIdtEntry\r |
233 | InterruptEntryStubEnd:\r |
234 | \r |
235 | \r |
236 | \r |
237 | ;------------------------------------------------------------------------------\r |
238 | ; CommonIdtEntry\r |
239 | ;\r |
240 | ; Abstract: This code is not a function, but is the common part for all IDT\r |
241 | ; vectors.\r |
242 | ;\r |
243 | CommonIdtEntry::\r |
244 | ;;\r |
245 | ;; At this point, the stub has saved the current application stack esp into AppRsp\r |
246 | ;; and switched stacks to the debug stack, where it pushed the vector number\r |
247 | ;;\r |
248 | ;; The application stack looks like this:\r |
249 | ;;\r |
250 | ;; ...\r |
251 | ;; (last application stack entry)\r |
252 | ;; [16 bytes alignment, do not care it]\r |
253 | ;; SS from interrupted task\r |
254 | ;; RSP from interrupted task\r |
255 | ;; rflags from interrupted task\r |
256 | ;; CS from interrupted task\r |
257 | ;; RIP from interrupted task\r |
258 | ;; Error code <-------------------- Only present for some exeption types\r |
259 | ;;\r |
260 | ;; Vector Number <----------------- pushed in our IDT Entry\r |
261 | ;;\r |
262 | \r |
263 | \r |
264 | ;; The stub switched us to the debug stack and pushed the interrupt number.\r |
265 | ;;\r |
266 | ;; Next, construct the context record. It will be build on the debug stack by\r |
267 | ;; pushing the registers in the correct order so as to create the context structure\r |
268 | ;; on the debug stack. The context record must be built from the end back to the\r |
269 | ;; beginning because the stack grows down...\r |
270 | ;\r |
271 | ;; For reference, the context record looks like this:\r |
272 | ;;\r |
273 | ;; typedef\r |
274 | ;; struct {\r |
275 | ;; UINT64 ExceptionData;\r |
276 | ;; FX_SAVE_STATE_X64 FxSaveState;\r |
277 | ;; UINT64 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7;\r |
278 | ;; UINT64 Cr0, Cr2, Cr3, Cr4, Cr8;\r |
279 | ;; UINT64 RFlags;\r |
280 | ;; UINT64 Ldtr, Tr;\r |
281 | ;; UINT64 Gdtr[2], Idtr[2];\r |
282 | ;; UINT64 Rip;\r |
283 | ;; UINT64 Gs, Fs, Es, Ds, Cs, Ss;\r |
284 | ;; UINT64 Rdi, Rsi, Rbp, Rsp, Rbx, Rdx, Rcx, Rax;\r |
285 | ;; UINT64 R8, R9, R10, R11, R12, R13, R14, R15;\r |
286 | ;; } SYSTEM_CONTEXT_X64; // 64 bit system context record\r |
287 | \r |
288 | ;; NOTE: we save rsp here to prevent compiler put rip reference cause error AppRsp\r |
289 | push rax\r |
290 | mov rax, qword ptr [rsp][8] ; save vector number\r |
291 | mov ExceptionNumber, rax ; save vector number\r |
292 | pop rax\r |
293 | add rsp, 8 ; pop vector number\r |
294 | mov AppRsp, rsp ; save stack top\r |
295 | mov rsp, offset DebugStackBegin ; switch to debugger stack\r |
296 | sub rsp, 8 ; leave space for vector number\r |
297 | \r |
298 | ;; UINT64 Rdi, Rsi, Rbp, Rsp, Rbx, Rdx, Rcx, Rax;\r |
299 | ;; UINT64 R8, R9, R10, R11, R12, R13, R14, R15;\r |
300 | push r15\r |
301 | push r14\r |
302 | push r13\r |
303 | push r12\r |
304 | push r11\r |
305 | push r10\r |
306 | push r9\r |
307 | push r8\r |
308 | push rax\r |
309 | push rcx\r |
310 | push rdx\r |
311 | push rbx\r |
312 | push rsp\r |
313 | push rbp\r |
314 | push rsi\r |
315 | push rdi\r |
316 | \r |
317 | ;; Save interrupt state rflags register...\r |
318 | pushfq\r |
319 | pop rax\r |
320 | mov qword ptr Rflags, rax\r |
321 | \r |
322 | ;; We need to determine if any extra data was pushed by the exception, and if so, save it\r |
323 | ;; To do this, we check the exception number pushed by the stub, and cache the\r |
324 | ;; result in a variable since we'll need this again.\r |
325 | cmp ExceptionNumber, EXCPT64_DOUBLE_FAULT\r |
326 | jz ExtraPushOne\r |
327 | cmp ExceptionNumber, EXCPT64_INVALID_TSS\r |
328 | jz ExtraPushOne\r |
329 | cmp ExceptionNumber, EXCPT64_SEG_NOT_PRESENT\r |
330 | jz ExtraPushOne\r |
331 | cmp ExceptionNumber, EXCPT64_STACK_FAULT\r |
332 | jz ExtraPushOne\r |
333 | cmp ExceptionNumber, EXCPT64_GP_FAULT\r |
334 | jz ExtraPushOne\r |
335 | cmp ExceptionNumber, EXCPT64_PAGE_FAULT\r |
336 | jz ExtraPushOne\r |
337 | cmp ExceptionNumber, EXCPT64_ALIGNMENT_CHECK\r |
338 | jz ExtraPushOne\r |
339 | mov ExtraPush, 0\r |
340 | mov ExceptData, 0\r |
341 | jmp ExtraPushDone\r |
342 | ExtraPushOne:\r |
343 | mov ExtraPush, 1\r |
344 | \r |
345 | ;; If there's some extra data, save it also, and modify the saved AppRsp to effectively\r |
346 | ;; pop this value off the application's stack.\r |
347 | mov rax, AppRsp\r |
348 | mov rbx, [rax]\r |
349 | mov ExceptData, rbx\r |
350 | add rax, 8\r |
351 | mov AppRsp, rax\r |
352 | \r |
353 | ExtraPushDone:\r |
354 | \r |
355 | ;; The "push" above pushed the debug stack rsp. Since what we're actually doing\r |
356 | ;; is building the context record on the debug stack, we need to save the pushed\r |
357 | ;; debug RSP, and replace it with the application's last stack entry...\r |
358 | mov rax, [rsp + 24]\r |
359 | mov DebugRsp, rax\r |
360 | mov rax, AppRsp\r |
361 | add rax, 40\r |
362 | ; application stack has ss, rsp, rflags, cs, & rip, so\r |
363 | ; last actual application stack entry is\r |
364 | ; 40 bytes into the application stack.\r |
365 | mov [rsp + 24], rax\r |
366 | \r |
367 | ;; continue building context record\r |
368 | ;; UINT64 Gs, Fs, Es, Ds, Cs, Ss; insure high 16 bits of each is zero\r |
369 | mov rax, ss\r |
370 | push rax\r |
371 | \r |
372 | ; CS from application is one entry back in application stack\r |
373 | mov rax, AppRsp\r |
374 | movzx rax, word ptr [rax + 8]\r |
375 | push rax\r |
376 | \r |
377 | mov rax, ds\r |
378 | push rax\r |
379 | mov rax, es\r |
380 | push rax\r |
381 | mov rax, fs\r |
382 | push rax\r |
383 | mov rax, gs\r |
384 | push rax\r |
385 | \r |
386 | ;; UINT64 Rip;\r |
387 | ; Rip from application is on top of application stack\r |
388 | mov rax, AppRsp\r |
389 | push qword ptr [rax]\r |
390 | \r |
391 | ;; UINT64 Gdtr[2], Idtr[2];\r |
392 | push 0\r |
393 | push 0\r |
394 | sidt fword ptr [rsp]\r |
395 | push 0\r |
396 | push 0\r |
397 | sgdt fword ptr [rsp]\r |
398 | \r |
399 | ;; UINT64 Ldtr, Tr;\r |
400 | xor rax, rax\r |
401 | str ax\r |
402 | push rax\r |
403 | sldt ax\r |
404 | push rax\r |
405 | \r |
406 | ;; UINT64 RFlags;\r |
407 | ;; Rflags from application is two entries back in application stack\r |
408 | mov rax, AppRsp\r |
409 | push qword ptr [rax + 16]\r |
410 | \r |
411 | ;; UINT64 Cr0, Cr1, Cr2, Cr3, Cr4, Cr8;\r |
412 | ;; insure FXSAVE/FXRSTOR is enabled in CR4...\r |
413 | ;; ... while we're at it, make sure DE is also enabled...\r |
414 | mov rax, cr8\r |
415 | push rax\r |
416 | mov rax, cr4\r |
417 | or rax, 208h\r |
418 | mov cr4, rax\r |
419 | push rax\r |
420 | mov rax, cr3\r |
421 | push rax\r |
422 | mov rax, cr2\r |
423 | push rax\r |
424 | push 0\r |
425 | mov rax, cr0\r |
426 | push rax\r |
427 | \r |
428 | ;; UINT64 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7;\r |
429 | mov rax, dr7\r |
430 | push rax\r |
431 | ;; clear Dr7 while executing debugger itself\r |
432 | xor rax, rax\r |
433 | mov dr7, rax\r |
434 | \r |
435 | mov rax, dr6\r |
436 | push rax\r |
437 | ;; insure all status bits in dr6 are clear...\r |
438 | xor rax, rax\r |
439 | mov dr6, rax\r |
440 | \r |
441 | mov rax, dr3\r |
442 | push rax\r |
443 | mov rax, dr2\r |
444 | push rax\r |
445 | mov rax, dr1\r |
446 | push rax\r |
447 | mov rax, dr0\r |
448 | push rax\r |
449 | \r |
450 | ;; FX_SAVE_STATE_X64 FxSaveState;\r |
451 | sub rsp, 512\r |
452 | mov rdi, rsp\r |
453 | ; IMPORTANT!! The debug stack has been carefully constructed to\r |
454 | ; insure that rsp and rdi are 16 byte aligned when we get here.\r |
455 | ; They MUST be. If they are not, a GP fault will occur.\r |
456 | FXSTOR_RDI\r |
457 | \r |
458 | ;; UINT64 ExceptionData;\r |
459 | mov rax, ExceptData\r |
460 | push rax\r |
461 | \r |
462 | ; call to C code which will in turn call registered handler\r |
463 | ; pass in the vector number\r |
464 | mov rdx, rsp\r |
465 | mov rcx, ExceptionNumber\r |
466 | sub rsp, 40\r |
467 | call InterruptDistrubutionHub\r |
468 | add rsp, 40\r |
469 | \r |
470 | ; restore context...\r |
471 | ;; UINT64 ExceptionData;\r |
472 | add rsp, 8\r |
473 | \r |
474 | ;; FX_SAVE_STATE_X64 FxSaveState;\r |
475 | mov rsi, rsp\r |
476 | FXRSTOR_RSI\r |
477 | add rsp, 512\r |
478 | \r |
479 | ;; UINT64 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7;\r |
480 | pop rax\r |
481 | mov dr0, rax\r |
482 | pop rax\r |
483 | mov dr1, rax\r |
484 | pop rax\r |
485 | mov dr2, rax\r |
486 | pop rax\r |
487 | mov dr3, rax\r |
488 | ;; skip restore of dr6. We cleared dr6 during the context save.\r |
489 | add rsp, 8\r |
490 | pop rax\r |
491 | mov dr7, rax\r |
492 | \r |
493 | ;; UINT64 Cr0, Cr1, Cr2, Cr3, Cr4, Cr8;\r |
494 | pop rax\r |
495 | mov cr0, rax\r |
496 | add rsp, 8\r |
497 | pop rax\r |
498 | mov cr2, rax\r |
499 | pop rax\r |
500 | mov cr3, rax\r |
501 | pop rax\r |
502 | mov cr4, rax\r |
503 | pop rax\r |
504 | mov cr8, rax\r |
505 | \r |
506 | ;; UINT64 RFlags;\r |
507 | mov rax, AppRsp\r |
508 | pop qword ptr [rax + 16]\r |
509 | \r |
510 | ;; UINT64 Ldtr, Tr;\r |
511 | ;; UINT64 Gdtr[2], Idtr[2];\r |
512 | ;; Best not let anyone mess with these particular registers...\r |
513 | add rsp, 48\r |
514 | \r |
515 | ;; UINT64 Rip;\r |
516 | pop qword ptr [rax]\r |
517 | \r |
518 | ;; UINT64 Gs, Fs, Es, Ds, Cs, Ss;\r |
519 | ;; NOTE - modified segment registers could hang the debugger... We\r |
520 | ;; could attempt to insulate ourselves against this possibility,\r |
521 | ;; but that poses risks as well.\r |
522 | ;;\r |
523 | \r |
524 | pop rax\r |
525 | ; mov gs, rax\r |
526 | pop rax\r |
527 | ; mov fs, rax\r |
528 | pop rax\r |
529 | mov es, rax\r |
530 | pop rax\r |
531 | mov ds, rax\r |
532 | mov rax, AppRsp\r |
533 | pop qword ptr [rax + 8]\r |
534 | pop rax\r |
535 | mov ss, rax\r |
536 | \r |
537 | ;; The next stuff to restore is the general purpose registers that were pushed\r |
538 | ;; using the "push" instruction.\r |
539 | ;;\r |
540 | ;; The value of RSP as stored in the context record is the application RSP\r |
541 | ;; including the 5 entries on the application stack caused by the exception\r |
542 | ;; itself. It may have been modified by the debug agent, so we need to\r |
543 | ;; determine if we need to relocate the application stack.\r |
544 | \r |
545 | mov rbx, [rsp + 24] ; move the potentially modified AppRsp into rbx\r |
546 | mov rax, AppRsp\r |
547 | add rax, 40\r |
548 | cmp rbx, rax\r |
549 | je NoAppStackMove\r |
550 | \r |
551 | mov rax, AppRsp\r |
552 | mov rcx, [rax] ; RIP\r |
553 | mov [rbx], rcx\r |
554 | \r |
555 | mov rcx, [rax + 8] ; CS\r |
556 | mov [rbx + 8], rcx\r |
557 | \r |
558 | mov rcx, [rax + 16] ; RFLAGS\r |
559 | mov [rbx + 16], rcx\r |
560 | \r |
561 | mov rcx, [rax + 24] ; RSP\r |
562 | mov [rbx + 24], rcx\r |
563 | \r |
564 | mov rcx, [rax + 32] ; SS\r |
565 | mov [rbx + 32], rcx\r |
566 | \r |
567 | mov rax, rbx ; modify the saved AppRsp to the new AppRsp\r |
568 | mov AppRsp, rax\r |
569 | NoAppStackMove:\r |
570 | mov rax, DebugRsp ; restore the DebugRsp on the debug stack\r |
571 | ; so our "pop" will not cause a stack switch\r |
572 | mov [rsp + 24], rax\r |
573 | \r |
574 | cmp ExceptionNumber, 068h\r |
575 | jne NoChain\r |
576 | \r |
577 | Chain:\r |
578 | \r |
579 | ;; Restore rflags so when we chain, the flags will be exactly as if we were never here.\r |
580 | ;; We gin up the stack to do an iretq so we can get ALL the flags.\r |
581 | mov rax, AppRsp\r |
582 | mov rbx, [rax + 40]\r |
583 | push rbx\r |
584 | mov rax, ss\r |
585 | push rax\r |
586 | mov rax, rsp\r |
587 | add rax, 16\r |
588 | push rax\r |
589 | mov rax, AppRsp\r |
590 | mov rbx, [rax + 16]\r |
591 | and rbx, NOT 300h ; special handling for IF and TF\r |
592 | push rbx\r |
593 | mov rax, cs\r |
594 | push rax\r |
595 | mov rax, offset PhonyIretq\r |
596 | push rax\r |
597 | iretq\r |
598 | PhonyIretq:\r |
599 | \r |
600 | ;; UINT64 Rdi, Rsi, Rbp, Rsp, Rbx, Rdx, Rcx, Rax;\r |
601 | ;; UINT64 R8, R9, R10, R11, R12, R13, R14, R15;\r |
602 | pop rdi\r |
603 | pop rsi\r |
604 | pop rbp\r |
605 | pop rsp\r |
606 | pop rbx\r |
607 | pop rdx\r |
608 | pop rcx\r |
609 | pop rax\r |
610 | pop r8\r |
611 | pop r9\r |
612 | pop r10\r |
613 | pop r11\r |
614 | pop r12\r |
615 | pop r13\r |
616 | pop r14\r |
617 | pop r15\r |
618 | \r |
619 | ;; Switch back to application stack\r |
620 | mov rsp, AppRsp\r |
621 | \r |
622 | ;; Jump to original handler\r |
623 | jmp OrigVector\r |
624 | \r |
625 | NoChain:\r |
626 | ;; UINT64 Rdi, Rsi, Rbp, Rsp, Rbx, Rdx, Rcx, Rax;\r |
627 | ;; UINT64 R8, R9, R10, R11, R12, R13, R14, R15;\r |
628 | pop rdi\r |
629 | pop rsi\r |
630 | pop rbp\r |
631 | pop rsp\r |
632 | pop rbx\r |
633 | pop rdx\r |
634 | pop rcx\r |
635 | pop rax\r |
636 | pop r8\r |
637 | pop r9\r |
638 | pop r10\r |
639 | pop r11\r |
640 | pop r12\r |
641 | pop r13\r |
642 | pop r14\r |
643 | pop r15\r |
644 | \r |
645 | ;; Switch back to application stack\r |
646 | mov rsp, AppRsp\r |
647 | \r |
648 | ;; We're outa here...\r |
649 | iretq\r |
650 | text ENDS\r |
651 | \r |
652 | END\r |
653 | \r |
654 | \r |
655 | \r |