在WinDbg命令中,如何引用与全局变量同名的寄存器?

时间:2016-06-09 05:17:13

标签: debugging windbg

假设我想使用适用于Windows的WinDbg,cdb或ntsd调试器调试此程序:

/* test.c */
#include <stdio.h>

int rip = 42;

int main(void)
{
    puts("Hello world!");
    return (0);
}

我为AMD64编译程序并在WinDbg下运行它。我在main()处设置断点,当断点命中时,我想检查RIP寄存器(程序计数器)的值,如果该值被视为指针,则检查该值周围的内存。

我可以直接用r rip看到寄存器的值,但是当我尝试查看该地址周围的内存时,WinDbg会向我显示不同的地址!读完test.pdb中的符号后,WinDbg看到rip是C代码中声明的全局变量,并向我显示&rip周围的内存。

0:000> bu test!main

0:000> g
Breakpoint 0 hit
test!main:
00007ff6`de1868d0 4883ec28        sub     rsp,28h

0:000> r rip
rip=00007ff6de1868d0

0:000> db rip
00007ff6`de1f2000  2a 00 00 00 ff ff ff ff-01 00 00 00 00 00 00 00  *...............
00007ff6`de1f2010  01 00 00 00 02 00 00 00-ff ff ff ff ff ff ff ff  ................
00007ff6`de1f2020  00 00 00 00 00 00 00 00-43 46 92 e5 1b df 00 00  ........CF......
00007ff6`de1f2030  bc b9 6d 1a e4 20 ff ff-00 00 00 00 00 00 00 00  ..m.. ..........
00007ff6`de1f2040  00 01 00 00 00 00 00 00-ca b0 1e de f6 7f 00 00  ................
00007ff6`de1f2050  00 00 00 00 00 80 00 00-00 00 00 00 00 80 00 00  ................
00007ff6`de1f2060  d0 66 fc c2 f2 01 03 00-ab 90 ec 5e 22 c0 b2 44  .f.........^"..D
00007ff6`de1f2070  a5 dd fd 71 6a 22 2a 15-00 00 00 00 00 00 00 00  ...qj"*.........

0:000> ? rip
Evaluate expression: 140698265264128 = 00007ff6`de1f2000

0:000> ? dwo(rip)
Evaluate expression: 42 = 00000000`0000002a

这真的很烦人,但只要我知道它,手动读取这样的数据就不是问题了。但是,如果我想使用寄存器值,例如在编写调试器脚本时,则没有简单的解决方法:

0:000> bu test!main ".if (dwo(rip) == 0n42) { .echo Whoops! I don't want to get here! }"

0:000> g
Whoops! I don't want to get here!
test!main:
00007ff6`de1868d0 4883ec28        sub     rsp,28h

这个问题,程序中的符号隐藏了寄存器名称,这对我来说非常困难。这破坏了一个实际情况:

  1. 我想在CreateFileW()上设置断点,这是一种非常常见的Windows API函数。
  2. 由于我只关心一个特定的文件,我想检查在RCX寄存器中传递的文件名,并继续超过断点,除非文件名与我想要的文件匹配。
  3. 但是我无法写出这个条件,因为程序中的另一个模块定义了一个符号foobar!rcx,并且我在命令中对rcx的任何引用都是在断点上执行的,这是指全局变量<!/ LI>

    那么如何告诉WinDbg是的,我真的想读取寄存器?如果我想写那个寄存器怎么办?我必须在这里找到一件简单的事情。

1 个答案:

答案 0 :(得分:5)

如通过another question所述,您可以在寄存器名称前加上一个符号(@),以强制它被解释为寄存器或伪寄存器,绕过该尝试将其解析为十六进制数字或符号。

  

Registers and Pseudo-Registers in MASM Expressions

     

您可以在MASM表达式中使用寄存器和伪寄存器。 您可以在所有寄存器和伪寄存器之前添加at符号(@)。 at符号使调试器更快地访问该值。对于最常见的基于x86的寄存器,此符号是不必要的。对于其他寄存器和伪寄存器,我们建议您添加at符号,但实际上并不需要。如果省略不常见寄存器的at符号,调试器会尝试将文本解析为十六进制数,然后作为符号解析,最后作为寄存器。