如何使用Visual Studio调试amd64上的未对齐访问?

时间:2011-03-31 09:59:46

标签: debugging visual-c++ assembly 64-bit alignment

我想调试和分析一些执行未对齐访问的64位软件,如下例所示:

int foo[2] = { 1, 2 };
*((int *)((char *)foo + 2)) = 3;

gcc方式

使用 gcc gdb 时,我知道有两种方法可以实现。第一种方法是直接在我的C或C ++代码中启用eflags寄存器中的对齐检查位(位18):

asm volatile("pushf \n"
             "pop %%rax \n"
             "or $0x40000, %%rax \n"
             "push %%rax \n"
             "popf \n" ::: "rax");

这非常方便,因为我可以在应用程序本身中选择是否绕过未对齐的访问检查,例如在调用已知的错误库时。

另一种方式来自 gdb ,在调试可执行文件的任何时刻:

set $eflags |= 1<<18

同样,这可以随意启用或禁用,编写脚本等。非常方便。

Visual Studio

现在,我在Vista64上使用 Visual Studio 2008 2010 完全无法做到这一点。在任何版本的Visual Studio中,C ++程序中的内联汇编在x64模式下为no longer available,但我可以使用intrinsics代替:

#include <intrin.h>
/* ... */
__writeeflags(__readeflags() | 0x40000);

这与Linux上的代码完全相同。 有点工作:当我的错误代码运行时,我得到了异常。每次遇到断点时,EFL.AC标志都会重置为零。这意味着我无法正确调试具有大量复杂断点的大型应用程序,除非我通过调用我的asm函数来丢弃代码。

所以我尝试从Visual Studio注册调试会话中手动更改EFL |= 0x40000(这正是我在Linux上通常所做的)。也没有效果,一旦我恢复调试,该位就设置为零。这意味着我无法正确调试我没有源代码的代码。

我不明白这里发生了什么。是Visual Studio强行设置EFL.AC=0吗?如果是这样,我可以禁用该“功能”吗?另外,有没有办法在调试会话期间启用/禁用EFL.AC

现实世界的Windows开发人员如何跟踪代码中的未对齐访问?

修改:了解__readeflagslist of x64 intrinsics不在{{3}}。

3 个答案:

答案 0 :(得分:3)

不幸的是,在VS中调试x64调试器时会清除任何异常上的对齐检查标志(包括首先进入调试器的抛出)。您是否尝试使用windbg(更强大的Windows调试器)来逐步执行代码?我无法使用AC标志尝试它,但它应该是简单的r efl =或直接来自寄存器窗口。 如果您没有安装windbg,可以从最新的Windows SDK获取它。

答案 1 :(得分:0)

答案 2 :(得分:0)

一个非常混乱的解决方法是在程序中有一个不断设置此位的线程。每100毫秒左右。

然后您将知道从断点恢复后不久,将再次检查对齐。不是100%安全但它可能足够好。