【问题标题】:Program crashes normally but not with Valgrind程序正常崩溃,但 Valgrind 不崩溃
【发布时间】:2016-11-15 03:46:02
【问题描述】:

我正在尝试调试一段汇编程序(x86 64-bit),根据gdb的信息,使用以下指令时它会崩溃:

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 中崩溃?

【问题讨论】:

    标签: assembly x86 gdb 64-bit valgrind


    【解决方案1】:

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


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

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

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

    【讨论】:

    • 谢谢彼得。现在我知道得更好了。你知道应该如何解决这个问题吗?由于此指针 (S_0x403230) 指向 .rodata 部分中的位置,因此强制 .rodata 部分的 16b 对齐可能会起作用吗?
    • 如果我没记错的话,大约 1.5 年前,当我使用这个二进制重写器并处理上面完全相同的一段代码时,我应该以某种方式在生成的汇编代码中进行一些对齐,但我没有'不记得细节了。我会试着弄清楚。谢谢!
    • @computereasy:是的,做任何你需要做的事情来对齐你的向量常量,而不是改变你的程序来使用未对齐的加载到一个 tmp 寄存器。如果至少没有保留部分指定的对齐方式,这听起来像是重写软件中的错误。您可以通过readelf -S foo.o 看到这一点。 .rodata 部分应该是文本段的一部分,通常至少 16B 对齐。 S_0x403230 听起来像原来的地址是对齐的,因为最后一个十六进制数字是 0。
    • .rodata.data 部分的开头添加.align 16 可以解决上述问题。非常感谢您的帮助!
    猜你喜欢
    • 2011-11-22
    • 2020-02-01
    • 2015-03-31
    • 2013-01-30
    • 2011-06-26
    • 1970-01-01
    • 2018-12-11
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多