【问题标题】:How can I debug x64 windows exceptions?如何调试 x64 windows 异常?
【发布时间】:2021-03-19 22:59:00
【问题描述】:

我很好奇 Windows 如何处理异常。更准确地说,Windows 如何找到 try/catch 的 catch 块。我看到编译器在汇编中为 catch 块创建了一个单独的函数。由于 catch 块由汇编中的另一个函数表示,因此我无法找到生成异常的指令与 .pdata 部分的 RUNTIME_FUNCTION 条目之间的任何关联。

我尝试在 RaiseException、RtlRaiseException 和 RtlVirtualUnwind 上设置断点,但我只能找到 RaiseException 调用之后的地址。尝试调试除以 0 异常,但调试器似乎有一些额外的异常处理程序,并且未打印 catch 块中的消息。

欢迎提供有关 Windows 64 位堆栈展开的任何其他信息:D。

【问题讨论】:

  • RtlVirtualUnwind 访问了 Runtime_Function 数据,我认为您无法调试它,因为这是调试器与异常处理机制交互的内部机制,从而给您一种简单的 goto on error 错觉。这一点都不简单,因为您需要知道方法中每条指令的确切堆栈布局,才能在堆栈上找到返回地址。这就是 Runtime_Function 数据的用途。
  • 当我在玩那些东西时,请从一些指针中查看web.archive.org/web/20160306065103/http://geekswithblogs.net/…。有些链接可能仍然有效。

标签: windows exception 64-bit stack-unwinding


【解决方案1】:

异常由异常处理例程处理。 当您向 C++ 代码添加 try/catch 块时,您将看到编译器将 __CxxFrameHandler3 添加到您的导入表中(假设 MSVCRT 不是静态链接的)。所以这是你的异常处理程序,当 try 块中发生异常时将调用它。 当您将 __try/__except 块添加到 C 或 C++ 代码时,会导入另一个 __C_specific_handler。 还有一些其他的,但这两个在 C/C++ 代码中使用。

要回答您的问题,最好的方法是挂钩(将导入表指针替换为指向本地例程的指针)其中一个函数,并查看在引发异常时如何调用您的“处理程序”。

【讨论】:

    【解决方案2】:

    以找到 C++ catch 为目标,您可以设置 Vectored Exception Handler 并在其中设置断点。 VEH 先于基于帧的处理程序,所以现在还为时不晚:

    LONG NTAPI vh(EXCEPTION_POINTERS* ExceptionInfo)
    {
        return EXCEPTION_CONTINUE_SEARCH;
    }
    
    AddVectoredExceptionHandler(TRUE, vh);
    

    或者,如果您想将断点设置为更接近catch 块,则在调用堆栈中将__try...__except 设置为比目标catch 块更深,在__except 表达式中返回EXCEPTION_CONTINUE_SEARCH 并在那里设置断点。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-07-03
      • 2014-02-16
      • 2011-02-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-05-29
      • 1970-01-01
      相关资源
      最近更新 更多