【问题标题】:"gdb" and "valgrind" execute binary in different way?“gdb”和“valgrind”以不同的方式执行二进制文件?
【发布时间】:2019-02-20 01:43:29
【问题描述】:

我的程序收到有关堆内存损坏的错误。

osboxes@osboxes:/mnt/hgfs/VM_Shared/ISSUES/_[02]$ ./shuf /dev/null
*** Error in `./shuf': corrupted double-linked list: 0xb7f01ac0 ***



在仅使用 gdb 进行调试时,我遇到了valgrind。 (感谢Here
而且...我使用 valgrind 获得了日志。

(对不起,日志太长了,提问前我想把它缩写,但我担心我可能会错过一些分析所需的信息。)

osboxes@osboxes:~/Desktop/VM_Shared/ISSUES/_[02]$ valgrind --run-libc-freeres=no ./shuf /dev/null
==23373== Command: ./shuf /dev/null
==23373== 
==23373== Invalid read of size 4
==23373==    at 0x40B7859: _IO_file_close_it@@GLIBC_2.1 (fileops.c:178)
==23373==    by 0x40B4AE6: freopen64 (freopen64.c:49)
==23373==    by 0x804EECF: ??? (shuf.s:22773)
==23373==  Address 0x20 is not stack'd, malloc'd or (recently) free'd
==23373== 
==23373== Process terminating with default action of signal 11 (SIGSEGV)
==23373==  Access not within mapped region at address 0x20
==23373==    at 0x40B7859: _IO_file_close_it@@GLIBC_2.1 (fileops.c:178)
==23373==    by 0x40B4AE6: freopen64 (freopen64.c:49)
==23373==    by 0x804EECF: ??? (shuf.s:22773)
==23373==  If you believe this happened as a result of a stack
==23373==  overflow in your program's main thread (unlikely but
==23373==  possible), you can try to increase the size of the
==23373==  main thread stack using the --main-stacksize= flag.
==23373==  The main thread stack size used in this run was 8388608.
==23373== 
==23373== HEAP SUMMARY:
==23373==     in use at exit: 2,020 bytes in 31 blocks
==23373==   total heap usage: 32 allocs, 1 frees, 2,025 bytes allocated
==23373== 
==23373== LEAK SUMMARY:
==23373==    definitely lost: 0 bytes in 0 blocks
==23373==    indirectly lost: 0 bytes in 0 blocks
==23373==      possibly lost: 0 bytes in 0 blocks
==23373==    still reachable: 2,020 bytes in 31 blocks
==23373==         suppressed: 0 bytes in 0 blocks
==23373== Rerun with --leak-check=full to see details of leaked memory
==23373== 
==23373== For counts of detected and suppressed errors, rerun with: -v
==23373== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)
Segmentation fault (core dumped)



问题:

valgrind无效读取 发生在 178 line in fileopc.c
但是,我发现这个程序在被gdb调试时从来没有去178 line in fileopc.c
控制流以不同的方式进行,如下所示。

pwndbg> 
176 in fileops.c
────────────────────────────[ DISASM ]────────────────────────────
   0xb7e7184f <_IO_file_close_it+63>     mov    edx, dword ptr [ebx + 0x68]
   0xb7e71852 <_IO_file_close_it+66>     test   edx, edx
 > 0xb7e71854 <_IO_file_close_it+68>   ✔ jle    _IO_file_close_it+151 <0xb7e718a7>
    ↓
   0xb7e718a7 <_IO_file_close_it+151>    push   0
   0xb7e718a9 <_IO_file_close_it+153>    push   0
   0xb7e718ab <_IO_file_close_it+155>    push   0


pwndbg> 
185 in fileops.c
────────────────────────────[ DISASM ]────────────────────────────
   0xb7e7184f <_IO_file_close_it+63>     mov    edx, dword ptr [ebx + 0x68]
   0xb7e71852 <_IO_file_close_it+66>     test   edx, edx
   0xb7e71854 <_IO_file_close_it+68>     jle    _IO_file_close_it+151 <0xb7e718a7>
    ↓
 > 0xb7e718a7 <_IO_file_close_it+151>    push   0
   0xb7e718a9 <_IO_file_close_it+153>    push   0
   0xb7e718ab <_IO_file_close_it+155>    push   0


问题(续):

如您所见,控制流没有到达178 line in fileopc.c,其中valgrind 表示错误嵌套在其中。
相反,控制流直接从176 in fileops.c 跳转到185 in fileops.c


问题:

这里发生了什么? 为什么valgrindgdb 之间的控制流不同?
是因为这两个工具在生成被检查程序时使用不同的方式吗?

【问题讨论】:

    标签: debugging gdb valgrind heap-corruption memory-corruption


    【解决方案1】:

    这里发生了什么?

    来自valgrind FAQ

    程序在 Valgrind 上运行正常,但在退出时会产生一堆涉及 __libc_freeres 的错误,然后因分段错误而死。

    当程序退出时,Valgrind 运行 glibc 中的 __libc_freeres 过程。这是内存调试器的一个钩子,因此他们可以要求 glibc 释放它使用的任何内存。这样做是为了确保 Valgrind 不会错误地报告 glibc 中的空间泄漏。

    问题是在旧 glibc 版本中运行 __libc_freeres 会导致此崩溃。

    1.1.X 和更高版本的 Valgrind 的解决方法:使用 --run-libc-freeres=no 选项。然后您可能会收到有关 glibc 分配的空间泄漏报告(请不要将这些报告给 glibc 人员,因为它们不是真正的泄漏),但至少程序可以运行。

    请注意,虽然上面的文字讨论的是较旧的 GLIBC,但这也可能发生在破坏 GLIBC 内部状态的程序中,这里显然就是这种情况。

    为什么 valgrind 和 gdb 的控制流不同

    GDB 不会调用__libc_freeres,Valgrind 会。 (还有许多其他细微的差异,但这是观察到的崩溃最可能的解释。)

    【讨论】:

    • 感谢您的建议!使用--run-libc-freers=no 选项,我可以消除关于__libc_freeres 的第二个错误。 (编辑了上面的日志)但是,我仍然不知道我在问题中提到的fileops.c:178 上的 invalid read 问题......虽然这个问题与 glibc freer 无关(可以见上面的调用堆栈),控制流与gdb仍然不同...这是valgrind上的另一个问题吗?
    猜你喜欢
    • 1970-01-01
    • 2015-04-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-02-20
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多