Отладка
Хорошая книжка по отладке: https://en.wikibooks.org/wiki/Linux_Applications_Debugging_Techniques
TODO: раскрыть пункты, больше примеров!
О структуре исполняемых файлов (коротко)
ELF:
nm
readelf / objdump
ldd (LD_LIBRARY_PATH=, LD_PRELOAD=)
Что нужно для отладки
- Без оптимизации
- В ассемблерном виде + имена
Привязка к исходнику — debuginfo
- То же для всех библиотек
- + их исходники
-debuginfo-версии пакетов с библиотеками
⇒ cc -O0 -g
GDB
* Выполнение
run
continue
next
step
finish
advance
- Точки останова
По номеру строки (оптимизация ) breakpoint
По изменению ячейки (=> выражения) watchpoint
По C++-исключению или syscall-у catchpoint
- Просмотр
Ячейки (=> выражения, в т. ч. адресного) print, display, x
куска исходника вокруг точки останова list
дампа памяти dump
- Стек вызовов
Просмотр backtrace
Переход up, down
- …!
TODO пример на bt с несколькими функциями
Пример игры со стеком:
- Он ещё и не падает, скотина!
Падает, если закомментировать вызов tst(&b);
Материалы:
Шпаргалка по GDB: https://sourceware.org/gdb/onlinedocs/refcard.pdf
ptrace_scope и gdb -p
- Способ удалённой отладки / отладки программ, работающих с экраном (например, с curses)
Интерфейсы для gdb
Сценарии для GDB
TODO упорядочить
.gdbinit
Пример (перекрашивание, сохранение истории и специальные функции для вывода содержимого QString):
set history save on set style address foreground yellow define printqs5static set $d=$arg0.d printf "(Qt5 QString)0x%x length=%i: \"",&$arg0,$d->size set $i=0 set $ca=(const ushort*)(((const char*)$d)+$d->offset) while $i < $d->size set $c=$ca[$i++] if $c < 32 || $c > 127 printf "\\u%04x", $c else printf "%c" , (char)$c end end printf "\"\n" end define printqs5dynamic set $d=(QStringData*)$arg0.d printf "(Qt5 QString)0x%x length=%i: \"",&$arg0,$d->size set $i=0 while $i < $d->size set $c=$d->data()[$i++] if $c < 32 || $c > 127 printf "\\u%04x", $c else printf "%c" , (char)$c end end printf "\"\n" end
Сценарии для gdb на Питоне (в документации). А что, так можно было?
Д/З
Установить в сборочное окружение -debuginfo версии библиотек. В разных дистрибутивах могут называться по-разному, приезжать вместе с -devel версиями и даже отсутствовать. В ALT называются libчтототам-debuginfo-версия и лежат в отдельной секции репозитория (вот пример sources.list с сервера практикума)
frbrgeorge@linuxprac ~/src $ grep "^[^#]" /etc/apt/sources.list.d/yandex.list rpm [alt] http://mirror.yandex.ru/altlinux Sisyphus/x86_64 classic debuginfo rpm [alt] http://mirror.yandex.ru/altlinux Sisyphus/x86_64-i586 classic rpm [alt] http://mirror.yandex.ru/altlinux Sisyphus/noarch classic
Прощёлкать как минимум make-your-debugging-easier и gdb-scripting
- Задача.
Написать простейшую (или нет, см. далее ☺) программу-генератор арифметической прогрессии range.c, принимающую от одного до трёх параметров по аналогии с питоновским range()
- Без параметров — выводит help
- С одним параметром N — выводит в столбик последовательность [0, 1, … N-1]
- С двумя — M, N — последовательность [M, M+1, … N-1]
- С тремя — M, N, S — последовательность [M, M+S, M+2S, … N-1]
- Написать следующие gdb-сценарии (формат вывода произвольный):
Запустить ./range с параметрами 1 12 и вывести содержимое переменных, отвечающих на зачало, конец, шаг и текущее значение элемента прогрессии, только когда этот элемент кратен 5
Запустить ./range с параметрами -100 100 3 и вывести содержимое переменных, отвечающих на зачало, конец, шаг и текущее значение элемента прогрессии только для 28, 29, 30, 31, 32, 33, 34, и 35 по счёту элементов прогрессии
Написать Makefile, в котором будут
Компиляция бинарника с ключами -O0 -g
Цель test: — запуск gdb-сценариев и сравнение их вывода с эталонным
gdb любит выводить много лишней информации, я использовал в сценариях связку echo @@@ и print …, после чего grep-ал строки, начинающиеся на @@@
Ещё я использовал --batch и --quiet, а вот logging не использовал
Чтобы вывод утилиты range не мешал, его надо перенаправлять в /dev/null прямо в самой команде run
Цель clean: — удаление всех генератов
Вариант для тех, кому скучно так тупо программировать на Си. Дописать функции и типы данных к этой программе, решить Д/З с ней:
- Заодно и поотлаживаете ☺!
Создать в репозитории с решениями подкаталог 05_Debugging и положить туда все исходники решения этой задачи