我想调试和分析一些执行未对齐访问的64位软件,如下例所示:
int foo[2] = { 1, 2 };
*((int *)((char *)foo + 2)) = 3;
使用 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
同样,这可以随意启用或禁用,编写脚本等。非常方便。
现在,我在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开发人员如何跟踪代码中的未对齐访问?
修改:了解__readeflags
,list of x64 intrinsics不在{{3}}。
答案 0 :(得分:3)
不幸的是,在VS中调试x64调试器时会清除任何异常上的对齐检查标志(包括首先进入调试器的抛出)。您是否尝试使用windbg(更强大的Windows调试器)来逐步执行代码?我无法使用AC标志尝试它,但它应该是简单的r efl =或直接来自寄存器窗口。 如果您没有安装windbg,可以从最新的Windows SDK获取它。
答案 1 :(得分:0)
使用asmjit http://code.google.com/p/asmjit/
答案 2 :(得分:0)
一个非常混乱的解决方法是在程序中有一个不断设置此位的线程。每100毫秒左右。
然后您将知道从断点恢复后不久,将再次检查对齐。不是100%安全但它可能足够好。