2023年1月

User Mode 32bit

0:000> dt nt!_TEB.Stack*

ntdll!_TEB

+0x000 NtTib :

  +0x004 StackBase : Ptr Void

  +0x008 StackLimit : Ptr Void

User Mode 64bit

0:000> dt nt!_TEB NtTib.Stack*

ntdll!_TEB

+0x000 NtTib :

  +0x008 StackBase : Ptr64 Void

  +0x010 StackLimit : Ptr64 Void

Kernel Mode 32bit

0:000> dt nt!_KTHREAD Stack*

ntdll!_KTHREAD

+0x01c StackLimit : Ptr Void (NT v5.0 - Windows 2000)

+0x01c StackLimit : Ptr Void (NT v5.1 - Windows XP SP3)

+0x01c StackLimit : Ptr Void (NT v5.2 - Windows 2003 SP2)

+0x02c StackLimit : Ptr Void (NT v6.0 - Windows Vista/2008)

+0x02c StackLimit : Ptr Void (NT v6.1 - Windows 7/2008R2)

+0x15c StackBase : Ptr Void (NT v5.0 - Windows 2000)

+0x15c StackBase : Ptr Void (NT v5.1 - Windows XP SP3)

+0x158 StackBase : Ptr Void (NT v5.2 - Windows 2003 SP2)

+0x174 StackBase : Ptr Void (NT v6.0 - Windows Vista/2008)

+0x194 StackBase : Ptr Void (NT v6.1 - Windows 7/2008R2)

Kernel Mode 64bit

0:000> dt nt!_KTHREAD Stack*

ntdll!_KTHREAD

+0x??? StackLimit : Ptr64 Void(NT v5.1 - Windows XP SP3)

+0x??? StackLimit : Ptr64 Void(NT v5.2 - Windows 2003 SP2)

+0x030 StackLimit : Ptr64 Void(NT v6.0 - Windows Vista/2008)

+0x030 StackLimit : Ptr64 Void(NT v6.1 - Windows 7/2008R2)

+0x??? StackBase : Ptr64 Void(NT v5.1 - Windows XP SP3)

+0x??? StackBase : Ptr64 Void(NT v5.2 - Windows 2003 SP2)

+0x250 StackBase : Ptr64 Void(NT v6.0 - Windows Vista/2008)

+0x278 StackBase : Ptr64 Void(NT v6.1 - Windows 7/2008R2)

想在win10上重温下经典VC++6.0,结果单步调试时弹出个异常对话框,报((OLE32.DLL): 0xC0000005: Access Violation)

解决方法如下:

1、菜单 工具->选项 中的调试,反汇编下的来源注解取消

2、点确定保存设置,然后即可单步调试
3、再将工具->选项 中的调试,反汇编下的来源注解勾上

很长一段时间以来,我有一个注册表文件来为WinDbg创建上下文菜单项。这些条目允许您选择x86或x64调试器。在公司内部,我有另一个版本的注册表文件,其中包含了私有符号服务器的另外两个上下文菜单项。你可以在这个截图中看到我在内部添加的所有4个选项。

 

注意,注册表文件假定WinDBG安装在c:\调试器_x86和c:\调试器中(分别用于x86和AMD64调试器)。

