"gdb" и "valgrind" выполняют двоичные файлы по-разному? - PullRequest
0 голосов
/ 15 сентября 2018

Моя программа получила ошибку о повреждении памяти кучи.

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



При отладке с использованием только gdb я сталкиваюсь с valgrind.(спасибо Здесь )
И ... Я получил журнал, используя 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.
Однако я обнаружил, что эта программа никогда не доходила до 178 line in fileopc.c, покаотладка с помощью gdb!
Поток управления проходил иначе, как показано ниже.

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 напрямую.


Вопрос:

Что здесь происходит?Почему потоки управления различаются между valgrind и gdb?
Это потому, что эти два инструмента используют разные способы для запуска проверяемой программы?

1 Ответ

0 голосов
/ 15 сентября 2018

Что здесь происходит?

Из FAQ по Valgrind :

Программы работают нормально на Valgrind, но при выходе выдают кучу ошибок, включая __libc_freeres, а затем умирают с ошибкой сегментации.

Когда программа закрывается, Valgrind запускает процедуру __libc_freeres в glibc. Это ловушка для отладчиков памяти, поэтому они могут попросить glibc освободить любую используемую память. Это необходимо для того, чтобы Valgrind не сообщал неправильно о утечках пространства в glibc.

Проблема в том, что запуск __libc_freeres в более старых версиях glibc вызывает этот сбой.

Обходной путь для 1.1.X и более поздних версий Valgrind: используйте параметр --run-libc-freeres = no. После этого вы можете получить отчеты об утечке пространства для распределения glibc (не сообщайте об этом людям glibc, поскольку они не являются настоящими утечками), но по крайней мере программа запускается.

Обратите внимание, что хотя приведенный выше текст говорит о более старых GLIBC, это также может происходить в программах, которые повреждают внутреннее состояние GLIBC, что, очевидно, имеет место в данном случае.

Почему потоки управления различаются между valgrind и gdb

GDB не вызывает __libc_freeres, Вальгринд делает. (Есть много других тонких различий, но это наиболее вероятное объяснение наблюдаемого сбоя.)

...