• 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)

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


  • 相关阅读:
    Rest Project Performace Pressure Test
    Tomcat APR & Linux Optimization
    关于启用 HTTPS 的一些经验分享(二)
    关于启用 HTTPS 的一些经验分享(一)
    JVM垃圾回收机制总结:调优方法
    LVS+Keepalived搭建高可用负载均衡
    LVS搭建负载均衡(二)DR模型
    LVS搭建负载均衡(一)NAT模型
    编译安装Nginx和PHP(带编译mysql)
    centos7下利用httpd2.4配置svn并使用Ldap用户认证
  • 原文地址:https://www.cnblogs.com/yilang/p/11410785.html
Copyright © 2020-2023  润新知