符号组包含一组符号,便于作为一个整体进行有效操作。 可以手动创建和填充符号组,也可以根据词法范围内的符号(例如局部变量和函数参数)自动生成和更新。 接口 IDebugSymbolGroup 用于表示符号组。
有两种方法可以创建符号组。 CreateSymbolGroup 返回空符号组,当前词法范围的符号组由 GetScopeSymbolGroup 返回。
注意 从当前作用域生成的符号组是局部变量的快照。 如果目标中发生任何执行过程,数据符号可能不再准确。 此外,如果当前作用域发生更改,符号组将不再表示 当前 范围(因为它将继续表示为其创建的范围)。
可以使用 AddSymbol 将符号添加到符号组中,并使用 RemoveSymbolByIndex 或 RemoveSymbolByName 将其删除。 OutputAsType 方法指示调试器处理符号数据时使用不同的符号类型。
注意 范围符号的值可能不准确。 具体而言,计算机体系结构和编译器优化可能会阻止调试器准确确定符号的值。
符号项信息是符号的说明,包括符号的位置和类型。 若要在模块中查找符号的此信息,请使用 IDebugSymbols3::GetSymbolEntryInformation。 若要查找符号组中符号的此信息,请使用 IDebugSymbolGroup2::GetSymbolEntryInformation。 关于符号条目的信息,请参阅 DEBUG_SYMBOL_ENTRY。
以下方法返回有关符号组中符号的信息:
GetSymbolName 返回符号的名称。
如果符号具有绝对地址,GetSymbolOffset 将返回目标虚拟地址空间中的绝对地址。
如果符号包含在寄存器中,GetSymbolRegister 将返回包含符号的寄存器。
GetSymbolSize 返回符号的数据大小。
GetSymbolTypeName 返回符号类型的名称。
GetSymbolValueText 将符号的值作为字符串返回。
如果符号存储在寄存器或调试器引擎已知的内存位置中,则可以使用 WriteSymbol 更改其值。
如果符号包含其他符号,则符号是 父 符号。 例如,结构包含其成员。 如果符号包含在另一个符号中,则符号是 子符号 。 符号可以是父符号和子符号。 每个符号组别都有一个平面结构,其中包含父符号及其子级。 每个符号都有 深度 -- 符号组中没有父级符号的深度为零,每个子符号的深度大于其父符号的深度。 父符号的子级可能会存在于符号组中,也可能不会。 当子符号存在于符号组中时,父符号被称作展开的符号。 若要在符号组中添加或删除符号的子级,请使用 ExpandSymbol。
GetNumberSymbols 返回符号组中的符号数。 符号组中符号的 索引 是标识号;索引范围从零到符号数减去 1。 每次向符号组添加或从符号组中删除符号时(例如,展开符号)时,符号组中所有符号的索引可能会更改。
可以使用 GetSymbolParameters 找到符号参数,包括有关父子关系的信息。 此方法返回 DEBUG_SYMBOL_PARAMETERS 结构。
可以使用 OutputSymbols 方法将符号组中的符号打印到调试器的输出流。
范围
当前作用域或当前本地上下文确定调试器引擎公开的局部变量。 范围有三个组件:
堆栈帧。
当前指令。
寄存器上下文。
如果堆栈帧位于调用堆栈的顶部,则当前指令是导致最后一个事件的指令。 否则,当前指令是导致下一个更高的堆栈帧的函数调用。
GetScope 和 SetScope 方法可用于获取和设置当前范围。 事件发生时,当前作用域设置为事件的范围。 可以使用 ResetScope 将当前范围重置为最后一个事件的范围。
线程上下文
线程上下文是在切换线程时 Windows 保留的状态。 这类似于寄存器上下文,只是有一些仅内核处理器状态是寄存器上下文的一部分,而不是线程上下文。 在内核模式调试期间,此额外状态可用作寄存器。
线程上下文由 ntddk.h 中定义的 CONTEXT 结构表示。 此结构依赖于平台,其解释取决于有效的处理器类型。 GetThreadContext 和 SetThreadContext 的方法可用于获取和设置线程上下文。