程序正常,但没有崩溃,Valgrind的

问题描述:

我试图调试一块汇编程序(x86 64-bit),并根据gdb信息,它使用下面的指令时崩溃:程序正常,但没有崩溃,Valgrind的

xorpd 0x1770(%rip),%xmm12  # 0x40337c <S_0x403230> 

然而,似乎对我来说,内存0x40337c是完全正常的:

(gdb) x /10x 0x40337c 
0x40337c <S_0x403230>: 0x00000000  0x80000000  0x00000000  0x00000000 
0x40338c <S_0x403240>: 0xf149f2ca  0x00000000  0x746e7973  0x203a7861 
0x40339c <S_0x403248+8>:  0x206d626c  0x6d69743c 

另一个有线的是,这段代码崩溃每次当我在命令行中运行它,以及里面gdb。但是,当我在valgrind中调试它时,它不会崩溃!

☁ src [master] ⚡ valgrind ./a.out 20 reference.dat 0 1 100_100_130_cf_a.of 
==18329== Memcheck, a memory error detector 
==18329== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al. 
==18329== Using Valgrind-3.10.0 and LibVEX; rerun with -h for copyright info 
==18329== Command: ./a.out 20 reference.dat 0 1 100_100_130_cf_a.of 
==18329== 
MAIN_printInfo: 
    grid size  : 100 x 100 x 130 = 1.30 * 10^6 Cells 
    nTimeSteps  : 20 
    result file : reference.dat 
    action   : nothing 
    simulation type: channel flow 
    obstacle file : 100_100_130_cf_a.of 

LBM_showGridStatistics: 
    nObstacleCells: 498440 nAccelCells:  0 nFluidCells: 801560 
    minRho: 1.0000 maxRho: 1.0000 mass: 1.300000e+06 
minU: 0.000000e+00 maxU: 0.000000e+00 

LBM_showGridStatistics: 
    nObstacleCells: 498440 nAccelCells:  0 nFluidCells: 801560 
    minRho: 1.0000 maxRho: 1.0431 mass: 1.300963e+06 
    minU: 0.000000e+00 maxU: 1.272361e-02 

==18329== 
==18329== HEAP SUMMARY: 
    ==18329==  in use at exit: 0 bytes in 0 blocks 
==18329== total heap usage: 4 allocs, 4 frees, 428,801,136 bytes allocated 
==18329== 
==18329== All heap blocks were freed -- no leaks are possible 
==18329== 
==18329== For counts of detected and suppressed errors, rerun with: -v 
==18329== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0) 

我上传了二进制代码here供您参考,如果您有兴趣。汇编程序实际上是由二进制重写器生成的,我曾经能够生成无错代码。所以我相信这可能不是一个难以调试的指针解引用问题,应该是非常容易修复的东西。但是,我真的不知道哪里出了问题,并且在gdb调试中看起来非常正常(x/10x 0x40337

因此,这里是我的问题,

  1. 给出的调试信息(x/10x 0x40337c),其中可能出问题?

  2. 为什么二进制代码不会在valgrind中崩溃?

Valgrind runs your code on a simulated x86 CPU。显然它不模拟对齐检查。


对SSE指令的128位和更大内存操作数始终需要自然对齐。 (例如,对于这种16B负载的16B边界)。例外是MOVUPS_mm_loadu_ps)(和MOVUPD/MOVDQU)。

0x40337c不是16B对齐,只有4B。 (所以你使用它与XORPD是很奇怪的,因为我期望至少8B对齐double)。

AVX指令正好相反:默认值不需要对齐,但VMOVAPS确实需要对齐。

+0

谢谢彼得。现在我知道更好..你有什么想法,应该如何解决这个问题?由于该指针('S_0x403230')引用'.rodata'节中的某个位置,因此可能会强制'.rodata'节的16b对齐会起作用? – computereasy

+0

如果我在1.5年前正确记得,当我使用这个二进制重写器并且在上面完全相同的一段代码上工作时,我应该以某种方式在生成的汇编代码中进行一些对齐,但我不记得详细信息了..我会试图弄清楚。谢谢! – computereasy

+0

@computereasy:是的,做任何你需要做的事情,以便你的向量常量是对齐的,而不是改变你的程序使用未对齐的加载到tmp寄存器中。这听起来像是你的重写软件中的一个错误,如果它不能保留部分指定的对齐。你可以用'readelf -S foo.o'来看。 '.rodata'部分应该是文本段的一部分,通常至少16B对齐。 'S_0x403230'听起来像原来的地址是对齐的,因为最后一个十六进制数字是0. –