Windbg命令的语法规则系列(一)

本文介绍使用调试器命令必须遵循的语法规则。使用Windbg调试时,应遵守以下一般语法规则:

  • 您可以在命令和参数中使用大小写字母的任意组合,除非在本节的主题中特别指出。
  • 可以用一个或多个空格或逗号(,)分隔多个命令参数。
  • 通常可以省略命令与其第一个参数之间的空格。如果这种省略不会造成任何歧义,则可以经常省略其他空格。

阅读本文中的命令引用注意以下事项:

  • 粗体字体的字符表示必须逐字键入的项目。
  • 斜体字体的字符表示参考主题“参数”部分中解释的参数。
  • 括号([xxx])中的参数是可选的。带有竖线([XXX|YYY])的括号表示可以使用一个或无一个封闭参数。
  • 带竖线(XXX|YYY)的大括号表示必须仅使用其中一个封闭参数。

一、数字表达式

调试器接受两个不同类型的数值表达式:C++表达式MASM 表达式每个这些表达式遵循用于输入和输出自己语法规则。

1.1、MASM 数字和运算符

 在Windows包的4.0版调试工具之前,ntsd、cdb、kd和windbg仅使用Microsoft宏汇编程序(masm)表达式语法。
  • MASM表达式中的数字
    在masm表达式中我们可以输入二进制、八进制、十进制、十六进制数字。使用n(设置基数)命令将默认基数设置为16、10或8。所有未固定的数字都将在此基数中解释。可以通过指定0x前缀(十六进制)、0n前缀(十进制)、0t前缀(八进制)或0y前缀(二进制)来重写默认基数。您还可以通过在数字后面添加h来指定十六进制数字。您可以在数字中使用大写或小写字母。例如,“0x4ab3”、“0x4ab3”、“4ab3h”、“4ab3h”和“4ab3h”具有相同的含义。如果不在表达式的前缀后面添加数字,则该数字将被读取为0。因此,您可以将0写为0,前缀后跟0,并且只写前缀。例如,在十六进制中,“0”、“0x0”和“0x”具有相同的含义。您可以以XXXXXXXX`XXXXXXXX格式输入十六进制64位值。
  • MASM表达式中的符号
    在masm表达式中,任何符号的数值都是其内存地址。根据符号所指的内容,此地址是全局变量、局部变量、函数、段、模块或任何其他可识别标签的地址。要指定与地址关联的模块,请包括模块名称和感叹号(!)在符号名称之前。如果符号可以解释为十六进制数,请在符号名之前包含模块名和感叹号,或仅包含感叹号。使用两个冒号(:)或两个下划线(_)指示类的成员。只有在符号名称前面添加模块名称和感叹号时,才能在符号名称中使用重音符(`)或撇号(')。
  •  MASM表达式中的数字运算符
     可以使用一元运算符修改表达式的任何组件。您可以使用二进制运算符组合任意两个组件。一元运算符优先于二元运算符。使用多个二进制运算符时,运算符遵循下表中描述的固定优先级规则。 您可以始终使用括号来覆盖优先规则。如果一个MASM表达式的一部分被括在括号中,并且在表达式之前出现两个符号(@),则表达式根据C++表达式规则进行解释。不能在两个at符号和左括号之间添加空格。还可以使用@ @ C++(…)指定表达式计算器。或@@masm(…).执行算术计算时,MASM表达式计算器将所有数字和符号视为ulong64类型。一元地址运算符将ds作为地址的默认段。表达式按运算符优先顺序计算。如果相邻运算符的优先级相等,则表达式将从左到右进行计算。
    可以使用以下一元运算符:
    运算符含义

    +

    一元加

    -

    一元负

    如果参数为零,则返回 1。 任何非零值的参数,则返回零。

    hi

    高 16 位

    low

    低 16 位

    by

    从指定的地址的低序位字节。

    $pby

    与相同通过,但前者的物理地址。 可以读取仅使用默认缓存行为的物理内存。

    wo

    从指定的地址的低序位字。

    $pwo

    与相同wo ,但前者的物理地址。 可以读取仅使用默认缓存行为的物理内存。

    dwo

    从指定的地址双字。

    $pdwo

    与相同dwo ,但前者的物理地址。 可以读取仅使用默认缓存行为的物理内存。

    qwo

    从指定的地址四字。

    $pqwo

    与相同qwo ,但前者的物理地址。 可以读取仅使用默认缓存行为的物理内存。

    poi

    从指定的地址指针大小的数据。 指针大小为 32 位或 64 位。 在内核调试,此大小基于的处理器目标计算机。 在用户模式下调试在基于 Itanium 的计算机上,此大小为 32 位或 64 位,具体取决于目标应用程序。 因此, poi是要使用如果你想指针大小的数据的最佳运算符。

    $ppoi

    与相同poi ,但前者的物理地址。 可以读取仅使用默认缓存行为的物理内存。

    可以使用以下二进制运算符。 每个单元格中的运算符优先于较小的单元中。 相同单元中的运算符均属于相同的优先级,从左到右进行分析。

    运算符含义

    *

    /

    mod (或 %)

    乘法

    整数除法

    取模 (余数)

    +

    -

    添加

    减法

    <<

    >>

    >>>

    左的移

    逻辑右移位

    算术右移位运算

    = (或 = =)

    <

    >

    <=

    >=

    !=

    等于

    小于

    大于

    小于或等于

    大于或等于

    不等于

    (或 &)

    位与

    xor (或 ^)

    按位 XOR (异或)

    (或 |)

    按位 OR 运算符

    <, >、 =、 = =、 和 ! = 的比较运算符计算结果为 1,如果表达式为 true 或为零,如果表达式为 false。 单个等号 (=) 是双等号 (= =) 相同。 不能使用副作用或 MASM 表达式中的分配。在"操作数错误"中无效的操作 (如被零除) 结果返回到调试器命令窗口。

  •  MASM表达式中的非数字运算符

    此外可以在 MASM 表达式中使用以下其他运算符。

    运算符含义

    $fnsucc(FnAddress, RetVal, Flag)

    解释RetVal位于函数的返回值的值FnAddress地址。 如果此返回值被返回成功代码,称为$fnsucc返回TRUE否则为$fnsucc返回FALSE

    如果返回类型为布尔值、 bool、 句柄、 HRESULT 或 NTSTATUS, $fnsucc正确理解是否在指定的返回值被称为成功代码。 返回类型是否为指针,所有值,而NULL才会被视为成功代码。 成功的值对于任何其他类型进行定义标志如果标志为 0,一个非零值的RetVal为 success。 如果标志为 1,零值的RetVal为 success。

    $iment (地址)

    加载的模块列表中返回映像入口点的地址。 地址指定的可移植可执行文件 (PE) 映像基址。 通过查找映像的 PE 映像标头中的映像入口点找到该项,地址指定。

    您可以使用此函数的是已在模块列表中,并设置这两个模块无法解析的断点通过使用bu命令。

    $scmp("String1", "String2")

    计算结果为-1、 0 或 1,如strcmp C 函数。

    $sicmp("String1", "String2")

    计算结果为-1、 0 或 1,如stricmp Microsoft Win32 函数。

    $spat("String", "Pattern")

    计算结果为,则返回 TRUEFALSE取决于是否字符串匹配模式匹配不区分大小写。 模式可以包含各种通配符和说明符。 有关语法的详细信息,请参阅字符串通配符语法。

    $vvalid(Address, Length)

    确定是否内存范围的开始处地址,并为扩展长度字节是否有效。 如果有效,内存$vvalid的计算结果为 1。 如果内存是无效的$vvalid计算结果为 0。

     
  • MASM表达式中的寄存器和伪寄存器
     您可以在masm表达式中使用寄存器和伪寄存器。您可以在所有寄存器和伪寄存器之前添加at符号(@)。at符号使调试器更快地访问该值。对于最常见的基于x86的寄存器来说,这个at符号是不必要的。对于其他寄存器和伪寄存器,我们建议您添加at符号,但实际上并不需要它。如果省略了较不常用的寄存器的at符号,调试器将尝试将文本解析为十六进制数,然后作为符号,最后作为寄存器。还可以使用句点(.)指示当前指令指针。在此期间之前不应添加at符号,并且不能将期间用作r命令的第一个参数。此期间的含义与$IP伪寄存器相同。
  • MASM表达式中的源行号
    可以在masm表达式中使用源文件和行号表达式。必须使用重音符(`)将这些表达式括起来。

 1.2、C++数字和运算符

Windbg中的C++表达式解析器支持所有形式的C++表达式语法。该语法包括所有数据类型(包括指针、浮点数和数组)和所有C++一元和二元运算符。

  • C++表达式中的数字
    C++表达式中的数字被解释为十进制数,除非用另一种方式指定它们。要指定十六进制整数,请在数字前面添加0x。要指定一个八进制整数,请在数字前面加0(零)。默认调试器基数不影响您输入C++表达式的方式。不能直接输入二进制数(除非在C++表达式中嵌套了一个MASM表达式)。您可以以XXXXXXX`XXXXXXXXX格式输入一个十六进制的64位值。(您也可以省略重音符('.))两种格式产生相同的值。可以使用带整数值的L、U和I64后缀。创建的数字的实际大小取决于后缀和输入的数字。有关此解释的更多信息,请参见C++语言引用。C++表达式计算器的输出保持C++表达式规则指定的数据类型。但是,如果将此表达式用作命令的参数,则始终进行强制转换。例如,当整数值用作命令参数中的地址时,不必向指针强制转换整数值。如果表达式的值不能有效地转换为整数或指针,则会出现语法错误。对于某些输出,可以使用0N(十进制)前缀,但不能将其用于C++表达式输入。
  • C++表达式中的字符和字符串
    您可以通过将字符用单引号(“)包围来输入字符。标准的C++转义字符是允许的。您可以通过将字符串文本用双引号(“)包围来输入字符串文本。您可以在这样的字符串中使用“作为转义序列。但是,字符串对表达式计算器没有意义。
  • C++表达式中的符号
    在C++表达式中,每个符号根据其类型来解释。根据符号所指的内容,可以将其解释为整数、数据结构、函数指针或任何其他数据类型。如果在C++表达式中使用与C++数据类型(如未修改的模块名)不符的符号,则会出现语法错误。如果符号可能不明确,可以添加模块名和感叹号(!)或者只在符号前加一个感叹号。只有在符号名称前添加模块名称和感叹号,才能在符号名称中使用重音符(`)或撇号(“)。在模板名称后面添加分隔符时,可以在这些分隔符之间添加空格。
  •  C++表达式中的运算符
    您可以始终使用括号来覆盖优先规则。如果在括号中包含一部分C++表达式,并在表达式之前加上两个符号(@),则根据MASM表达式规则对表达式进行解释。不能在两个at符号和左括号之间添加空格。此表达式的最终值作为ULUN64值传递给C++表达式求值器。还可以使用@ @ C++(…)指定表达式计算器。或@@masm(…).数据类型通常以C++语言表示。指示数组([])、指针成员(->)和UDT成员(.)的符号。和类(::)的成员都可以识别。支持所有算术运算符,包括赋值和副作用运算符。但是,不能使用new、delete和throw运算符,也不能实际调用函数。支持指针算法并正确缩放偏移量。请注意,不能向函数指针添加偏移量。(如果必须向函数指针添加偏移量,请先将偏移量强制转换为字符指针。)与C++一样,如果使用具有无效数据类型的运算符,则会发生语法错误。调试器的C++表达式分析器使用的规则比大多数C++编译器稍微宽松一些,但是所有的主要规则都被强制执行。例如,不能移动非整数值。可以使用以下运算符。每个单元格中的运算符优先于较低单元格中的运算符。同一单元格中的运算符具有相同的优先级,并从左到右进行分析。与C++一样,表达式评估在其值已知时结束。这个结尾使您能够有效地使用表达式,例如??myptr和&*myptr。
    运算符含义

    表达式 // 注释

    忽略所有后续文本

    ::成员

    :: ~成员

    ::名称

    类的成员

    类 (析构函数) 的成员

    全局

    结构 字段

    指针 - > 字段

    Name [integer]

    LValue ++

    LValue --

    dynamic_cast <type>(Value)

    static_cast <type>(Value)

    reinterpret_cast <type>(Value)

    const_cast <type>(Value)

    结构中的字段

    引用结构中的字段

    数组下标

    增量 (之后评估版)

    递减 (后评估版)

    类型转换 (始终执行)

    类型转换 (始终执行)

    类型转换 (始终执行)

    类型转换 (始终执行)

    (type) Value

    sizeof value

    sizeof( type )

    ++ 左值

    -- 左值

    ~

    ! ReplTest1

    ReplTest1

    +

    & 左值

    类型转换 (始终执行)

    表达式的大小

    数据类型的大小

    增量 (之前评估版)

    递减 (在之前评估版)

    位求补

    不 (布尔值)

    一元负

    一元加

    数据类型的地址

    取消引用

    结构 指针

    Pointer -> * Pointer

    指向成员的结构的指针

    指向引用结构成员的指针

    Value Value

    Value / Value

    Value % Value

    乘法

    部门

    取模

    Value + Value

    Value - Value

    添加

    减法

    Value << Value

    Value >> Value

    按位左移

    按位右移

    Value < Value

    Value <= Value

    Value > Value

    Value >= Value

    早于 (比较)

    小于或等于 (比较)

    大于 (比较)

    大于或等于 (比较)

    Value == Value

    Value != Value

    等于 (比较)

    不等于 (比较)

    Value & Value

    位与

    Value ^ Value

    按位 XOR (异或)

    Value | Value

    按位 OR 运算符

    Value && Value

    逻辑与

    Value || Value

    逻辑或

    LValue =Value

    LValue = Value

    LValue /= Value

    LValue %=Value

    LValue +=Value

    LValue -= Value

    LValue <<= Value

    LValue >>= Value

    LValue &= Value

    LValue |= Value

    LValue ^= Value

    分配

    乘并赋值

    相除并赋值

    取模和分配

    添加和分配

    相减并赋值

    左移位,并将分配

    右移位和分配

    和分配

    或和分配

    XOR 并赋值

    :

    条件评估

    评估所有值,然后丢弃最右侧的值之外的所有

  • C++语言中的寄存器和伪寄存器
     

    可以在C++表达式中使用寄存器和伪寄存器。必须在寄存器或伪寄存器之前添加at符号(@)。表达式计算器自动执行正确的强制转换。实际寄存器和整数值伪寄存器被转换为ulong64。所有地址都转换为puchar,$thread转换为ethread*,$proc转换为eprocess*,$teb转换为teb*,$peb转换为peb*。不能通过赋值或副作用运算符更改寄存器或伪寄存器。必须使用r(寄存器)命令更改这些值。

  • C++表达式中的宏
    可以在C++表达式中使用宏。必须在宏之前添加数字符号(#)。可以使用以下宏。这些宏与具有相同名称的Microsoft Windows宏具有相同的定义。(Windows宏在winnt.h中定义。)
    返回值

    #CONTAINING_RECORD (地址类型字段)

    返回给定类型的结构和结构中的字段的地址结构的实例的基址。

    #FIELD_OFFSET (类型字段)

    返回命名的字段的字节偏移量中的已知的结构类型。

    #RTL_CONTAINS_FIELD (Struct大小字段)

    指示给定的字节大小是否包括所需的字段。

    #RTL_FIELD_SIZE(Type, Field)

    而无需字段的类型返回已知类型的结构中的字段的大小。

    #RTL_NUMBER_OF(Array)

    以静态方式调整大小的数组中返回元素的数。

    #RTL_SIZEOF_THROUGH_FIELD(Type, Field)

    通过和包括在指定的字段会返回已知类型的结构的大小。


原文地址:https://www.cnblogs.com/yilang/p/11410785.html