注册表项传入Microsoft公共符号服务器(http://msdl.Microsoft.com/download/symbols)和Microsoft专用符号服务器的符号路径。在这两种情况下,符号都通过SRV*链接在本地缓存(例如c:\符号)。与体系结构条目非常相似,这种技术为您提供了一种在公共和私有符号之间切换的快速方法(在我的例子中)。符号路径的传递,而不是使用-NT_symbol_path环境变量,是绕过WinDBG所做的具体化的唯一方法。如果设置了环境变量,则该变量将位于传递的符号路径的前面。这意味着仍然可以使用环境变量路径而不是传递路径。我承认,这只是一个问题,为人们需要支持的两个符号商店和绝大多数人,环境变量是一个更好的方式去做。如果这样做,只需删除命令行的-y部分。

注册表文件为所有转储变量建立关联,包括反射转储文件(*.ini)。反射转储可以使用ProcDump和-r开关(例如ProcDump.exe-r-ma notepad.exe)进行。目前,我使用Visual Studio 2010键来获取图标,并且仍然支持通过Open条目在Visual Studio中打开转储(我不知道您为什么要这样做)。
我做的另一件事是加载常用的调试器扩展。在这个(示例)注册表文件中,我只是通过-a开关(为MSDN Magazine调试API系列创建的扩展名)包含了自己的一个扩展名(myext.dll)。如果要加载更多内容,只需在命令行中包含多个-a myext.dll条目。(另请注意,如果对cdb执行相同操作,则不能在-a和dll名称之间留有空格)。在我的个人版本中,我加载了六个扩展。
您可能需要考虑的一件事是添加-WX开关以忽略默认工作区。我亲自按照自己喜欢的方式设置默认工作区(命令窗口停靠、在主监视器上最大化WinDbg、为每个文本类型设置字体颜色等),并将其用作每个新调试会话的模板。因此,我不希望使用-WX开关(这是一个双负数),因为我希望应用工作区。但是,如果要始终使用“开箱即用”默认值,请添加-WX开关。

Windows Registry Editor Version 5.00[HKEY_CLASSES_ROOT\.dmp]
@
="VisualStudio.dmp.10.0"[HKEY_CLASSES_ROOT\.hdmp]
@
="VisualStudio.dmp.10.0"[HKEY_CLASSES_ROOT\.mdmp]
@
="VisualStudio.dmp.10.0"[HKEY_CLASSES_ROOT\.kdmp]
@
="VisualStudio.dmp.10.0"[HKEY_CLASSES_ROOT\.ini]
@
="VisualStudio.dmp.10.0"[HKEY_CLASSES_ROOT\VisualStudio.dmp.10.0\shell]
@
="WinDbg_x64_public"[HKEY_CLASSES_ROOT\VisualStudio.dmp.10.0\shell\WinDbg_x86_public]
@
="Open with WinDbg x86 (Public)"[HKEY_CLASSES_ROOT\VisualStudio.dmp.10.0\shell\WinDbg_x86_public\Command]
@
="\"C:\\Debuggers_x86\\windbg.exe\" -z \"%1\" -a myext.dll -y \"SRV*C:\\Symbols*http://msdl.microsoft.com/download/symbols\\ [HKEY_CLASSES_ROOT\VisualStudio.dmp.10.0\shell\WinDbg_x64_public]
@
="Open with WinDbg x64 (Public)"[HKEY_CLASSES_ROOT\VisualStudio.dmp.10.0\shell\WinDbg_x64_public\Command]
@
="\"C:\\Debuggers\\windbg.exe\" -z \"%1\" -a myext.dll -y \"SRV*C:\\Symbols*http://msdl.microsoft.com/download/symbols\\

“选项”对话框(“工具”菜单)中的“调试”文件夹提供以下页,可以使用它们指定调试器工具选项。下面详细说说。

“选项”对话框 ->“调试”->“常规”

若要访问“常规”页,请单击“工具”菜单并选择“选项”。 在“选项”对话框中,展开“调试”节点并选择“常规”。 该页可设置下列常规调试选项。

  • 在删除所有断点之前询问
    在完成“删除所有断点”命令前需要进行确认。
    就是这个对话框

  • 一个进程中断时则中断所有进程
    发生一个中断时,同时中断调试器附加到的所有进程。

  • 当异常跨越 AppDomain 或托管/本机边界时中断
    在托管或混合模式调试中,如果满足以下条件,公共语言运行时可能会捕获跨越应用程序域边界或托管/本机边界的异常:

    1) 当本机代码使用 COM 互操作调用托管代码而托管代码却引发异常时。

    2) 当在应用程序域 A 中运行的托管代码调用应用程序域 B 中的托管代码而应用程序域 B 中的代码却引发异常时。

    3) 当代码使用反射调用一个函数而该函数却引发异常时。 有关反射的更多信息,请参见 反射。

    在第 2) 和 3) 条中,异常有时由 mscorlib 中的托管代码而不是公共语言运行时捕获。 此选项不影响在 mscorlib 捕获到异常时中断。

  • 启用地址级调试
    启用在地址级上进行调试的高级功能(“反汇编”窗口、“寄存器”窗口和地址断点)。也就是说如果启用该项,将会得到另外三个调试工具:“反汇编”窗口、“寄存器”窗口和地址断点。如果不选中此项,就不会有。

  • 如果源不可用,则显示反汇编
    自动在尝试调试源不可用的代码时显示“反汇编”窗口。

  • 启用断点筛选器
    使您可以在断点上设置筛选器以使其仅影响特定的进程、线程或计算机。当勾选上时,在断点处点击右键可见

    否则不可见

  • 启用异常助手
    仅用于托管代码。 选中此选项时,托管异常打开新的“异常助手”对话框而不是旧的“异常”对话框。 “异常助手”更详细,可提供关于异常的更好帮助。
    勾选上时

    否则

  • 出现未经处理的异常时展开调用堆栈
    导致“调用堆栈”窗口将调用堆栈回滚到未经处理的异常发生之前的点。

  • 启用“仅我的代码”(仅限托管)
    启用此功能时,调试器仅显示和单步执行用户代码(“我的代码”),而忽略系统代码和其他经过优化或没有调试符号的代码。
    那么那些是“你的”代码呢?

    1、你的代码被优化过。
    2、你的代码没有符号
    3、你的代码没有标记DebuggerNonUserCodeAttribute

    例如在一个解决方案里有两个项目:ClassLibrary1 and
    ConsoleApplication1,ConsoleApplication1调用ClassLibrary1 的类在控制台显示一个“hello
    world”,在生成的时候比较ClassLibrary1为优化,在ConsoleApplication1中封装Console.WriteLine方法地方设置一个断点,然后单步调试,到达断点时候,发现在断点处中断了,继续按F11,并没有进入方法内部,而是跳到了下一行。

  • 在变量窗口中显示非用户对象的所有成员(仅限 Visual Basic)
    启用非用户代码(不是“我的代码”)中对象中的非公共成员的显示。

  • 启动时若没有用户代码则发出警告(仅限托管)
    当启用“仅我的代码”进行调试时,此选项在没有用户代码(“我的代码”)的情况下发出警告。

  • 启用 .NET Framework 源代码单步执行
    允许调试器单步执行 .NET Framework 源代码。 自动启用此选项会禁用“仅我的代码”,.NET Framework 符号将下载到缓存位置。 可以在“选项”对话框中“调试”类别下的“符号”页中更改缓存位置。

  • 逐过程执行属性和运算符(仅限托管)
    使调试器无法单步执行托管代码中的属性和运算符。

  • 启用属性求值和其他隐式函数调用
    在变量窗口和“快速监视”对话框中打开属性的自动求值和隐式函数调用。

  • 在变量窗口中对对象调用字符串转换函数(仅限 C# 和 JavaScript)
    在变量窗口中计算对象时,执行隐式字符串转换调用。 因此,结果将显示为字符串而不是类型名。 仅在 C# 代码中进行调试期间适用。 此设置可以由 DebuggerDisplay 特性重写。

  • 启用源服务器支持
    告知 Visual Studio 调试器从用于 Windows 的调试工具中的 SrcSrv 源服务器 (srcsrv.dll) 获取代码。

  • 将源服务器诊断消息打印到输出窗口
    启用源服务器支持时,此设置打开诊断显示。

  • 为断点和当前语句突出显示整个行
    调试器突出显示断点或当前语句时,会突出显示整个行。
    勾选上时

    否则

  • 要求源文件与原始版本完全匹配
    告知调试器验证源文件是否匹配于用于生成正在调试的可执行文件的源代码版本。 如果版本不匹配,则会提示您查找匹配源。 如果未找到匹配源,则在调试过程中不会显示源代码。

  • 将所有输出窗口文本重定向到即时窗口
    将通常显示在“输出”窗口中的所有调试器消息改为发送到“即时”窗口。
    不勾选时

     

    勾选后

     


  • 在变量窗口中显示对象的原始结构
    关闭所有对象结构视图自定义。

  • 在模块加载时取消 JIT 优化(仅限托管)
    在附加调试器的情况下,加载模块并编译 JIT 后,禁用托管代码的 JIT 优化。 禁用优化可能更易于调试某些问题,尽管这会降低性能。 如果正在使用“仅我的代码”,则取消 JIT 优化会导致非用户代码显示为用户代码(“我的代码”)。

  • 启动时若无符号则发出警告(仅限本机)
    选定后,如果您尝试对调试器没有其符号信息的程序进行调试,系统将显示警告对话框。

  • 如果启动时禁用了脚本调试,则发出警告
    选定后,如果在启动调试器时禁用了脚本调试,则会显示警告对话框。

  • 当通过 IL 解释(仅托管)进行小型转储调试时,启用功能评估。
    启用调试器来解释 IL 操作码,以在调试托管转储时模拟功能评估。

  • 自下而上显示并行堆栈关系图
    控制“并行堆栈”窗口中堆栈的显示方向。

“选项”对话框 ->“调试”->“编辑并继续”

若要访问“编辑并继续”页,请打开“工具”菜单并选择“选项”。 在“选项”对话框中,展开“调试”文件夹并选择“编辑并继续”。 该页允许为“编辑并继续”设置下列选项。

  • 启用“编辑并继续”
    选定后,启用“编辑并继续”。

    “编辑并继续”能够在程序处于中断模式(有一些限制)时更改源代码,并能应用这些更改,而无需结束调试会话和重新生成程序。

    调试期间无法更改此设置。

  • 由调试命令调用
    (仅限本机)选定后,可使“编辑并继续”由执行命令(例如“单步执行”)调用。

  • 首先询问
    (仅限本机)告知调试器在从调试命令调用“编辑并继续”前首先询问您。 这样,您可以根据需要取消调用。

  • 就陈旧的代码发出警告
    (仅限本机)选定后,调试器使用“陈旧代码警告”对话框就陈旧代码向您发出警告。

    在某些情况下,“编辑并继续”无法将代码更改立即应用于可执行文件,但如果您继续调试,则可能稍后会应用代码更改。 “编辑并继续”此时将更新代码。 代码更新之前,源窗口一直以灰色显示原始代码。 因为此代码已被代码更改取代,它已经过时或陈旧。 无法编辑陈旧的代码。

  • 调试后重新链接代码更改
    (仅限本机)调试后重新链接本机代码更改。

    “编辑并继续”不调用自定义生成步骤。 如果程序使用自定义生成步骤,则可能要手动重新生成这些步骤才能调用它们。 在这种情况下,可以在“编辑并继续”后禁用重新链接,以确保系统会提示您手动重新生成。

  • 允许预编译
    (仅限本机)允许“编辑并继续”在后台加载并处理预编译头,以加快对代码更改的处理。 加载预编译头需要分配物理内存,如果您正在一台 RAM
    有限的计算机上进行编译,这可能会是一个问题。 通过在调试期间使用任务管理器确定可用物理内存的数量,可以确定这是否是个问题。
    如果此数量大于预编译头的大小,则“编辑并继续”应没有问题。
    如果此数量小于预编译头的大小,可以通过清除该选项禁止“编辑并继续”在后台加载预编译头。

  • 在远程调试或对以另一个用户帐户运行的应用程序进行调试时启用
    (仅限本机)在计算机之间或跨用户帐户调试时允许执行“编辑并继续”操作。