如果按照功能,你會在這種情況下看意思是說你指的是,代碼在傳遞給RtlRestoreContext的上下文中,在堆棧上建立假機器框架(相對於只填充了RIP和RSP的[r8])。然後它將原始上下文複製到機器框架下分配的堆棧空間中。
有關機器框架的更多信息(在UWOP_PUSH_MACHFRAME下),請參見http://msdn.microsoft.com/en-us/library/ck9asaa9.aspx。
0:004> u ntdll!RtlRestoreContext+0x296
00000000`771f0c05 83ec30 sub esp,30h
00000000`771f0c08 4c8bc4 mov r8,rsp
00000000`771f0c0b 4881ecd0040000 sub rsp,4D0h
00000000`771f0c12 488bf1 mov rsi,rcx
00000000`771f0c15 488bfc mov rdi,rsp
00000000`771f0c18 b99a000000 mov ecx,9Ah
00000000`771f0c1d f348a5 rep movs qword ptr [rdi],qword ptr [rsi]
00000000`771f0c20 488b842498000000 mov rax,qword ptr [rsp+98h]
0:004> u
ntdll!RtlRestoreContext+0x2ba:
00000000`771f0c28 49894018 mov qword ptr [r8+18h],rax
00000000`771f0c2c 488b8424f8000000 mov rax,qword ptr [rsp+0F8h]
00000000`771f0c34 498900 mov qword ptr [r8],rax
00000000`771f0c37 488bca mov rcx,rdx
00000000`771f0c3a eb12 jmp ntdll!RcFrameConsolidation (00000000`771f0c4e)
代碼跳轉到博客正在討論的僞函數NTDLL!RcFrameConsolidation。
如果我們檢查函數表身心條目這個功能,我們看到它包含對應於假堆棧幀設置的元數據:
0:004>.fnent ntdll!rcframeconsolidation
...snip...
Unwind info at 00000000`772c8e0c, 52 bytes
version 1, flags 0, prolog 0, codes 27
00: offs 0, unwind op 8, op info f UWOP_SAVE_XMM128 FrameOffset: 290 reg: xmm15.
02: offs 0, unwind op 8, op info e UWOP_SAVE_XMM128 FrameOffset: 280 reg: xmm14.
04: offs 0, unwind op 8, op info d UWOP_SAVE_XMM128 FrameOffset: 270 reg: xmm13.
06: offs 0, unwind op 8, op info c UWOP_SAVE_XMM128 FrameOffset: 260 reg: xmm12.
08: offs 0, unwind op 8, op info b UWOP_SAVE_XMM128 FrameOffset: 250 reg: xmm11.
0a: offs 0, unwind op 8, op info a UWOP_SAVE_XMM128 FrameOffset: 240 reg: xmm10.
0c: offs 0, unwind op 8, op info 9 UWOP_SAVE_XMM128 FrameOffset: 230 reg: xmm9.
0e: offs 0, unwind op 8, op info 8 UWOP_SAVE_XMM128 FrameOffset: 220 reg: xmm8.
10: offs 0, unwind op 8, op info 7 UWOP_SAVE_XMM128 FrameOffset: 210 reg: xmm7.
12: offs 0, unwind op 8, op info 6 UWOP_SAVE_XMM128 FrameOffset: 200 reg: xmm6.
14: offs 0, unwind op 4, op info f UWOP_SAVE_NONVOL FrameOffset: f0 reg: r15.
16: offs 0, unwind op 4, op info e UWOP_SAVE_NONVOL FrameOffset: e8 reg: r14.
18: offs 0, unwind op 4, op info d UWOP_SAVE_NONVOL FrameOffset: e0 reg: r13.
1a: offs 0, unwind op 4, op info c UWOP_SAVE_NONVOL FrameOffset: d8 reg: r12.
1c: offs 0, unwind op 4, op info 7 UWOP_SAVE_NONVOL FrameOffset: b0 reg: rdi.
1e: offs 0, unwind op 4, op info 6 UWOP_SAVE_NONVOL FrameOffset: a8 reg: rsi.
20: offs 0, unwind op 4, op info 5 UWOP_SAVE_NONVOL FrameOffset: a0 reg: rbp.
22: offs 0, unwind op 4, op info 3 UWOP_SAVE_NONVOL FrameOffset: 90 reg: rbx.
24: offs 0, unwind op 1, op info 0 UWOP_ALLOC_LARGE FrameOffset: 4d0.
26: offs 0, unwind op a, op info 0 UWOP_PUSH_MACHFRAME.
這樣做的效果是「欺騙」 VirtualUnwindEx /異常處理代碼認爲ContextRecord描述的函數是RtlRestoreContext的直接調用者。
從VirtualUnwind的角度來看,callstack是OriginalContext - > RtlRestoreContext - > [用戶提供的回調],兩者之間沒有任何內容。因此,如果堆棧被「解開」,ContextRecord描述的幀與RtlRestoreContext中的當前上下文之間的所有中間幀都被「遺忘」了。即幀被合併爲一個單獨的幀,作爲單個功能展開。 因此,如果在ExceptionRecord中傳遞的回調函數內發生異常,那些中間幀中的任何異常處理程序都將被隱藏。正如博客指出的那樣,這個功能在語言異常處理中非常有用。
正如MS文檔指出的那樣,中間棧幀的本地在調用回調之前不會被銷燬,如果某個語言的異常對象被分配在該函數的堆棧幀上,這非常有用。