Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/137.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
当ExceptionCode为STATUS\u UNWIND\u CONSOLIDATE时,RTLRESTORECOTEXT做什么? 我试图理解C++异常处理是如何在VisualC++运行时在X64上实现的。_C++_64 Bit_Seh - Fatal编程技术网

当ExceptionCode为STATUS\u UNWIND\u CONSOLIDATE时,RTLRESTORECOTEXT做什么? 我试图理解C++异常处理是如何在VisualC++运行时在X64上实现的。

当ExceptionCode为STATUS\u UNWIND\u CONSOLIDATE时,RTLRESTORECOTEXT做什么? 我试图理解C++异常处理是如何在VisualC++运行时在X64上实现的。,c++,64-bit,seh,C++,64 Bit,Seh,在阅读Nynave关于x64 at上SEH实现的博客后,RtlUnwindEx似乎调用了RtlRestoreContext,将ExceptionCode设置为STATUS_UNWIND_CONSOLIDATE以进行帧合并展开 我不完全清楚的是RtlRestoreContext会做什么?MSDN声明“在调用回调函数之前,RtlRestoreContext在其帧和上下文记录中指定的帧之间合并调用帧。这会隐藏帧,使其不受回调函数中可能发生的任何异常处理的影响。” “在其帧和上下文记录中指定的帧之间合并

在阅读Nynave关于x64 at上SEH实现的博客后,RtlUnwindEx似乎调用了RtlRestoreContext,将ExceptionCode设置为STATUS_UNWIND_CONSOLIDATE以进行帧合并展开

我不完全清楚的是RtlRestoreContext会做什么?MSDN声明“在调用回调函数之前,RtlRestoreContext在其帧和上下文记录中指定的帧之间合并调用帧。这会隐藏帧,使其不受回调函数中可能发生的任何异常处理的影响。”

“在其帧和上下文记录中指定的帧之间合并调用帧”是什么意思?这是如何“对回调函数中可能发生的任何异常处理隐藏帧”?“框架整合”是什么意思?框架整合在哪里

让我们说,C++ catch抓取器是由RTLRebug Enter调用的,它抛出另一个异常——是(抛出)异常被某种SEH块保护吗?或者,这个框架整合业务以某种方式解决了这个问题?如果是,如何进行?

请参阅

图6从异常中解除

可能是“合并”的意思参见

图6从异常中解除


可能是“合并”的意思如果您遵循该函数,您将看到在您所指的情况下,代码在堆栈上设置了一个伪机器框架(相对于[r8],仅填充RIP和RSP),从原始上下文传递到RtlRestoreContext。然后,它将原始上下文复制到机器框架下分配的堆栈空间中

有关机架的更多信息,请参阅(UWOP_PUSH_MACHFRAME下)

代码跳转到博客中提到的伪函数NTDLL!RCF框架整合

如果我们检查该函数的函数表和展开项,就会发现它包含与伪堆栈帧设置相对应的元数据:

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的角度来看,调用堆栈是OriginalContext->RtlRestoreContext->[用户提供的回调],其间没有任何内容

因此,如果堆栈“展开”,则ContextRecord描述的帧与RtlRestoreContext中的当前上下文之间的所有中间帧都“被遗忘”。i、 e.框架已合并为单个框架,该框架作为单个功能展开。 因此,如果在ExceptionRecord中传递的回调函数中发生异常,则这些中间帧中的任何异常处理程序都将隐藏。 正如博客所指出的,这个功能对于语言异常处理非常有用


正如MS文档还指出的那样,中间堆栈帧的局部变量在调用回调之前不会被破坏,如果在该函数的堆栈帧上分配了某种语言的异常对象,这将非常有用。

如果您遵循该函数,您将看到在您所指的情况下,代码在堆栈上设置了一个伪机器框架(相对于[r8],仅填充RIP和RSP),该框架来自传递给RTLRESTORENCTEXT的原始上下文。然后,它将原始上下文复制到机器框架下分配的堆栈空间中

有关机架的更多信息,请参阅(UWOP_PUSH_MACHFRAME下)

代码跳转到博客中提到的伪函数NTDLL!RCF框架整合

如果我们检查该函数的函数表和展开项,就会发现它包含与伪堆栈帧设置相对应的元数据:

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的角度来看,调用堆栈是OriginalContext->RtlRestoreContext->[用户提供的回调],其间没有任何内容

因此,如果堆栈“展开”,则ContextRecord描述的帧与RtlRestoreContext中的当前上下文之间的所有中间帧都“被遗忘”。i、 e.框架已合并为单个框架,该框架作为单个功能展开。 因此,如果在ExceptionRecord中传递的回调函数中发生异常,则这些中间帧中的任何异常处理程序都将隐藏。 正如博客所指出的,这个功能对于语言异常处理非常有用

正如MS文档还指出的那样,中间堆栈帧的局部变量在调用回调之前不会被破坏,如果在该函数的堆栈帧上分配了某种语言的异常对象,这将非常有用